github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/gcp/iam.go (about)

     1  // Copyright 2018 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 gcp
    16  
    17  import (
    18  	"context"
    19  	"log"
    20  	"regexp"
    21  
    22  	admin "cloud.google.com/go/iam/admin/apiv1"
    23  	"google.golang.org/api/cloudresourcemanager/v1"
    24  	"google.golang.org/api/iterator"
    25  	adminpb "google.golang.org/genproto/googleapis/iam/admin/v1"
    26  
    27  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    28  )
    29  
    30  var IamAllowEmptyValues = []string{"tags."}
    31  
    32  var IamAdditionalFields = map[string]interface{}{}
    33  
    34  type IamGenerator struct {
    35  	GCPService
    36  }
    37  
    38  func (g IamGenerator) createServiceAccountResources(serviceAccountsIterator *admin.ServiceAccountIterator) []terraformutils.Resource {
    39  	resources := []terraformutils.Resource{}
    40  	re := regexp.MustCompile(`^[a-z]`)
    41  	for {
    42  		serviceAccount, err := serviceAccountsIterator.Next()
    43  		if err == iterator.Done {
    44  			break
    45  		}
    46  		if err != nil {
    47  			log.Println("error with service account:", err)
    48  			continue
    49  		}
    50  		if !re.MatchString(serviceAccount.Email) {
    51  			log.Printf("skipping %s: service account email must start with [a-z]\n", serviceAccount.Name)
    52  			continue
    53  		}
    54  		resources = append(resources, terraformutils.NewSimpleResource(
    55  			serviceAccount.Name,
    56  			serviceAccount.UniqueId,
    57  			"google_service_account",
    58  			g.ProviderName,
    59  			IamAllowEmptyValues,
    60  		))
    61  	}
    62  	return resources
    63  }
    64  
    65  func (g *IamGenerator) createIamCustomRoleResources(rolesResponse *adminpb.ListRolesResponse, project string) []terraformutils.Resource {
    66  	resources := []terraformutils.Resource{}
    67  	for _, role := range rolesResponse.Roles {
    68  		if role.Deleted {
    69  			// Note: no need to log that the resource has been deleted
    70  			continue
    71  		}
    72  		resources = append(resources, terraformutils.NewResource(
    73  			role.Name,
    74  			role.Name,
    75  			"google_project_iam_custom_role",
    76  			g.ProviderName,
    77  			map[string]string{
    78  				"role_id": role.Name,
    79  				"project": project,
    80  			},
    81  			IamAllowEmptyValues,
    82  			map[string]interface{}{
    83  				"stage": role.Stage.String(),
    84  			},
    85  		))
    86  	}
    87  
    88  	return resources
    89  }
    90  
    91  func (g *IamGenerator) createIamMemberResources(policy *cloudresourcemanager.Policy, project string) []terraformutils.Resource {
    92  	resources := []terraformutils.Resource{}
    93  	for _, b := range policy.Bindings {
    94  		for _, m := range b.Members {
    95  			resources = append(resources, terraformutils.NewResource(
    96  				b.Role+m,
    97  				b.Role+m,
    98  				"google_project_iam_member",
    99  				g.ProviderName,
   100  				map[string]string{
   101  					"role":    b.Role,
   102  					"project": project,
   103  					"member":  m,
   104  				},
   105  				IamAllowEmptyValues,
   106  				IamAdditionalFields,
   107  			))
   108  		}
   109  	}
   110  
   111  	return resources
   112  }
   113  
   114  func (g *IamGenerator) InitResources() error {
   115  	ctx := context.Background()
   116  
   117  	projectID := g.GetArgs()["project"].(string)
   118  	client, err := admin.NewIamClient(ctx)
   119  	if err != nil {
   120  		return err
   121  	}
   122  	serviceAccountsIterator := client.ListServiceAccounts(ctx, &adminpb.ListServiceAccountsRequest{Name: "projects/" + projectID})
   123  	rolesResponse, err := client.ListRoles(ctx, &adminpb.ListRolesRequest{Parent: "projects/" + projectID})
   124  	if err != nil {
   125  		return err
   126  	}
   127  
   128  	cm, err := cloudresourcemanager.NewService(context.Background())
   129  	if err != nil {
   130  		return err
   131  	}
   132  	rb := &cloudresourcemanager.GetIamPolicyRequest{}
   133  	policyResponse, err := cm.Projects.GetIamPolicy(projectID, rb).Context(context.Background()).Do()
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	g.Resources = g.createServiceAccountResources(serviceAccountsIterator)
   139  	g.Resources = append(g.Resources, g.createIamCustomRoleResources(rolesResponse, projectID)...)
   140  	g.Resources = append(g.Resources, g.createIamMemberResources(policyResponse, projectID)...)
   141  	return nil
   142  }