From 902e1f0158ce894918a794eabb1d0e801f231852 Mon Sep 17 00:00:00 2001 From: Hector Machin <38859646+hectormachin@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:13:23 -0400 Subject: [PATCH] Consolidate WAF rules into a single one by default for FilmDrop endpoints (#76) --- CHANGELOG.md | 4 ++ README.md | 1 + ci.tfvars | 12 +++++- default.tfvars | 12 +++++- filmdrop.tf | 4 ++ inputs.tf | 34 ++++++++++++++- .../apigw_endpoint/api_gateway_endpoint.tf | 1 - .../cloudfront/custom_origin/custom_origin.tf | 12 +----- modules/cloudfront/custom_origin/inputs.tf | 18 -------- modules/cloudfront/lb_endpoint/input.tf | 5 +++ .../lb_endpoint/load_balancer_endpoint.tf | 1 + modules/cloudfront/s3_origin/inputs.tf | 18 -------- modules/cloudfront/s3_origin/s3_origin.tf | 13 +----- modules/cloudfront/s3_website/input.tf | 6 +++ modules/cloudfront/s3_website/s3_website.tf | 2 +- modules/cloudfront/waf/data.tf | 4 +- modules/cloudfront/waf/inputs.tf | 22 +++++++--- modules/cloudfront/waf/logging.tf | 2 +- profiles/analytics/inputs.tf | 8 ++++ profiles/analytics/main.tf | 1 + profiles/base/inputs.tf | 24 +++++++++++ profiles/base/main.tf | 11 +++++ profiles/base/outputs.tf | 5 +++ profiles/cirrus-dashboard/inputs.tf | 9 ++++ profiles/cirrus-dashboard/main.tf | 1 + profiles/console-ui/inputs.tf | 12 +++++- profiles/console-ui/main.tf | 1 + profiles/core/inputs.tf | 43 ++++++++++++++++--- profiles/core/main.tf | 8 ++++ profiles/stac-server/inputs.tf | 14 ++++-- profiles/stac-server/main.tf | 2 +- 31 files changed, 224 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4505af1c..046900d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Builtin lambdas added to cirrus module along with script to update deployment zip - API Gateway infrastructure for Cirrus API +### Changed + +- Consolidated WAF rules into a single one by default for cost savings + ## 2.27.0 - 2024-05-31 ### Changed diff --git a/README.md b/README.md index 96f9f636..fe75f618 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,7 @@ deploy_titiler = false deploy_console_ui = false deploy_cirrus_dashboard = false deploy_local_stac_server_artifacts = false +deploy_waf_rule = false ``` ```shell diff --git a/ci.tfvars b/ci.tfvars index 7a9d0fb0..9df66b24 100644 --- a/ci.tfvars +++ b/ci.tfvars @@ -24,6 +24,7 @@ stac_server_inputs = { app_name = "stac_server" version = "v3.8.0" deploy_cloudfront = false + web_acl_id = "" domain_alias = "" enable_transactions_extension = false collection_to_index_mappings = "" @@ -40,7 +41,6 @@ stac_server_inputs = { cors_methods = "" cors_headers = "" authorized_s3_arns = [] - web_acl_id = "" auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -94,6 +94,7 @@ analytics_inputs = { jupyterhub_elb_acm_cert_arn = "" jupyterhub_elb_domain_alias = "" create_credentials = true + web_acl_id = "" auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -123,6 +124,7 @@ console_ui_inputs = { app_name = "console" domain_alias = "" deploy_cloudfront = false + web_acl_id = "" version = "v5.3.0" filmdrop_ui_config_file = "./profiles/console-ui/default-config/config.dev.json" filmdrop_ui_logo_file = "./profiles/console-ui/default-config/logo.png" @@ -186,6 +188,7 @@ cirrus_dashboard_inputs = { app_name = "dashboard" domain_alias = "" deploy_cloudfront = false + web_acl_id = "" version = "v0.5.1" custom_error_response = [ { @@ -225,3 +228,10 @@ deploy_console_ui = true deploy_cirrus = true deploy_cirrus_dashboard = true deploy_local_stac_server_artifacts = false +deploy_waf_rule = true + + +#### WAF Rule Settings +ext_web_acl_id = "" # Specify if bringing an externally managed WAF +ip_blocklist = [] +whitelist_ips = [] diff --git a/default.tfvars b/default.tfvars index 362091d8..ef4cf5dc 100644 --- a/default.tfvars +++ b/default.tfvars @@ -26,6 +26,7 @@ stac_server_inputs = { app_name = "stac_server" version = "v3.8.0" deploy_cloudfront = true + web_acl_id = "" domain_alias = "" enable_transactions_extension = false collection_to_index_mappings = "" @@ -42,7 +43,6 @@ stac_server_inputs = { cors_methods = "" cors_headers = "" authorized_s3_arns = [] - web_acl_id = "" auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -96,6 +96,7 @@ analytics_inputs = { jupyterhub_elb_acm_cert_arn = "" jupyterhub_elb_domain_alias = "" create_credentials = true + web_acl_id = "" auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -125,6 +126,7 @@ console_ui_inputs = { app_name = "console" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" version = "v5.3.0" filmdrop_ui_config_file = "./profiles/console-ui/default-config/config.dev.json" filmdrop_ui_logo_file = "./profiles/console-ui/default-config/logo.png" @@ -190,6 +192,7 @@ cirrus_dashboard_inputs = { app_name = "dashboard" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" version = "v0.5.1" cirrus_api_endpoint = "" metrics_api_endpoint = "" @@ -229,3 +232,10 @@ deploy_console_ui = true deploy_cirrus = true deploy_cirrus_dashboard = true deploy_local_stac_server_artifacts = false +deploy_waf_rule = true + + +#### WAF Rule Settings +ext_web_acl_id = "" # Specify if bringing an externally managed WAF +ip_blocklist = [] +whitelist_ips = [] diff --git a/filmdrop.tf b/filmdrop.tf index d08d04e9..28c01779 100644 --- a/filmdrop.tf +++ b/filmdrop.tf @@ -40,4 +40,8 @@ module "filmdrop" { deploy_cirrus = var.deploy_cirrus deploy_cirrus_dashboard = var.deploy_cirrus_dashboard deploy_local_stac_server_artifacts = var.deploy_local_stac_server_artifacts + deploy_waf_rule = var.deploy_waf_rule + ext_web_acl_id = var.ext_web_acl_id + ip_blocklist = var.ip_blocklist + whitelist_ips = var.whitelist_ips } diff --git a/inputs.tf b/inputs.tf index 54e2db63..6b96f40b 100644 --- a/inputs.tf +++ b/inputs.tf @@ -94,6 +94,7 @@ variable "stac_server_inputs" { app_name = string version = string deploy_cloudfront = bool + web_acl_id = string domain_alias = string enable_transactions_extension = bool collection_to_index_mappings = string @@ -110,7 +111,6 @@ variable "stac_server_inputs" { cors_methods = string cors_headers = string authorized_s3_arns = list(string) - web_acl_id = string auth_function = object({ cf_function_name = string cf_function_runtime = string @@ -139,6 +139,7 @@ variable "stac_server_inputs" { app_name = "stac_server" version = "v3.8.0" deploy_cloudfront = true + web_acl_id = "" domain_alias = "" enable_transactions_extension = false collection_to_index_mappings = "" @@ -155,7 +156,6 @@ variable "stac_server_inputs" { cors_methods = "" cors_headers = "" authorized_s3_arns = [] - web_acl_id = "" auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -233,6 +233,7 @@ variable "analytics_inputs" { type = object({ app_name = string domain_alias = string + web_acl_id = string jupyterhub_elb_acm_cert_arn = string jupyterhub_elb_domain_alias = string create_credentials = bool @@ -261,6 +262,7 @@ variable "analytics_inputs" { default = { app_name = "analytics" domain_alias = "" + web_acl_id = "" jupyterhub_elb_acm_cert_arn = "" jupyterhub_elb_domain_alias = "" create_credentials = true @@ -294,6 +296,7 @@ variable "console_ui_inputs" { app_name = string domain_alias = string deploy_cloudfront = bool + web_acl_id = string custom_error_response = list(object({ error_caching_min_ttl = string error_code = string @@ -319,6 +322,7 @@ variable "console_ui_inputs" { app_name = "console" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" custom_error_response = [ { error_caching_min_ttl = "10" @@ -422,6 +426,7 @@ variable "cirrus_dashboard_inputs" { app_name = string domain_alias = string deploy_cloudfront = bool + web_acl_id = string version = string cirrus_api_endpoint = string metrics_api_endpoint = string @@ -446,6 +451,7 @@ variable "cirrus_dashboard_inputs" { app_name = "dashboard" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" version = "v0.5.1" cirrus_api_endpoint = "" metrics_api_endpoint = "" @@ -548,3 +554,27 @@ variable "deploy_local_stac_server_artifacts" { type = bool default = true } + +variable "deploy_waf_rule" { + description = "Deploy FilmDrop WAF rule" + type = bool + default = true +} + +variable "ip_blocklist" { + description = "List of ip cidr ranges to block access to. " + type = set(string) + default = [] +} + +variable "whitelist_ips" { + description = "List of ips to filter access for." + type = set(string) + default = [] +} + +variable "ext_web_acl_id" { + description = "The id of the external WAF resource to attach to the FilmDrop CloudFront Endpoints." + type = string + default = "" +} diff --git a/modules/cloudfront/apigw_endpoint/api_gateway_endpoint.tf b/modules/cloudfront/apigw_endpoint/api_gateway_endpoint.tf index 270ba4a9..424278a9 100644 --- a/modules/cloudfront/apigw_endpoint/api_gateway_endpoint.tf +++ b/modules/cloudfront/apigw_endpoint/api_gateway_endpoint.tf @@ -29,7 +29,6 @@ module "cloudfront_distribution" { default_ttl = var.default_ttl max_ttl = var.max_ttl custom_error_response = var.custom_error_response - create_waf_rule = var.web_acl_id == "" ? true : false web_acl_id = var.web_acl_id project_name = var.project_name environment = var.environment diff --git a/modules/cloudfront/custom_origin/custom_origin.tf b/modules/cloudfront/custom_origin/custom_origin.tf index bf94a548..6476c8ac 100644 --- a/modules/cloudfront/custom_origin/custom_origin.tf +++ b/modules/cloudfront/custom_origin/custom_origin.tf @@ -74,7 +74,7 @@ resource "aws_cloudfront_distribution" "filmdrop_managed_cloudfront_distribution enabled = var.enabled is_ipv6_enabled = var.ipv6_enabled default_root_object = var.default_root - web_acl_id = var.create_waf_rule == false ? var.web_acl_id : module.cloudfront_waf[0].web_acl_id + web_acl_id = var.web_acl_id logging_config { include_cookies = var.log_cookies @@ -155,16 +155,6 @@ resource "aws_cloudfront_distribution" "filmdrop_managed_cloudfront_distribution ] } -module "cloudfront_waf" { - count = var.create_waf_rule == false ? 0 : 1 - source = "../waf" - - logging_bucket_name = var.create_log_bucket ? aws_s3_bucket.log_bucket[0].id : var.log_bucket_name - whitelist_ips = var.whitelist_ips - ip_blocklist = var.ip_blocklist - cf_origin_appendix = replace(replace(local.origin_id_prefix, "_", ""), "-", "") -} - resource "aws_ssm_parameter" "cloudfront_custom_origin" { name = "${local.origin_id_prefix}-origin" type = "String" diff --git a/modules/cloudfront/custom_origin/inputs.tf b/modules/cloudfront/custom_origin/inputs.tf index 925d071a..a08a6fa0 100644 --- a/modules/cloudfront/custom_origin/inputs.tf +++ b/modules/cloudfront/custom_origin/inputs.tf @@ -142,24 +142,6 @@ variable "price_class" { default = "PriceClass_100" } -variable "create_waf_rule" { - description = "Create WAF for cloudfront" - type = string - default = true -} - -variable "ip_blocklist" { - description = "List of ip cidr ranges to block access to. " - type = set(string) - default = [] -} - -variable "whitelist_ips" { - description = "List of ips to filter access for." - type = set(string) - default = [] -} - variable "cf_function_name" { description = "Name of the CF function" type = string diff --git a/modules/cloudfront/lb_endpoint/input.tf b/modules/cloudfront/lb_endpoint/input.tf index 946c7816..1074abc6 100644 --- a/modules/cloudfront/lb_endpoint/input.tf +++ b/modules/cloudfront/lb_endpoint/input.tf @@ -49,6 +49,11 @@ variable "load_balancer_dns_name" { type = string } +variable "web_acl_id" { + description = "The id of the WAF resource to attach to the CloudFront endpoint." + type = string + default = "" +} variable "min_ttl" { description = "Minimum amount of time, in seconds, that you want objects to stay in the CloudFront cache before CloudFront sends another request to the origin to determine whether the object has been updated." diff --git a/modules/cloudfront/lb_endpoint/load_balancer_endpoint.tf b/modules/cloudfront/lb_endpoint/load_balancer_endpoint.tf index 2158efe0..ebbfdbe1 100644 --- a/modules/cloudfront/lb_endpoint/load_balancer_endpoint.tf +++ b/modules/cloudfront/lb_endpoint/load_balancer_endpoint.tf @@ -29,6 +29,7 @@ module "cloudfront_distribution" { default_ttl = var.default_ttl max_ttl = var.max_ttl custom_error_response = var.custom_error_response + web_acl_id = var.web_acl_id project_name = var.project_name environment = var.environment create_log_bucket = var.create_log_bucket diff --git a/modules/cloudfront/s3_origin/inputs.tf b/modules/cloudfront/s3_origin/inputs.tf index f83419df..4a05ebaa 100644 --- a/modules/cloudfront/s3_origin/inputs.tf +++ b/modules/cloudfront/s3_origin/inputs.tf @@ -94,30 +94,12 @@ variable "create_content_website" { default = true } -variable "create_waf_rule" { - description = "Create WAF for cloudfront" - type = bool - default = true -} - variable "price_class" { description = "CloudFront Price Class." type = string default = "PriceClass_100" } -variable "ip_blocklist" { - description = "List of ip cidr ranges to block access to. " - type = set(string) - default = [] -} - -variable "whitelist_ips" { - description = "List of ips to filter access for." - type = set(string) - default = [] -} - variable "cf_function_name" { description = "Name of the CF function" type = string diff --git a/modules/cloudfront/s3_origin/s3_origin.tf b/modules/cloudfront/s3_origin/s3_origin.tf index 16908502..7bf37825 100644 --- a/modules/cloudfront/s3_origin/s3_origin.tf +++ b/modules/cloudfront/s3_origin/s3_origin.tf @@ -48,7 +48,7 @@ resource "aws_cloudfront_distribution" "filmdrop_managed_cloudfront_distribution enabled = var.enabled is_ipv6_enabled = var.ipv6_enabled default_root_object = var.default_root - web_acl_id = var.create_waf_rule == false ? var.web_acl_id : module.cloudfront_waf[0].web_acl_id + web_acl_id = var.web_acl_id logging_config { include_cookies = var.log_cookies @@ -147,17 +147,6 @@ module "content_website" { origin_id = local.origin_id_prefix } - -module "cloudfront_waf" { - count = var.create_waf_rule == false ? 0 : 1 - source = "../waf" - - logging_bucket_name = var.create_log_bucket ? aws_s3_bucket.log_bucket[0].id : var.log_bucket_name - whitelist_ips = var.whitelist_ips - ip_blocklist = var.ip_blocklist - cf_origin_appendix = replace(replace(local.origin_id_prefix, "_", ""), "-", "") -} - module "cloudfront_function" { count = var.create_cf_function == true && var.create_cf_basicauth_function == false ? 1 : 0 source = "../cf_function" diff --git a/modules/cloudfront/s3_website/input.tf b/modules/cloudfront/s3_website/input.tf index 79487653..22189a61 100644 --- a/modules/cloudfront/s3_website/input.tf +++ b/modules/cloudfront/s3_website/input.tf @@ -20,6 +20,12 @@ variable "min_ttl" { default = 0 } +variable "web_acl_id" { + description = "The id of the WAF resource to attach to the CloudFront endpoint." + type = string + default = "" +} + variable "default_ttl" { description = "Default amount of time, in seconds, that you want objects to stay in CloudFront caches before CloudFront forwards another request to your origin to determine whether the object has been updated" type = number diff --git a/modules/cloudfront/s3_website/s3_website.tf b/modules/cloudfront/s3_website/s3_website.tf index 344e2334..feb6bfb2 100644 --- a/modules/cloudfront/s3_website/s3_website.tf +++ b/modules/cloudfront/s3_website/s3_website.tf @@ -19,7 +19,6 @@ module "cloudfront_distribution" { source = "../s3_origin" create_content_website = var.create_content_website - create_waf_rule = true ssl_certificate_arn = module.cloudfront_certificate.certificate_arn domain_aliases = var.domain_alias == "" ? [] : [var.domain_alias] min_ttl = var.min_ttl @@ -27,6 +26,7 @@ module "cloudfront_distribution" { max_ttl = var.max_ttl domain_name = var.domain_name custom_error_response = var.custom_error_response + web_acl_id = var.web_acl_id cf_function_name = var.cf_function_name cf_function_runtime = var.cf_function_runtime cf_function_code_path = var.cf_function_code_path diff --git a/modules/cloudfront/waf/data.tf b/modules/cloudfront/waf/data.tf index e51afbcf..872119c5 100644 --- a/modules/cloudfront/waf/data.tf +++ b/modules/cloudfront/waf/data.tf @@ -3,5 +3,5 @@ data "aws_caller_identity" "current" { } locals { - origin_appendix = lower(substr(var.cf_origin_appendix, 0, 18)) -} + origin_appendix = lower(substr(replace(replace("fd-${var.project_name}-${var.environment}", "-", ""), "_", ""), 0, 18)) +} \ No newline at end of file diff --git a/modules/cloudfront/waf/inputs.tf b/modules/cloudfront/waf/inputs.tf index 590a32cb..91e0da59 100644 --- a/modules/cloudfront/waf/inputs.tf +++ b/modules/cloudfront/waf/inputs.tf @@ -1,8 +1,3 @@ -variable "cf_origin_appendix" { - description = "Unique CloudFront Orign appendix for the WAF. Required if the account needs more than one WAF." - type = string -} - variable "logging_bucket_name" { description = "Name for bucket used for cloudfront logging" type = string @@ -32,3 +27,20 @@ variable "whitelist_ips" { default = [] } +variable "environment" { + description = "Project environment." + type = string + validation { + condition = length(var.environment) <= 10 + error_message = "The environment value must be 10 or fewer characters." + } +} + +variable "project_name" { + description = "Project Name" + type = string + validation { + condition = length(var.project_name) <= 10 + error_message = "The project_name value must be a 10 or fewer characters." + } +} diff --git a/modules/cloudfront/waf/logging.tf b/modules/cloudfront/waf/logging.tf index 6c867a34..d439ac79 100644 --- a/modules/cloudfront/waf/logging.tf +++ b/modules/cloudfront/waf/logging.tf @@ -1,5 +1,5 @@ resource "aws_kinesis_firehose_delivery_stream" "fd_waf_cf_logging_firehose_stream" { - name = "aws-waf-logs-cloudfront-${var.cf_origin_appendix}" + name = "aws-waf-logs-cloudfront-${local.origin_appendix}" destination = "extended_s3" extended_s3_configuration { diff --git a/profiles/analytics/inputs.tf b/profiles/analytics/inputs.tf index a86679de..d46c78be 100644 --- a/profiles/analytics/inputs.tf +++ b/profiles/analytics/inputs.tf @@ -66,6 +66,7 @@ variable "analytics_inputs" { type = object({ app_name = string domain_alias = string + web_acl_id = string jupyterhub_elb_acm_cert_arn = string jupyterhub_elb_domain_alias = string create_credentials = bool @@ -94,6 +95,7 @@ variable "analytics_inputs" { default = { app_name = "analytics" domain_alias = "" + web_acl_id = "" jupyterhub_elb_acm_cert_arn = "" jupyterhub_elb_domain_alias = "" create_credentials = true @@ -138,3 +140,9 @@ variable "log_bucket_domain_name" { type = string default = "" } + +variable "fd_web_acl_id" { + description = "The id of the FilmDrop WAF resource." + type = string + default = "" +} diff --git a/profiles/analytics/main.tf b/profiles/analytics/main.tf index 97f39d4c..a9270f72 100644 --- a/profiles/analytics/main.tf +++ b/profiles/analytics/main.tf @@ -60,6 +60,7 @@ module "cloudfront_load_balancer_endpoint" { log_bucket_domain_name = var.log_bucket_domain_name filmdrop_archive_bucket_name = var.s3_logs_archive_bucket load_balancer_dns_name = var.analytics_inputs.jupyterhub_elb_domain_alias + web_acl_id = var.analytics_inputs.web_acl_id == "" ? var.fd_web_acl_id : var.analytics_inputs.web_acl_id project_name = var.project_name environment = var.environment cf_function_name = var.analytics_inputs.auth_function.cf_function_name diff --git a/profiles/base/inputs.tf b/profiles/base/inputs.tf index d31f8f9e..4d36f2de 100644 --- a/profiles/base/inputs.tf +++ b/profiles/base/inputs.tf @@ -106,3 +106,27 @@ variable "deploy_vpc_search" { default = true description = "Perform a FilmDrop VPC search" } + +variable "deploy_waf_rule" { + description = "Deploy FilmDrop WAF rule" + type = bool + default = true +} + +variable "ip_blocklist" { + description = "List of ip cidr ranges to block access to. " + type = set(string) + default = [] +} + +variable "whitelist_ips" { + description = "List of ips to filter access for." + type = set(string) + default = [] +} + +variable "ext_web_acl_id" { + description = "The id of the external WAF resource to attach to the FilmDrop CloudFront Endpoints." + type = string + default = "" +} diff --git a/profiles/base/main.tf b/profiles/base/main.tf index 2f4f12f9..f3da8a22 100644 --- a/profiles/base/main.tf +++ b/profiles/base/main.tf @@ -61,3 +61,14 @@ module "sns_critical_subscriptions" { sns_topics_subscriptions_map = var.sns_critical_subscriptions_map sns_topic_arn = module.sns_alarm_topics[0].sns_topic_arns["FilmDropCritical"] } + +module "fd_waf_acl" { + count = var.deploy_waf_rule ? 1 : 0 + source = "../../modules/cloudfront/waf" + + logging_bucket_name = var.deploy_log_archive ? module.filmdrop_log_archive[0].s3_logs_archive_bucket : var.s3_logs_archive_bucket + whitelist_ips = var.whitelist_ips + ip_blocklist = var.ip_blocklist + environment = var.environment + project_name = var.project_name +} diff --git a/profiles/base/outputs.tf b/profiles/base/outputs.tf index c0295416..e89f3126 100644 --- a/profiles/base/outputs.tf +++ b/profiles/base/outputs.tf @@ -42,3 +42,8 @@ output "s3_logs_archive_bucket" { description = "FilmDrop S3 Archive Log Bucket Name" value = var.deploy_log_archive ? module.filmdrop_log_archive[0].s3_logs_archive_bucket : var.s3_logs_archive_bucket } + +output "web_acl_id" { + description = "The id of the FilmDrop WAF ACL" + value = var.deploy_waf_rule ? module.fd_waf_acl[0].web_acl_id : var.ext_web_acl_id +} diff --git a/profiles/cirrus-dashboard/inputs.tf b/profiles/cirrus-dashboard/inputs.tf index 51807af8..980eb102 100644 --- a/profiles/cirrus-dashboard/inputs.tf +++ b/profiles/cirrus-dashboard/inputs.tf @@ -37,6 +37,7 @@ variable "cirrus_dashboard_inputs" { app_name = string domain_alias = string deploy_cloudfront = bool + web_acl_id = string version = string cirrus_api_endpoint = string metrics_api_endpoint = string @@ -61,9 +62,11 @@ variable "cirrus_dashboard_inputs" { app_name = "dashboard" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" version = "v0.5.1" cirrus_api_endpoint = "" metrics_api_endpoint = "" + custom_error_response = [ { error_caching_min_ttl = "10" @@ -112,3 +115,9 @@ variable "log_bucket_domain_name" { type = string default = "" } + +variable "fd_web_acl_id" { + description = "The id of the FilmDrop WAF resource." + type = string + default = "" +} diff --git a/profiles/cirrus-dashboard/main.tf b/profiles/cirrus-dashboard/main.tf index 2407b767..b4457108 100644 --- a/profiles/cirrus-dashboard/main.tf +++ b/profiles/cirrus-dashboard/main.tf @@ -37,6 +37,7 @@ module "cloudfront_s3_website" { create_cf_function = var.cirrus_dashboard_inputs.auth_function.create_cf_function create_cf_basicauth_function = var.cirrus_dashboard_inputs.auth_function.create_cf_basicauth_function cf_function_arn = var.cirrus_dashboard_inputs.auth_function.cf_function_arn + web_acl_id = var.cirrus_dashboard_inputs.web_acl_id == "" ? var.fd_web_acl_id : var.cirrus_dashboard_inputs.web_acl_id } module "content_website" { diff --git a/profiles/console-ui/inputs.tf b/profiles/console-ui/inputs.tf index 7a487e82..1baa6506 100644 --- a/profiles/console-ui/inputs.tf +++ b/profiles/console-ui/inputs.tf @@ -37,6 +37,7 @@ variable "console_ui_inputs" { app_name = string domain_alias = string deploy_cloudfront = bool + web_acl_id = string custom_error_response = list(object({ error_caching_min_ttl = string error_code = string @@ -62,6 +63,7 @@ variable "console_ui_inputs" { app_name = "console" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" custom_error_response = [ { error_caching_min_ttl = "10" @@ -71,8 +73,8 @@ variable "console_ui_inputs" { } ] version = "v5.3.0" - filmdrop_ui_config_file = "./default-config/config.dev.json" - filmdrop_ui_logo_file = "./default-config/logo.png" + filmdrop_ui_config_file = "./profiles/console-ui/default-config/config.dev.json" + filmdrop_ui_logo_file = "./profiles/console-ui/default-config/logo.png" filmdrop_ui_logo = "bm9uZQo=" # Base64: 'none' auth_function = { cf_function_name = "" @@ -114,3 +116,9 @@ variable "log_bucket_domain_name" { type = string default = "" } + +variable "fd_web_acl_id" { + description = "The id of the FilmDrop WAF resource." + type = string + default = "" +} diff --git a/profiles/console-ui/main.tf b/profiles/console-ui/main.tf index 0d7fff77..d970387a 100644 --- a/profiles/console-ui/main.tf +++ b/profiles/console-ui/main.tf @@ -39,6 +39,7 @@ module "cloudfront_s3_website" { create_cf_function = var.console_ui_inputs.auth_function.create_cf_function create_cf_basicauth_function = var.console_ui_inputs.auth_function.create_cf_basicauth_function cf_function_arn = var.console_ui_inputs.auth_function.cf_function_arn + web_acl_id = var.console_ui_inputs.web_acl_id == "" ? var.fd_web_acl_id : var.console_ui_inputs.web_acl_id } module "content_website" { diff --git a/profiles/core/inputs.tf b/profiles/core/inputs.tf index 8dee5ae0..3de9931f 100644 --- a/profiles/core/inputs.tf +++ b/profiles/core/inputs.tf @@ -94,6 +94,7 @@ variable "stac_server_inputs" { app_name = string version = string deploy_cloudfront = bool + web_acl_id = string domain_alias = string enable_transactions_extension = bool collection_to_index_mappings = string @@ -105,12 +106,11 @@ variable "stac_server_inputs" { ingest_sns_topic_arns = list(string) additional_ingest_sqs_senders_arns = list(string) opensearch_ebs_volume_size = number - authorized_s3_arns = list(string) cors_origin = string cors_credentials = bool cors_methods = string cors_headers = string - web_acl_id = string + authorized_s3_arns = list(string) auth_function = object({ cf_function_name = string cf_function_runtime = string @@ -139,6 +139,7 @@ variable "stac_server_inputs" { app_name = "stac_server" version = "v3.8.0" deploy_cloudfront = true + web_acl_id = "" domain_alias = "" enable_transactions_extension = false collection_to_index_mappings = "" @@ -150,12 +151,11 @@ variable "stac_server_inputs" { ingest_sns_topic_arns = [] additional_ingest_sqs_senders_arns = [] opensearch_ebs_volume_size = 35 - authorized_s3_arns = [] cors_origin = "*" cors_credentials = false cors_methods = "" cors_headers = "" - web_acl_id = "" + authorized_s3_arns = [] auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -233,6 +233,7 @@ variable "analytics_inputs" { type = object({ app_name = string domain_alias = string + web_acl_id = string jupyterhub_elb_acm_cert_arn = string jupyterhub_elb_domain_alias = string create_credentials = bool @@ -261,6 +262,7 @@ variable "analytics_inputs" { default = { app_name = "analytics" domain_alias = "" + web_acl_id = "" jupyterhub_elb_acm_cert_arn = "" jupyterhub_elb_domain_alias = "" create_credentials = true @@ -294,6 +296,7 @@ variable "console_ui_inputs" { app_name = string domain_alias = string deploy_cloudfront = bool + web_acl_id = string custom_error_response = list(object({ error_caching_min_ttl = string error_code = string @@ -319,6 +322,7 @@ variable "console_ui_inputs" { app_name = "console" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" custom_error_response = [ { error_caching_min_ttl = "10" @@ -328,8 +332,8 @@ variable "console_ui_inputs" { } ] version = "v5.3.0" - filmdrop_ui_config_file = "../console-ui/default-config/config.dev.json" - filmdrop_ui_logo_file = "../console-ui/default-config/logo.png" + filmdrop_ui_config_file = "./profiles/console-ui/default-config/config.dev.json" + filmdrop_ui_logo_file = "./profiles/console-ui/default-config/logo.png" filmdrop_ui_logo = "bm9uZQo=" # Base64: 'none' auth_function = { cf_function_name = "" @@ -422,6 +426,7 @@ variable "cirrus_dashboard_inputs" { app_name = string domain_alias = string deploy_cloudfront = bool + web_acl_id = string version = string cirrus_api_endpoint = string metrics_api_endpoint = string @@ -446,9 +451,11 @@ variable "cirrus_dashboard_inputs" { app_name = "dashboard" domain_alias = "" deploy_cloudfront = true + web_acl_id = "" version = "v0.5.1" cirrus_api_endpoint = "" metrics_api_endpoint = "" + custom_error_response = [ { error_caching_min_ttl = "10" @@ -547,3 +554,27 @@ variable "deploy_stac_server_outside_vpc" { default = false description = "Deploy FilmDrop Stac-Server resources, including OpenSearch outside VPC. Defaults to false. If False, Stac-server resources will be deployed within the vpc." } + +variable "deploy_waf_rule" { + description = "Deploy FilmDrop WAF rule" + type = bool + default = true +} + +variable "ip_blocklist" { + description = "List of ip cidr ranges to block access to. " + type = set(string) + default = [] +} + +variable "whitelist_ips" { + description = "List of ips to filter access for." + type = set(string) + default = [] +} + +variable "ext_web_acl_id" { + description = "The id of the external WAF resource to attach to the FilmDrop CloudFront Endpoints." + type = string + default = "" +} diff --git a/profiles/core/main.tf b/profiles/core/main.tf index 78a6aa8f..6128106c 100644 --- a/profiles/core/main.tf +++ b/profiles/core/main.tf @@ -5,6 +5,10 @@ module "base_infra" { deploy_vpc_search = var.deploy_vpc_search deploy_alarms = var.deploy_alarms deploy_log_archive = var.deploy_log_archive + deploy_waf_rule = var.deploy_waf_rule + ext_web_acl_id = var.ext_web_acl_id + ip_blocklist = var.ip_blocklist + whitelist_ips = var.whitelist_ips environment = var.environment project_name = var.project_name vpc_cidr = var.vpc_cidr @@ -48,6 +52,7 @@ module "stac-server" { domain_zone = var.domain_zone deploy_stac_server_opensearch_serverless = var.deploy_stac_server_opensearch_serverless deploy_stac_server_outside_vpc = var.deploy_stac_server_outside_vpc + fd_web_acl_id = var.deploy_waf_rule ? module.base_infra.web_acl_id : var.ext_web_acl_id depends_on = [ module.setup @@ -92,6 +97,7 @@ module "analytics" { environment = var.environment domain_zone = var.domain_zone analytics_inputs = var.analytics_inputs + fd_web_acl_id = var.deploy_waf_rule ? module.base_infra.web_acl_id : var.ext_web_acl_id } module "console-ui" { @@ -111,6 +117,7 @@ module "console-ui" { console_ui_inputs = var.console_ui_inputs domain_zone = var.domain_zone s3_logs_archive_bucket = module.base_infra.s3_logs_archive_bucket + fd_web_acl_id = var.deploy_waf_rule ? module.base_infra.web_acl_id : var.ext_web_acl_id } module "cirrus" { @@ -141,4 +148,5 @@ module "cirrus-dashboard" { s3_logs_archive_bucket = module.base_infra.s3_logs_archive_bucket domain_zone = var.domain_zone cirrus_dashboard_inputs = var.cirrus_dashboard_inputs + fd_web_acl_id = var.deploy_waf_rule ? module.base_infra.web_acl_id : var.ext_web_acl_id } diff --git a/profiles/stac-server/inputs.tf b/profiles/stac-server/inputs.tf index 8b1d6e78..bd694ede 100644 --- a/profiles/stac-server/inputs.tf +++ b/profiles/stac-server/inputs.tf @@ -42,6 +42,7 @@ variable "stac_server_inputs" { app_name = string version = string deploy_cloudfront = bool + web_acl_id = string domain_alias = string enable_transactions_extension = bool collection_to_index_mappings = string @@ -53,12 +54,11 @@ variable "stac_server_inputs" { ingest_sns_topic_arns = list(string) additional_ingest_sqs_senders_arns = list(string) opensearch_ebs_volume_size = number - authorized_s3_arns = list(string) cors_origin = string cors_credentials = bool cors_methods = string cors_headers = string - web_acl_id = string + authorized_s3_arns = list(string) auth_function = object({ cf_function_name = string cf_function_runtime = string @@ -87,6 +87,7 @@ variable "stac_server_inputs" { app_name = "stac_server" version = "v3.8.0" deploy_cloudfront = true + web_acl_id = "" domain_alias = "" enable_transactions_extension = false collection_to_index_mappings = "" @@ -98,12 +99,11 @@ variable "stac_server_inputs" { ingest_sns_topic_arns = [] additional_ingest_sqs_senders_arns = [] opensearch_ebs_volume_size = 35 - authorized_s3_arns = [] cors_origin = "*" cors_credentials = false cors_methods = "" cors_headers = "" - web_acl_id = "" + authorized_s3_arns = [] auth_function = { cf_function_name = "" cf_function_runtime = "cloudfront-js-2.0" @@ -169,3 +169,9 @@ variable "deploy_stac_server_outside_vpc" { default = false description = "Deploy FilmDrop Stac-Server resources, including OpenSearch outside VPC. Defaults to false. If False, Stac-server resources will be deployed within the vpc." } + +variable "fd_web_acl_id" { + description = "The id of the FilmDrop WAF resource." + type = string + default = "" +} diff --git a/profiles/stac-server/main.tf b/profiles/stac-server/main.tf index da0ccd63..bb58e997 100644 --- a/profiles/stac-server/main.tf +++ b/profiles/stac-server/main.tf @@ -41,7 +41,7 @@ module "cloudfront_api_gateway_endpoint" { application_name = var.stac_server_inputs.app_name api_gateway_dns_name = module.stac-server.stac_server_api_domain_name api_gateway_path = module.stac-server.stac_server_api_path - web_acl_id = var.stac_server_inputs.web_acl_id + web_acl_id = var.stac_server_inputs.web_acl_id == "" ? var.fd_web_acl_id : var.stac_server_inputs.web_acl_id project_name = var.project_name environment = var.environment create_log_bucket = var.create_log_bucket