hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.73k stars 9.09k forks source link

[Bug]: AWS SSO / AWS IAM Identity Center - Permission Set creation not returning error when it should #38544

Open TacetVenator opened 1 month ago

TacetVenator commented 1 month ago

Terraform Core Version

1.8.4

AWS Provider Version

5.59.0

Affected Resource(s)

Expected Behavior

When creating a permission set that has a name that has the same name as an existing permission set. We should have an error: "errorCode": "ConflictException", "errorMessage": "PermissionSet with name SREDev already exists."

Actual Behavior

Terraform hangs. It waits but it will not resolve. It does not throw an error.

Relevant Error/Panic Output Snippet

# The stdout of the terraform apply will look like this
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [20s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [30s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [40s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [50s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [1m0s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [1m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [1m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [1m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [1m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [1m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [2m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [2m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [2m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [2m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [2m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [2m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [3m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [3m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [3m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [3m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [3m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [3m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [4m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [4m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [4m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [4m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [4m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [4m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [5m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [5m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [5m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [5m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [5m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [5m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [6m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [6m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [6m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [6m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [6m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [6m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [7m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [7m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [7m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [7m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [7m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [7m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [8m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [8m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [8m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [8m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [8m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [8m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [9m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [9m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [9m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [9m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [9m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [9m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [10m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [11m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [11m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [11m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [11m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [11m41s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [11m51s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [12m1s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [12m11s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [12m21s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [12m31s elapsed]
aws_ssoadmin_permission_set.this["SREDev"]: Still creating... [12m41s elapsed]

When in AWS we clearly have an error:

"eventTime": "2024-07-25T20:14:27Z",
    "eventSource": "sso.amazonaws.com",
    "eventName": "CreatePermissionSet",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "172.177.6.26",
    "userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.8.4 (+https://www.terraform.io) terraform-provider-aws/5.59.0 (+https://registry.terraform.io/providers/hashicorp/aws) aws-sdk-go-v2/1.30.3 os/linux lang/go#1.22.5 md/GOOS#linux md/GOARCH#amd64 api/ssoadmin#1.27.3",
    "errorCode": "ConflictException",
    "errorMessage": "PermissionSet with name SREDev already exists.",

Terraform Configuration Files

data "aws_ssoadmin_instances" "this" {}

resource "aws_ssoadmin_permission_set" "SREDev" {
  name             = "SREDev"
  description      = "SRE Role in Dev"
  instance_arn     = tolist(data.aws_ssoadmin_instances.this.arns)[0]
  session_duration = "PT1H"
}
resource "aws_ssoadmin_permission_set" "SREDev2" {
  name             = "SREDev"
  description      = "SRE Role in Dev second one for testing purposes"
  instance_arn     = tolist(data.aws_ssoadmin_instances.this.arns)[0]
  session_duration = "PT1H"
}

Steps to Reproduce

Deploy SREDev and then try to deploy SREDev2. The idea is to make sure it crashes in case someone created a permission set with the same name. It could also be created outside of the state, like in my case.

Debug Output

No response

Panic Output

No response

Important Factoids

It is easy to test working with: https://github.com/aws-samples/identity-center-with-terraform

References

No response

Would you like to implement a fix?

None

github-actions[bot] commented 1 month ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

TacetVenator commented 1 month ago

I went through the code and I can't see why the error is not triggering. https://github.com/hashicorp/terraform-provider-aws/blob/4a44f6796adc574bfac983d98befc75b44f6916e/internal/service/ssoadmin/permission_set.go#L127

Could it be because the API is too slow to respond? This service is quite slow for some unknown reason. I see it is suppose to catch the error. There is one, so... what's up?

TacetVenator commented 1 month ago

Anybody would like to try it out? `func resourcePermissionSetCreate(ctx context.Context, d schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics conn := meta.(conns.AWSClient).SSOAdminClient(ctx)

instanceARN := d.Get("instance_arn").(string)
name := d.Get(names.AttrName).(string)
input := &ssoadmin.CreatePermissionSetInput{
    InstanceArn: aws.String(instanceARN),
    Name:        aws.String(name),
    Tags:        getTagsIn(ctx),
}

if v, ok := d.GetOk(names.AttrDescription); ok {
    input.Description = aws.String(v.(string))
}

if v, ok := d.GetOk("relay_state"); ok {
    input.RelayState = aws.String(v.(string))
}

if v, ok := d.GetOk("session_duration"); ok {
    input.SessionDuration = aws.String(v.(string))
}

output, err := conn.CreatePermissionSet(ctx, input)

if err != nil {
    if isDuplicatePermissionSetError(err) {
        return sdkdiag.AppendErrorf(diags, "creating SSO Permission Set (%s): permission set already exists", name)
    }
    return sdkdiag.AppendErrorf(diags, "creating SSO Permission Set (%s): %s", name, err)
}

d.SetId(fmt.Sprintf("%s,%s", aws.ToString(output.PermissionSet.PermissionSetArn), instanceARN))

return append(diags, resourcePermissionSetRead(ctx, d, meta)...)

}

// Helper function to check for duplicate permission set error func isDuplicatePermissionSetError(err error) bool { var resourceConflictException *ssoadmin.ResourceConflictException if errors.As(err, &resourceConflictException) { return true } return false } ` I saw the unit tests and creating a permission set doesn't seem to be covered and I never built a Terraform provider so... Anybody care for a quick win?