s3: support s3:x-amz-server-side-encryption policy condition (#8806)

* s3: support s3:x-amz-server-side-encryption policy condition (#7680)

- Normalize x-amz-server-side-encryption header values to canonical form
  (aes256 → AES256, aws:kms mixed-case → aws:kms) so StringEquals
  conditions work regardless of client capitalisation
- Exempt UploadPart and UploadPartCopy from SSE Null conditions: these
  actions inherit SSE from the initial CreateMultipartUpload request and
  do not re-send the header, so Deny/Null("true") should not block them
- Add sse_condition_test.go covering StringEquals, Null, case-insensitive
  normalisation, and multipart continuation action exemption

* s3: address review comments on SSE condition support

- Replace "inherited" sentinel in injectSSEForMultipart with "AES256" so
  that StringEquals/Null conditions evaluate against a meaningful value;
  add TODO noting that KMS multipart uploads need the actual algorithm
  looked up from the upload state
- Rewrite TestSSECaseInsensitiveNormalization to drive normalisation
  through EvaluatePolicyForRequest with a real *http.Request so regressions
  in the production code path are caught; split into AES256 and aws:kms
  variants to cover both normalisation branches

* s3: plumb real inherited SSE from multipart upload state into policy eval

Instead of injecting a static "AES256" sentinel for UploadPart/UploadPartCopy,
look up the actual SSE algorithm from the stored CreateMultipartUpload entry
and pass it through the evaluation chain.

Changes:
- PolicyEvaluationArgs gains InheritedSSEAlgorithm string; set by the
  BucketPolicyEngine wrapper for multipart continuation actions
- injectSSEForMultipart(conditions, inheritedSSE) now accepts the real
  algorithm; empty string means no SSE → Null("true") fires correctly
- IsMultipartContinuationAction exported so the s3api wrapper can use it
- BucketPolicyEngine gets a MultipartSSELookup callback (set by S3ApiServer)
  that fetches the upload entry and reads SeaweedFSSSEKMSKeyID /
  SeaweedFSSSES3Encryption to determine the algorithm
- S3ApiServer.getMultipartSSEAlgorithm implements the lookup via getEntry
- Tests updated: three multipart cases (AES256, aws:kms, no-SSE-must-deny)
  plus UploadPartCopy coverage
This commit is contained in:
Chris Lu
2026-03-27 23:15:01 -07:00
committed by GitHub
parent e3f052cd84
commit 7d5cbfd547
6 changed files with 354 additions and 1 deletions

View File

@@ -213,6 +213,11 @@ func NewS3ApiServerWithStore(router *mux.Router, option *S3ApiServerOption, expl
// This avoids circular dependency by not passing the entire S3ApiServer
iam.policyEngine = policyEngine
// Give the policy engine a way to look up the SSE algorithm that was
// stored at CreateMultipartUpload time, so that UploadPart/UploadPartCopy
// policy conditions on s3:x-amz-server-side-encryption evaluate correctly.
policyEngine.MultipartSSELookup = s3ApiServer.getMultipartSSEAlgorithm
// Initialize advanced IAM system if config is provided or explicitly enabled
if option.IamConfig != "" || option.EnableIam {
configSource := "defaults"