mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-20 03:11:46 +00:00
fix: return ValidationError for IAM name, path and enum violations
AWS answers a bad name charset, a path not bounded by slashes and an enum violation such as UpdateAccessKey's status with ValidationError. Length and tag violations keep InvalidInput until AWS's code for them is captured.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user