yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/ram_policy.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 "strings" 20 "time" 21 22 "yunion.io/x/jsonutils" 23 "yunion.io/x/pkg/errors" 24 25 "yunion.io/x/cloudmux/pkg/cloudprovider" 26 ) 27 28 const ( 29 POLICY_TYPE_SYSTEM = "System" 30 POLICY_TYPE_CUSTOM = "Custom" 31 ) 32 33 /** 34 {"AttachmentCount":0, 35 "CreateDate":"2018-10-12T05:05:16Z", 36 "DefaultVersion":"v1", 37 "Description":"只读访问Data Lake Analytics的权限", 38 "PolicyName":"AliyunDLAReadOnlyAccess", 39 "PolicyType":"System", 40 "UpdateDate":"2018-10-12T05:05:16Z"} 41 */ 42 43 type SDefaultPolicyVersion struct { 44 CreateDate time.Time 45 IsDefaultVersion bool 46 PolicyDocument string 47 VersionId string 48 } 49 50 type SPolicyDetails struct { 51 Policy SPolicy 52 DefaultPolicyVersion SDefaultPolicyVersion 53 } 54 55 type sPolicies struct { 56 Policy []SPolicy 57 } 58 59 type SPolicies struct { 60 Policies sPolicies 61 Marker string 62 IsTruncated bool 63 } 64 65 type SPolicy struct { 66 client *SAliyunClient 67 AttachmentCount int 68 CreateDate time.Time 69 UpdateDate time.Time 70 DefaultVersion string 71 Description string 72 PolicyName string 73 PolicyType string 74 } 75 76 func (policy *SPolicy) GetName() string { 77 return policy.PolicyName 78 } 79 80 func (policy *SPolicy) GetDescription() string { 81 return policy.Description 82 } 83 84 func (policy *SPolicy) GetGlobalId() string { 85 return policy.PolicyName 86 } 87 88 func (policy *SPolicy) UpdateDocument(document *jsonutils.JSONDict) error { 89 return policy.client.CreatePolicyVersion(policy.PolicyName, document.String(), true) 90 } 91 92 func (policy *SPolicy) Delete() error { 93 return policy.client.DeletePolicy(policy.PolicyType, policy.PolicyName) 94 } 95 96 func (policy *SPolicy) GetDocument() (*jsonutils.JSONDict, error) { 97 details, err := policy.client.GetPolicy(policy.PolicyType, policy.PolicyName) 98 if err != nil { 99 return nil, errors.Wrapf(err, "GetPolicy(%s,%s)", policy.PolicyType, policy.PolicyName) 100 } 101 obj, err := jsonutils.Parse([]byte(details.DefaultPolicyVersion.PolicyDocument)) 102 if err != nil { 103 return nil, errors.Wrap(err, "jsonutils.Parse") 104 } 105 return obj.(*jsonutils.JSONDict), nil 106 } 107 108 func (self *SAliyunClient) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { 109 ret := []cloudprovider.ICloudpolicy{} 110 offset := "" 111 for { 112 part, err := self.ListPolicies(POLICY_TYPE_SYSTEM, offset, 1000) 113 if err != nil { 114 return nil, errors.Wrapf(err, "ListPolicies") 115 } 116 for i := range part.Policies.Policy { 117 part.Policies.Policy[i].client = self 118 ret = append(ret, &part.Policies.Policy[i]) 119 } 120 offset = part.Marker 121 if len(offset) == 0 || !part.IsTruncated { 122 break 123 } 124 } 125 return ret, nil 126 } 127 128 func (self *SAliyunClient) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) { 129 ret := []cloudprovider.ICloudpolicy{} 130 offset := "" 131 for { 132 part, err := self.ListPolicies(POLICY_TYPE_CUSTOM, offset, 1000) 133 if err != nil { 134 return nil, errors.Wrapf(err, "ListPolicies") 135 } 136 for i := range part.Policies.Policy { 137 part.Policies.Policy[i].client = self 138 ret = append(ret, &part.Policies.Policy[i]) 139 } 140 offset = part.Marker 141 if len(offset) == 0 || !part.IsTruncated { 142 break 143 } 144 } 145 return ret, nil 146 } 147 148 func (self *SAliyunClient) AttachPolicyToUser(policyName, policyType, userName string) error { 149 params := map[string]string{ 150 "UserName": userName, 151 "PolicyName": policyName, 152 "PolicyType": policyType, 153 } 154 _, err := self.ramRequest("AttachPolicyToUser", params) 155 if err != nil && !strings.Contains(err.Error(), "EntityAlreadyExists.User.Policy") { 156 return errors.Wrap(err, "AttachPolicyToUser") 157 } 158 return nil 159 } 160 161 func (self *SAliyunClient) DetachPolicyFromUser(policyName, policyType, userName string) error { 162 if len(policyType) == 0 { 163 policyType = "System" 164 } 165 params := map[string]string{ 166 "UserName": userName, 167 "PolicyName": policyName, 168 "PolicyType": policyType, 169 } 170 _, err := self.ramRequest("DetachPolicyFromUser", params) 171 if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound { 172 return errors.Wrap(err, "DetachPolicyFromUser") 173 } 174 return nil 175 } 176 177 // https://help.aliyun.com/document_detail/28719.html?spm=a2c4g.11174283.6.764.27055662H6TGg5 178 func (self *SAliyunClient) ListPolicies(policyType string, offset string, limit int) (*SPolicies, error) { 179 if limit < 1 || limit > 1000 { 180 limit = 1000 181 } 182 params := map[string]string{ 183 "MaxItems": fmt.Sprintf("%d", limit), 184 } 185 if len(policyType) > 0 { 186 params["PolicyType"] = policyType 187 } 188 if len(offset) > 0 { 189 params["Marker"] = offset 190 } 191 192 body, err := self.ramRequest("ListPolicies", params) 193 if err != nil { 194 return nil, errors.Wrapf(err, "ListPolicies") 195 } 196 policies := &SPolicies{} 197 198 err = body.Unmarshal(&policies) 199 if err != nil { 200 return nil, errors.Wrapf(err, "body.Unmarshal") 201 } 202 203 return policies, nil 204 } 205 206 func (self *SAliyunClient) GetPolicy(policyType string, policyName string) (*SPolicyDetails, error) { 207 params := make(map[string]string) 208 params["PolicyType"] = policyType 209 params["PolicyName"] = policyName 210 211 body, err := self.ramRequest("GetPolicy", params) 212 if err != nil { 213 if isError(err, "EntityNotExist.Role") { 214 return nil, cloudprovider.ErrNotFound 215 } 216 return nil, err 217 } 218 219 policy := SPolicyDetails{} 220 221 err = body.Unmarshal(&policy) 222 if err != nil { 223 return nil, err 224 } 225 226 return &policy, nil 227 } 228 229 type SStatement struct { 230 Action []string `json:"Action,allowempty"` 231 Effect string `json:"Effect"` 232 Resource []string `json:"Resource"` 233 } 234 235 type SPolicyDocument struct { 236 Statement []SStatement `json:"Statement,allowempty"` 237 Version string `json:"Version"` 238 } 239 240 func (self *SAliyunClient) CreateICloudpolicy(opts *cloudprovider.SCloudpolicyCreateOptions) (cloudprovider.ICloudpolicy, error) { 241 if opts.Document == nil { 242 return nil, errors.Error("nil document") 243 } 244 policy, err := self.CreatePolicy(opts.Name, opts.Document.String(), opts.Desc) 245 if err != nil { 246 return nil, errors.Wrapf(err, "CreatePolicy") 247 } 248 return policy, nil 249 } 250 251 func (self *SAliyunClient) CreatePolicy(name string, document string, desc string) (*SPolicy, error) { 252 params := make(map[string]string) 253 params["PolicyName"] = name 254 params["PolicyDocument"] = document 255 if len(desc) > 0 { 256 params["Description"] = desc 257 } 258 259 body, err := self.ramRequest("CreatePolicy", params) 260 if err != nil { 261 return nil, err 262 } 263 264 policy := SPolicy{client: self} 265 266 err = body.Unmarshal(&policy, "Policy") 267 if err != nil { 268 return nil, err 269 } 270 271 return &policy, nil 272 } 273 274 func (self *SAliyunClient) DeletePolicy(policyType string, policyName string) error { 275 params := make(map[string]string) 276 params["PolicyName"] = policyName 277 params["PolicyType"] = policyType 278 279 _, err := self.ramRequest("DeletePolicy", params) 280 return err 281 } 282 283 func (self *SAliyunClient) DeleteRole(roleName string) error { 284 params := make(map[string]string) 285 params["RoleName"] = roleName 286 287 _, err := self.ramRequest("DeleteRole", params) 288 return err 289 } 290 291 func (self *SAliyunClient) AttachPolicy2Role(policyType string, policyName string, roleName string) error { 292 params := make(map[string]string) 293 params["PolicyType"] = policyType 294 params["PolicyName"] = policyName 295 params["RoleName"] = roleName 296 297 _, err := self.ramRequest("AttachPolicyToRole", params) 298 if err != nil { 299 return errors.Wrap(err, "AttachPolicyToRole") 300 } 301 302 return nil 303 } 304 305 func (self *SAliyunClient) CreatePolicyVersion(name, document string, isDefault bool) error { 306 params := map[string]string{ 307 "PolicyName": name, 308 "PolicyDocument": document, 309 "RotateStrategy": "DeleteOldestNonDefaultVersionWhenLimitExceeded", 310 } 311 if isDefault { 312 params["SetAsDefault"] = "true" 313 } 314 _, err := self.ramRequest("CreatePolicyVersion", params) 315 return err 316 }