Browse Source

cache bucket policy

pull/7471/head
chrislu 2 months ago
parent
commit
2da5460c1c
  1. 15
      weed/s3api/auth_credentials_subscribe.go
  2. 15
      weed/s3api/s3api_bucket_config.go
  3. 25
      weed/s3api/s3api_bucket_handlers.go

15
weed/s3api/auth_credentials_subscribe.go

@ -1,11 +1,13 @@
package s3api package s3api
import ( import (
"encoding/json"
"errors" "errors"
"time" "time"
"github.com/seaweedfs/seaweedfs/weed/filer" "github.com/seaweedfs/seaweedfs/weed/filer"
"github.com/seaweedfs/seaweedfs/weed/glog" "github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/iam/policy"
"github.com/seaweedfs/seaweedfs/weed/pb" "github.com/seaweedfs/seaweedfs/weed/pb"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
@ -145,6 +147,19 @@ func (s3a *S3ApiServer) updateBucketConfigCacheFromEntry(entry *filer_pb.Entry)
} else { } else {
glog.V(3).Infof("updateBucketConfigCacheFromEntry: no Object Lock configuration found for bucket %s", bucket) glog.V(3).Infof("updateBucketConfigCacheFromEntry: no Object Lock configuration found for bucket %s", bucket)
} }
// Parse bucket policy if present (for performance optimization)
if policyJSON, exists := entry.Extended[BUCKET_POLICY_METADATA_KEY]; exists && len(policyJSON) > 0 {
var policyDoc policy.PolicyDocument
if err := json.Unmarshal(policyJSON, &policyDoc); err != nil {
glog.Errorf("updateBucketConfigCacheFromEntry: failed to parse bucket policy for %s: %v", bucket, err)
} else {
config.BucketPolicy = &policyDoc
glog.V(2).Infof("updateBucketConfigCacheFromEntry: cached bucket policy for bucket %s", bucket)
}
} else {
glog.V(4).Infof("updateBucketConfigCacheFromEntry: no bucket policy found for bucket %s", bucket)
}
} }
// Load CORS configuration from bucket directory content // Load CORS configuration from bucket directory content

15
weed/s3api/s3api_bucket_config.go

@ -14,6 +14,7 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"github.com/seaweedfs/seaweedfs/weed/glog" "github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/iam/policy"
"github.com/seaweedfs/seaweedfs/weed/kms" "github.com/seaweedfs/seaweedfs/weed/kms"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/pb/s3_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 IsPublicRead bool // Cached flag to avoid JSON parsing on every request
CORS *cors.CORSConfiguration CORS *cors.CORSConfiguration
ObjectLockConfig *ObjectLockConfiguration // Cached parsed Object Lock configuration 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 KMSKeyCache *BucketKMSCache // Per-bucket KMS key cache for SSE-KMS operations
LastModified time.Time LastModified time.Time
Entry *filer_pb.Entry Entry *filer_pb.Entry
@ -376,6 +378,19 @@ func (s3a *S3ApiServer) getBucketConfig(bucket string) (*BucketConfig, s3err.Err
} else { } else {
glog.V(3).Infof("getBucketConfig: no Object Lock config found in extended attributes for bucket %s", bucket) glog.V(3).Infof("getBucketConfig: no Object Lock config found in extended attributes for bucket %s", bucket)
} }
// Parse bucket policy if present (for performance optimization)
if policyJSON, exists := entry.Extended[BUCKET_POLICY_METADATA_KEY]; exists && len(policyJSON) > 0 {
var policyDoc policy.PolicyDocument
if err := json.Unmarshal(policyJSON, &policyDoc); err != nil {
glog.Errorf("getBucketConfig: failed to parse bucket policy for %s: %v", bucket, err)
} else {
config.BucketPolicy = &policyDoc
glog.V(3).Infof("getBucketConfig: loaded bucket policy from extended attributes for bucket %s", bucket)
}
} else {
glog.V(4).Infof("getBucketConfig: no bucket policy found for bucket %s", bucket)
}
} }
// Load CORS configuration from bucket directory content // Load CORS configuration from bucket directory content

25
weed/s3api/s3api_bucket_handlers.go

@ -581,25 +581,32 @@ func isPublicReadGrants(grants []*s3.Grant) bool {
// isBucketPolicyAllowed checks if a bucket policy allows anonymous access for the given action and resource // isBucketPolicyAllowed checks if a bucket policy allows anonymous access for the given action and resource
func (s3a *S3ApiServer) isBucketPolicyAllowed(bucket, object string, action Action) bool { func (s3a *S3ApiServer) isBucketPolicyAllowed(bucket, object string, action Action) bool {
// Get bucket policy
policyDoc, err := s3a.getBucketPolicy(bucket)
if err != nil {
// No bucket policy or error retrieving it
glog.V(4).Infof("isBucketPolicyAllowed: no bucket policy for %s: %v", bucket, err)
// Get cached bucket config which includes the policy
config, errCode := s3a.getBucketConfig(bucket)
if errCode != s3err.ErrNone {
glog.V(4).Infof("isBucketPolicyAllowed: failed to get bucket config for %s: %v", bucket, errCode)
return false return false
} }
// Check if bucket has a policy
if config.BucketPolicy == nil {
glog.V(4).Infof("isBucketPolicyAllowed: no bucket policy for %s", bucket)
return false
}
policyDoc := config.BucketPolicy
// Convert action to S3 action format // Convert action to S3 action format
s3Action := actionToS3Action(action) s3Action := actionToS3Action(action)
// Build resource ARN // Build resource ARN
resource := buildResourceARN(bucket, object) resource := buildResourceARN(bucket, object)
glog.V(4).Infof("isBucketPolicyAllowed: evaluating bucket=%s, resource=%s, action=%s", bucket, resource, s3Action)
glog.V(4).Infof("isBucketPolicyAllowed: evaluating bucket=%s, resource=%s, action=%s (cached policy)", bucket, resource, s3Action)
// Evaluate policy using AWS policy evaluation logic: // Evaluate policy using AWS policy evaluation logic:
// 1. Check for explicit Deny - if found, return false // 1. Check for explicit Deny - if found, return false
// 2. Check for explicit Allow - if found, return true
// 2. Check for explicit Allow - if found, return true
// 3. If no explicit Allow is found, return false (default deny) // 3. If no explicit Allow is found, return false (default deny)
hasExplicitAllow := false hasExplicitAllow := false

Loading…
Cancel
Save