From 05a44f55339ec437eb6532cd0a02dc95e520050b Mon Sep 17 00:00:00 2001 From: Jarrod Lowe Date: Thu, 15 Aug 2024 14:41:02 +1200 Subject: [PATCH] Add WAF --- .github/workflows/terraform.yaml | 1 + Makefile | 17 ++- terraform/environment/aws-dev/main.tf | 16 +-- terraform/environment/wildsea-dev/main.tf | 2 +- terraform/environment/wildsea-dev/plan | Bin 18260 -> 21243 bytes terraform/environment/wildsea/main.tf | 2 +- terraform/module/iac-roles/policy.tf | 113 +++++++++++++++++- terraform/module/iac-roles/roles.tf | 4 +- terraform/module/oidc/main.tf | 2 +- terraform/module/state-bucket/s3.tf | 2 +- terraform/module/wildsea/cognito.tf | 6 +- terraform/module/wildsea/graphql.tf | 139 ++++++++++++++++++---- terraform/module/wildsea/main.tf | 8 +- 13 files changed, 263 insertions(+), 49 deletions(-) diff --git a/.github/workflows/terraform.yaml b/.github/workflows/terraform.yaml index 3dea7ea7..f85dd0ef 100644 --- a/.github/workflows/terraform.yaml +++ b/.github/workflows/terraform.yaml @@ -4,6 +4,7 @@ on: pull_request: paths: - terraform/environment/wildsea/** + - terraform/modules/wildsea/** push: branches: - main diff --git a/Makefile b/Makefile index 7eddd28f..3e2707be 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ default: all TERRAFORM_ENVIRONMENTS := aws github wildsea aws-dev wildsea-dev TERRAFOM_VALIDATE := $(addsuffix /.validate,$(addprefix terraform/environment/, $(TERRAFORM_ENVIRONMENTS))) +TERRAFORM_MODULES := iac-roles oidc state-bucket wildsea ACCOUNT_ID := $(shell aws sts get-caller-identity --query 'Account' --output text) AWS_REGION ?= "ap-southeast-2" RO_ROLE = arn:aws:iam::$(ACCOUNT_ID):role/GitHubAction-Wildsea-ro-dev @@ -9,13 +10,25 @@ RW_ROLE = arn:aws:iam::$(ACCOUNT_ID):role/GitHubAction-Wildsea-rw-dev all: $(TERRAFOM_VALIDATE) -terraform/environment/%/.validate: terraform/environment/%/*.tf +.PHONY: terraform-format +terraform-format: $(addprefix terraform-format-environment-,$(TERRAFORM_ENVIRONMENTS)) $(addprefix terraform-format-module-,$(TERRAFORM_MODULES)) + @true + +.PHONY: terraform-format-environment-% +terraform-format-environment-%: + cd terraform/environment/$*; terraform fmt + +.PHONY: terraform-format-module-% +terraform-format-module-%: + cd terraform/module/$*; terraform fmt + +terraform/environment/%/.validate: terraform/environment/%/*.tf terraform-format cd terraform/environment/$* ; terraform fmt cd terraform/environment/$* ; terraform validate touch $@ .PHONY: dev -dev: terraform/environment/aws-dev/.apply terraform/environment/wildsea-dev/.apply +dev: terraform-format terraform/environment/aws-dev/.apply terraform/environment/wildsea-dev/.apply @true terraform/environment/aws-dev/.apply: terraform/environment/aws-dev/*.tf terraform/module/iac-roles/*.tf diff --git a/terraform/environment/aws-dev/main.tf b/terraform/environment/aws-dev/main.tf index a32f67c2..af062a9e 100644 --- a/terraform/environment/aws-dev/main.tf +++ b/terraform/environment/aws-dev/main.tf @@ -46,13 +46,13 @@ provider "aws" { } module "iac-roles" { - source = "../../module/iac-roles" - app_name = var.app_name - environment = var.environment - action_prefix = var.action_prefix - workspace = "none" - repo = var.repo + source = "../../module/iac-roles" + app_name = var.app_name + environment = var.environment + action_prefix = var.action_prefix + workspace = "none" + repo = var.repo state_bucket_arn = "arn:${data.aws_partition.current.id}:s3:::${var.state_bucket}" - oidc_type = "AWS" - oidc_arn = data.aws_caller_identity.current.account_id + oidc_type = "AWS" + oidc_arn = data.aws_caller_identity.current.account_id } diff --git a/terraform/environment/wildsea-dev/main.tf b/terraform/environment/wildsea-dev/main.tf index 0fb7a6d3..6399df3f 100644 --- a/terraform/environment/wildsea-dev/main.tf +++ b/terraform/environment/wildsea-dev/main.tf @@ -28,5 +28,5 @@ module "wildsea" { source = "../../module/wildsea" saml_metadata_url = var.saml_metadata_url - prefix = local.prefix + prefix = local.prefix } diff --git a/terraform/environment/wildsea-dev/plan b/terraform/environment/wildsea-dev/plan index ff4b49b62a877b4516f3a564bc7dd2d48b31fe88..b31203bff753d23e1cb4dd11ccbf0ac6f088bf86 100644 GIT binary patch delta 17862 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 diff --git a/terraform/environment/wildsea/main.tf b/terraform/environment/wildsea/main.tf index b9254771..2c99957b 100644 --- a/terraform/environment/wildsea/main.tf +++ b/terraform/environment/wildsea/main.tf @@ -33,5 +33,5 @@ module "wildsea" { source = "../../module/wildsea" saml_metadata_url = var.saml_metadata_url - prefix = local.prefix + prefix = local.prefix } diff --git a/terraform/module/iac-roles/policy.tf b/terraform/module/iac-roles/policy.tf index 927b0eda..babc7eef 100644 --- a/terraform/module/iac-roles/policy.tf +++ b/terraform/module/iac-roles/policy.tf @@ -46,6 +46,9 @@ data "aws_iam_policy_document" "ro" { sid = "CognitoIdpGlobal" actions = [ "cognito-idp:DescribeUserPoolDomain", + "appsync:SetWebACL", + "wafv2:GetWebACLForResource", + "wafv2:GetWebAcl", ] resources = [ "*" @@ -107,6 +110,19 @@ data "aws_iam_policy_document" "ro" { "arn:${data.aws_partition.current.id}:logs:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:log-group:*" ] } + + statement { + actions = [ + "wafv2:ListWebACLs", + "wafv2:ListTagsForResource", + ] + resources = ["*"] + condition { + test = "StringEquals" + variable = "aws:ResourceTag/Name" + values = [local.prefix] + } + } } data "aws_iam_policy_document" "rw" { @@ -254,7 +270,7 @@ data "aws_iam_policy_document" "rw" { } statement { - actions = ["iam:CreateServiceLinkedRole"] + actions = ["iam:CreateServiceLinkedRole"] resources = ["*"] condition { test = "StringEquals" @@ -262,6 +278,44 @@ data "aws_iam_policy_document" "rw" { values = ["appsync.${data.aws_partition.current.dns_suffix}"] } } + + statement { + actions = [ + "wafv2:CreateWebAcl", + "wafv2:TagResource", + ] + resources = ["*"] + condition { + test = "StringEquals" + variable = "aws:RequestTag/Name" + values = [local.prefix] + } + } + + statement { + actions = [ + "wafv2:CreateWebACL", + ] + resources = [ + "arn:aws:wafv2:ap-southeast-2:021891603679:regional/managedruleset/*/*" + ] + } + + statement { + actions = [ + "wafv2:UpdateWebACL", + "wafv2:DeleteWebACL", + "wafv2:ListTagsForResource", + "wafv2:AssociateWebACL", + ] + resources = ["*"] + condition { + test = "StringEquals" + variable = "aws:ResourceTag/Name" + values = [local.prefix] + } + } + } data "aws_iam_policy_document" "rw_boundary" { @@ -326,9 +380,11 @@ data "aws_iam_policy_document" "rw_boundary" { } statement { - sid = "CognitoIdpGlobal" actions = [ "cognito-idp:DescribeUserPoolDomain", + "appsync:SetWebACL", + "wafv2:GetWebACLForResource", + "wafv2:GetWebAcl", ] resources = [ "*" @@ -441,7 +497,7 @@ data "aws_iam_policy_document" "rw_boundary" { } statement { - actions = ["iam:CreateServiceLinkedRole"] + actions = ["iam:CreateServiceLinkedRole"] resources = ["*"] condition { test = "StringEquals" @@ -449,4 +505,55 @@ data "aws_iam_policy_document" "rw_boundary" { values = ["appsync.${data.aws_partition.current.dns_suffix}"] } } + + statement { + actions = [ + "wafv2:CreateWebAcl", + "wafv2:TagResource", + ] + resources = ["*"] + condition { + test = "StringEquals" + variable = "aws:RequestTag/Name" + values = [local.prefix] + } + } + + statement { + actions = [ + "wafv2:CreateWebACL", + ] + resources = [ + "arn:aws:wafv2:ap-southeast-2:021891603679:regional/managedruleset/*/*" + ] + } + + statement { + actions = [ + "wafv2:UpdateWebACL", + "wafv2:DeleteWebACL", + "wafv2:UpdatebACL", + "wafv2:ListTagsForResource", + "wafv2:AssociateWebACL", + ] + resources = ["*"] + condition { + test = "StringEquals" + variable = "aws:ResourceTag/Name" + values = [local.prefix] + } + } + + statement { + actions = [ + "wafv2:ListWebACLs", + "wafv2:ListTagsForResource", + ] + resources = ["*"] + condition { + test = "StringEquals" + variable = "aws:ResourceTag/Name" + values = [local.prefix] + } + } } diff --git a/terraform/module/iac-roles/roles.tf b/terraform/module/iac-roles/roles.tf index cbcfdbcd..9bf09ec6 100644 --- a/terraform/module/iac-roles/roles.tf +++ b/terraform/module/iac-roles/roles.tf @@ -9,7 +9,7 @@ resource "aws_iam_role" "ro" { data "aws_iam_policy_document" "ro_assume" { statement { - actions = [ var.oidc_type == "Federated" ? "sts:AssumeRoleWithWebIdentity" : "sts:AssumeRole" ] + actions = [var.oidc_type == "Federated" ? "sts:AssumeRoleWithWebIdentity" : "sts:AssumeRole"] principals { type = var.oidc_type identifiers = [var.oidc_arn] @@ -59,7 +59,7 @@ resource "aws_iam_role" "rw" { data "aws_iam_policy_document" "rw_assume" { statement { - actions = [ var.oidc_type == "Federated" ? "sts:AssumeRoleWithWebIdentity" : "sts:AssumeRole" ] + actions = [var.oidc_type == "Federated" ? "sts:AssumeRoleWithWebIdentity" : "sts:AssumeRole"] principals { type = var.oidc_type identifiers = [var.oidc_arn] diff --git a/terraform/module/oidc/main.tf b/terraform/module/oidc/main.tf index d3e0c5f2..b7b501d0 100644 --- a/terraform/module/oidc/main.tf +++ b/terraform/module/oidc/main.tf @@ -11,5 +11,5 @@ resource "aws_iam_openid_connect_provider" "oidc" { } output "oidc_arn" { - value = aws_iam_openid_connect_provider.oidc.arn + value = aws_iam_openid_connect_provider.oidc.arn } diff --git a/terraform/module/state-bucket/s3.tf b/terraform/module/state-bucket/s3.tf index 3e6f0de6..ebcb36bc 100644 --- a/terraform/module/state-bucket/s3.tf +++ b/terraform/module/state-bucket/s3.tf @@ -57,5 +57,5 @@ resource "aws_s3_bucket_versioning" "state" { output "arn" { description = "ARN of the state bucket" - value = aws_s3_bucket.state.arn + value = aws_s3_bucket.state.arn } diff --git a/terraform/module/wildsea/cognito.tf b/terraform/module/wildsea/cognito.tf index 7f6f5932..bc16d35f 100644 --- a/terraform/module/wildsea/cognito.tf +++ b/terraform/module/wildsea/cognito.tf @@ -7,7 +7,7 @@ resource "aws_cognito_user_pool" "cognito" { } resource "aws_cognito_identity_provider" "idp" { - for_each = var.saml_metadata_url == "" ? toset([]) : toset([1]) + for_each = var.saml_metadata_url == "" ? toset([]) : toset([1]) user_pool_id = aws_cognito_user_pool.cognito.id provider_name = "SAML" provider_type = "SAML" @@ -34,7 +34,7 @@ resource "aws_cognito_user_pool_client" "cognito" { logout_urls = ["https://TODO"] allowed_oauth_flows = ["code", "implicit"] allowed_oauth_scopes = ["openid"] - supported_identity_providers = [ var.saml_metadata_url == "" ? "COGNITO" : aws_cognito_identity_provider.idp[0].provider_name ] + supported_identity_providers = [var.saml_metadata_url == "" ? "COGNITO" : aws_cognito_identity_provider.idp[0].provider_name] } resource "aws_cognito_identity_pool" "cognito" { @@ -86,7 +86,7 @@ resource "aws_iam_policy" "cognito" { name = "${var.prefix}-user" policy = data.aws_iam_policy_document.cognito.json } - + data "aws_iam_policy_document" "cognito" { statement { actions = [ diff --git a/terraform/module/wildsea/graphql.tf b/terraform/module/wildsea/graphql.tf index ea4b03d4..26dd77ef 100644 --- a/terraform/module/wildsea/graphql.tf +++ b/terraform/module/wildsea/graphql.tf @@ -1,29 +1,32 @@ resource "aws_appsync_graphql_api" "graphql" { - name = var.prefix - schema = file("../../../graphql/schema.graphql") - authentication_type = "AWS_IAM" - xray_enabled = true + name = var.prefix + schema = file("../../../graphql/schema.graphql") + authentication_type = "AWS_IAM" + xray_enabled = true - log_config { - cloudwatch_logs_role_arn = aws_iam_role.graphql_log.arn - field_log_level = "ERROR" - } + log_config { + cloudwatch_logs_role_arn = aws_iam_role.graphql_log.arn + field_log_level = "ERROR" + } - additional_authentication_provider { - authentication_type = "AMAZON_COGNITO_USER_POOLS" - user_pool_config { - user_pool_id = aws_cognito_user_pool.cognito.id - aws_region = data.aws_region.current.name - } + additional_authentication_provider { + authentication_type = "AMAZON_COGNITO_USER_POOLS" + user_pool_config { + user_pool_id = aws_cognito_user_pool.cognito.id + aws_region = data.aws_region.current.name } + } tags = { Name = var.prefix } } +# nosemgrep: aws-cloudwatch-log-group-unencrypted // AWS Key is fine resource "aws_cloudwatch_log_group" "graphql_log" { - name = "/aws/appsync/${var.prefix}" + # checkov:skip=CKV_AWS_338:Two weeks is enough, we don't need a year + # checkov:skip=CKV_AWS_158:AWS Key is fine + name = "/aws/appsync/${var.prefix}" retention_in_days = 14 tags = { @@ -32,25 +35,115 @@ resource "aws_cloudwatch_log_group" "graphql_log" { } resource "aws_iam_role" "graphql_log" { - name = "${var.prefix}-graphql-log" - assume_role_policy = data.aws_iam_policy_document.graphql_log_assume.json + name = "${var.prefix}-graphql-log" + assume_role_policy = data.aws_iam_policy_document.graphql_log_assume.json - tags = { - Name = var.prefix - } + tags = { + Name = var.prefix + } } data "aws_iam_policy_document" "graphql_log_assume" { statement { actions = ["sts:AssumeRole"] principals { - type = "Service" + type = "Service" identifiers = ["appsync.${data.aws_partition.current.dns_suffix}"] } } } resource "aws_iam_role_policy_attachment" "grahql_log" { - role = aws_iam_role.graphql_log.name - policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" + role = aws_iam_role.graphql_log.name + policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs" +} + +resource "aws_wafv2_web_acl_association" "graphql" { + resource_arn = aws_appsync_graphql_api.graphql.arn + web_acl_arn = aws_wafv2_web_acl.graphql.arn +} + +resource "aws_wafv2_web_acl" "graphql" { + name = "${var.prefix}-graphql-waf" + scope = "REGIONAL" + + default_action { + allow {} + } + + rule { + name = "Ratelimit" + priority = 10 + + action { + block {} + } + + statement { + rate_based_statement { + limit = 1000 + aggregate_key_type = "IP" + + } + } + + visibility_config { + cloudwatch_metrics_enabled = false + metric_name = "Ratelimit" + sampled_requests_enabled = false + } + } + + + rule { + name = "AWSManagedRulesCommonRuleSet" + priority = 20 + statement { + managed_rule_group_statement { + name = "AWSManagedRulesCommonRuleSet" + vendor_name = "AWS" + } + } + override_action { + count { + + } + } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesCommonRuleSet" + sampled_requests_enabled = true + } + } + + rule { + name = "AWSManagedRulesAmazonIpReputationList" + priority = 30 + statement { + managed_rule_group_statement { + name = "AWSManagedRulesAmazonIpReputationList" + vendor_name = "AWS" + } + } + override_action { + count { + + } + } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesAmazonIpReputationList" + sampled_requests_enabled = true + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "GraphQLWAF" + sampled_requests_enabled = true + } + + tags = { + Name = var.prefix + } } diff --git a/terraform/module/wildsea/main.tf b/terraform/module/wildsea/main.tf index a8e354f4..61c12747 100644 --- a/terraform/module/wildsea/main.tf +++ b/terraform/module/wildsea/main.tf @@ -3,11 +3,11 @@ data "aws_partition" "current" {} data "aws_caller_identity" "current" {} variable "prefix" { - description = "Resource name prefix" - type = string + description = "Resource name prefix" + type = string } variable "saml_metadata_url" { - description = "SAML metadata URL" - type = string + description = "SAML metadata URL" + type = string }