Skip to content

feat: add cross-cloud CORS configuration for buckets#914

Open
tom-groves wants to merge 2 commits intonitrictech:mainfrom
airesolve:feat/bucket-cors
Open

feat: add cross-cloud CORS configuration for buckets#914
tom-groves wants to merge 2 commits intonitrictech:mainfrom
airesolve:feat/bucket-cors

Conversation

@tom-groves
Copy link
Copy Markdown

Description

Add CORS rule support to the Bucket deployment spec, with full implementations across all three cloud providers (AWS, GCP, Azure) and both deployment paths (Pulumi, Terraform CDK).

This enables users to configure CORS rules on storage buckets as part of their Nitric deployment, with appropriate cross-cloud behavior:

  • AWS: Full CORS support via BucketCorsConfigurationV2 (Pulumi) / aws_s3_bucket_cors_configuration (Terraform)
  • GCP: Full CORS support via bucket cors block. AllowedHeaders is not supported by GCS (it auto-allows all request headers) — a warning is emitted when specified.
  • Azure: Returns a deployment error — Azure Blob Storage does not support per-container CORS. CORS must be configured at the Storage Account level.

Changes

Proto:

  • Add BucketCorsRule message with allowed_origins, allowed_methods, allowed_headers, expose_headers, and max_age_seconds fields
  • Add repeated BucketCorsRule cors_rules field to Bucket message

AWS (Pulumi + Terraform CDK):

  • Pulumi: creates s3.BucketCorsConfigurationV2 resource when CORS rules present
  • Terraform: adds cors_rules variable and aws_s3_bucket_cors_configuration resource to HCL module

GCP (Pulumi + Terraform CDK):

  • Pulumi: sets BucketCorArray on bucket args
  • Terraform: adds cors_rules variable and dynamic "cors" block on google_storage_bucket
  • Both paths warn when AllowedHeaders is specified (GCS does not support it)

Azure (Pulumi + Terraform CDK):

  • Both paths return an error when CORS rules are configured

Documentation:

  • Added CORS section to main storage guide (docs/docs/storage.mdx)
  • Updated AWS, GCP, and Azure provider mapping docs with CORS details and limitations

Design decisions

  • MaxAgeSeconds only emitted when > 0 in Pulumi providers to avoid overriding cloud defaults. Always sent in TF wrappers to satisfy HCL variable type requirements.
  • GCP AllowedHeaders is a warning, not an error, because GCS behavior is a superset (allows all headers).
  • Azure is an error, not a warning, because CORS would be silently non-functional.
  • SDK changes (TypeScript, Python, etc.) are in separate repos and not included in this PR.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Testing

Build verification

All 6 deployment targets compile cleanly:

  • cloud/awsgo build ./deploy/... and go build ./deploytf/...
  • cloud/gcpgo build ./deploy/... and go build ./deploytf/...
  • cloud/azurego build ./deploy/... and go build ./deploytf/...

Terraform module validation

  • terraform validate passes for AWS bucket module (aws_s3_bucket_cors_configuration) ✓
  • terraform validate passes for GCP bucket module (google_storage_bucket cors block) ✓

Pulumi mock tests (6 new tests — first deploy-level tests in this codebase)

AWS (3 tests):

  • TestBucket_WithCorsRules_CreatesS3CorsConfiguration — verifies BucketCorsConfigurationV2 resource created with correct field values (origins, methods, headers, expose headers, max age) ✓
  • TestBucket_WithoutCorsRules_NoCorsConfiguration — verifies no CORS resource when rules absent ✓
  • TestBucket_MultipleCorsRules — verifies single CORS config resource containing multiple rules ✓

GCP (3 tests):

  • TestBucket_WithCorsRules_SetsCorsOnBucket — verifies cors property set on bucket with correct field values (origins, methods, responseHeaders, maxAge) ✓
  • TestBucket_WithoutCorsRules_NoCorsOnBucket — verifies no cors property when rules absent ✓
  • TestBucket_MultipleCorsRules — verifies 2 CORS rules on bucket ✓

Regression

  • All existing test suites pass (cloud/aws, cloud/gcp, cloud/azure, core, cloud/common) ✓
  • Pre-existing cmd/ failures in GCP/Azure (missing embedded runtime binary) are unrelated to this change

Add CORS rule support to the Bucket deployment spec, with implementations
across all providers (AWS, GCP, Azure) and both deployment paths (Pulumi,
Terraform CDK).

- Proto: add BucketCorsRule message with origins, methods, headers,
  expose headers, and max age fields
- AWS: creates S3 BucketCorsConfigurationV2 (Pulumi) /
  aws_s3_bucket_cors_configuration (TF)
- GCP: sets cors block on storage bucket; warns that AllowedHeaders
  is not supported by GCS (auto-allows all request headers)
- Azure: returns error — per-container CORS not supported, must be
  configured at the Storage Account level
- MaxAgeSeconds only emitted when > 0 to avoid overriding provider
  defaults (Pulumi path); always sent in TF path to satisfy HCL
  variable type requirements
Document CORS support in the main storage guide, including the
per-provider behavior differences and limitations. Update AWS,
GCP, and Azure provider mapping docs with CORS-specific details.
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 16, 2026

@tom-groves is attempting to deploy a commit to the Nitric Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant