mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-22 06:22:38 +00:00
s3tables: authorize CreateNamespace before revealing a missing bucket
A bucket that is absent or not a table bucket used to answer 404 before the permission check ran, while a denied existing bucket answered 403. An unauthorized caller now gets the same denial unless it may learn the name is absent (admin, trusted handler, identity grant).
This commit is contained in:
@@ -459,6 +459,20 @@ func isAuthError(err error) bool {
|
||||
return errors.As(err, &authErr) || errors.Is(err, ErrAccessDenied)
|
||||
}
|
||||
|
||||
// mayLearnAbsence reports whether the caller may be shown that an operation's
|
||||
// target is absent rather than the operation's denial: the admin, a trusted
|
||||
// handler, or a grant the request itself carries (an identity-level action
|
||||
// grant, or the open default-allow context).
|
||||
func (h *S3TablesHandler) mayLearnAbsence(r *http.Request, operation, bucketName string) bool {
|
||||
if h.getAccountID(r) == s3_constants.AccountAdminId || h.defaultAllowFor(r) {
|
||||
return true
|
||||
}
|
||||
return hasIdentityPermission(operation, &PolicyContext{
|
||||
TableBucketName: bucketName,
|
||||
IdentityActions: getIdentityActions(r),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *S3TablesHandler) readTags(ctx context.Context, client filer_pb.SeaweedFilerClient, path string) (map[string]string, error) {
|
||||
data, err := h.getExtendedAttribute(ctx, client, path, ExtendedKeyTags)
|
||||
if err != nil {
|
||||
|
||||
@@ -140,6 +140,12 @@ func (h *S3TablesHandler) handleCreateNamespace(w http.ResponseWriter, r *http.R
|
||||
return ErrAccessDenied
|
||||
}
|
||||
if errors.Is(err, filer_pb.ErrNotFound) {
|
||||
// An absent name and a denied one must read alike; the caller is
|
||||
// told the bucket is missing only when it may learn that.
|
||||
if !h.mayLearnAbsence(r, "CreateNamespace", bucketName) {
|
||||
h.writeError(w, http.StatusForbidden, ErrCodeAccessDenied, "not authorized to create namespace in this bucket")
|
||||
return ErrAccessDenied
|
||||
}
|
||||
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 check table bucket: %v", err))
|
||||
|
||||
Reference in New Issue
Block a user