diff --git a/spinifex/handlers/iam/groups_test.go b/spinifex/handlers/iam/groups_test.go index 48c906456..cd0d8a652 100644 --- a/spinifex/handlers/iam/groups_test.go +++ b/spinifex/handlers/iam/groups_test.go @@ -95,7 +95,7 @@ func TestCreateGroup_InvalidPath(t *testing.T) { Path: aws.String("no-leading-slash/"), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestGetGroup(t *testing.T) { @@ -773,7 +773,7 @@ func TestPutGroupPolicy_InvalidName(t *testing.T) { PolicyDocument: aws.String(validPolicyDocument()), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestPutGroupPolicy_MalformedDocument(t *testing.T) { diff --git a/spinifex/handlers/iam/instance_profiles_test.go b/spinifex/handlers/iam/instance_profiles_test.go index b0fe3757e..dd03f18d4 100644 --- a/spinifex/handlers/iam/instance_profiles_test.go +++ b/spinifex/handlers/iam/instance_profiles_test.go @@ -82,7 +82,7 @@ func TestCreateInstanceProfile_InvalidPath(t *testing.T) { Path: aws.String("missing-slashes"), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestCreateInstanceProfile_Duplicate(t *testing.T) { diff --git a/spinifex/handlers/iam/roles_test.go b/spinifex/handlers/iam/roles_test.go index 1ce0d6caf..2f9ffee7d 100644 --- a/spinifex/handlers/iam/roles_test.go +++ b/spinifex/handlers/iam/roles_test.go @@ -110,7 +110,7 @@ func TestCreateRole_InvalidPath(t *testing.T) { Path: aws.String("no-leading-slash/"), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestCreateRole_PermissionsBoundarySet(t *testing.T) { @@ -1028,7 +1028,7 @@ func TestPutRolePolicy_InvalidName(t *testing.T) { PolicyDocument: aws.String(validPolicyDocument()), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestPutRolePolicy_MalformedDocument(t *testing.T) { diff --git a/spinifex/handlers/iam/service_impl.go b/spinifex/handlers/iam/service_impl.go index e36d42c33..a920a2098 100644 --- a/spinifex/handlers/iam/service_impl.go +++ b/spinifex/handlers/iam/service_impl.go @@ -2111,7 +2111,7 @@ func validateIAMName(field, name string, maxLen int) error { } for i := range len(name) { if !isIAMNameChar(name[i]) { - return awserrors.Errorf(awserrors.ErrorIAMInvalidInput, + return awserrors.Errorf(awserrors.ErrorValidationError, "The specified value for %s is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_-", field) } } @@ -2124,7 +2124,7 @@ func lengthViolation(value, field, bound string) error { } func enumViolation(field string, allowed []string) error { - return awserrors.Errorf(awserrors.ErrorIAMInvalidInput, + return awserrors.Errorf(awserrors.ErrorValidationError, "1 validation error detected: Value at '%s' failed to satisfy constraint: Member must satisfy enum value set: [%s]", field, strings.Join(allowed, ", ")) } @@ -2141,7 +2141,7 @@ func validatePermissionsBoundary(boundary *string) error { func validatePath(path string) error { if !strings.HasPrefix(path, "/") || !strings.HasSuffix(path, "/") { - return awserrors.Errorf(awserrors.ErrorIAMInvalidInput, + return awserrors.Errorf(awserrors.ErrorValidationError, "The specified value for path is invalid. It must begin and end with / and contain only alphanumeric characters and/or / characters.") } if len(path) > 512 { diff --git a/spinifex/handlers/iam/service_impl_test.go b/spinifex/handlers/iam/service_impl_test.go index 9c9a2c0c8..4679244d5 100644 --- a/spinifex/handlers/iam/service_impl_test.go +++ b/spinifex/handlers/iam/service_impl_test.go @@ -396,7 +396,7 @@ func TestCreateUser_InvalidName_BadChars(t *testing.T) { _, err := svc.CreateUser(testAccountID, &iam.CreateUserInput{ UserName: aws.String("bad name!"), }) - requireIAMInvalidInput(t, err, + requireIAMError(t, err, awserrors.ErrorValidationError, "The specified value for userName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_-") } @@ -408,7 +408,7 @@ func TestCreateUser_InvalidPath(t *testing.T) { UserName: aws.String("validuser"), Path: aws.String("noslash"), }) - requireIAMInvalidInput(t, err, + requireIAMError(t, err, awserrors.ErrorValidationError, "The specified value for path is invalid. It must begin and end with / and contain only alphanumeric characters and/or / characters.") } @@ -435,7 +435,7 @@ func TestCreatePolicy_InvalidPath(t *testing.T) { Path: aws.String("bad-path"), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestValidatePolicyDocument_TooLarge(t *testing.T) { @@ -690,7 +690,7 @@ func TestUpdateAccessKey_InvalidStatus(t *testing.T) { AccessKeyId: keyOut.AccessKey.AccessKeyId, Status: aws.String("Invalid"), }) - requireIAMInvalidInput(t, err, + requireIAMError(t, err, awserrors.ErrorValidationError, "1 validation error detected: Value at 'status' failed to satisfy constraint: Member must satisfy enum value set: [Expired, Active, Inactive]") } @@ -2585,25 +2585,27 @@ func TestIsIAMNameChar(t *testing.T) { func TestValidateIAMName(t *testing.T) { t.Parallel() const charset = "It must contain only alphanumeric characters and/or the following: +=,.@_-" + invalid, validation := awserrors.ErrorIAMInvalidInput, awserrors.ErrorValidationError tests := []struct { - name string - field string - input string - maxLen int - wantMsg string + name string + field string + input string + maxLen int + wantCode string + wantMsg string }{ - {"valid simple", "userName", "alice", 64, ""}, - {"valid with special chars", "userName", "alice.bob+test@example_com", 64, ""}, - {"valid single char", "userName", "a", 64, ""}, - {"valid at max length", "userName", strings.Repeat("a", 64), 64, ""}, - {"valid policy at max length", "policyName", strings.Repeat("x", 128), 128, ""}, - {"empty", "userName", "", 64, + {"valid simple", "userName", "alice", 64, "", ""}, + {"valid with special chars", "userName", "alice.bob+test@example_com", 64, "", ""}, + {"valid single char", "userName", "a", 64, "", ""}, + {"valid at max length", "userName", strings.Repeat("a", 64), 64, "", ""}, + {"valid policy at max length", "policyName", strings.Repeat("x", 128), 128, "", ""}, + {"empty", "userName", "", 64, invalid, "1 validation error detected: Value '' at 'userName' failed to satisfy constraint: Member must have length greater than or equal to 1"}, - {"too long", "policyName", strings.Repeat("x", 129), 128, + {"too long", "policyName", strings.Repeat("x", 129), 128, invalid, "1 validation error detected: Value '" + strings.Repeat("x", 129) + "' at 'policyName' failed to satisfy constraint: Member must have length less than or equal to 128"}, - {"space", "userName", "bad name!", 64, "The specified value for userName is invalid. " + charset}, - {"slash", "roleName", "alice/bob", 64, "The specified value for roleName is invalid. " + charset}, - {"colon", "groupName", "alice:bob", 128, "The specified value for groupName is invalid. " + charset}, + {"space", "userName", "bad name!", 64, validation, "The specified value for userName is invalid. " + charset}, + {"slash", "roleName", "alice/bob", 64, validation, "The specified value for roleName is invalid. " + charset}, + {"colon", "groupName", "alice:bob", 128, validation, "The specified value for groupName is invalid. " + charset}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -2613,17 +2615,17 @@ func TestValidateIAMName(t *testing.T) { assert.NoError(t, err) return } - requireIAMInvalidInput(t, err, tt.wantMsg) + requireIAMError(t, err, tt.wantCode, tt.wantMsg) }) } } -func requireIAMInvalidInput(t *testing.T, err error, wantMsg string) { +func requireIAMError(t *testing.T, err error, wantCode, wantMsg string) { t.Helper() require.Error(t, err) code, msg, ok := awserrors.ResolveErrorDetail(err) require.True(t, ok, "error must carry a registered code: %v", err) - assert.Equal(t, awserrors.ErrorIAMInvalidInput, code) + assert.Equal(t, wantCode, code) assert.Equal(t, wantMsg, msg) } @@ -2631,19 +2633,21 @@ func TestValidatePath(t *testing.T) { t.Parallel() const shape = "The specified value for path is invalid. It must begin and end with / and contain only alphanumeric characters and/or / characters." tooLong := "/" + strings.Repeat("a", 511) + "/" + invalid, validation := awserrors.ErrorIAMInvalidInput, awserrors.ErrorValidationError tests := []struct { - name string - input string - wantMsg string + name string + input string + wantCode string + wantMsg string }{ - {"root path", "/", ""}, - {"nested path", "/division/engineering/", ""}, - {"no leading slash", "division/", shape}, - {"no trailing slash", "/division", shape}, - {"empty string", "", shape}, - {"just text", "noslash", shape}, - {"max length 512", "/" + strings.Repeat("a", 510) + "/", ""}, - {"over max length 513", tooLong, + {"root path", "/", "", ""}, + {"nested path", "/division/engineering/", "", ""}, + {"no leading slash", "division/", validation, shape}, + {"no trailing slash", "/division", validation, shape}, + {"empty string", "", validation, shape}, + {"just text", "noslash", validation, shape}, + {"max length 512", "/" + strings.Repeat("a", 510) + "/", "", ""}, + {"over max length 513", tooLong, invalid, "1 validation error detected: Value '" + tooLong + "' at 'path' failed to satisfy constraint: Member must have length less than or equal to 512"}, } for _, tt := range tests { @@ -2654,7 +2658,7 @@ func TestValidatePath(t *testing.T) { assert.NoError(t, err) return } - requireIAMInvalidInput(t, err, tt.wantMsg) + requireIAMError(t, err, tt.wantCode, tt.wantMsg) }) } } diff --git a/spinifex/handlers/iam/tags_test.go b/spinifex/handlers/iam/tags_test.go index 5208d7c87..fe87aed92 100644 --- a/spinifex/handlers/iam/tags_test.go +++ b/spinifex/handlers/iam/tags_test.go @@ -75,7 +75,7 @@ func TestValidateTags_NamesFailingMember(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { t.Parallel() - requireIAMInvalidInput(t, validateTags(tc.tags), tc.wantMsg) + requireIAMError(t, validateTags(tc.tags), awserrors.ErrorIAMInvalidInput, tc.wantMsg) }) } } diff --git a/spinifex/handlers/iam/user_inline_test.go b/spinifex/handlers/iam/user_inline_test.go index 090f577ee..140a90b82 100644 --- a/spinifex/handlers/iam/user_inline_test.go +++ b/spinifex/handlers/iam/user_inline_test.go @@ -82,7 +82,7 @@ func TestPutUserPolicy_InvalidName(t *testing.T) { PolicyDocument: aws.String(validPolicyDocument()), }) assert.Error(t, err) - assert.Contains(t, err.Error(), awserrors.ErrorIAMInvalidInput) + assert.Contains(t, err.Error(), awserrors.ErrorValidationError) } func TestPutUserPolicy_MalformedDocument(t *testing.T) {