mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-25 10:16:12 +08:00
305 lines
9.8 KiB
Go
305 lines
9.8 KiB
Go
// Copyright 2019 Yunion
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package models
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/util/compare"
|
|
"yunion.io/x/pkg/util/samlutils"
|
|
"yunion.io/x/sqlchemy"
|
|
|
|
"yunion.io/x/onecloud/pkg/apis"
|
|
api "yunion.io/x/onecloud/pkg/apis/cloudid"
|
|
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
|
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
|
"yunion.io/x/onecloud/pkg/cloudid/options"
|
|
"yunion.io/x/onecloud/pkg/mcclient"
|
|
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
|
)
|
|
|
|
type SSAMLProviderManager struct {
|
|
db.SStatusInfrasResourceBaseManager
|
|
db.SExternalizedResourceBaseManager
|
|
SCloudaccountResourceBaseManager
|
|
SCloudproviderResourceBaseManager
|
|
}
|
|
|
|
var SAMLProviderManager *SSAMLProviderManager
|
|
|
|
func init() {
|
|
SAMLProviderManager = &SSAMLProviderManager{
|
|
SStatusInfrasResourceBaseManager: db.NewStatusInfrasResourceBaseManager(
|
|
SSAMLProvider{},
|
|
"saml_provider_tbl",
|
|
"saml_provider",
|
|
"saml_providers",
|
|
),
|
|
}
|
|
SAMLProviderManager.SetVirtualObject(SAMLProviderManager)
|
|
}
|
|
|
|
type SSAMLProvider struct {
|
|
db.SStatusInfrasResourceBase
|
|
db.SExternalizedResourceBase
|
|
|
|
SCloudaccountResourceBase
|
|
SCloudproviderResourceBase
|
|
|
|
EntityId string `get:"domain" create:"domain_optional" list:"domain"`
|
|
MetadataDocument string `get:"domain" create:"domain_optional"`
|
|
AuthUrl string `width:"512" charset:"ascii" get:"domain" list:"domain"`
|
|
}
|
|
|
|
func (manager *SSAMLProviderManager) GetIVirtualModelManager() db.IVirtualModelManager {
|
|
return manager.GetVirtualObject().(db.IVirtualModelManager)
|
|
}
|
|
|
|
func (manager *SSAMLProviderManager) GetResourceCount() ([]db.SScopeResourceCount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (manager *SSAMLProviderManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
|
|
accountId, _ := data.GetString("cloudaccount_id")
|
|
return jsonutils.Marshal(map[string]string{"cloudaccount_id": accountId})
|
|
}
|
|
|
|
func (manager *SSAMLProviderManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
|
|
accountId, _ := values.GetString("cloudaccount_id")
|
|
if len(accountId) > 0 {
|
|
q = q.Equals("cloudaccount_id", accountId)
|
|
}
|
|
return q
|
|
}
|
|
|
|
func (self *SSAMLProvider) GetCloudprovider() (*SCloudprovider, error) {
|
|
provider, err := CloudproviderManager.FetchById(self.ManagerId)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "CloudproviderManager.FetchById(%s)", self.ManagerId)
|
|
}
|
|
return provider.(*SCloudprovider), nil
|
|
}
|
|
|
|
func (self *SSAMLProvider) GetProvider() (cloudprovider.ICloudProvider, error) {
|
|
if len(self.ManagerId) > 0 {
|
|
provider, err := self.GetCloudprovider()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "GetCloudprovider")
|
|
}
|
|
return provider.GetProvider()
|
|
}
|
|
account, err := self.GetCloudaccount()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "GetCloudaccount")
|
|
}
|
|
return account.GetProvider()
|
|
}
|
|
|
|
// 公有云身份提供商列表
|
|
func (manager *SSAMLProviderManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.SAMLProviderListInput) (*sqlchemy.SQuery, error) {
|
|
var err error
|
|
q, err = manager.SStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusInfrasResourceBaseListInput)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
q, err = manager.SCloudaccountResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudaccountResourceListInput)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
q, err = manager.SCloudproviderResourceBaseManager.ListItemFilter(ctx, q, userCred, query.CloudproviderResourceListInput)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return q, nil
|
|
}
|
|
|
|
// 删除
|
|
func (self *SSAMLProvider) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
|
params := jsonutils.NewDict()
|
|
return self.StartSAMLProviderDeleteTask(ctx, userCred, params, "")
|
|
}
|
|
|
|
func (self *SSAMLProvider) StartSAMLProviderDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error {
|
|
task, err := taskman.TaskManager.NewTask(ctx, "SAMLProviderDeleteTask", self, userCred, data, parentTaskId, "", nil)
|
|
if err != nil {
|
|
return errors.Wrap(err, "NewTask")
|
|
}
|
|
self.SetStatus(ctx, userCred, apis.STATUS_DELETING, "")
|
|
return task.ScheduleRun(nil)
|
|
}
|
|
|
|
func (self *SSAMLProvider) GetISAMLProvider() (cloudprovider.ICloudSAMLProvider, error) {
|
|
if len(self.ExternalId) == 0 {
|
|
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
|
|
}
|
|
provider, err := self.GetProvider()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
samlProviders, err := provider.GetICloudSAMLProviders()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i := range samlProviders {
|
|
if samlProviders[i].GetGlobalId() == self.ExternalId {
|
|
return samlProviders[i], nil
|
|
}
|
|
}
|
|
return nil, errors.Wrapf(cloudprovider.ErrNotFound, self.ExternalId)
|
|
}
|
|
|
|
func (self *SSAMLProvider) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
return nil
|
|
}
|
|
|
|
func (self *SSAMLProvider) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
return self.SStatusInfrasResourceBase.Delete(ctx, userCred)
|
|
}
|
|
|
|
func (self *SSAMLProvider) syncRemove(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
return self.RealDelete(ctx, userCred)
|
|
}
|
|
|
|
func (self *SSAMLProvider) SyncWithCloudSAMLProvider(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSAMLProvider, managerId string) error {
|
|
_, err := db.Update(self, func() error {
|
|
self.ExternalId = ext.GetGlobalId()
|
|
self.AuthUrl = ext.GetAuthUrl(options.Options.ApiServer)
|
|
metadata, _ := ext.GetMetadataDocument()
|
|
if metadata != nil {
|
|
self.EntityId = metadata.EntityId
|
|
self.MetadataDocument = metadata.String()
|
|
}
|
|
self.Status = apis.STATUS_UNKNOWN
|
|
if self.EntityId == options.Options.ApiServer && strings.Contains(self.MetadataDocument, "login/"+self.ManagerId) {
|
|
self.Status = apis.STATUS_AVAILABLE
|
|
}
|
|
if len(managerId) > 0 {
|
|
self.ManagerId = managerId
|
|
}
|
|
return nil
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (self *SSAMLProvider) GetMetadataDocument() (samlutils.EntityDescriptor, error) {
|
|
return samlutils.ParseMetadata([]byte(self.MetadataDocument))
|
|
}
|
|
|
|
func (manager *SSAMLProviderManager) FetchCustomizeColumns(
|
|
ctx context.Context,
|
|
userCred mcclient.TokenCredential,
|
|
query jsonutils.JSONObject,
|
|
objs []interface{},
|
|
fields stringutils2.SSortedStrings,
|
|
isList bool,
|
|
) []api.SAMLProviderDetails {
|
|
rows := make([]api.SAMLProviderDetails, len(objs))
|
|
infRows := manager.SStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
|
acRows := manager.SCloudaccountResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
|
for i := range rows {
|
|
rows[i] = api.SAMLProviderDetails{
|
|
StatusInfrasResourceBaseDetails: infRows[i],
|
|
CloudaccountResourceDetails: acRows[i],
|
|
}
|
|
}
|
|
return rows
|
|
}
|
|
|
|
func (self *SCloudaccount) SyncSAMLProviders(ctx context.Context, userCred mcclient.TokenCredential, samls []cloudprovider.ICloudSAMLProvider, managerId string) compare.SyncResult {
|
|
result := compare.SyncResult{}
|
|
dbSamls, err := self.GetSAMLProviders(managerId)
|
|
if err != nil {
|
|
result.Error(errors.Wrap(err, "GetSAMLProviders"))
|
|
return result
|
|
}
|
|
|
|
removed := make([]SSAMLProvider, 0)
|
|
commondb := make([]SSAMLProvider, 0)
|
|
commonext := make([]cloudprovider.ICloudSAMLProvider, 0)
|
|
added := make([]cloudprovider.ICloudSAMLProvider, 0)
|
|
|
|
err = compare.CompareSets(dbSamls, samls, &removed, &commondb, &commonext, &added)
|
|
if err != nil {
|
|
result.Error(errors.Wrap(err, "compare.CompareSets"))
|
|
return result
|
|
}
|
|
|
|
for i := 0; i < len(removed); i++ {
|
|
err = removed[i].RealDelete(ctx, userCred)
|
|
if err != nil {
|
|
result.DeleteError(err)
|
|
continue
|
|
}
|
|
result.Delete()
|
|
}
|
|
|
|
for i := 0; i < len(commondb); i++ {
|
|
err = commondb[i].SyncWithCloudSAMLProvider(ctx, userCred, commonext[i], managerId)
|
|
if err != nil {
|
|
result.UpdateError(err)
|
|
continue
|
|
}
|
|
result.Update()
|
|
}
|
|
|
|
for i := 0; i < len(added); i++ {
|
|
err = self.newFromCloudSAMLProvider(ctx, userCred, added[i], managerId)
|
|
if err != nil {
|
|
result.AddError(err)
|
|
continue
|
|
}
|
|
result.Add()
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (self *SCloudaccount) newFromCloudSAMLProvider(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSAMLProvider, managerId string) error {
|
|
saml := &SSAMLProvider{}
|
|
saml.SetModelManager(SAMLProviderManager, saml)
|
|
saml.Name = ext.GetName()
|
|
saml.ExternalId = ext.GetGlobalId()
|
|
saml.DomainId = self.DomainId
|
|
saml.CloudaccountId = self.Id
|
|
saml.ManagerId = managerId
|
|
saml.AuthUrl = ext.GetAuthUrl(options.Options.ApiServer)
|
|
metadata, _ := ext.GetMetadataDocument()
|
|
if metadata != nil {
|
|
saml.EntityId = metadata.EntityId
|
|
saml.MetadataDocument = metadata.String()
|
|
}
|
|
saml.Status = ext.GetStatus()
|
|
saml.Status = apis.STATUS_UNKNOWN
|
|
if saml.EntityId == options.Options.ApiServer && strings.Contains(saml.MetadataDocument, "login/"+saml.ManagerId) {
|
|
saml.Status = apis.STATUS_AVAILABLE
|
|
}
|
|
return SAMLProviderManager.TableSpec().Insert(ctx, saml)
|
|
}
|
|
|
|
func (self *SCloudprovider) GetSamlProviders() ([]SSAMLProvider, error) {
|
|
q := SAMLProviderManager.Query().Equals("manager_id", self.Id)
|
|
ret := []SSAMLProvider{}
|
|
err := db.FetchModelObjects(SAMLProviderManager, q, &ret)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ret, nil
|
|
}
|