mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-20 11:22:19 +08:00
347 lines
10 KiB
Go
347 lines
10 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"
|
|
"database/sql"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/tristate"
|
|
|
|
"yunion.io/x/onecloud/pkg/apis"
|
|
"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/mcclient/auth"
|
|
"yunion.io/x/onecloud/pkg/mcclient/informer"
|
|
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
|
|
)
|
|
|
|
// +onecloud:swagger-gen-ignore
|
|
type SCloudaccountManager struct {
|
|
db.SDomainLevelResourceBaseManager
|
|
}
|
|
|
|
var CloudaccountManager *SCloudaccountManager
|
|
|
|
func init() {
|
|
CloudaccountManager = &SCloudaccountManager{
|
|
SDomainLevelResourceBaseManager: db.NewDomainLevelResourceBaseManager(
|
|
SCloudaccount{},
|
|
"cloudaccounts_tbl",
|
|
"cloudaccount",
|
|
"cloudaccounts",
|
|
),
|
|
}
|
|
CloudaccountManager.SetVirtualObject(CloudaccountManager)
|
|
}
|
|
|
|
type SCloudaccount struct {
|
|
db.SStandaloneResourceBase
|
|
db.SDomainizedResourceBase
|
|
|
|
AccountId string `width:"128" charset:"utf8" nullable:"true" list:"domain" create:"domain_optional"`
|
|
Provider string `width:"64" charset:"ascii" list:"domain"`
|
|
Brand string `width:"64" charset:"utf8" nullable:"true" list:"domain"`
|
|
IamLoginUrl string `width:"512" charset:"ascii"`
|
|
SAMLAuth tristate.TriState `list:"domain" default:"false"`
|
|
|
|
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
|
|
|
|
ReadOnly bool `default:"false" create:"domain_optional" list:"domain" update:"domain"`
|
|
}
|
|
|
|
func (manager *SCloudaccountManager) GetResourceCount() ([]db.SScopeResourceCount, error) {
|
|
return []db.SScopeResourceCount{}, nil
|
|
}
|
|
|
|
func (manager *SCloudaccountManager) GetCloudaccounts() ([]SCloudaccount, error) {
|
|
accounts := []SCloudaccount{}
|
|
q := manager.Query()
|
|
err := db.FetchModelObjects(manager, q, &accounts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return accounts, nil
|
|
}
|
|
|
|
func (self *SCloudaccount) GetCloudproviderId() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SCloudaccount) GetSamlusers() ([]SSamluser, error) {
|
|
q := SamluserManager.Query().Equals("cloudaccount_id", self.Id)
|
|
users := []SSamluser{}
|
|
err := db.FetchModelObjects(SamluserManager, q, &users)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
func (self *SCloudaccount) GetProvider() (cloudprovider.ICloudProvider, error) {
|
|
ctx := context.Background()
|
|
s := auth.GetAdminSession(ctx, options.Options.Region)
|
|
return modules.Cloudaccounts.GetProvider(ctx, s, self.Id)
|
|
}
|
|
|
|
func (self *SCloudaccount) GetDriver() (IProviderDriver, error) {
|
|
return GetProviderDriver(self.Provider)
|
|
}
|
|
|
|
func (self *SCloudaccount) GetCloudpolicies(managerId string) ([]SCloudpolicy, error) {
|
|
q := CloudpolicyManager.Query().Equals("cloudaccount_id", self.Id)
|
|
if len(managerId) > 0 {
|
|
q = q.Equals("manager_id", managerId)
|
|
}
|
|
policies := []SCloudpolicy{}
|
|
err := db.FetchModelObjects(CloudpolicyManager, q, &policies)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "db.FetchModelObjects")
|
|
}
|
|
return policies, nil
|
|
}
|
|
|
|
func (self *SCloudaccount) GetCloudproviders() ([]SCloudprovider, error) {
|
|
q := CloudproviderManager.Query().Equals("cloudaccount_id", self.Id)
|
|
providers := []SCloudprovider{}
|
|
err := db.FetchModelObjects(CloudproviderManager, q, &providers)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "db.FetchModelObjects")
|
|
}
|
|
return providers, nil
|
|
}
|
|
|
|
func (self *SCloudaccount) GetCloudgroups(managerId string) ([]SCloudgroup, error) {
|
|
groups := []SCloudgroup{}
|
|
q := CloudgroupManager.Query().Equals("cloudaccount_id", self.Id)
|
|
if len(managerId) > 0 {
|
|
q = q.Equals("manager_id", managerId)
|
|
}
|
|
err := db.FetchModelObjects(CloudgroupManager, q, &groups)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "db.FetchModelObjects")
|
|
}
|
|
return groups, nil
|
|
}
|
|
|
|
func (manager *SCloudaccountManager) SyncCloudaccountResources(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
|
accounts, err := manager.GetCloudaccounts()
|
|
if err != nil {
|
|
log.Errorf("GetCloudaccounts error: %v", err)
|
|
return
|
|
}
|
|
for i := range accounts {
|
|
err = accounts[i].StartSyncCloudaccountResourcesTask(ctx, userCred, "")
|
|
if err != nil {
|
|
log.Errorf("StartCloudaccountSyncResourcesTask for account %s(%s) error: %v", accounts[i].Name, accounts[i].Provider, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (self *SCloudaccount) IsSAMLProviderValid() (*SSAMLProvider, bool) {
|
|
provider, err := self.RegisterSAMProvider()
|
|
if err != nil {
|
|
return provider, false
|
|
}
|
|
if len(provider.ExternalId) == 0 {
|
|
return provider, false
|
|
}
|
|
return provider, true
|
|
}
|
|
|
|
func (self *SCloudaccount) RegisterSAMProvider() (*SSAMLProvider, error) {
|
|
if len(options.Options.ApiServer) == 0 {
|
|
return nil, fmt.Errorf("empty api server")
|
|
}
|
|
sps, err := self.GetSAMLProviders("")
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "GetSAMLProviders")
|
|
}
|
|
for i := range sps {
|
|
if sps[i].EntityId == options.Options.ApiServer {
|
|
return &sps[i], nil
|
|
}
|
|
}
|
|
sp := &SSAMLProvider{}
|
|
sp.SetModelManager(SAMLProviderManager, sp)
|
|
sp.Name = func() string {
|
|
name := strings.TrimPrefix(options.Options.ApiServer, "https://")
|
|
name = strings.TrimPrefix(name, "http://")
|
|
return name
|
|
}()
|
|
sp.EntityId = options.Options.ApiServer
|
|
sp.CloudaccountId = self.Id
|
|
sp.DomainId = self.DomainId
|
|
sp.Status = apis.STATUS_CREATING
|
|
metadata := SamlIdpInstance().GetMetadata(self.Id).String()
|
|
sp.MetadataDocument = metadata
|
|
err = SAMLProviderManager.TableSpec().Insert(context.TODO(), sp)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "Insert")
|
|
}
|
|
return sp, nil
|
|
}
|
|
|
|
func (self *SCloudaccount) StartSAMLProviderCreateTask(ctx context.Context, userCred mcclient.TokenCredential) error {
|
|
params := jsonutils.NewDict()
|
|
task, err := taskman.TaskManager.NewTask(ctx, "SAMLProviderCreateTask", self, userCred, params, "", "", nil)
|
|
if err != nil {
|
|
return errors.Wrap(err, "NewTask")
|
|
}
|
|
return task.ScheduleRun(nil)
|
|
}
|
|
|
|
func (self *SCloudaccount) GetSAMLProviders(managerId string) ([]SSAMLProvider, error) {
|
|
q := SAMLProviderManager.Query().Equals("cloudaccount_id", self.Id).Desc("external_id")
|
|
if len(managerId) > 0 {
|
|
q = q.Equals("manager_id", managerId)
|
|
}
|
|
samls := []SSAMLProvider{}
|
|
err := db.FetchModelObjects(SAMLProviderManager, q, &samls)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
|
}
|
|
return samls, nil
|
|
}
|
|
|
|
func (self *SCloudaccount) StartSyncCloudaccountResourcesTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
|
params := jsonutils.NewDict()
|
|
task, err := taskman.TaskManager.NewTask(ctx, "CloudaccountSyncResourcesTask", self, userCred, params, parentTaskId, "", nil)
|
|
if err != nil {
|
|
return errors.Wrap(err, "NewTask")
|
|
}
|
|
return task.ScheduleRun(nil)
|
|
}
|
|
|
|
func (self *SCloudaccount) GetCloudroles(managerId string) ([]SCloudrole, error) {
|
|
roles := []SCloudrole{}
|
|
q := CloudroleManager.Query().Equals("cloudaccount_id", self.Id)
|
|
if len(managerId) > 0 {
|
|
q = q.Equals("manager_id", managerId)
|
|
}
|
|
err := db.FetchModelObjects(CloudroleManager, q, &roles)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
|
}
|
|
return roles, nil
|
|
}
|
|
|
|
func (m *SCloudaccountManager) StartWatchSAMLInRegion() error {
|
|
adminSession := auth.GetAdminSession(context.Background(), "")
|
|
watchMan, err := informer.NewWatchManagerBySession(adminSession)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resMan := &modules.Cloudaccounts
|
|
return watchMan.For(resMan).AddEventHandler(context.Background(), m)
|
|
}
|
|
|
|
func (m *SCloudaccountManager) OnAdd(obj *jsonutils.JSONDict) {
|
|
account := &SCloudaccount{}
|
|
obj.Unmarshal(account)
|
|
log.Debugf("OnAdd provider %s %s(%s)", account.Provider, account.Name, account.Id)
|
|
account.SetModelManager(m, account)
|
|
ctx := context.Background()
|
|
if len(account.Provider) == 0 {
|
|
s := auth.GetAdminSession(ctx, options.Options.Region)
|
|
data, err := modules.Cloudaccounts.GetById(s, account.Id, nil)
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = data.Unmarshal(account)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
err := m.TableSpec().Insert(ctx, account)
|
|
if err != nil {
|
|
return
|
|
}
|
|
account.StartSyncCloudaccountResourcesTask(ctx, auth.AdminCredential(), "")
|
|
}
|
|
|
|
func (m *SCloudaccountManager) FetchAccount(id string) (*SCloudaccount, error) {
|
|
account, err := m.FetchById(id)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "fetch by id %s", id)
|
|
}
|
|
return account.(*SCloudaccount), nil
|
|
}
|
|
|
|
func (self *SCloudaccount) GetSamlProvider() (*SSAMLProvider, error) {
|
|
q := SAMLProviderManager.Query().Equals("status", apis.STATUS_AVAILABLE).
|
|
Equals("entity_id", options.Options.ApiServer).Equals("cloudaccount_id", self.Id).IsNotEmpty("external_id")
|
|
ret := &SSAMLProvider{}
|
|
ret.SetModelManager(SAMLProviderManager, ret)
|
|
err := q.First(ret)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (m *SCloudaccountManager) OnDelete(obj *jsonutils.JSONDict) {
|
|
log.Debugf("OnDelete %s", obj)
|
|
account, err := func() (*SCloudaccount, error) {
|
|
id, err := obj.GetString("id")
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "get id")
|
|
}
|
|
return m.FetchAccount(id)
|
|
}()
|
|
if err != nil {
|
|
log.Errorf("fetch account error: %v", err)
|
|
return
|
|
}
|
|
err = account.purge(context.Background())
|
|
if err != nil {
|
|
log.Errorf("purge account error: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func (m *SCloudaccountManager) OnUpdate(oldObj, newObj *jsonutils.JSONDict) {
|
|
id, err := newObj.GetString("id")
|
|
if err != nil {
|
|
return
|
|
}
|
|
account, err := m.FetchAccount(id)
|
|
if err != nil {
|
|
if errors.Cause(err) == sql.ErrNoRows {
|
|
m.OnAdd(newObj)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
db.Update(account, func() error {
|
|
newObj.Unmarshal(account)
|
|
return nil
|
|
})
|
|
oSaml, _ := oldObj.Bool("saml_auth")
|
|
nSaml, _ := newObj.Bool("saml_auth")
|
|
if !oSaml && nSaml {
|
|
log.Debugf("OnUpdate provider %s %s(%s) enable saml auth", account.Provider, account.Name, account.Id)
|
|
account.StartSAMLProviderCreateTask(context.Background(), auth.AdminCredential())
|
|
}
|
|
}
|