Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iam: Improve ISO tag handling #23283

Merged
merged 13 commits into from
Feb 18, 2022
27 changes: 27 additions & 0 deletions .changelog/23283.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```release-note:bug
resource/aws_iam_instance_profile: Improve tag handling in ISO regions
```

```release-note:bug
resource/aws_iam_openid_connect_provider: Improve tag handling in ISO regions
```

```release-note:bug
resource/aws_iam_policy: Improve tag handling in ISO regions
```

```release-note:bug
resource/aws_iam_saml_provider: Improve tag handling in ISO regions
```

```release-note:bug
resource/aws_iam_server_certificate: Improve tag handling in ISO regions
```

```release-note:bug
resource/aws_iam_service_linked_role: Improve tag handling in ISO regions
```

```release-note:bug
resource/aws_iam_virtual_mfa_device: Improve tag handling in ISO regions
```
4 changes: 2 additions & 2 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1421,7 +1421,7 @@ func Provider() *schema.Provider {
"aws_iam_role": iam.ResourceRole(),
"aws_iam_role_policy": iam.ResourceRolePolicy(),
"aws_iam_role_policy_attachment": iam.ResourceRolePolicyAttachment(),
"aws_iam_saml_provider": iam.ResourceSamlProvider(),
"aws_iam_saml_provider": iam.ResourceSAMLProvider(),
"aws_iam_server_certificate": iam.ResourceServerCertificate(),
"aws_iam_service_linked_role": iam.ResourceServiceLinkedRole(),
"aws_iam_service_specific_credential": iam.ResourceServiceSpecificCredential(),
Expand All @@ -1432,7 +1432,7 @@ func Provider() *schema.Provider {
"aws_iam_user_policy": iam.ResourceUserPolicy(),
"aws_iam_user_policy_attachment": iam.ResourceUserPolicyAttachment(),
"aws_iam_user_ssh_key": iam.ResourceUserSSHKey(),
"aws_iam_virtual_mfa_device": iam.ResourceVirtualMfaDevice(),
"aws_iam_virtual_mfa_device": iam.ResourceVirtualMFADevice(),

"aws_imagebuilder_component": imagebuilder.ResourceComponent(),
"aws_imagebuilder_container_recipe": imagebuilder.ResourceContainerRecipe(),
Expand Down
2 changes: 1 addition & 1 deletion internal/service/iam/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func FindRoleByName(conn *iam.IAM, name string) (*iam.Role, error) {
return output.Role, nil
}

func FindVirtualMfaDevice(conn *iam.IAM, serialNum string) (*iam.VirtualMFADevice, error) {
func FindVirtualMFADevice(conn *iam.IAM, serialNum string) (*iam.VirtualMFADevice, error) {
input := &iam.ListVirtualMFADevicesInput{}

output, err := conn.ListVirtualMFADevices(input)
Expand Down
44 changes: 40 additions & 4 deletions internal/service/iam/instance_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,27 @@ func resourceInstanceProfileCreate(d *schema.ResourceData, meta interface{}) err
request := &iam.CreateInstanceProfileInput{
InstanceProfileName: aws.String(name),
Path: aws.String(d.Get("path").(string)),
Tags: Tags(tags.IgnoreAWS()),
}

if len(tags) > 0 {
request.Tags = Tags(tags.IgnoreAWS())
}

var err error
response, err := conn.CreateInstanceProfile(request)

// Some partitions (i.e., ISO) may not support tag-on-create
if request.Tags != nil && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed creating IAM Instance Profile (%s) with tags: %s. Trying create without tags.", name, err)
request.Tags = nil

response, err = conn.CreateInstanceProfile(request)
}

if err == nil {
err = instanceProfileReadResult(d, response.InstanceProfile, meta)
err = instanceProfileReadResult(d, response.InstanceProfile, meta) // sets id
}

if err != nil {
return fmt.Errorf("creating IAM instance profile %s: %w", name, err)
}
Expand All @@ -117,6 +130,21 @@ func resourceInstanceProfileCreate(d *schema.ResourceData, meta interface{}) err
return fmt.Errorf("timed out while waiting for instance profile %s: %w", name, err)
}

// Some partitions (i.e., ISO) may not support tag-on-create, attempt tag after create
if request.Tags == nil && len(tags) > 0 {
err := instanceProfileUpdateTags(conn, d.Id(), nil, tags)

// If default tags only, log and continue. Otherwise, error.
if v, ok := d.GetOk("tags"); (!ok || len(v.(map[string]interface{})) == 0) && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed adding tags after create for IAM Instance Profile (%s): %s", d.Id(), err)
return resourceInstanceProfileUpdate(d, meta)
}

if err != nil {
return fmt.Errorf("error updating tags for IAM Instance Profile (%s): %w", d.Id(), err)
YakDriver marked this conversation as resolved.
Show resolved Hide resolved
}
}

return resourceInstanceProfileUpdate(d, meta)
}

