yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/clouduser.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package azure 16 17 import ( 18 "fmt" 19 "net/url" 20 "strings" 21 "time" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/pkg/errors" 25 26 "yunion.io/x/cloudmux/pkg/cloudprovider" 27 "yunion.io/x/cloudmux/pkg/multicloud" 28 "yunion.io/x/onecloud/pkg/util/httputils" 29 ) 30 31 type SClouduserPasswordProfile struct { 32 Password string 33 forceChangePasswordNextLogin bool 34 enforceChangePasswordPolicy bool 35 } 36 37 type SClouduser struct { 38 client *SAzureClient 39 multicloud.SBaseClouduser 40 41 OdataType string `json:"odata.type"` 42 ObjectType string 43 Id string 44 DeletionTimestamp string 45 AccountEnabled bool 46 AgeGroup string 47 City string 48 CompanyName string 49 ConsentProvidedForMinor string 50 Country string 51 CreatedDateTime time.Time 52 CreationType string 53 Department string 54 DirSyncEnabled string 55 DisplayName string 56 EmployeeId string 57 FacsimileTelephoneNumber string 58 GivenName string 59 ImmutableId string 60 IsCompromised string 61 JobTitle string 62 LastDirSyncTime string 63 LegalAgeGroupClassification string 64 Mail string 65 MailNickname string 66 Mobile string 67 OnPremisesDistinguishedName string 68 OnPremisesSecurityIdentifier string 69 PasswordPolicies string 70 PasswordProfile SClouduserPasswordProfile 71 PhysicalDeliveryOfficeName string 72 PostalCode string 73 PreferredLanguage string 74 RefreshTokensValidFromDateTime time.Time 75 ShowInAddressList string 76 SipProxyAddress string 77 State string 78 StreetAddress string 79 Surname string 80 TelephoneNumber string 81 ThumbnailPhotoOdataMediaEditLink string `json:"thumbnailPhoto@odata.mediaEditLink"` 82 UsageLocation string 83 UserPrincipalName string 84 UserState string 85 UserStateChangedOn string 86 UserType string 87 88 inviteRedeemUrl string 89 } 90 91 func (user *SClouduser) GetName() string { 92 return user.UserPrincipalName 93 } 94 95 func (user *SClouduser) GetGlobalId() string { 96 return user.Id 97 } 98 99 func (user *SClouduser) GetEmailAddr() string { 100 return user.Mail 101 } 102 103 func (user *SClouduser) GetInviteUrl() string { 104 return user.inviteRedeemUrl 105 } 106 107 func (user *SClouduser) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { 108 policies, err := user.client.GetCloudpolicies(user.Id) 109 if err != nil { 110 return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id) 111 } 112 ret := []cloudprovider.ICloudpolicy{} 113 for i := range policies { 114 if policies[i].Properties.Type == "BuiltInRole" { 115 ret = append(ret, &policies[i]) 116 } 117 } 118 return ret, nil 119 } 120 121 func (user *SClouduser) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { 122 policies, err := user.client.GetCloudpolicies(user.Id) 123 if err != nil { 124 return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id) 125 } 126 ret := []cloudprovider.ICloudpolicy{} 127 for i := range policies { 128 if policies[i].Properties.Type != "BuiltInRole" { 129 ret = append(ret, &policies[i]) 130 } 131 } 132 return ret, nil 133 } 134 135 func (user *SClouduser) AttachSystemPolicy(policyId string) error { 136 for _, subscription := range user.client.subscriptions { 137 err := user.client.AssignPolicy(user.Id, policyId, subscription.SubscriptionId) 138 if err != nil { 139 return errors.Wrapf(err, "AssignPolicy for subscription %s", subscription.SubscriptionId) 140 } 141 } 142 return nil 143 } 144 145 func (user *SClouduser) AttachCustomPolicy(policyId string) error { 146 for _, subscription := range user.client.subscriptions { 147 err := user.client.AssignPolicy(user.Id, policyId, subscription.SubscriptionId) 148 if err != nil { 149 return errors.Wrapf(err, "AssignPolicy for subscription %s", subscription.SubscriptionId) 150 } 151 } 152 return nil 153 } 154 155 func (user *SClouduser) DetachSystemPolicy(policyId string) error { 156 assignments, err := user.client.GetAssignments(user.Id) 157 if err != nil { 158 return errors.Wrapf(err, "GetAssignments(%s)", user.Id) 159 } 160 for _, assignment := range assignments { 161 role, err := user.client.GetRole(assignment.Properties.RoleDefinitionId) 162 if err != nil { 163 return errors.Wrapf(err, "GetRule(%s)", assignment.Properties.RoleDefinitionId) 164 } 165 if role.Properties.RoleName == policyId { 166 return user.client.gdel(assignment.Id) 167 } 168 } 169 return nil 170 } 171 172 func (user *SClouduser) DetachCustomPolicy(policyId string) error { 173 return user.DetachSystemPolicy(policyId) 174 } 175 176 func (user *SClouduser) IsConsoleLogin() bool { 177 return true 178 } 179 180 // 需要当前应用有User administrator权限 181 func (user *SClouduser) Delete() error { 182 return user.client.DeleteClouduser(user.UserPrincipalName) 183 } 184 185 func (user *SClouduser) ResetPassword(password string) error { 186 return user.client.ResetClouduserPassword(user.Id, password) 187 } 188 189 func (user *SClouduser) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) { 190 groups, err := user.client.GetUserGroups(user.Id) 191 if err != nil { 192 return nil, errors.Wrap(err, "GetUserGroups") 193 } 194 ret := []cloudprovider.ICloudgroup{} 195 for i := range groups { 196 groups[i].client = user.client 197 ret = append(ret, &groups[i]) 198 } 199 return ret, nil 200 } 201 202 func (self *SAzureClient) GetUserGroups(userId string) ([]SCloudgroup, error) { 203 resource := fmt.Sprintf("users/%s/memberOf", userId) 204 groups := []SCloudgroup{} 205 err := self.glist(resource, url.Values{}, &groups) 206 return groups, err 207 } 208 209 func (self *SAzureClient) ResetClouduserPassword(id, password string) error { 210 body := jsonutils.Marshal(map[string]interface{}{ 211 "passwordPolicies": "DisablePasswordExpiration, DisableStrongPassword", 212 "passwordProfile": map[string]interface{}{ 213 "password": password, 214 }, 215 }) 216 resource := fmt.Sprintf("%s/users/%s", self.tenantId, id) 217 _, err := self.gpatch(resource, body) 218 return err 219 } 220 221 func (self *SAzureClient) GetClouduser(name string) (*SClouduser, error) { 222 users, err := self.GetCloudusers() 223 if err != nil { 224 return nil, err 225 } 226 for i := range users { 227 if users[i].DisplayName == name || users[i].UserPrincipalName == name { 228 users[i].client = self 229 return &users[i], nil 230 } 231 } 232 return nil, cloudprovider.ErrNotFound 233 } 234 235 func (self *SAzureClient) GetCloudusers() ([]SClouduser, error) { 236 users := []SClouduser{} 237 params := url.Values{} 238 err := self.glist("users", params, &users) 239 if err != nil { 240 return nil, err 241 } 242 return users, nil 243 } 244 245 func (self *SAzureClient) DeleteClouduser(id string) error { 246 _, err := self.msGraphRequest(string(httputils.DELETE), "users/"+id, nil) 247 return err 248 } 249 250 func (self *SAzureClient) GetICloudusers() ([]cloudprovider.IClouduser, error) { 251 users, err := self.ListGraphUsers() 252 if err != nil { 253 return nil, errors.Wrap(err, "ListGraphUsers") 254 } 255 ret := []cloudprovider.IClouduser{} 256 for i := range users { 257 users[i].client = self 258 ret = append(ret, &users[i]) 259 } 260 return ret, nil 261 } 262 263 func (self *SAzureClient) GetIClouduserByName(name string) (cloudprovider.IClouduser, error) { 264 user, err := self.GetClouduser(name) 265 if err != nil { 266 return nil, errors.Wrap(err, "GetCloudusers") 267 } 268 return user, nil 269 } 270 271 func (self *SAzureClient) CreateIClouduser(conf *cloudprovider.SClouduserCreateConfig) (cloudprovider.IClouduser, error) { 272 if conf.UserType == "Guest" { 273 return self.InviteUser(conf.Email) 274 } 275 return self.CreateClouduser(conf.Name, conf.Password) 276 } 277 278 type SDomain struct { 279 Name string 280 AuthenticationType string 281 AvailabilityStatus string 282 IsAdminManaged bool 283 IsDefault bool 284 IsDefaultForCloudRedirections bool 285 IsInitial bool 286 IsRoot bool 287 IsVerified bool 288 ForceDeleteState string 289 State string 290 PasswordValidityPeriodInDays string 291 PasswordNotificationWindowInDays string 292 } 293 294 func (self *SAzureClient) GetDomains() ([]SDomain, error) { 295 domains := []SDomain{} 296 err := self.glist("domains", nil, &domains) 297 if err != nil { 298 return nil, errors.Wrap(err, "glist") 299 } 300 return domains, nil 301 } 302 303 func (self *SAzureClient) GetDefaultDomain() (string, error) { 304 users, err := self.ListGraphUsers() 305 if err != nil { 306 return "", errors.Wrapf(err, "ListGraphUsers") 307 } 308 for i := range users { 309 idx := strings.Index(users[i].UserPrincipalName, "@") 310 if idx > -1 { 311 return users[i].UserPrincipalName[idx+1:], nil 312 } 313 } 314 return "", cloudprovider.ErrNotFound 315 } 316 317 func (self *SAzureClient) CreateClouduser(name, password string) (*SClouduser, error) { 318 passwordProfile := map[string]interface{}{ 319 "password": "Lomo1824", 320 } 321 if len(password) > 0 { 322 passwordProfile["password"] = password 323 } 324 params := map[string]interface{}{ 325 "accountEnabled": true, 326 "displayName": name, 327 "mailNickname": name, 328 "passwordProfile": passwordProfile, 329 "userPrincipalName": name, 330 } 331 domain, err := self.GetDefaultDomain() 332 if err != nil { 333 return nil, errors.Wrap(err, "GetDefaultDomain") 334 } 335 params["userPrincipalName"] = fmt.Sprintf("%s@%s", name, domain) 336 user := SClouduser{client: self} 337 resp, err := self.msGraphRequest(string(httputils.POST), "users", jsonutils.Marshal(params)) 338 if err != nil { 339 return nil, errors.Wrap(err, "Create") 340 } 341 err = resp.Unmarshal(&user) 342 if err != nil { 343 return nil, err 344 } 345 return &user, nil 346 } 347 348 func (self *SAzureClient) ListGraphUsers() ([]SClouduser, error) { 349 resp, err := self.msGraphRequest("GET", "users", nil) 350 if err != nil { 351 return nil, errors.Wrapf(err, "msGraphRequest.users") 352 } 353 users := []SClouduser{} 354 err = resp.Unmarshal(&users, "value") 355 if err != nil { 356 return nil, errors.Wrapf(err, "resp.Unmarshal") 357 } 358 return users, nil 359 }