diff --git a/weed/s3api/s3tables/permissions.go b/weed/s3api/s3tables/permissions.go index d14eecad5d..2cbdca7e89 100644 --- a/weed/s3api/s3tables/permissions.go +++ b/weed/s3api/s3tables/permissions.go @@ -200,11 +200,12 @@ func deniedByPolicy(operation, principal, resourcePolicy, resourceARN string, ct } // adminCaller reports whether the admin principal bypass applies. Trusted -// transports carry no action list, and an identified caller holds it only -// when the identity administers the operation's service — a principal that -// merely normalizes to the admin id does not bypass policy denies. +// transports carry no action list, while an identified caller always has one +// — possibly empty — and holds the bypass only when the identity administers +// the operation's service: a principal that merely normalizes to the admin +// id does not bypass policy denies. func adminCaller(operation string, ctx *PolicyContext) bool { - return ctx == nil || len(ctx.IdentityActions) == 0 || hasAdminActionFor(operation, ctx.IdentityActions) + return ctx == nil || ctx.IdentityActions == nil || hasAdminActionFor(operation, ctx.IdentityActions) } // matchesDenyStatement reports whether the JSON policy carries a statement diff --git a/weed/s3api/s3tables/permissions_test.go b/weed/s3api/s3tables/permissions_test.go index 84752afdf7..f2dabcda8e 100644 --- a/weed/s3api/s3tables/permissions_test.go +++ b/weed/s3api/s3tables/permissions_test.go @@ -323,6 +323,10 @@ func TestCheckPermissionAdminRequiresAdminAction(t *testing.T) { if !CheckPermissionWithContext("s3tables:DeleteTable", "admin", "admin", denyAll, arn, nil) { t.Error("a caller with no action list keeps the trusted bypass") } + empty := &PolicyContext{IdentityActions: []string{}} + if CheckPermissionWithContext("s3tables:DeleteTable", "admin", "admin", denyAll, arn, empty) { + t.Error("an identified admin with an empty action list must not bypass a deny") + } } func TestCheckTableOrBucketPermissionOwnerlessFailsClosed(t *testing.T) {