github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/ibm/iam.go (about) 1 // Copyright 2019 The Terraformer Authors. 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 ibm 16 17 import ( 18 "fmt" 19 "os" 20 "strconv" 21 22 "github.com/GoogleCloudPlatform/terraformer/terraformutils" 23 bluemix "github.com/IBM-Cloud/bluemix-go" 24 "github.com/IBM-Cloud/bluemix-go/api/iampap/iampapv1" 25 "github.com/IBM-Cloud/bluemix-go/api/iamuum/iamuumv2" 26 "github.com/IBM-Cloud/bluemix-go/api/usermanagement/usermanagementv2" 27 "github.com/IBM-Cloud/bluemix-go/session" 28 "github.com/IBM/go-sdk-core/core" 29 "github.com/IBM/platform-services-go-sdk/iamidentityv1" 30 "github.com/IBM/platform-services-go-sdk/iampolicymanagementv1" 31 ) 32 33 type IAMGenerator struct { 34 IBMService 35 } 36 37 func (g IAMGenerator) loadUserPolicies(policyID string, user string) terraformutils.Resource { 38 resources := terraformutils.NewSimpleResource( 39 fmt.Sprintf("%s/%s", user, policyID), 40 normalizeResourceName("iam_user_policy", true), 41 "ibm_iam_user_policy", 42 "ibm", 43 []string{}) 44 return resources 45 } 46 47 func (g IAMGenerator) loadAccessGroups() func(grpID, grpName string) terraformutils.Resource { 48 names := make(map[string]struct{}) 49 random := false 50 return func(grpID, grpName string) terraformutils.Resource { 51 names, random = getRandom(names, grpName, random) 52 resources := terraformutils.NewSimpleResource( 53 grpID, 54 normalizeResourceName(grpName, random), 55 "ibm_iam_access_group", 56 "ibm", 57 []string{}) 58 return resources 59 } 60 } 61 62 func (g IAMGenerator) loadServiceIDs() func(serviceID, grpName string) terraformutils.Resource { 63 names := make(map[string]struct{}) 64 random := false 65 return func(grpID, grpName string) terraformutils.Resource { 66 names, random = getRandom(names, grpName, random) 67 resources := terraformutils.NewSimpleResource( 68 grpID, 69 normalizeResourceName(grpName, random), 70 "ibm_iam_service_id", 71 "ibm", 72 []string{}) 73 return resources 74 } 75 } 76 77 func (g IAMGenerator) loadAuthPolicies(policyID string) terraformutils.Resource { 78 resources := terraformutils.NewSimpleResource( 79 policyID, 80 normalizeResourceName("iam_authorization_policy", true), 81 "ibm_iam_authorization_policy", 82 "ibm", 83 []string{}) 84 return resources 85 } 86 87 func (g IAMGenerator) loadCustomRoles() func(roleID, roleName string) terraformutils.Resource { 88 names := make(map[string]struct{}) 89 random := false 90 return func(roleID, roleName string) terraformutils.Resource { 91 names, random = getRandom(names, roleName, random) 92 resources := terraformutils.NewSimpleResource( 93 roleID, 94 normalizeResourceName(roleName, random), 95 "ibm_iam_custom_role", 96 "ibm", 97 []string{}) 98 return resources 99 } 100 } 101 102 func (g IAMGenerator) loadServicePolicies(serviceID, policyID string, dependsOn []string) terraformutils.Resource { 103 resources := terraformutils.NewResource( 104 fmt.Sprintf("%s/%s", serviceID, policyID), 105 normalizeResourceName("iam_service_policy", true), 106 "ibm_iam_service_policy", 107 "ibm", 108 map[string]string{}, 109 []string{}, 110 map[string]interface{}{ 111 "depends_on": dependsOn, 112 }) 113 return resources 114 } 115 116 func (g IAMGenerator) loadAccessGroupMembers() func(grpID string, dependsOn []string, grpName string) terraformutils.Resource { 117 names := make(map[string]struct{}) 118 random := false 119 return func(grpID string, dependsOn []string, grpName string) terraformutils.Resource { 120 names, random = getRandom(names, grpName, random) 121 resources := terraformutils.NewResource( 122 fmt.Sprintf("%s/%s", grpID, grpID), 123 normalizeResourceName(grpName, random), 124 "ibm_iam_access_group_members", 125 "ibm", 126 map[string]string{}, 127 []string{}, 128 map[string]interface{}{ 129 "depends_on": dependsOn, 130 }) 131 return resources 132 } 133 } 134 135 func (g IAMGenerator) loadAccessGroupPolicies(grpID, policyID string, dependsOn []string) terraformutils.Resource { 136 resources := terraformutils.NewResource( 137 fmt.Sprintf("%s/%s", grpID, policyID), 138 normalizeResourceName("iam_access_group_policy", true), 139 "ibm_iam_access_group_policy", 140 "ibm", 141 map[string]string{}, 142 []string{}, 143 map[string]interface{}{ 144 "depends_on": dependsOn, 145 }) 146 return resources 147 } 148 149 func (g IAMGenerator) loadAccessGroupDynamicPolicies() func(grpID, ruleID, name string, dependsOn []string) terraformutils.Resource { 150 names := make(map[string]struct{}) 151 random := false 152 return func(grpID, ruleID, name string, dependsOn []string) terraformutils.Resource { 153 names, random = getRandom(names, name, random) 154 resources := terraformutils.NewResource( 155 fmt.Sprintf("%s/%s", grpID, ruleID), 156 normalizeResourceName(name, random), 157 "ibm_iam_access_group_dynamic_rule", 158 "ibm", 159 map[string]string{}, 160 []string{}, 161 map[string]interface{}{ 162 "depends_on": dependsOn, 163 }) 164 return resources 165 } 166 } 167 168 func (g *IAMGenerator) InitResources() error { 169 bmxConfig := &bluemix.Config{ 170 BluemixAPIKey: os.Getenv("IC_API_KEY"), 171 } 172 sess, err := session.New(bmxConfig) 173 if err != nil { 174 return err 175 } 176 177 userManagementAPI, err := usermanagementv2.New(sess) 178 if err != nil { 179 return err 180 } 181 err = authenticateAPIKey(sess) 182 if err != nil { 183 return err 184 } 185 generation := envFallBack([]string{"Generation"}, "2") 186 gen, err := strconv.Atoi(generation) 187 if err != nil { 188 return err 189 } 190 userInfo, err := fetchUserDetails(sess, gen) 191 if err != nil { 192 return err 193 } 194 accountID := userInfo.userAccount 195 196 users, err := userManagementAPI.UserInvite().GetUsers(userInfo.userAccount) 197 if err != nil { 198 return err 199 } 200 iampap, err := iampapv1.New(sess) 201 if err != nil { 202 return err 203 } 204 205 for _, u := range users.Resources { 206 // User policies 207 policies, err := iampap.V1Policy().List(iampapv1.SearchParams{ 208 AccountID: accountID, 209 IAMID: u.IamID, 210 Type: iampapv1.AccessPolicyType, 211 }) 212 if err != nil { 213 return err 214 } 215 for _, p := range policies { 216 g.Resources = append(g.Resources, g.loadUserPolicies(p.ID, u.Email)) 217 } 218 } 219 220 iamuumClient, err := iamuumv2.New(sess) 221 if err != nil { 222 return err 223 } 224 225 agrps, err := iamuumClient.AccessGroup().List(accountID) 226 if err != nil { 227 return err 228 } 229 fnObjt := g.loadAccessGroups() 230 agmfnObj := g.loadAccessGroupMembers() 231 for _, group := range agrps { 232 g.Resources = append(g.Resources, fnObjt(group.ID, group.Name)) 233 resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName 234 var dependsOn []string 235 dependsOn = append(dependsOn, 236 "ibm_iam_access_group."+resourceName) 237 g.Resources = append(g.Resources, agmfnObj(group.ID, dependsOn, group.Name)) 238 239 policies, err := iampap.V1Policy().List(iampapv1.SearchParams{ 240 AccountID: accountID, 241 AccessGroupID: group.ID, 242 Type: iampapv1.AccessPolicyType, 243 }) 244 if err != nil { 245 return fmt.Errorf("error retrieving access group policy: %s", err) 246 } 247 for _, p := range policies { 248 g.Resources = append(g.Resources, g.loadAccessGroupPolicies(group.ID, p.ID, dependsOn)) 249 } 250 251 dynamicPolicies, err := iamuumClient.DynamicRule().List(group.ID) 252 if err != nil { 253 return err 254 } 255 dpfnObj := g.loadAccessGroupDynamicPolicies() 256 for _, d := range dynamicPolicies { 257 g.Resources = append(g.Resources, dpfnObj(group.ID, d.RuleID, d.Name, dependsOn)) 258 } 259 } 260 261 // service id and service policy 262 apiKey := os.Getenv("IC_API_KEY") 263 if apiKey == "" { 264 return fmt.Errorf("no API key set") 265 } 266 267 iamIDurl := "https://iam.cloud.ibm.com" 268 iamOptions := &iamidentityv1.IamIdentityV1Options{ 269 URL: envFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, iamIDurl), 270 Authenticator: &core.IamAuthenticator{ 271 ApiKey: apiKey, 272 }, 273 } 274 275 iamPolicyOptions := &iampolicymanagementv1.IamPolicyManagementV1Options{ 276 URL: envFallBack([]string{"IBMCLOUD_IAM_API_ENDPOINT"}, iamIDurl), 277 Authenticator: &core.IamAuthenticator{ 278 ApiKey: apiKey, 279 }, 280 } 281 282 iamIDClient, err := iamidentityv1.NewIamIdentityV1(iamOptions) 283 if err != nil { 284 return err 285 } 286 287 iamPolicyClient, err := iampolicymanagementv1.NewIamPolicyManagementV1(iamPolicyOptions) 288 if err != nil { 289 return err 290 } 291 292 start := "" 293 allrecs := []iamidentityv1.ServiceID{} 294 var pg int64 = 100 295 296 for { 297 listServiceIDOptions := iamidentityv1.ListServiceIdsOptions{ 298 AccountID: &accountID, 299 Pagesize: &pg, 300 } 301 if start != "" { 302 listServiceIDOptions.Pagetoken = &start 303 } 304 305 serviceIDs, resp, err := iamIDClient.ListServiceIds(&listServiceIDOptions) 306 if err != nil { 307 return fmt.Errorf("[ERROR] Error listing Service Ids %s %s", err, resp) 308 } 309 start = GetNextIAM(serviceIDs.Next) 310 allrecs = append(allrecs, serviceIDs.Serviceids...) 311 if start == "" { 312 break 313 } 314 } 315 servicefnObjt := g.loadServiceIDs() 316 // loop through all service IDs and fetch policies correspponds to each service ID 317 for _, service := range allrecs { 318 g.Resources = append(g.Resources, servicefnObjt(*service.ID, *service.Name)) 319 resourceName := g.Resources[len(g.Resources)-1:][0].ResourceName 320 var dependsOn []string 321 dependsOn = append(dependsOn, 322 "ibm_iam_service_id."+resourceName) 323 324 listServicePolicyOptions := iampolicymanagementv1.ListPoliciesOptions{ 325 AccountID: core.StringPtr(accountID), 326 IamID: core.StringPtr(*service.IamID), 327 Type: core.StringPtr("access"), 328 } 329 330 policyList, _, err := iamPolicyClient.ListPolicies(&listServicePolicyOptions) 331 policies := policyList.Policies 332 333 if err != nil { 334 return fmt.Errorf("error retrieving service policy: %s", err) 335 } 336 337 for _, p := range policies { 338 g.Resources = append(g.Resources, g.loadServicePolicies(*service.ID, *p.ID, dependsOn)) 339 } 340 } 341 342 // Authorization policy 343 listAuthPolicyOptions := iampolicymanagementv1.ListPoliciesOptions{ 344 AccountID: core.StringPtr(accountID), 345 Type: core.StringPtr("authorization"), 346 } 347 348 authPolicyList, _, err := iamPolicyClient.ListPolicies(&listAuthPolicyOptions) 349 authPolicies := authPolicyList.Policies 350 351 if err != nil { 352 return fmt.Errorf("error retrieving authorization policy: %s", err) 353 } 354 355 for _, ap := range authPolicies { 356 g.Resources = append(g.Resources, g.loadAuthPolicies(*ap.ID)) 357 } 358 359 // Custom role 360 listCustomRoleOptions := iampolicymanagementv1.ListRolesOptions{ 361 AccountID: core.StringPtr(accountID), 362 } 363 364 rolesList, _, err := iamPolicyClient.ListRoles(&listCustomRoleOptions) 365 customRoles := rolesList.CustomRoles 366 367 if err != nil { 368 return fmt.Errorf("error retrieving custom roles: %s", err) 369 } 370 rolefnObjt := g.loadCustomRoles() 371 for _, r := range customRoles { 372 g.Resources = append(g.Resources, rolefnObjt(*r.ID, *r.Name)) 373 } 374 375 return nil 376 }