Add tagging support for AWS IAM Roles

This commit is contained in:
Peter Rifel 2020-12-21 20:22:40 -06:00
parent aff0ae2d39
commit 4ee5d7a543
No known key found for this signature in database
GPG Key ID: BC6469E5B16DB2B6
4 changed files with 66 additions and 2 deletions

View File

@ -64,6 +64,7 @@ func (m *MockIAM) CreateRole(request *iam.CreateRoleInput) (*iam.CreateRoleOutpu
},
RoleName: request.RoleName,
RoleId: &roleID,
Tags: request.Tags,
}
if m.Roles == nil {

View File

@ -136,6 +136,7 @@ func (b *IAMModelBuilder) buildIAMRole(role iam.Subject, iamName string, c *fi.M
Lifecycle: b.Lifecycle,
RolePolicyDocument: rolePolicy,
Tags: b.CloudTags(iamName, false),
}
if isServiceAccount {

View File

@ -44,6 +44,8 @@ type IAMRole struct {
RolePolicyDocument fi.Resource // "inline" IAM policy
PermissionsBoundary *string
Tags map[string]string
// ExportWithId will expose the name & ARN for reuse as part of a larger system. Only supported by terraform currently.
ExportWithID *string
}
@ -110,6 +112,7 @@ func (e *IAMRole) Find(c *fi.Context) (*IAMRole, error) {
actual.RolePolicyDocument = fi.NewStringResource(actualPolicy)
}
actual.Tags = mapIAMTagsToMap(r.Tags)
klog.V(2).Infof("found matching IAMRole %q", aws.StringValue(actual.ID))
e.ID = actual.ID
@ -150,6 +153,7 @@ func (_ *IAMRole) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *IAMRole) error
request := &iam.CreateRoleInput{}
request.AssumeRolePolicyDocument = aws.String(policy)
request.RoleName = e.Name
request.Tags = mapToIAMTags(e.Tags)
if e.PermissionsBoundary != nil {
request.PermissionsBoundary = e.PermissionsBoundary
@ -215,7 +219,32 @@ func (_ *IAMRole) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *IAMRole) error
return fmt.Errorf("error updating IAMRole: %v", err)
}
}
}
if changes.Tags != nil {
if len(a.Tags) > 0 {
existingTagKeys := make([]*string, 0)
for k := range a.Tags {
existingTagKeys = append(existingTagKeys, &k)
}
untagRequest := &iam.UntagRoleInput{
RoleName: e.Name,
TagKeys: existingTagKeys,
}
_, err = t.Cloud.IAM().UntagRole(untagRequest)
if err != nil {
return fmt.Errorf("error untagging IAMRole: %v", err)
}
}
if len(e.Tags) > 0 {
tagRequest := &iam.TagRoleInput{
RoleName: e.Name,
Tags: mapToIAMTags(e.Tags),
}
_, err = t.Cloud.IAM().TagRole(tagRequest)
if err != nil {
return fmt.Errorf("error tagging IAMRole: %v", err)
}
}
}
}
@ -227,6 +256,7 @@ type terraformIAMRole struct {
Name *string `json:"name" cty:"name"`
AssumeRolePolicy *terraform.Literal `json:"assume_role_policy" cty:"assume_role_policy"`
PermissionsBoundary *string `json:"permissions_boundary,omitempty" cty:"permissions_boundary"`
Tags map[string]string `json:"tags,omitempty" cty:"tags"`
}
func (_ *IAMRole) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *IAMRole) error {
@ -238,6 +268,7 @@ func (_ *IAMRole) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *I
tf := &terraformIAMRole{
Name: e.Name,
AssumeRolePolicy: policy,
Tags: e.Tags,
}
if e.PermissionsBoundary != nil {
@ -260,6 +291,7 @@ type cloudformationIAMRole struct {
RoleName *string `json:"RoleName"`
AssumeRolePolicyDocument map[string]interface{}
PermissionsBoundary *string `json:"PermissionsBoundary,omitempty"`
Tags []cloudformationTag `json:"Tags,omitempty"`
}
func (_ *IAMRole) RenderCloudformation(t *cloudformation.CloudformationTarget, a, e, changes *IAMRole) error {
@ -277,6 +309,7 @@ func (_ *IAMRole) RenderCloudformation(t *cloudformation.CloudformationTarget, a
cf := &cloudformationIAMRole{
RoleName: e.Name,
AssumeRolePolicyDocument: data,
Tags: buildCloudformationTags(e.Tags),
}
if e.PermissionsBoundary != nil {

View File

@ -21,6 +21,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
)
func mapEC2TagsToMap(tags []*ec2.Tag) map[string]string {
@ -37,6 +38,34 @@ func mapEC2TagsToMap(tags []*ec2.Tag) map[string]string {
return m
}
func mapIAMTagsToMap(tags []*iam.Tag) map[string]string {
if tags == nil {
return nil
}
m := make(map[string]string)
for _, t := range tags {
if strings.HasPrefix(aws.StringValue(t.Key), "aws:cloudformation:") {
continue
}
m[aws.StringValue(t.Key)] = aws.StringValue(t.Value)
}
return m
}
func mapToIAMTags(tags map[string]string) []*iam.Tag {
if tags == nil {
return nil
}
m := make([]*iam.Tag, 0)
for k, v := range tags {
m = append(m, &iam.Tag{
Key: aws.String(k),
Value: aws.String(v),
})
}
return m
}
func findNameTag(tags []*ec2.Tag) *string {
for _, tag := range tags {
if aws.StringValue(tag.Key) == "Name" {