Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ variable "search_api_domain" {
description = "The domain name of the API gateway"
}

variable "publishing_service_domain" {
type = string
description = "FQDN of the user-facing domain for the publishing apps, e.g. staging.publishing.service.gov.uk. This domain is included as a wildcard SAN on the TLS cert for Ingresses etc."
}

variable "publishing_certificate_arn" {
type = string
description = "The ARN of the publishing certificate"
Expand Down Expand Up @@ -139,6 +144,12 @@ variable "backend_public_base_rate_limit" {
default = 1000
}

variable "chat_domain_base_rate_limit" {
type = number
description = "An enforced rate limit threshold for the chat domain"
default = 75000
}

variable "backend_public_ja3_denylist" {
type = list(string)
description = "For the backend ALB. List of JA3 signatures for which we should block all requests."
Expand Down
84 changes: 84 additions & 0 deletions terraform/deployments/govuk-publishing-infrastructure/wafs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,90 @@ resource "aws_wafv2_web_acl" "backend_public" {
}
}

rule {
name = "chat-domain-rate-limit"
priority = 25

action {
block {
custom_response {
response_code = 429

response_header {
name = "Retry-After"
value = 30
}

response_header {
name = "Cache-Control"
value = "max-age=0, private"
}

custom_response_body_key = "backend-public-rule-429"
}
}
}

statement {
rate_based_statement {
limit = var.chat_domain_base_rate_limit
aggregate_key_type = "IP"

scope_down_statement {
byte_match_statement {
search_string = "chat.${var.publishing_service_domain}"
field_to_match {
single_header {
name = "host"
}
}
positional_constraint = "EXACTLY"
text_transformation {
priority = 0
type = "LOWERCASE"
}
}
}
}
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "chat-domain-rate-limit"
sampled_requests_enabled = true
}
}

rule {
name = "chat-domain-allow"
priority = 26

action {
allow {}
}

statement {
byte_match_statement {
search_string = "chat.${var.publishing_service_domain}"
field_to_match {
single_header {
name = "host"
}
}
positional_constraint = "EXACTLY"
text_transformation {
priority = 0
type = "LOWERCASE"
}
}
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "chat-domain-allow"
sampled_requests_enabled = true
}
}
# This rule is intended for monitoring only
# set a base rate limit per IP looking back over the last 5 minutes
# this is checked every 30s
Expand Down
Loading