From 7e2f2e8adaa4a2e9cae8fc37ff4921d1fc02ba72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Wed, 28 Sep 2022 15:27:17 +0800 Subject: [PATCH] fix(cloudid): azure cloudgroup (#15092) --- pkg/multicloud/azure/azure.go | 28 +++------ pkg/multicloud/azure/cloudgroup.go | 66 +++++++++------------ pkg/multicloud/azure/clouduser.go | 72 ++++++++++++++--------- pkg/multicloud/azure/provider/provider.go | 9 ++- pkg/multicloud/azure/shell/clouduser.go | 3 +- 5 files changed, 90 insertions(+), 88 deletions(-) diff --git a/pkg/multicloud/azure/azure.go b/pkg/multicloud/azure/azure.go index 135924830a..af744316bb 100644 --- a/pkg/multicloud/azure/azure.go +++ b/pkg/multicloud/azure/azure.go @@ -340,10 +340,10 @@ func (self *SAzureClient) get(resourceId string, params url.Values, retVal inter } func (self *SAzureClient) gcreate(resource string, body jsonutils.JSONObject, retVal interface{}) error { - path := fmt.Sprintf("%s/%s", self.tenantId, resource) - result, err := self.gjsonRequest("POST", path, body, url.Values{}) + path := resource + result, err := self.msGraphRequest("POST", path, body) if err != nil { - return errors.Wrapf(err, "gjsonRequest") + return errors.Wrapf(err, "msGraphRequest") } if retVal != nil { return result.Unmarshal(retVal) @@ -367,8 +367,11 @@ func (self *SAzureClient) glist(resource string, params url.Values, retVal inter } func (self *SAzureClient) _glist(resource string, params url.Values, retVal interface{}) error { - path := fmt.Sprintf("%s/%s", self.tenantId, resource) - body, err := self.gjsonRequest("GET", path, nil, params) + path := resource + if len(params) > 0 { + path = fmt.Sprintf("%s?%s", path, params.Encode()) + } + body, err := self.msGraphRequest("GET", path, nil) if err != nil { return err } @@ -596,7 +599,7 @@ func (self *SAzureClient) GDelete(resourceId string) error { } func (self *SAzureClient) gdel(resourceId string) error { - _, err := self.gjsonRequest("DELETE", resourceId, nil, url.Values{}) + _, err := self.msGraphRequest("DELETE", resourceId, nil) if err != nil { return errors.Wrapf(err, "gdel(%s)", resourceId) } @@ -1110,19 +1113,6 @@ func (self *SAzureClient) msGraphClient() *http.Client { return conf.Client(context.TODO()) } -func (self *SAzureClient) ListGraphUsers() ([]SClouduser, error) { - resp, err := self.msGraphRequest("GET", "users", nil) - if err != nil { - return nil, errors.Wrapf(err, "msGraphRequest.users") - } - users := []SClouduser{} - err = resp.Unmarshal(&users, "value") - if err != nil { - return nil, errors.Wrapf(err, "resp.Unmarshal") - } - return users, nil -} - func (self *SAzureClient) msGraphRequest(method string, resource string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) { client := self.msGraphClient() url := fmt.Sprintf("https://graph.microsoft.com/v1.0/%s", resource) diff --git a/pkg/multicloud/azure/cloudgroup.go b/pkg/multicloud/azure/cloudgroup.go index 849bbd8eeb..ad459dbc17 100644 --- a/pkg/multicloud/azure/cloudgroup.go +++ b/pkg/multicloud/azure/cloudgroup.go @@ -28,9 +28,7 @@ import ( type SCloudgroup struct { client *SAzureClient - OdataType string `json:"odata.type"` - ObjectType string - ObjectId string + Id string DeletionTimestamp string Description string DirSyncEnabled string @@ -47,7 +45,7 @@ func (group *SCloudgroup) GetName() string { } func (group *SCloudgroup) GetGlobalId() string { - return group.ObjectId + return group.Id } func (group *SCloudgroup) GetDescription() string { @@ -55,9 +53,9 @@ func (group *SCloudgroup) GetDescription() string { } func (group *SCloudgroup) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { - policies, err := group.client.GetCloudpolicies(group.ObjectId) + policies, err := group.client.GetCloudpolicies(group.Id) if err != nil { - return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", group.ObjectId) + return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", group.Id) } ret := []cloudprovider.ICloudpolicy{} for i := range policies { @@ -69,9 +67,9 @@ func (group *SCloudgroup) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolic } func (group *SCloudgroup) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { - policies, err := group.client.GetCloudpolicies(group.ObjectId) + policies, err := group.client.GetCloudpolicies(group.Id) if err != nil { - return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", group.ObjectId) + return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", group.Id) } ret := []cloudprovider.ICloudpolicy{} for i := range policies { @@ -83,7 +81,7 @@ func (group *SCloudgroup) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolic } func (group *SCloudgroup) GetICloudusers() ([]cloudprovider.IClouduser, error) { - users, err := group.client.ListGroupMemebers(group.ObjectId) + users, err := group.client.ListGroupMemebers(group.Id) if err != nil { return nil, errors.Wrap(err, "ListGroupMemebers") } @@ -96,25 +94,25 @@ func (group *SCloudgroup) GetICloudusers() ([]cloudprovider.IClouduser, error) { } func (group *SCloudgroup) AddUser(name string) error { - return group.client.AddGroupUser(group.ObjectId, name) + return group.client.AddGroupUser(group.Id, name) } func (group *SCloudgroup) RemoveUser(name string) error { - return group.client.RemoveGroupUser(group.ObjectId, name) + return group.client.RemoveGroupUser(group.Id, name) } func (group *SCloudgroup) AttachSystemPolicy(policyId string) error { - return group.client.AssignPolicy(group.ObjectId, policyId, "") + return group.client.AssignPolicy(group.Id, policyId, "") } func (group *SCloudgroup) AttachCustomPolicy(policyId string) error { - return group.client.AssignPolicy(group.ObjectId, policyId, "") + return group.client.AssignPolicy(group.Id, policyId, "") } func (group *SCloudgroup) DetachSystemPolicy(policyId string) error { - assignments, err := group.client.GetAssignments(group.ObjectId) + assignments, err := group.client.GetAssignments(group.Id) if err != nil { - return errors.Wrapf(err, "GetAssignments(%s)", group.ObjectId) + return errors.Wrapf(err, "GetAssignments(%s)", group.Id) } for _, assignment := range assignments { role, err := group.client.GetRole(assignment.Properties.RoleDefinitionId) @@ -133,7 +131,7 @@ func (group *SCloudgroup) DetachCustomPolicy(policyId string) error { } func (group *SCloudgroup) Delete() error { - return group.client.DeleteGroup(group.ObjectId) + return group.client.DeleteGroup(group.Id) } func (self *SAzureClient) GetCloudgroups(name string) ([]SCloudgroup, error) { @@ -188,16 +186,22 @@ func (self *SAzureClient) ListGroupMemebers(id string) ([]SClouduser, error) { } func (self *SAzureClient) DeleteGroup(id string) error { - return self.gdel(fmt.Sprintf("%s/groups/%s", self.tenantId, id)) + return self.gdel(fmt.Sprintf("groups/%s", id)) } func (self *SAzureClient) CreateGroup(name, desc string) (*SCloudgroup, error) { params := map[string]interface{}{ "displayName": name, - "mailNickname": name, "mailEnabled": false, "securityEnabled": true, } + nickName := "" + for _, s := range name { + if s >= 0 && s <= 127 { + nickName += string(s) + } + } + params["mailNickname"] = nickName if len(desc) > 0 { params["Description"] = desc } @@ -210,17 +214,11 @@ func (self *SAzureClient) CreateGroup(name, desc string) (*SCloudgroup, error) { } func (self *SAzureClient) RemoveGroupUser(id, userName string) error { - users, err := self.GetCloudusers(userName) + user, err := self.GetClouduser(userName) if err != nil { return errors.Wrapf(err, "GetCloudusers(%s)", userName) } - if len(users) == 0 { - return nil - } - if len(users) > 1 { - return cloudprovider.ErrDuplicateId - } - return self.gdel(fmt.Sprintf("%s/groups/%s/$links/members/%s", self.tenantId, id, users[0].ObjectId)) + return self.gdel(fmt.Sprintf("/groups/%s/members/%s/$ref", id, user.Id)) } func (self *SAzureClient) CreateICloudgroup(name, desc string) (cloudprovider.ICloudgroup, error) { @@ -233,23 +231,13 @@ func (self *SAzureClient) CreateICloudgroup(name, desc string) (cloudprovider.IC } func (self *SAzureClient) AddGroupUser(id, userName string) error { - users, err := self.GetCloudusers(userName) + user, err := self.GetClouduser(userName) if err != nil { return errors.Wrapf(err, "GetCloudusers(%s)", userName) } - if len(users) == 0 { - return nil - } - if len(users) > 1 { - return cloudprovider.ErrDuplicateId - } - cli, err := self.getGraphClient() - if err != nil { - return errors.Wrapf(err, "getGraphClient") - } - resource := fmt.Sprintf("groups/%s/$links/members", id) + resource := fmt.Sprintf("groups/%s/members/$ref", id) params := map[string]string{ - "url": fmt.Sprintf("%s%s/directoryObjects/%s", cli.domain, self.tenantId, users[0].ObjectId), + "@odata.id": fmt.Sprintf("https://graph.microsoft.com/v1.0/directoryObjects/%s", user.Id), } err = self.gcreate(resource, jsonutils.Marshal(params), nil) if err != nil && !strings.Contains(err.Error(), "One or more added object references already exist for the following modified properties") { diff --git a/pkg/multicloud/azure/clouduser.go b/pkg/multicloud/azure/clouduser.go index 8094581126..aab89f893f 100644 --- a/pkg/multicloud/azure/clouduser.go +++ b/pkg/multicloud/azure/clouduser.go @@ -40,7 +40,7 @@ type SClouduser struct { OdataType string `json:"odata.type"` ObjectType string - ObjectId string + Id string DeletionTimestamp string AccountEnabled bool AgeGroup string @@ -93,7 +93,7 @@ func (user *SClouduser) GetName() string { } func (user *SClouduser) GetGlobalId() string { - return user.ObjectId + return user.Id } func (user *SClouduser) GetEmailAddr() string { @@ -105,9 +105,9 @@ func (user *SClouduser) GetInviteUrl() string { } func (user *SClouduser) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { - policies, err := user.client.GetCloudpolicies(user.ObjectId) + policies, err := user.client.GetCloudpolicies(user.Id) if err != nil { - return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.ObjectId) + return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id) } ret := []cloudprovider.ICloudpolicy{} for i := range policies { @@ -119,9 +119,9 @@ func (user *SClouduser) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, } func (user *SClouduser) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { - policies, err := user.client.GetCloudpolicies(user.ObjectId) + policies, err := user.client.GetCloudpolicies(user.Id) if err != nil { - return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.ObjectId) + return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id) } ret := []cloudprovider.ICloudpolicy{} for i := range policies { @@ -134,7 +134,7 @@ func (user *SClouduser) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, func (user *SClouduser) AttachSystemPolicy(policyId string) error { for _, subscription := range user.client.subscriptions { - err := user.client.AssignPolicy(user.ObjectId, policyId, subscription.SubscriptionId) + err := user.client.AssignPolicy(user.Id, policyId, subscription.SubscriptionId) if err != nil { return errors.Wrapf(err, "AssignPolicy for subscription %s", subscription.SubscriptionId) } @@ -144,7 +144,7 @@ func (user *SClouduser) AttachSystemPolicy(policyId string) error { func (user *SClouduser) AttachCustomPolicy(policyId string) error { for _, subscription := range user.client.subscriptions { - err := user.client.AssignPolicy(user.ObjectId, policyId, subscription.SubscriptionId) + err := user.client.AssignPolicy(user.Id, policyId, subscription.SubscriptionId) if err != nil { return errors.Wrapf(err, "AssignPolicy for subscription %s", subscription.SubscriptionId) } @@ -153,9 +153,9 @@ func (user *SClouduser) AttachCustomPolicy(policyId string) error { } func (user *SClouduser) DetachSystemPolicy(policyId string) error { - assignments, err := user.client.GetAssignments(user.ObjectId) + assignments, err := user.client.GetAssignments(user.Id) if err != nil { - return errors.Wrapf(err, "GetAssignments(%s)", user.ObjectId) + return errors.Wrapf(err, "GetAssignments(%s)", user.Id) } for _, assignment := range assignments { role, err := user.client.GetRole(assignment.Properties.RoleDefinitionId) @@ -174,7 +174,7 @@ func (user *SClouduser) DetachCustomPolicy(policyId string) error { } func (user *SClouduser) IsConsoleLogin() bool { - return user.AccountEnabled + return true } // 需要当前应用有User administrator权限 @@ -183,11 +183,11 @@ func (user *SClouduser) Delete() error { } func (user *SClouduser) ResetPassword(password string) error { - return user.client.ResetClouduserPassword(user.ObjectId, password) + return user.client.ResetClouduserPassword(user.Id, password) } func (user *SClouduser) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) { - groups, err := user.client.GetUserGroups(user.ObjectId) + groups, err := user.client.GetUserGroups(user.Id) if err != nil { return nil, errors.Wrap(err, "GetUserGroups") } @@ -200,9 +200,9 @@ func (user *SClouduser) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) { } func (self *SAzureClient) GetUserGroups(userId string) ([]SCloudgroup, error) { - resource := fmt.Sprintf("%s/users/%s/memberOf", self.tenantId, userId) + resource := fmt.Sprintf("users/%s/memberOf", userId) groups := []SCloudgroup{} - err := self.glist(resource, url.Values{}, groups) + err := self.glist(resource, url.Values{}, &groups) return groups, err } @@ -218,12 +218,23 @@ func (self *SAzureClient) ResetClouduserPassword(id, password string) error { return err } -func (self *SAzureClient) GetCloudusers(name string) ([]SClouduser, error) { +func (self *SAzureClient) GetClouduser(name string) (*SClouduser, error) { + users, err := self.GetCloudusers() + if err != nil { + return nil, err + } + for i := range users { + if users[i].DisplayName == name || users[i].UserPrincipalName == name { + users[i].client = self + return &users[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + +func (self *SAzureClient) GetCloudusers() ([]SClouduser, error) { users := []SClouduser{} params := url.Values{} - if len(name) > 0 { - params.Set("$filter", fmt.Sprintf("userPrincipalName eq '%s'", name)) - } err := self.glist("users", params, &users) if err != nil { return nil, err @@ -250,17 +261,11 @@ func (self *SAzureClient) GetICloudusers() ([]cloudprovider.IClouduser, error) { } func (self *SAzureClient) GetIClouduserByName(name string) (cloudprovider.IClouduser, error) { - users, err := self.ListGraphUsers() + user, err := self.GetClouduser(name) if err != nil { return nil, errors.Wrap(err, "GetCloudusers") } - for i := range users { - if users[i].GetName() == name || strings.HasPrefix(name+"@", users[i].GetName()) { - users[i].client = self - return &users[i], nil - } - } - return nil, cloudprovider.ErrNotFound + return user, nil } func (self *SAzureClient) CreateIClouduser(conf *cloudprovider.SClouduserCreateConfig) (cloudprovider.IClouduser, error) { @@ -339,3 +344,16 @@ func (self *SAzureClient) CreateClouduser(name, password string) (*SClouduser, e } return &user, nil } + +func (self *SAzureClient) ListGraphUsers() ([]SClouduser, error) { + resp, err := self.msGraphRequest("GET", "users", nil) + if err != nil { + return nil, errors.Wrapf(err, "msGraphRequest.users") + } + users := []SClouduser{} + err = resp.Unmarshal(&users, "value") + if err != nil { + return nil, errors.Wrapf(err, "resp.Unmarshal") + } + return users, nil +} diff --git a/pkg/multicloud/azure/provider/provider.go b/pkg/multicloud/azure/provider/provider.go index 11a5bbf6f0..b60d52a793 100644 --- a/pkg/multicloud/azure/provider/provider.go +++ b/pkg/multicloud/azure/provider/provider.go @@ -141,12 +141,19 @@ func (self *SAzureProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) func (self *SAzureProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) { tenantId, appId, appKey, subId := parseAccount(info.Account, info.Secret) + defaultRegion := "" + switch info.Url { + case "AzurePublicCloud": + defaultRegion = "eastus" + case "AzureChinaCloud": + defaultRegion = "chinaeast2" + } return map[string]string{ "AZURE_DIRECTORY_ID": tenantId, "AZURE_SUBSCRIPTION_ID": subId, "AZURE_APPLICATION_ID": appId, "AZURE_APPLICATION_KEY": appKey, - "AZURE_REGION_ID": "", + "AZURE_REGION_ID": defaultRegion, "AZURE_CLOUD_ENV": info.Url, }, nil } diff --git a/pkg/multicloud/azure/shell/clouduser.go b/pkg/multicloud/azure/shell/clouduser.go index eac9fa8400..8ea289efe3 100644 --- a/pkg/multicloud/azure/shell/clouduser.go +++ b/pkg/multicloud/azure/shell/clouduser.go @@ -21,10 +21,9 @@ import ( func init() { type ClouduserListOptions struct { - Name string } shellutils.R(&ClouduserListOptions{}, "cloud-user-list", "List cloudusers", func(cli *azure.SRegion, args *ClouduserListOptions) error { - users, err := cli.GetClient().GetCloudusers(args.Name) + users, err := cli.GetClient().GetCloudusers() if err != nil { return err }