s3tables: update bucket handlers for multi-account support

Ensured bucket ownership is correctly attributed to the authenticated
account ID and updated ARNs to use the request-derived account ID. Added
standard S3 existence checks for bucket deletion.
This commit is contained in:
Chris Lu
2026-01-28 13:25:27 -08:00
parent 31867b6f75
commit 922b0c3171
2 changed files with 18 additions and 11 deletions

View File

@@ -78,7 +78,7 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
metadata := &tableBucketMetadata{ metadata := &tableBucketMetadata{
Name: req.Name, Name: req.Name,
CreatedAt: now, CreatedAt: now,
OwnerID: h.accountID, OwnerID: h.getAccountID(r),
} }
metadataBytes, err := json.Marshal(metadata) metadataBytes, err := json.Marshal(metadata)
@@ -90,8 +90,10 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
err = filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error { err = filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
// Ensure root tables directory exists // Ensure root tables directory exists
if !h.entryExists(r.Context(), client, TablesPath) {
if err := h.createDirectory(r.Context(), client, TablesPath); err != nil { if err := h.createDirectory(r.Context(), client, TablesPath); err != nil {
return fmt.Errorf("failed to ensure root tables directory: %w", err) return fmt.Errorf("failed to create root tables directory: %w", err)
}
} }
// Create bucket directory // Create bucket directory
@@ -125,7 +127,7 @@ func (h *S3TablesHandler) handleCreateTableBucket(w http.ResponseWriter, r *http
} }
resp := &CreateTableBucketResponse{ resp := &CreateTableBucketResponse{
ARN: h.generateTableBucketARN(req.Name), ARN: h.generateTableBucketARN(r, req.Name),
} }
h.writeJSON(w, http.StatusOK, resp) h.writeJSON(w, http.StatusOK, resp)

View File

@@ -15,7 +15,8 @@ import (
func (h *S3TablesHandler) handleGetTableBucket(w http.ResponseWriter, r *http.Request, filerClient FilerClient) error { func (h *S3TablesHandler) handleGetTableBucket(w http.ResponseWriter, r *http.Request, filerClient FilerClient) error {
// Check permission // Check permission
principal := h.getPrincipalFromRequest(r) principal := h.getPrincipalFromRequest(r)
if !CanGetTableBucket(principal, h.accountID) { accountID := h.getAccountID(r)
if !CanGetTableBucket(principal, accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get table bucket details") h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get table bucket details")
return NewAuthError("GetTableBucket", principal, "not authorized to get table bucket details") return NewAuthError("GetTableBucket", principal, "not authorized to get table bucket details")
} }
@@ -58,7 +59,7 @@ func (h *S3TablesHandler) handleGetTableBucket(w http.ResponseWriter, r *http.Re
} }
resp := &GetTableBucketResponse{ resp := &GetTableBucketResponse{
ARN: h.generateTableBucketARN(bucketName), ARN: h.generateTableBucketARN(r, bucketName),
Name: metadata.Name, Name: metadata.Name,
OwnerAccountID: metadata.OwnerID, OwnerAccountID: metadata.OwnerID,
CreatedAt: metadata.CreatedAt, CreatedAt: metadata.CreatedAt,
@@ -78,7 +79,8 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http.
// Check permission // Check permission
principal := h.getPrincipalFromRequest(r) principal := h.getPrincipalFromRequest(r)
if !CanListTableBuckets(principal, h.accountID) { accountID := h.getAccountID(r)
if !CanListTableBuckets(principal, accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to list table buckets") h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to list table buckets")
return NewAuthError("ListTableBuckets", principal, "not authorized to list table buckets") return NewAuthError("ListTableBuckets", principal, "not authorized to list table buckets")
} }
@@ -150,7 +152,7 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http.
} }
buckets = append(buckets, TableBucketSummary{ buckets = append(buckets, TableBucketSummary{
ARN: h.generateTableBucketARN(entry.Entry.Name), ARN: h.generateTableBucketARN(r, entry.Entry.Name),
Name: entry.Entry.Name, Name: entry.Entry.Name,
CreatedAt: metadata.CreatedAt, CreatedAt: metadata.CreatedAt,
}) })
@@ -197,7 +199,8 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http.
func (h *S3TablesHandler) handleDeleteTableBucket(w http.ResponseWriter, r *http.Request, filerClient FilerClient) error { func (h *S3TablesHandler) handleDeleteTableBucket(w http.ResponseWriter, r *http.Request, filerClient FilerClient) error {
// Check permission // Check permission
principal := h.getPrincipalFromRequest(r) principal := h.getPrincipalFromRequest(r)
if !CanDeleteTableBucket(principal, h.accountID) { accountID := h.getAccountID(r)
if !CanDeleteTableBucket(principal, accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete table buckets") h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete table buckets")
return NewAuthError("DeleteTableBucket", principal, "not authorized to delete table buckets") return NewAuthError("DeleteTableBucket", principal, "not authorized to delete table buckets")
} }
@@ -250,10 +253,12 @@ func (h *S3TablesHandler) handleDeleteTableBucket(w http.ResponseWriter, r *http
}) })
if err != nil { if err != nil {
if !errors.Is(err, filer_pb.ErrNotFound) { if errors.Is(err, filer_pb.ErrNotFound) {
h.writeError(w, http.StatusInternalServerError, ErrCodeInternalError, fmt.Sprintf("failed to list bucket entries: %v", err)) h.writeError(w, http.StatusNotFound, ErrCodeNoSuchBucket, fmt.Sprintf("table bucket %s not found", bucketName))
return err return err
} }
h.writeError(w, http.StatusInternalServerError, ErrCodeInternalError, fmt.Sprintf("failed to list bucket entries: %v", err))
return err
} }
if hasChildren { if hasChildren {