milliHQ / terraform-aws-next-js

Terraform module for building and deploying Next.js apps to AWS. Supports SSR (Lambda), Static (S3) and API (Lambda) pages.
https://registry.terraform.io/modules/milliHQ/next-js/aws
Apache License 2.0
1.46k stars 152 forks source link

Support for Passing Custom S3 Bucket Resources #224

Open curtis-trynow-io opened 2 years ago

curtis-trynow-io commented 2 years ago

This would resolve https://github.com/milliHQ/terraform-aws-next-js/issues/216 trivially.

I am proposing that just like how you can (and must) create your own aws_cloudfront_distribution and pass it into:

cloudfront_external_id = aws_cloudfront_distribution.something.id
cloudfront_external_arn = aws_cloudfront_distribution.something.arn

for the tf_next module, you also allow passing aws_s3_bucket resources to be used for static_upload and static_deploy inside tf_next/modules/statics-deploy/main.tf.

My use case is that I need to be able to serve assets from my NextJS app on occasion which requires CORS headers. I can override the origin access policy in the CloudFront resource, but I cannot set anything for cors_rule inside those S3 buckets. By doing so, Terraform plans to remove those rules every time:

  # module.tf_next.module.statics_deploy.aws_s3_bucket.static_deploy will be updated in-place
  ~ resource "aws_s3_bucket" "static_deploy" {                                      
        id                          = "next-tf-static-deploy<redacted>"
        tags                        = {}                                              
        # (11 unchanged attributes hidden)

      - cors_rule {  
          - allowed_headers = [] -> null
          - allowed_methods = [                                                                                                                                             
              - "GET",
              - "HEAD",                                                                                                                                                     
            ] -> null
          - allowed_origins = [
              - "*",
            ] -> null
          - expose_headers  = [] -> null
          - max_age_seconds = 0 -> null
        }

        # (2 unchanged blocks hidden)
    }

If we can wire up the buckets ourselves and pass them into the child module, that would allow any S3 customization a user could want (CORS, public access restriction, lifecycle rules, uploads, paid metrics, etc). This would be just the buckets themselves and nothing deeper like the aws_s3_bucket_policy that gets created.

ofhouse commented 2 years ago

Yep, had the same idea after reading through #126 👍

What is currently blocking is that the static_deploy S3 bucket also requires that a policy is added which grants CloudFront access to it (CloudFront origin access identity). I plan to remove origin access identity completely from the module with the addition of custom response headers in #9.

Adding support for custom response headers would also resolve your cors issue, but I still think that it would be a nice addition when external S3 buckets could be added.