s3: enforce authentication and JSON error format for Iceberg REST Catalog (#8192)

* s3: enforce authentication and JSON error format for Iceberg REST Catalog

* s3/iceberg: align error exception types with OpenAPI spec examples

* s3api: refactor AuthenticateRequest to return identity object

* s3/iceberg: propagate full identity object to request context

* s3/iceberg: differentiate NotAuthorizedException and ForbiddenException

* s3/iceberg: reject requests if authenticator is nil to prevent auth bypass

* s3/iceberg: refactor Auth middleware to build context incrementally and use switch for error mapping

* s3api: update misleading comment for authRequestWithAuthType

* s3api: return ErrAccessDenied if IAM is not configured to prevent auth bypass

* s3/iceberg: optimize context update in Auth middleware

* s3api: export CanDo for external authorization use

* s3/iceberg: enforce identity-based authorization in all API handlers

* s3api: fix compilation errors by updating internal CanDo references

* s3/iceberg: robust identity validation and consistent action usage in handlers

* s3api: complete CanDo rename across tests and policy engine integration

* s3api: fix integration tests by allowing admin access when auth is disabled and explicit gRPC ports

* duckdb

* create test bucket
This commit is contained in:
Chris Lu
2026-02-03 11:55:12 -08:00
committed by GitHub
parent 746df25164
commit 1274cf038c
19 changed files with 335 additions and 130 deletions

View File

@@ -723,7 +723,7 @@ func TestListBucketsIssue7647(t *testing.T) {
assert.True(t, isVisible, "Admin user should see all buckets, even ones they don't own")
// Test permission check for List action
canList := rootIdentity.canDo(s3_constants.ACTION_LIST, "test", "")
canList := rootIdentity.CanDo(s3_constants.ACTION_LIST, "test", "")
assert.True(t, canList, "Root user with List action should be able to list buckets")
})
@@ -823,7 +823,7 @@ func TestListBucketsIssue7796(t *testing.T) {
assert.False(t, isOwner, "geoserver user should not be owner of bucket created by admin")
// Test permission check - should return true (has List:geoserver permission)
canList := geoserverIdentity.canDo(s3_constants.ACTION_LIST, "geoserver", "")
canList := geoserverIdentity.CanDo(s3_constants.ACTION_LIST, "geoserver", "")
assert.True(t, canList, "geoserver user with List:geoserver should be able to list geoserver bucket")
// Verify the combined visibility logic: ownership OR permission
@@ -856,7 +856,7 @@ func TestListBucketsIssue7796(t *testing.T) {
assert.False(t, isOwner, "No owner metadata means not owned")
// But has permission
canList := geoserverIdentity.canDo(s3_constants.ACTION_LIST, "geoserver", "")
canList := geoserverIdentity.CanDo(s3_constants.ACTION_LIST, "geoserver", "")
assert.True(t, canList, "Has explicit List:geoserver permission")
// Verify the combined visibility logic: ownership OR permission
@@ -891,7 +891,7 @@ func TestListBucketsIssue7796(t *testing.T) {
assert.False(t, isOwner, "geoserver doesn't own otherbucket")
// No permission for this bucket
canList := geoserverIdentity.canDo(s3_constants.ACTION_LIST, "otherbucket", "")
canList := geoserverIdentity.CanDo(s3_constants.ACTION_LIST, "otherbucket", "")
assert.False(t, canList, "geoserver has no List permission for otherbucket")
// Verify the combined visibility logic: ownership OR permission
@@ -939,8 +939,8 @@ func TestListBucketsIssue7796(t *testing.T) {
assert.False(t, isOwnerGeoTTL)
// But has permission via wildcard
canListGeo := geoIdentity.canDo(s3_constants.ACTION_LIST, "geoserver", "")
canListGeoTTL := geoIdentity.canDo(s3_constants.ACTION_LIST, "geoserver-ttl", "")
canListGeo := geoIdentity.CanDo(s3_constants.ACTION_LIST, "geoserver", "")
canListGeoTTL := geoIdentity.CanDo(s3_constants.ACTION_LIST, "geoserver-ttl", "")
assert.True(t, canListGeo)
assert.True(t, canListGeoTTL)
@@ -949,7 +949,7 @@ func TestListBucketsIssue7796(t *testing.T) {
assert.True(t, isOwnerGeoTTL || canListGeoTTL, "geoserver-ttl bucket should be visible via wildcard permission")
// Should NOT have permission for unrelated buckets
canListOther := geoIdentity.canDo(s3_constants.ACTION_LIST, "otherbucket", "")
canListOther := geoIdentity.CanDo(s3_constants.ACTION_LIST, "otherbucket", "")
assert.False(t, canListOther, "No permission for otherbucket")
assert.False(t, false || canListOther, "otherbucket should NOT be visible (no ownership, no permission)")
})
@@ -1020,7 +1020,7 @@ func TestListBucketsIssue7796(t *testing.T) {
// Skip permission check if user is already the owner (optimization)
if !isOwner {
// Check permission
hasPermission := geoserverIdentity.canDo(s3_constants.ACTION_LIST, entry.Name, "")
hasPermission := geoserverIdentity.CanDo(s3_constants.ACTION_LIST, entry.Name, "")
if !hasPermission {
continue
}