aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/s3api_bucket_config.go
diff options
context:
space:
mode:
authorChris Lu <chrislusf@users.noreply.github.com>2025-11-12 22:14:50 -0800
committerGitHub <noreply@github.com>2025-11-12 22:14:50 -0800
commit508d06d9a5c763668ba149a8f1182e8552505c2b (patch)
treea34d21d801d2b71dc3c6968cbb4ff8568e0fa8da /weed/s3api/s3api_bucket_config.go
parent50f067bcfd99ecf1821ba2d34fc2f109e90428bb (diff)
downloadseaweedfs-508d06d9a5c763668ba149a8f1182e8552505c2b.tar.xz
seaweedfs-508d06d9a5c763668ba149a8f1182e8552505c2b.zip
S3: Enforce bucket policy (#7471)
* evaluate policies during authorization * cache bucket policy * refactor * matching with regex special characters * Case Sensitivity, pattern cache, Dead Code Removal * Fixed Typo, Restored []string Case, Added Cache Size Limit * hook up with policy engine * remove old implementation * action mapping * validate * if not specified, fall through to IAM checks * fmt * Fail-close on policy evaluation errors * Explicit `Allow` bypasses IAM checks * fix error message * arn:seaweed => arn:aws * remove legacy support * fix tests * Clean up bucket policy after this test * fix for tests * address comments * security fixes * fix tests * temp comment out
Diffstat (limited to 'weed/s3api/s3api_bucket_config.go')
-rw-r--r--weed/s3api/s3api_bucket_config.go30
1 files changed, 30 insertions, 0 deletions
diff --git a/weed/s3api/s3api_bucket_config.go b/weed/s3api/s3api_bucket_config.go
index 128b17c06..c71069d08 100644
--- a/weed/s3api/s3api_bucket_config.go
+++ b/weed/s3api/s3api_bucket_config.go
@@ -14,6 +14,7 @@ import (
"google.golang.org/protobuf/proto"
"github.com/seaweedfs/seaweedfs/weed/glog"
+ "github.com/seaweedfs/seaweedfs/weed/iam/policy"
"github.com/seaweedfs/seaweedfs/weed/kms"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/pb/s3_pb"
@@ -32,6 +33,7 @@ type BucketConfig struct {
IsPublicRead bool // Cached flag to avoid JSON parsing on every request
CORS *cors.CORSConfiguration
ObjectLockConfig *ObjectLockConfiguration // Cached parsed Object Lock configuration
+ BucketPolicy *policy.PolicyDocument // Cached bucket policy for performance
KMSKeyCache *BucketKMSCache // Per-bucket KMS key cache for SSE-KMS operations
LastModified time.Time
Entry *filer_pb.Entry
@@ -318,6 +320,28 @@ func (bcc *BucketConfigCache) RemoveNegativeCache(bucket string) {
delete(bcc.negativeCache, bucket)
}
+// loadBucketPolicyFromExtended loads and parses bucket policy from entry extended attributes
+func loadBucketPolicyFromExtended(entry *filer_pb.Entry, bucket string) *policy.PolicyDocument {
+ if entry.Extended == nil {
+ return nil
+ }
+
+ policyJSON, exists := entry.Extended[BUCKET_POLICY_METADATA_KEY]
+ if !exists || len(policyJSON) == 0 {
+ glog.V(4).Infof("loadBucketPolicyFromExtended: no bucket policy found for bucket %s", bucket)
+ return nil
+ }
+
+ var policyDoc policy.PolicyDocument
+ if err := json.Unmarshal(policyJSON, &policyDoc); err != nil {
+ glog.Errorf("loadBucketPolicyFromExtended: failed to parse bucket policy for %s: %v", bucket, err)
+ return nil
+ }
+
+ glog.V(3).Infof("loadBucketPolicyFromExtended: loaded bucket policy for bucket %s", bucket)
+ return &policyDoc
+}
+
// getBucketConfig retrieves bucket configuration with caching
func (s3a *S3ApiServer) getBucketConfig(bucket string) (*BucketConfig, s3err.ErrorCode) {
// Check negative cache first
@@ -376,8 +400,14 @@ func (s3a *S3ApiServer) getBucketConfig(bucket string) (*BucketConfig, s3err.Err
} else {
glog.V(3).Infof("getBucketConfig: no Object Lock config found in extended attributes for bucket %s", bucket)
}
+
+ // Load bucket policy if present (for performance optimization)
+ config.BucketPolicy = loadBucketPolicyFromExtended(entry, bucket)
}
+ // Sync bucket policy to the policy engine for evaluation
+ s3a.syncBucketPolicyToEngine(bucket, config.BucketPolicy)
+
// Load CORS configuration from bucket directory content
if corsConfig, err := s3a.loadCORSFromBucketContent(bucket); err != nil {
if errors.Is(err, filer_pb.ErrNotFound) {