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  }