yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/ram_user.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 aliyun 16 17 import ( 18 "fmt" 19 "time" 20 21 "yunion.io/x/log" 22 "yunion.io/x/pkg/errors" 23 24 "yunion.io/x/cloudmux/pkg/cloudprovider" 25 "yunion.io/x/cloudmux/pkg/multicloud" 26 ) 27 28 type sUsers struct { 29 User []SUser 30 } 31 32 type SUsers struct { 33 Users sUsers 34 Marker string 35 IsTruncated bool 36 } 37 38 type SUser struct { 39 client *SAliyunClient 40 multicloud.SBaseClouduser 41 42 Comments string 43 CreateDate time.Time 44 DisplayName string 45 Email string 46 MobilePhone string 47 UserId string 48 UserName string 49 } 50 51 func (user *SUser) GetGlobalId() string { 52 if len(user.UserId) > 0 { 53 return user.UserId 54 } 55 u, err := user.client.GetUser(user.UserName) 56 if err != nil { 57 return "" 58 } 59 return u.UserId 60 } 61 62 func (user *SUser) GetName() string { 63 return user.UserName 64 } 65 66 func (user *SUser) GetEmailAddr() string { 67 return user.Email 68 } 69 70 func (user *SUser) GetInviteUrl() string { 71 return "" 72 } 73 74 func (user *SUser) Delete() error { 75 groups, err := user.client.ListGroupsForUser(user.UserName) 76 if err != nil { 77 return errors.Wrap(err, "ListGroupsForUser") 78 } 79 for i := range groups { 80 err = user.client.RemoveUserFromGroup(groups[i].GroupName, user.UserName) 81 if err != nil { 82 return errors.Wrapf(err, "RemoveUserFromGroup %s > %s", groups[i].GroupName, user.UserName) 83 } 84 } 85 policies, err := user.client.ListPoliciesForUser(user.UserName) 86 if err != nil { 87 return errors.Wrap(err, "ListPoliciesForUser") 88 } 89 for i := range policies { 90 err = user.client.DetachPolicyFromUser(policies[i].PolicyName, policies[i].PolicyType, user.UserName) 91 if err != nil { 92 return errors.Wrapf(err, "DetachPolicyFromUser %s %s %s", policies[i].PolicyName, policies[i].PolicyType, user.UserName) 93 } 94 } 95 return user.client.DeleteClouduser(user.UserName) 96 } 97 98 func (user *SUser) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) { 99 groups, err := user.client.ListGroupsForUser(user.UserName) 100 if err != nil { 101 return nil, errors.Wrapf(err, "ListGroupsForUser") 102 } 103 ret := []cloudprovider.ICloudgroup{} 104 for i := range groups { 105 groups[i].client = user.client 106 ret = append(ret, &groups[i]) 107 } 108 return ret, nil 109 } 110 111 func (user *SUser) UpdatePassword(password string) error { 112 return user.client.UpdateLoginProfile(user.UserName, password) 113 } 114 115 func (user *SUser) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { 116 policies, err := user.client.ListPoliciesForUser(user.UserName) 117 if err != nil { 118 return nil, errors.Wrap(err, "ListPoliciesForUser") 119 } 120 ret := []cloudprovider.ICloudpolicy{} 121 for i := range policies { 122 if policies[i].PolicyType == "System" { 123 policies[i].client = user.client 124 ret = append(ret, &policies[i]) 125 } 126 } 127 return ret, nil 128 } 129 130 func (user *SUser) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { 131 policies, err := user.client.ListPoliciesForUser(user.UserName) 132 if err != nil { 133 return nil, errors.Wrap(err, "ListPoliciesForUser") 134 } 135 ret := []cloudprovider.ICloudpolicy{} 136 for i := range policies { 137 if policies[i].PolicyType == "Custom" { 138 policies[i].client = user.client 139 ret = append(ret, &policies[i]) 140 } 141 } 142 return ret, nil 143 } 144 145 func (user *SUser) IsConsoleLogin() bool { 146 _, err := user.client.GetLoginProfile(user.UserName) 147 if errors.Cause(err) == cloudprovider.ErrNotFound { 148 return false 149 } 150 return true 151 } 152 153 func (user *SUser) ResetPassword(password string) error { 154 return user.client.ResetClouduserPassword(user.UserName, password) 155 } 156 157 func (user *SUser) AttachSystemPolicy(policyName string) error { 158 return user.client.AttachPolicyToUser(policyName, POLICY_TYPE_SYSTEM, user.UserName) 159 } 160 161 func (user *SUser) AttachCustomPolicy(policyName string) error { 162 return user.client.AttachPolicyToUser(policyName, POLICY_TYPE_CUSTOM, user.UserName) 163 } 164 165 func (user *SUser) DetachSystemPolicy(policyName string) error { 166 return user.client.DetachPolicyFromUser(policyName, POLICY_TYPE_SYSTEM, user.UserName) 167 } 168 169 func (user *SUser) DetachCustomPolicy(policyName string) error { 170 return user.client.DetachPolicyFromUser(policyName, POLICY_TYPE_CUSTOM, user.UserName) 171 } 172 173 func (self *SAliyunClient) DeleteClouduser(name string) error { 174 params := map[string]string{ 175 "UserName": name, 176 } 177 _, err := self.ramRequest("DeleteUser", params) 178 return err 179 } 180 181 func (self *SAliyunClient) CreateUser(name, phone, email, comments string) (*SUser, error) { 182 params := map[string]string{ 183 "UserName": name, 184 "DisplayName": name, 185 } 186 if len(phone) > 0 { 187 params["MobilePhone"] = phone 188 } 189 if len(email) > 0 { 190 params["Email"] = email 191 } 192 if len(comments) > 0 { 193 params["Comments"] = comments 194 } 195 resp, err := self.ramRequest("CreateUser", params) 196 if err != nil { 197 return nil, errors.Wrap(err, "ramRequest.CreateUser") 198 } 199 200 user := &SUser{client: self} 201 err = resp.Unmarshal(user, "User") 202 if err != nil { 203 return nil, errors.Wrap(err, "resp.Unmarshal") 204 } 205 return user, nil 206 } 207 208 func (self *SAliyunClient) ListUsers(offset string, limit int) (*SUsers, error) { 209 params := map[string]string{} 210 if len(offset) > 0 { 211 params["Marker"] = offset 212 } 213 if limit > 0 { 214 params["MaxItems"] = fmt.Sprintf("%d", limit) 215 } 216 resp, err := self.ramRequest("ListUsers", params) 217 if err != nil { 218 return nil, errors.Wrap(err, "ramRequest.ListUsers") 219 } 220 users := &SUsers{} 221 err = resp.Unmarshal(users) 222 if err != nil { 223 return nil, errors.Wrap(err, "resp.Unmarshal") 224 } 225 return users, nil 226 } 227 228 func (self *SAliyunClient) CreateIClouduser(conf *cloudprovider.SClouduserCreateConfig) (cloudprovider.IClouduser, error) { 229 user, err := self.CreateUser(conf.Name, conf.MobilePhone, conf.Email, conf.Desc) 230 if err != nil { 231 return nil, errors.Wrap(err, "CreateUser") 232 } 233 if len(conf.Password) > 0 { 234 _, err := self.CreateLoginProfile(conf.Name, conf.Password) 235 if err != nil { 236 return nil, errors.Wrap(err, "CreateLoginProfile") 237 } 238 } 239 for _, policyId := range conf.ExternalPolicyIds { 240 err := user.AttachSystemPolicy(policyId) 241 if err != nil { 242 log.Errorf("attach policy %s for user %s error: %v", policyId, conf.Name, err) 243 } 244 } 245 return user, nil 246 } 247 248 func (self *SAliyunClient) GetICloudusers() ([]cloudprovider.IClouduser, error) { 249 ret := []cloudprovider.IClouduser{} 250 offset := "" 251 for { 252 part, err := self.ListUsers(offset, 100) 253 if err != nil { 254 return nil, errors.Wrap(err, "GetCloudusers") 255 } 256 for i := range part.Users.User { 257 part.Users.User[i].client = self 258 ret = append(ret, &part.Users.User[i]) 259 } 260 offset = part.Marker 261 if len(offset) == 0 || !part.IsTruncated { 262 break 263 } 264 } 265 return ret, nil 266 } 267 268 func (self *SAliyunClient) GetUser(name string) (*SUser, error) { 269 params := map[string]string{ 270 "UserName": name, 271 } 272 resp, err := self.ramRequest("GetUser", params) 273 if err != nil { 274 return nil, errors.Wrap(err, "ramRequest.CreateUser") 275 } 276 user := &SUser{client: self} 277 err = resp.Unmarshal(user, "User") 278 if err != nil { 279 return nil, errors.Wrap(err, "resp.Unmarshal") 280 } 281 return user, nil 282 } 283 284 func (self *SAliyunClient) GetIClouduserByName(name string) (cloudprovider.IClouduser, error) { 285 return self.GetUser(name) 286 } 287 288 type SLoginProfile struct { 289 CreateDate string 290 MFABindRequired bool 291 PasswordResetRequired bool 292 UserName string 293 } 294 295 func (self *SAliyunClient) GetLoginProfile(name string) (*SLoginProfile, error) { 296 params := map[string]string{ 297 "UserName": name, 298 } 299 resp, err := self.ramRequest("GetLoginProfile", params) 300 if err != nil { 301 return nil, errors.Wrap(err, "ramRequest.GetLoginProfile") 302 } 303 profile := &SLoginProfile{} 304 err = resp.Unmarshal(profile, "LoginProfile") 305 if err != nil { 306 return nil, errors.Wrap(err, "resp.Unmarshal") 307 } 308 return profile, nil 309 } 310 311 func (self *SAliyunClient) DeleteLoginProfile(name string) error { 312 params := map[string]string{ 313 "UserName": name, 314 } 315 _, err := self.ramRequest("DeleteLoginProfile", params) 316 return err 317 } 318 319 func (self *SAliyunClient) CreateLoginProfile(name, password string) (*SLoginProfile, error) { 320 params := map[string]string{ 321 "UserName": name, 322 "Password": password, 323 } 324 resp, err := self.ramRequest("CreateLoginProfile", params) 325 if err != nil { 326 return nil, errors.Wrap(err, "ramRequest.CreateLoginProfile") 327 } 328 profile := &SLoginProfile{} 329 err = resp.Unmarshal(profile, "LoginProfile") 330 if err != nil { 331 return nil, errors.Wrap(err, "resp.Unmarshal") 332 } 333 return profile, nil 334 } 335 336 func (self *SAliyunClient) UpdateLoginProfile(name, password string) error { 337 params := map[string]string{ 338 "UserName": name, 339 "Password": password, 340 } 341 _, err := self.ramRequest("UpdateLoginProfile", params) 342 if err != nil { 343 return errors.Wrap(err, "ramRequest.CreateLoginProfile") 344 } 345 return nil 346 } 347 348 func (self *SAliyunClient) ResetClouduserPassword(name, password string) error { 349 _, err := self.GetLoginProfile(name) 350 if err != nil { 351 if errors.Cause(err) == cloudprovider.ErrNotFound { 352 _, err = self.CreateLoginProfile(name, password) 353 return err 354 } 355 return errors.Wrap(err, "GetLoginProfile") 356 } 357 return self.UpdateLoginProfile(name, password) 358 } 359 360 func (self *SAliyunClient) GetIamLoginUrl() string { 361 params := map[string]string{} 362 resp, err := self.ramRequest("GetAccountAlias", params) 363 if err != nil { 364 log.Errorf("GetAccountAlias error: %v", err) 365 return "" 366 } 367 alias, _ := resp.GetString("AccountAlias") 368 if len(alias) > 0 { 369 return fmt.Sprintf("https://signin.aliyun.com/%s.onaliyun.com/login.htm", alias) 370 } 371 return "" 372 } 373 374 // https://help.aliyun.com/document_detail/28707.html?spm=a2c4g.11186623.6.752.f4466bbfVy5j0s 375 func (self *SAliyunClient) ListGroupsForUser(user string) ([]SGroup, error) { 376 params := map[string]string{ 377 "UserName": user, 378 } 379 resp, err := self.ramRequest("ListGroupsForUser", params) 380 if err != nil { 381 return nil, errors.Wrap(err, "ListGroupsForUser") 382 } 383 groups := []SGroup{} 384 err = resp.Unmarshal(&groups, "Groups", "Group") 385 if err != nil { 386 return nil, errors.Wrap(err, "resp.Unmarshal") 387 } 388 return groups, nil 389 } 390 391 // https://help.aliyun.com/document_detail/28732.html?spm=a2c4g.11186623.6.777.580735b2m2xUh8 392 func (self *SAliyunClient) ListPoliciesForUser(user string) ([]SPolicy, error) { 393 params := map[string]string{ 394 "UserName": user, 395 } 396 resp, err := self.ramRequest("ListPoliciesForUser", params) 397 if err != nil { 398 return nil, errors.Wrap(err, "ListPoliciesForUser") 399 } 400 policies := []SPolicy{} 401 err = resp.Unmarshal(&policies, "Policies", "Policy") 402 if err != nil { 403 return nil, errors.Wrap(err, "resp.Unmarshal") 404 } 405 return policies, nil 406 }