diff --git a/internal/service/backup/consts.go b/internal/service/backup/consts.go index ea4860cd65f..573f338a20d 100644 --- a/internal/service/backup/consts.go +++ b/internal/service/backup/consts.go @@ -3,6 +3,12 @@ package backup +import "time" + +const ( + iamPropagationTimeout = 2 * time.Minute +) + const ( frameworkStatusCompleted = "COMPLETED" frameworkStatusCreationInProgress = "CREATE_IN_PROGRESS" diff --git a/internal/service/backup/errors.go b/internal/service/backup/errors.go index b8dff1cad97..38fd3926ae8 100644 --- a/internal/service/backup/errors.go +++ b/internal/service/backup/errors.go @@ -4,5 +4,6 @@ package backup const ( - errCodeAccessDeniedException = "AccessDeniedException" + errCodeAccessDeniedException = "AccessDeniedException" + errCodeInvalidParameterValueException = "InvalidParameterValueException" ) diff --git a/internal/service/backup/vault_policy.go b/internal/service/backup/vault_policy.go index 7a3240a7e04..c7b84e4aefd 100644 --- a/internal/service/backup/vault_policy.go +++ b/internal/service/backup/vault_policy.go @@ -72,7 +72,12 @@ func resourceVaultPolicyPut(ctx context.Context, d *schema.ResourceData, meta in Policy: aws.String(policy), } - _, err = conn.PutBackupVaultAccessPolicyWithContext(ctx, input) + _, err = tfresource.RetryWhenAWSErrMessageContains(ctx, iamPropagationTimeout, + func() (interface{}, error) { + return conn.PutBackupVaultAccessPolicyWithContext(ctx, input) + }, + errCodeInvalidParameterValueException, "Provided principal is not valid", + ) if err != nil { return sdkdiag.AppendErrorf(diags, "creating Backup Vault Policy (%s): %s", name, err) diff --git a/internal/service/backup/vault_policy_test.go b/internal/service/backup/vault_policy_test.go index e66e263e23b..a9540f9b67f 100644 --- a/internal/service/backup/vault_policy_test.go +++ b/internal/service/backup/vault_policy_test.go @@ -54,6 +54,28 @@ func TestAccBackupVaultPolicy_basic(t *testing.T) { }) } +func TestAccBackupVaultPolicy_eventualConsistency(t *testing.T) { + ctx := acctest.Context(t) + var vault backup.GetBackupVaultAccessPolicyOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_backup_vault_policy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, backup.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckVaultPolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccVaultPolicyConfig_eventualConsistency(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckVaultPolicyExists(ctx, resourceName, &vault), + resource.TestMatchResourceAttr(resourceName, "policy", regexache.MustCompile("^{\"Id\":\"default\".+"))), + }, + }, + }) +} + func TestAccBackupVaultPolicy_disappears(t *testing.T) { ctx := acctest.Context(t) var vault backup.GetBackupVaultAccessPolicyOutput @@ -285,3 +307,63 @@ resource "aws_backup_vault_policy" "test" { } `, rName) } + +func testAccVaultPolicyConfig_eventualConsistency(rName string) string { + return acctest.ConfigCompose( + fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "" + Principal = { + Service = "backup.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "test" { + role = aws_iam_role.test.name + policy_arn = "arn:${data.aws_partition.current.partition}:iam::${data.aws_partition.current.partition}:policy/service-role/AWSBackupServiceRolePolicyForBackup" +} + +resource "aws_backup_vault" "test" { + name = %[1]q +} + +resource "aws_backup_vault_policy" "test" { + backup_vault_name = aws_backup_vault.test.name + + policy = jsonencode({ + Version = "2012-10-17" + Id = "default" + Statement = [{ + Sid = "default" + Effect = "Allow" + Principal = { + AWS = "${aws_iam_role.test.arn}" + } + Action = [ + "backup:DescribeBackupVault", + "backup:DeleteBackupVault", + "backup:PutBackupVaultAccessPolicy", + "backup:DeleteBackupVaultAccessPolicy", + "backup:GetBackupVaultAccessPolicy", + "backup:StartBackupJob", + "backup:GetBackupVaultNotifications", + "backup:PutBackupVaultNotifications", + ] + Resource = aws_backup_vault.test.arn + }] + }) +} +`, rName)) +}