sec(iac): Lambda Function URL auth hardening -- CORS wildcard rejection + AWS_IAM OAC scaffolding (#390, #424)#574
Conversation
|
Warning Review limit reached
Your plan currently allows 2 reviews/hour. Refill in 25 minutes and 37 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
…aform validation (CR nit)
…424) Switch the lambda module's function_url_auth_type default from "NONE" to "AWS_IAM" and add the full infrastructure needed to enforce IAM-gated access via CloudFront OAC: - lambda module: new aws_lambda_permission.function_url_cloudfront resource grants cloudfront.amazonaws.com lambda:InvokeFunctionUrl scoped to a specific distribution ARN (source_arn). Created only when auth_type = "AWS_IAM" and cloudfront_distribution_arn is provided; no-op otherwise. - lambda module: new cloudfront_distribution_arn variable (default "") and updated function_url_auth_type description + validation block. - frontend module: new aws_cloudfront_origin_access_control.lambda resource (type=lambda, sigv4, always-sign) created when enable_oac = true. OAC id wired into the origin block alongside the existing custom_origin_config. - frontend module: new enable_oac variable (bool, default false). - environments/aws/compute.tf: pass cloudfront_distribution_arn to lambda module (length() guard prevents plan errors when enable_cdn = false). - environments/aws/frontend.tf: set enable_oac when platform = lambda + AWS_IAM. - All three env tfvars: keep lambda_function_url_auth_type = "NONE" (unchanged) and add a TODO(#424) comment with the 3-step cut-over instructions. The deployed environments retain their current "NONE" value until CloudFront is enabled per the follow-up issue. Flipping to AWS_IAM without a CloudFront OAC in place would make the Function URL return HTTP 403 on all requests. The frontend client.ts already uses X-Authorization (preserves the Authorization header for CloudFront OAC SigV4) and addContentHashHeader (x-amz-content-sha256 required for POST/PUT/PATCH/DELETE through OAC) -- no frontend changes needed. Verified: terraform fmt -check passes on all touched modules and the environment. Manual verification of the auth path required after CloudFront is deployed.
ca51ba6 to
fc37407
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
…refs #424) Remove the standalone lambda_function_url_auth_type variable and derive its value via a local in compute.tf: local.lambda_function_url_auth_type = var.enable_cdn ? "AWS_IAM" : "NONE" The two valid combinations were the only sensible ones anyway: enable_cdn = false -> auth_type = "NONE" SPA hits the Function URL directly; browsers cannot SigV4-sign, so the URL must be unauthenticated at the AWS-IAM layer; auth is enforced at the application layer (login session, CSRF, API keys). enable_cdn = true -> auth_type = "AWS_IAM" CloudFront fronts the URL with an OAC that SigV4-signs every request (aws_cloudfront_origin_access_control.lambda in the frontend module). The Function URL rejects anything not signed by CloudFront's OAC. Tying the two flags together prevents the two failure modes the previous "two variables operator must keep in sync" design exposed: (a) enable_cdn = true with auth_type = "NONE" -> public Lambda URL behind a pointless CloudFront (security goal of #424 defeated). (b) enable_cdn = false with auth_type = "AWS_IAM" -> direct browser hits to Function URL return 403 (no way to sign), site is unreachable. Updated three usages (compute.tf Lambda module call, the standalone aws_lambda_permission.function_url_cloudfront resource count, and frontend.tf enable_oac derivation) to use the local / enable_cdn directly. Removed the lambda_function_url_auth_type lines from all three env tfvars (github-dev/staging/prod) plus the two profile example tfvars and the top-level dev.tfvars.example; replaced the TODO(#424) cut-over comments with a short explanation of the enable_cdn -> auth_type mapping. Verified: terraform validate clean, terraform fmt clean. Refs #424
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Summary
allowed_originsvia module validation; replace["*"]in all envs with explicit origins. The Function URL usesallow_credentials = true-- a wildcard origin reflects any inboundOriginheader with credentials allowed, enabling any-origin CSRF.function_url_auth_typemodule default from"NONE"to"AWS_IAM". Addaws_cloudfront_origin_access_control(type=lambda, sigv4, always-sign) to the frontend module. Add a standaloneaws_lambda_permissionat the environment layer (breaks the cycle: Lambda URL is CloudFront's origin; distribution ARN feeds the permission -- they can't both live inside a single module). All three env tfvars keep"NONE"with aTODO(#424)cut-over comment untilenable_cdn = trueis set and CloudFront is deployed.The frontend
client.tswas already OAC-ready: it usesX-Authorization(preserves theAuthorizationheader for CloudFront SigV4 signing) andaddContentHashHeader(x-amz-content-sha256required for POST/PUT/PATCH/DELETE through OAC).Files changed
terraform/modules/compute/aws/lambda/variables.tffunction_url_auth_typeto"AWS_IAM"; add validation; expand descriptionterraform/modules/frontend/aws/main.tfaws_cloudfront_origin_access_control.lambda; wireorigin_access_control_idterraform/modules/frontend/aws/variables.tfenable_oacvariableterraform/environments/aws/compute.tfaws_lambda_permission.function_url_cloudfront(cycle-free)terraform/environments/aws/frontend.tfenable_oacwhen platform=lambda + auth_type=AWS_IAMterraform/environments/aws/github-{dev,staging,prod}.tfvarsTODO(#424)cut-over comments; no functional change to valuesTest plan
terraform fmt -checkpasses on all changed modules and environments (verified pre-commit hook)terraform validatepasses (pre-commit hook)terraform planwithallowed_origins = ["*"]fails with the validation error (regression test from sec(auth): CORS wildcard origin + credentials=true on staging Lambda URL #390)terraform planwithenable_cdn = true+lambda_function_url_auth_type = "AWS_IAM"showsaws_cloudfront_origin_access_control.lambda+aws_lambda_permission.function_url_cloudfrontbeing createdManual verification note
The runtime cut-over (flipping deployed envs to
AWS_IAM) requires a follow-up deploy. See theTODO(#424)comments in each tfvar for the 3-step procedure. A follow-up issue will be filed to track this.Closes
Closes #390
Partially addresses #424 (infrastructure scaffolding complete; runtime cut-over tracked separately)