Expand Down Expand Up @@ -197,8 +225,16 @@ func resourceInstanceProfileUpdate(d *schema.ResourceData, meta interface{}) err
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := instanceProfileUpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating tags for IAM Instance Profile (%s): %w", d.Id(), err)
err := instanceProfileUpdateTags(conn, d.Id(), o, n)

// Some partitions (i.e., ISO) may not support tagging, giving error
if verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed updating tags for IAM Instance Profile (%s): %s", d.Id(), err)
return nil
}

if err != nil {
return fmt.Errorf("failed updating tags for IAM Instance Profile (%s): %w", d.Id(), err)
}
}

Expand Down
41 changes: 38 additions & 3 deletions internal/service/iam/openid_connect_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,43 @@ func resourceOpenIDConnectProviderCreate(d *schema.ResourceData, meta interface{
Url: aws.String(d.Get("url").(string)),
ClientIDList: flex.ExpandStringList(d.Get("client_id_list").([]interface{})),
ThumbprintList: flex.ExpandStringList(d.Get("thumbprint_list").([]interface{})),
Tags: Tags(tags.IgnoreAWS()),
}

if len(tags) > 0 {
input.Tags = Tags(tags.IgnoreAWS())
}

out, err := conn.CreateOpenIDConnectProvider(input)

// Some partitions (i.e., ISO) may not support tag-on-create
if input.Tags != nil && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed creating IAM OIDC Provider with tags: %s. Trying create without tags.", err)
input.Tags = nil

out, err = conn.CreateOpenIDConnectProvider(input)
}

if err != nil {
return fmt.Errorf("error creating IAM OIDC Provider: %w", err)
}

d.SetId(aws.StringValue(out.OpenIDConnectProviderArn))

// Some partitions (i.e., ISO) may not support tag-on-create, attempt tag after create
if input.Tags == nil && len(tags) > 0 {
err := openIDConnectProviderUpdateTags(conn, d.Id(), nil, tags)

// If default tags only, log and continue. Otherwise, error.
if v, ok := d.GetOk("tags"); (!ok || len(v.(map[string]interface{})) == 0) && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed adding tags after create for IAM OIDC Provider (%s): %s", d.Id(), err)
return resourceOpenIDConnectProviderRead(d, meta)
}

if err != nil {
return fmt.Errorf("error updating tags for IAM OIDC Provider (%s): %w", d.Id(), err)
}
}

return resourceOpenIDConnectProviderRead(d, meta)
}

Expand Down Expand Up @@ -139,8 +166,16 @@ func resourceOpenIDConnectProviderUpdate(d *schema.ResourceData, meta interface{
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := openIDConnectProviderUpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating tags for IAM OIDC Provider (%s): %w", d.Id(), err)
err := openIDConnectProviderUpdateTags(conn, d.Id(), o, n)

// Some partitions (i.e., ISO) may not support tagging, giving error
if verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed updating tags for IAM OIDC Provider (%s): %s", d.Id(), err)
return resourceOpenIDConnectProviderRead(d, meta)
}

if err != nil {
return fmt.Errorf("failed updating tags for IAM OIDC Provider (%s): %w", d.Id(), err)
}
}

Expand Down
6 changes: 3 additions & 3 deletions internal/service/iam/openid_connect_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
tfiam "github.com/hashicorp/terraform-provider-aws/internal/service/iam"
)

func TestAccIAMOpenidConnectProvider_basic(t *testing.T) {
func TestAccIAMOpenIDConnectProvider_basic(t *testing.T) {
rString := sdkacctest.RandString(5)
url := "accounts.testle.com/" + rString
resourceName := "aws_iam_openid_connect_provider.test"
Expand Down Expand Up @@ -62,7 +62,7 @@ func TestAccIAMOpenidConnectProvider_basic(t *testing.T) {
})
}

