feat: per-bucket CORS configuration (S3 ?cors) with enforcement - #71
feat: per-bucket CORS configuration (S3 ?cors) with enforcement#71h5vx wants to merge 6 commits into
Conversation
Signed-off-by: h5vx <h5v@protonmail.com>
Signed-off-by: h5vx <h5v@protonmail.com>
Signed-off-by: h5vx <h5v@protonmail.com>
Signed-off-by: h5vx <h5v@protonmail.com>
…T, e2e test) Signed-off-by: h5vx <h5v@protonmail.com>
Reformat cors_test.go per gofumpt and regenerate the rebrand-guard compatibility baseline to record the per-bucket CORS feature's new exported symbols (internal/bucket/cors types and BucketMetadata/ BucketMetadataSys additions). Signed-off-by: h5vx <h5v@protonmail.com>
|
Hi @Vonng! Recently, I found out that per-bucket CORS policies are not available in the MinIO Community Edition, but are provided in the paid MinIO AIStor. I need this feature, so I decided to implement it in Silo. Could you please let me know if there are any licensing, ideological, or technical concerns that could prevent this PR from being accepted? Right now, I also don't fully understand what the rebrand-guard is intended to protect against. If there is a chance that this PR could be merged, I'm also planning to add bucket-level CORS policy settings to the Silo Console UI. |
There was a problem hiding this comment.
Thank you for contributing this. Per-bucket CORS addresses a real S3 compatibility gap and is useful for browser clients that need bucket-specific policies.
I took another pass focused strictly on functional behavior and verified the PR against current main. The core single-site implementation works end to end with a standard minio-go client:
- PUT, GET, and DELETE the bucket CORS configuration
- accept a matching preflight and reject a non-matching origin
- apply the configured CORS headers to an actual object response
- retain the existing global fallback for buckets without a configuration
The overall implementation approach is sound: standard ?cors APIs, bucket-metadata persistence, and per-bucket evaluation ahead of the existing global fallback. Local build, targeted normal/race tests, lint, and generated-file checks all pass. GitHub does not currently report PR CI checks, so CI remains a separate merge gate.
I see one material integration item to finish before merge:
- Site replication sends
SRBucketMetaTypeCorsConfig, but the peer receive/apply path and the initial sync/heal/status paths do not yet carry the new CORS metadata. This can leave CORS configuration different between replicated sites even though the originating request succeeds. Please complete those paths and add focused tests. Alternatively, if site-replicated deployments are intentionally outside this PR's scope, please state that limitation clearly and avoid claiming site-replication parity.
A few protocol-hardening items can be handled here or as focused follow-ups: validate the supplied Content-MD5/checksum using the existing request helper, tighten wildcard and ID validation to the S3 constraints, and complete cache-variation headers for preflight responses. These do not change my positive assessment of the main feature.
Once the site-replication scope is resolved and CI is green, I would be happy to re-review. The Console UI can remain a separate follow-up.
Contribution Licensing (no CLA, inbound=outbound, DCO required)
This project does not use a CLA; contributions are accepted inbound=outbound.
By submitting this pull request I represent that I have the right to contribute
the changes, which are licensed under this repository's
GNU Affero General Public License v3.0 or later
and remain my copyright. Every commit must carry a DCO
Signed-off-bytrailer(
git commit -s) certifying theDeveloper Certificate of Origin — see
CONTRIBUTING.md.
Description
Implements S3-compatible per-bucket CORS. Clients manage a bucket's CORS
configuration through the standard
?corssubresource (PUT/GET/DELETE), andthe server enforces it on requests (OPTIONS preflight and
Access-Control-*response headers on actual requests).
internal/bucket/corspackage: the<CORSConfiguration>XML type,validation (≤100 rules, methods restricted to GET/PUT/HEAD/POST/DELETE,
non-empty origins/methods, non-negative
MaxAgeSeconds), and origin/method/header matching (single-
*wildcard, first-match, and preflightfall-through so a restrictive earlier rule does not shadow a later match).
CorsConfigXML/CorsConfigUpdatedAtadded toBucketMetadata(msgp regenerated), persisted as
cors.xml, cached inBucketMetadataSyswith
GetCorsConfig/GetCorsConfigXMLgetters.cmd/bucket-cors-handlers.goreplace the previousNotImplemented/stub handlers; the stalecorsentry is removed fromrejectedBucketAPIs.corsHandlermiddleware: a bucket with a stored configgoverns its own requests (no matching rule ⇒ no CORS headers / 403 on
preflight, per S3 semantics); buckets without a config keep today's global
rs/corsbehavior unchanged.Compatible with standard S3 tooling (aws-cli, boto3, the ansible
community.aws.s3_corsmodule).Motivation and Context
The
?corsroutes and policy actions (GetBucketCorsAction,PutBucketCorsAction,DeleteBucketCorsAction) already existed, but thehandlers were stubs returning
NotImplemented, and CORS could only beconfigured globally via
cors_allow_origin. This adds real per-bucket CORSso browser clients can be scoped per bucket, matching AWS S3 behavior.
How to test this PR?
Unit / package tests:
Manual smoke test with boto3:
Compatibility impact
stubs returning NotImplemented). Buckets with no CORS config behave exactly
as before (global rs/cors fallback). No client changes required.
CorsConfigUpdatedAt, persisted as the cors.xml per-bucket config file.
The msgp map header grows accordingly. Additive and backward-compatible:
older metadata decodes with empty CORS fields; a server without this change
ignores the extra cors.xml. Rollback-safe (no CORS enforcement, config
file left dormant on disk).
interoperability): error code NoSuchCORSConfiguration; policy actions
s3:GetBucketCors / PutBucketCors / DeleteBucketCors; the ?cors
subresource; x-amz-* request/response headers; the github.com/minio/*
import paths. New exported symbols are recorded in the rebrand-guard
compatibility baseline (buildscripts/rebrand-guard/compat-baseline.json).
(SRBucketMetaTypeCorsConfig) for parity with other per-bucket configs.
Types of changes
Checklist:
git commit -s) per the DCOcommit-idorPR #here)make verifierspassesmake buildpasspgsty/silo.pgsty.com, if needed