diff --git a/weed/s3api/s3api_tables.go b/weed/s3api/s3api_tables.go index 1a0f0a86f..3ab3d8f92 100644 --- a/weed/s3api/s3api_tables.go +++ b/weed/s3api/s3api_tables.go @@ -8,7 +8,6 @@ import ( "github.com/seaweedfs/seaweedfs/weed/glog" "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" - . "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/seaweedfs/seaweedfs/weed/s3api/s3tables" ) @@ -100,9 +99,9 @@ func (s3a *S3ApiServer) registerS3TablesRoutes(router *mux.Router) { // Register the S3 Tables handler router.Methods(http.MethodPost).Path("/").MatcherFunc(s3TablesMatcher). - HandlerFunc(track(s3a.iam.Auth(func(w http.ResponseWriter, r *http.Request) { + HandlerFunc(track(func(w http.ResponseWriter, r *http.Request) { s3TablesApi.S3TablesHandler(w, r) - }, ACTION_ADMIN), "S3Tables")) + }, "S3Tables")) glog.V(1).Infof("S3 Tables API enabled") } diff --git a/weed/s3api/s3tables/handler_bucket_get_list_delete.go b/weed/s3api/s3tables/handler_bucket_get_list_delete.go index 32e94ff54..9c677d0d7 100644 --- a/weed/s3api/s3tables/handler_bucket_get_list_delete.go +++ b/weed/s3api/s3tables/handler_bucket_get_list_delete.go @@ -48,7 +48,11 @@ func (h *S3TablesHandler) handleGetTableBucket(w http.ResponseWriter, r *http.Re }) if err != nil { - h.writeError(w, http.StatusNotFound, ErrCodeNoSuchBucket, fmt.Sprintf("table bucket %s not found", bucketName)) + if errors.Is(err, ErrNotFound) { + h.writeError(w, http.StatusNotFound, ErrCodeNoSuchBucket, fmt.Sprintf("table bucket %s not found", bucketName)) + } else { + h.writeError(w, http.StatusInternalServerError, ErrCodeInternalError, fmt.Sprintf("failed to get table bucket: %v", err)) + } return err } @@ -71,6 +75,13 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http. return err } + // Check permission + principal := h.getPrincipalFromRequest(r) + if !CanListTableBuckets(principal, h.accountID) { + h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to list table buckets") + return NewAuthError("ListTableBuckets", principal, "not authorized to list table buckets") + } + maxBuckets := req.MaxBuckets if maxBuckets <= 0 { maxBuckets = 100 diff --git a/weed/s3api/s3tables/handler_namespace.go b/weed/s3api/s3tables/handler_namespace.go index 1b3a01de4..077b7bbe1 100644 --- a/weed/s3api/s3tables/handler_namespace.go +++ b/weed/s3api/s3tables/handler_namespace.go @@ -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") diff --git a/weed/s3api/s3tables/permissions.go b/weed/s3api/s3tables/permissions.go index 47f9de374..5d3da336e 100644 --- a/weed/s3api/s3tables/permissions.go +++ b/weed/s3api/s3tables/permissions.go @@ -174,6 +174,9 @@ func ExtractPrincipalFromContext(contextID string) string { // Try to parse as ARN first if strings.HasPrefix(contextID, "arn:") { info := utils.ParsePrincipalARN(contextID) + if info.AccountID != "" { + return info.AccountID + } if info.RoleName != "" { return info.RoleName }