s3tables: implement granular authorization and refine error responses

- Remove mandatory ACTION_ADMIN at the router level
- Enforce granular permissions in bucket and namespace handlers
- Prioritize AccountID in ExtractPrincipalFromContext for ARN matching
- Distinguish between 404 (NoSuchBucket) and 500 (InternalError) in metadata lookups
- Clean up unused imports in s3api_tables.go
This commit is contained in:
Chris Lu
2026-01-28 11:31:38 -08:00
parent 580c2b4ad4
commit 04514071a7
4 changed files with 45 additions and 4 deletions

View File

@@ -19,6 +19,13 @@ func (h *S3TablesHandler) handleCreateNamespace(w http.ResponseWriter, r *http.R
return err
}
// Check permission
principal := h.getPrincipalFromRequest(r)
if !CanCreateNamespace(principal, h.accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to create namespace")
return NewAuthError("CreateNamespace", principal, "not authorized to create namespace")
}
if req.TableBucketARN == "" {
h.writeError(w, http.StatusBadRequest, ErrCodeInvalidRequest, "tableBucketARN is required")
return fmt.Errorf("tableBucketARN is required")
@@ -120,6 +127,13 @@ func (h *S3TablesHandler) handleGetNamespace(w http.ResponseWriter, r *http.Requ
return err
}
// Check permission
principal := h.getPrincipalFromRequest(r)
if !CanGetNamespace(principal, h.accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get namespace details")
return NewAuthError("GetNamespace", principal, "not authorized to get namespace details")
}
if req.TableBucketARN == "" {
h.writeError(w, http.StatusBadRequest, ErrCodeInvalidRequest, "tableBucketARN is required")
return fmt.Errorf("tableBucketARN is required")
@@ -172,6 +186,13 @@ func (h *S3TablesHandler) handleListNamespaces(w http.ResponseWriter, r *http.Re
return err
}
// Check permission
principal := h.getPrincipalFromRequest(r)
if !CanListNamespaces(principal, h.accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to list namespaces")
return NewAuthError("ListNamespaces", principal, "not authorized to list namespaces")
}
if req.TableBucketARN == "" {
h.writeError(w, http.StatusBadRequest, ErrCodeInvalidRequest, "tableBucketARN is required")
return fmt.Errorf("tableBucketARN is required")
@@ -276,6 +297,13 @@ func (h *S3TablesHandler) handleDeleteNamespace(w http.ResponseWriter, r *http.R
return err
}
// Check permission
principal := h.getPrincipalFromRequest(r)
if !CanDeleteNamespace(principal, h.accountID) {
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete namespace")
return NewAuthError("DeleteNamespace", principal, "not authorized to delete namespace")
}
if req.TableBucketARN == "" {
h.writeError(w, http.StatusBadRequest, ErrCodeInvalidRequest, "tableBucketARN is required")
return fmt.Errorf("tableBucketARN is required")