s3tables: Fetch bucket policy in handleListTagsForResource for permission evaluation
Update handleListTagsForResource to fetch and pass bucket policy to CheckPermission, matching the behavior of handleTagResource/handleUntagResource. This enables bucket-policy-based permission grants to be evaluated for ListTagsForResource, not just ownership-based checks.
This commit is contained in:
@@ -59,7 +59,7 @@ func (h *S3TablesHandler) handlePutTableBucketPolicy(w http.ResponseWriter, r *h
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanPutTableBucketPolicy(principal, bucketMetadata.OwnerAccountID, "") {
|
if !CanPutTableBucketPolicy(principal, bucketMetadata.OwnerAccountID, "") {
|
||||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to put table bucket policy")
|
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to put table bucket policy")
|
||||||
return NewAuthError("PutTableBucketPolicy", principal, "not authorized to put table bucket policy")
|
return NewAuthError("PutTableBucketPolicy", principal, "not authorized to put table bucket policy")
|
||||||
@@ -132,7 +132,7 @@ func (h *S3TablesHandler) handleGetTableBucketPolicy(w http.ResponseWriter, r *h
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanGetTableBucketPolicy(principal, bucketMetadata.OwnerAccountID, string(policy)) {
|
if !CanGetTableBucketPolicy(principal, bucketMetadata.OwnerAccountID, string(policy)) {
|
||||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get table bucket policy")
|
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get table bucket policy")
|
||||||
return NewAuthError("GetTableBucketPolicy", principal, "not authorized to get table bucket policy")
|
return NewAuthError("GetTableBucketPolicy", principal, "not authorized to get table bucket policy")
|
||||||
@@ -198,7 +198,7 @@ func (h *S3TablesHandler) handleDeleteTableBucketPolicy(w http.ResponseWriter, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanDeleteTableBucketPolicy(principal, bucketMetadata.OwnerAccountID, bucketPolicy) {
|
if !CanDeleteTableBucketPolicy(principal, bucketMetadata.OwnerAccountID, bucketPolicy) {
|
||||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete table bucket policy")
|
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete table bucket policy")
|
||||||
return NewAuthError("DeleteTableBucketPolicy", principal, "not authorized to delete table bucket policy")
|
return NewAuthError("DeleteTableBucketPolicy", principal, "not authorized to delete table bucket policy")
|
||||||
@@ -287,7 +287,7 @@ func (h *S3TablesHandler) handlePutTablePolicy(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanPutTablePolicy(principal, metadata.OwnerAccountID, bucketPolicy) {
|
if !CanPutTablePolicy(principal, metadata.OwnerAccountID, bucketPolicy) {
|
||||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to put table policy")
|
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to put table policy")
|
||||||
return NewAuthError("PutTablePolicy", principal, "not authorized to put table policy")
|
return NewAuthError("PutTablePolicy", principal, "not authorized to put table policy")
|
||||||
@@ -383,7 +383,7 @@ func (h *S3TablesHandler) handleGetTablePolicy(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanGetTablePolicy(principal, metadata.OwnerAccountID, bucketPolicy) {
|
if !CanGetTablePolicy(principal, metadata.OwnerAccountID, bucketPolicy) {
|
||||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get table policy")
|
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to get table policy")
|
||||||
return NewAuthError("GetTablePolicy", principal, "not authorized to get table policy")
|
return NewAuthError("GetTablePolicy", principal, "not authorized to get table policy")
|
||||||
@@ -461,7 +461,7 @@ func (h *S3TablesHandler) handleDeleteTablePolicy(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanDeleteTablePolicy(principal, metadata.OwnerAccountID, bucketPolicy) {
|
if !CanDeleteTablePolicy(principal, metadata.OwnerAccountID, bucketPolicy) {
|
||||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete table policy")
|
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to delete table policy")
|
||||||
return NewAuthError("DeleteTablePolicy", principal, "not authorized to delete table policy")
|
return NewAuthError("DeleteTablePolicy", principal, "not authorized to delete table policy")
|
||||||
@@ -553,7 +553,7 @@ func (h *S3TablesHandler) handleTagResource(w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check Permission inside the closure because we just got the ID
|
// Check Permission inside the closure because we just got the ID
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanManageTags(principal, ownerAccountID, bucketPolicy) {
|
if !CanManageTags(principal, ownerAccountID, bucketPolicy) {
|
||||||
return NewAuthError("TagResource", principal, "not authorized to tag resource")
|
return NewAuthError("TagResource", principal, "not authorized to tag resource")
|
||||||
}
|
}
|
||||||
@@ -629,6 +629,7 @@ func (h *S3TablesHandler) handleListTagsForResource(w http.ResponseWriter, r *ht
|
|||||||
}
|
}
|
||||||
|
|
||||||
tags := make(map[string]string)
|
tags := make(map[string]string)
|
||||||
|
var bucketPolicy string
|
||||||
err = filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
|
err = filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
|
||||||
// Read metadata for ownership check
|
// Read metadata for ownership check
|
||||||
data, err := h.getExtendedAttribute(r.Context(), client, resourcePath, ExtendedKeyMetadata)
|
data, err := h.getExtendedAttribute(r.Context(), client, resourcePath, ExtendedKeyMetadata)
|
||||||
@@ -637,23 +638,45 @@ func (h *S3TablesHandler) handleListTagsForResource(w http.ResponseWriter, r *ht
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ownerAccountID string
|
var ownerAccountID string
|
||||||
|
var bucketName string
|
||||||
if rType == ResourceTypeTable {
|
if rType == ResourceTypeTable {
|
||||||
var meta tableMetadataInternal
|
var meta tableMetadataInternal
|
||||||
if err := json.Unmarshal(data, &meta); err != nil {
|
if err := json.Unmarshal(data, &meta); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ownerAccountID = meta.OwnerAccountID
|
ownerAccountID = meta.OwnerAccountID
|
||||||
|
// Extract bucket name from resource path for tables
|
||||||
|
// resourcePath format: /tables/{bucket}/{namespace}/{table}
|
||||||
|
parts := strings.Split(strings.Trim(resourcePath, "/"), "/")
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
bucketName = parts[1]
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var meta tableBucketMetadata
|
var meta tableBucketMetadata
|
||||||
if err := json.Unmarshal(data, &meta); err != nil {
|
if err := json.Unmarshal(data, &meta); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ownerAccountID = meta.OwnerAccountID
|
ownerAccountID = meta.OwnerAccountID
|
||||||
|
// Extract bucket name from resource path for buckets
|
||||||
|
// resourcePath format: /tables/{bucket}
|
||||||
|
parts := strings.Split(strings.Trim(resourcePath, "/"), "/")
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
bucketName = parts[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch bucket policy if we have a bucket name
|
||||||
|
if bucketName != "" {
|
||||||
|
bucketPath := getTableBucketPath(bucketName)
|
||||||
|
policyData, err := h.getExtendedAttribute(r.Context(), client, bucketPath, ExtendedKeyPolicy)
|
||||||
|
if err == nil {
|
||||||
|
bucketPolicy = string(policyData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Permission
|
// Check Permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CheckPermission("ListTagsForResource", principal, ownerAccountID, "") {
|
if !CheckPermission("ListTagsForResource", principal, ownerAccountID, bucketPolicy) {
|
||||||
return NewAuthError("ListTagsForResource", principal, "not authorized to list tags for resource")
|
return NewAuthError("ListTagsForResource", principal, "not authorized to list tags for resource")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,7 +783,7 @@ func (h *S3TablesHandler) handleUntagResource(w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check Permission
|
// Check Permission
|
||||||
principal := h.getPrincipalFromRequest(r)
|
principal := h.getAccountID(r)
|
||||||
if !CanManageTags(principal, ownerAccountID, bucketPolicy) {
|
if !CanManageTags(principal, ownerAccountID, bucketPolicy) {
|
||||||
return NewAuthError("UntagResource", principal, "not authorized to untag resource")
|
return NewAuthError("UntagResource", principal, "not authorized to untag resource")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user