Add AWS IAM integration tests and refactor admin authorization (#8098)
* Add AWS IAM integration tests and refactor admin authorization - Added AWS IAM management integration tests (User, AccessKey, Policy) - Updated test framework to support IAM client creation with JWT/OIDC - Refactored s3api authorization to be policy-driven for IAM actions - Removed hardcoded role name checks for admin privileges - Added new tests to GitHub Actions basic test matrix * test(s3/iam): add UpdateUser and UpdateAccessKey tests and fix nil pointer dereference * feat(s3api): add DeletePolicy and update tests with cleanup logic * test(s3/iam): use t.Cleanup for managed policy deletion in CreatePolicy test
This commit is contained in:
@@ -289,8 +289,8 @@ func resolveBucketLevelAction(method string, baseAction string) string {
|
||||
// mapBaseActionToS3Format converts coarse-grained base actions to S3 format
|
||||
// This is the fallback when no specific resolution is found
|
||||
func mapBaseActionToS3Format(baseAction string) string {
|
||||
// Handle actions that already have s3: prefix
|
||||
if strings.HasPrefix(baseAction, "s3:") {
|
||||
// Handle actions that already have s3: or iam: prefix
|
||||
if strings.HasPrefix(baseAction, "s3:") || strings.HasPrefix(baseAction, "iam:") {
|
||||
return baseAction
|
||||
}
|
||||
|
||||
|
||||
@@ -341,6 +341,11 @@ type MockAssumedRoleUser struct {
|
||||
|
||||
// buildS3ResourceArn builds an S3 resource ARN from bucket and object
|
||||
func buildS3ResourceArn(bucket string, objectKey string) string {
|
||||
// If bucket is already an ARN, return it as-is
|
||||
if strings.HasPrefix(bucket, "arn:") {
|
||||
return bucket
|
||||
}
|
||||
|
||||
if bucket == "" {
|
||||
return "arn:aws:s3:::*"
|
||||
}
|
||||
|
||||
@@ -1003,16 +1003,20 @@ func (e *EmbeddedIamApi) AuthIam(f http.HandlerFunc, _ Action) http.HandlerFunc
|
||||
f(w, r)
|
||||
return
|
||||
}
|
||||
// Operating on another user: require admin
|
||||
// Operating on another user: require admin or permission
|
||||
if !identity.isAdmin() {
|
||||
s3err.WriteErrorResponse(w, r, s3err.ErrAccessDenied)
|
||||
return
|
||||
if e.iam.VerifyActionPermission(r, identity, Action("iam:"+action), "arn:aws:iam:::*", "") != s3err.ErrNone {
|
||||
s3err.WriteErrorResponse(w, r, s3err.ErrAccessDenied)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// All other IAM actions require admin (CreateUser, DeleteUser, PutUserPolicy, etc.)
|
||||
// All other IAM actions require admin or permission
|
||||
if !identity.isAdmin() {
|
||||
s3err.WriteErrorResponse(w, r, s3err.ErrAccessDenied)
|
||||
return
|
||||
if e.iam.VerifyActionPermission(r, identity, Action("iam:"+action), "arn:aws:iam:::*", "") != s3err.ErrNone {
|
||||
s3err.WriteErrorResponse(w, r, s3err.ErrAccessDenied)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1094,8 +1098,10 @@ func (e *EmbeddedIamApi) DoActions(w http.ResponseWriter, r *http.Request) {
|
||||
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidRequest)
|
||||
return
|
||||
}
|
||||
// CreatePolicy only validates the policy document and returns metadata.
|
||||
// Policies are not stored separately; they are attached inline via PutUserPolicy.
|
||||
case "DeletePolicy":
|
||||
// Managed policies are not stored separately, so deletion is a no-op.
|
||||
// Returns success for AWS compatibility.
|
||||
response = struct{}{}
|
||||
changed = false
|
||||
case "PutUserPolicy":
|
||||
response, iamErr = e.PutUserPolicy(s3cfg, values)
|
||||
|
||||
Reference in New Issue
Block a user