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.44k stars 152 forks source link

Cloudfront + Web ACL with static assets public accessible #350

Open lucas-leme opened 1 year ago

lucas-leme commented 1 year ago

Hi! I am building an internal next js application and i want it to be accessible only for certain IPs.

The solution that i am applying is to attach a web acl on cloudfront. But even with web acl all files inside _next/static are public available. How can i make it private?

My module code:

module "tf_next" {
  source  = "milliHQ/next-js/aws"
  version = "0.13.2"

  vpc_security_group_ids = var.vpc_security_group_ids
  vpc_subnet_ids         = var.vpc_subnet_ids
  lambda_attach_to_vpc   = true

  create_image_optimization = false

  cloudfront_webacl_id   = var.web_acl_arn
  cloudfront_price_class = "PriceClass_All"

  providers = {
    aws.global_region = aws.global
  }
}
ofhouse commented 1 year ago

Hey,

difficult to say what went wrong here. It should be possible to build an IP-allowList with WebACL but have not tried it by myself.

Do you have the Web ACL configuration in Terraform available (for reproduction) as well?

lucas-leme commented 1 year ago

Here is my code. The vpc is only for data access (AWS RDS)

############## NEXT ###################

module "tf_next" {
  source  = "milliHQ/next-js/aws"
  version = "0.13.2"

  depends_on = [
    aws_waf_web_acl.waf_acl
  ]

  deployment_name = "interface"

  vpc_security_group_ids = var.vpc_security_group_ids
  vpc_subnet_ids         = var.vpc_subnet_ids
  lambda_attach_to_vpc   = true

  create_image_optimization = false

  cloudfront_webacl_id   = aws_waf_web_acl.waf_acl.id
  cloudfront_price_class = "PriceClass_All"

  providers = {
    aws.global_region = aws.global
  }
}

output "cloudfront_domain_name" {
  value = module.tf_next.cloudfront_domain_name
}

############# WAF #####################
resource "aws_waf_ipset" "ipset" {
  name = "tfIPSet"

  ip_set_descriptors {
    type  = "IPV4"
    value = var.ip
  }
}

resource "aws_waf_rule" "rule" {
  depends_on  = [aws_waf_ipset.ipset]
  name        = "tfWAFRule"
  metric_name = "tfWAFRule"

  predicates {
    data_id = aws_waf_ipset.ipset.id
    negated = false
    type    = "IPMatch"
  }

}

resource "aws_waf_web_acl" "waf_acl" {
  depends_on = [
    aws_waf_ipset.ipset,
    aws_waf_rule.rule,
  ]
  name        = "tfWebACL"
  metric_name = "tfWebACL"

  default_action {
    type = "BLOCK"
  }

  rules {
    action {
      type = "ALLOW"
    }

    priority = 1
    rule_id  = aws_waf_rule.rule.id
    type     = "REGULAR"
  }

}
dgokcin commented 1 year ago

@lucas-leme how did this go? I am also looking for a solution to secure the deployed resources with this module.(we were using cloudflare waf in all of our other applications, can't found a way to use it here)