func TestAccIAMOpenidConnectProvider_tags(t *testing.T) {
func TestAccIAMOpenIDConnectProvider_tags(t *testing.T) {
rString := sdkacctest.RandString(5)
resourceName := "aws_iam_openid_connect_provider.test"

Expand Down Expand Up @@ -107,7 +107,7 @@ func TestAccIAMOpenidConnectProvider_tags(t *testing.T) {
})
}

func TestAccIAMOpenidConnectProvider_disappears(t *testing.T) {
func TestAccIAMOpenIDConnectProvider_disappears(t *testing.T) {
rString := sdkacctest.RandString(5)
resourceName := "aws_iam_openid_connect_provider.test"

Expand Down
43 changes: 39 additions & 4 deletions internal/service/iam/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,43 @@ func resourcePolicyCreate(d *schema.ResourceData, meta interface{}) error {
Path: aws.String(d.Get("path").(string)),
PolicyDocument: aws.String(policy),
PolicyName: aws.String(name),
Tags: Tags(tags.IgnoreAWS()),
}

if len(tags) > 0 {
request.Tags = Tags(tags.IgnoreAWS())
}

response, err := conn.CreatePolicy(request)

// Some partitions (i.e., ISO) may not support tag-on-create
if request.Tags != nil && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed creating IAM Policy (%s) with tags: %s. Trying create without tags.", name, err)
request.Tags = nil

response, err = conn.CreatePolicy(request)
}

if err != nil {
return fmt.Errorf("error creating IAM policy %s: %w", name, err)
return fmt.Errorf("error creating IAM Policy %s: %w", name, err)
}

d.SetId(aws.StringValue(response.Policy.Arn))

// Some partitions (i.e., ISO) may not support tag-on-create, attempt tag after create
if request.Tags == nil && len(tags) > 0 {
err := policyUpdateTags(conn, d.Id(), nil, tags)

// If default tags only, log and continue. Otherwise, error.
if v, ok := d.GetOk("tags"); (!ok || len(v.(map[string]interface{})) == 0) && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed adding tags after create for IAM Policy (%s): %s", d.Id(), err)
return resourcePolicyRead(d, meta)
}

if err != nil {
return fmt.Errorf("error updating tags for IAM Policy (%s): %w", d.Id(), err)
}
}

return resourcePolicyRead(d, meta)
}

Expand Down Expand Up @@ -277,8 +304,16 @@ func resourcePolicyUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := policyUpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating tags for IAM Policy (%s): %w", d.Id(), err)
err := policyUpdateTags(conn, d.Id(), o, n)

// Some partitions (i.e., ISO) may not support tagging, giving error
if verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed updating tags for IAM Policy (%s): %s", d.Id(), err)
return resourcePolicyRead(d, meta)
}

if err != nil {
return fmt.Errorf("failed updating tags for IAM Policy (%s): %w", d.Id(), err)
}
}

Expand Down
6 changes: 0 additions & 6 deletions internal/service/iam/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,6 @@ func resourceRoleRead(d *schema.ResourceData, meta interface{}) error {

tags := KeyValueTags(role.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

// Some partitions (i.e., ISO) may not support tagging, giving error
if meta.(*conns.AWSClient).Partition != endpoints.AwsPartitionID && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] failed listing tags for IAM Role (%s): %s", d.Id(), err)
return nil
}

//lintignore:AWSR002
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
Expand Down
9 changes: 0 additions & 9 deletions internal/service/iam/role_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@ package iam

import (
"fmt"
"log"
"net/url"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func DataSourceRole() *schema.Resource {
Expand Down Expand Up @@ -100,12 +97,6 @@ func dataSourceRoleRead(d *schema.ResourceData, meta interface{}) error {

tags := KeyValueTags(output.Role.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

// Some partitions (i.e., ISO) may not support tagging, giving error
if meta.(*conns.AWSClient).Partition != endpoints.AwsPartitionID && verify.CheckISOErrorTagsUnsupported(err) {
log.Printf("[WARN] Unable to list tags for IAM Role %s: %s", d.Id(), err)
return nil
}

//lintignore:AWSR002
if err := d.Set("tags", tags.Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
Expand Down
Loading