S3: list owned buckets (#7519)
* list owned buckets * simplify * add unit tests * no-owner buckets * set identity id * fallback to request header if iam is not enabled * refactor to test * fix comparing * fix security vulnerability * Update s3api_bucket_handlers.go * Update s3api_bucket_handlers.go * Update s3api_bucket_handlers.go
This commit is contained in:
@@ -59,11 +59,21 @@ func (s3a *S3ApiServer) ListBucketsHandler(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
identityId := r.Header.Get(s3_constants.AmzIdentityId)
|
||||
identityId := ""
|
||||
if identity != nil {
|
||||
identityId = identity.Name
|
||||
}
|
||||
// Note: For unauthenticated requests, identityId remains empty.
|
||||
// We never read from request headers to prevent reflecting unvalidated user input.
|
||||
|
||||
var listBuckets ListAllMyBucketsList
|
||||
for _, entry := range entries {
|
||||
if entry.IsDirectory {
|
||||
// Check ownership: only show buckets owned by this user (unless admin)
|
||||
if !isBucketVisibleToIdentity(entry, identity) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check permissions for each bucket
|
||||
if identity != nil {
|
||||
// For JWT-authenticated users, use IAM authorization
|
||||
@@ -99,6 +109,47 @@ func (s3a *S3ApiServer) ListBucketsHandler(w http.ResponseWriter, r *http.Reques
|
||||
writeSuccessResponseXML(w, r, response)
|
||||
}
|
||||
|
||||
// isBucketVisibleToIdentity checks if a bucket entry should be visible to the given identity
|
||||
// based on ownership rules. Returns true if the bucket should be visible, false otherwise.
|
||||
//
|
||||
// Visibility rules:
|
||||
// - Unauthenticated requests (identity == nil): no buckets visible
|
||||
// - Admin users: all buckets visible
|
||||
// - Non-admin users: only buckets they own (matching identity.Name) are visible
|
||||
// - Buckets without owner metadata are hidden from non-admin users
|
||||
func isBucketVisibleToIdentity(entry *filer_pb.Entry, identity *Identity) bool {
|
||||
if !entry.IsDirectory {
|
||||
return false
|
||||
}
|
||||
|
||||
// Unauthenticated users should not see any buckets (standard S3 behavior)
|
||||
if identity == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Admin users bypass ownership check
|
||||
if identity.isAdmin() {
|
||||
return true
|
||||
}
|
||||
|
||||
// Non-admin users with no name cannot own or see buckets.
|
||||
// This prevents misconfigured identities from matching buckets with empty owner IDs.
|
||||
if identity.Name == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Non-admin users: check ownership
|
||||
// Use the authenticated identity value directly (cannot be spoofed)
|
||||
id, ok := entry.Extended[s3_constants.AmzIdentityId]
|
||||
// Skip buckets that are not owned by the current user.
|
||||
// Buckets without an owner are also skipped.
|
||||
if !ok || string(id) != identity.Name {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s3a *S3ApiServer) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// collect parameters
|
||||
|
||||
Reference in New Issue
Block a user