diff --git a/README.md b/README.md index 9371c4d..92ecc6d 100644 --- a/README.md +++ b/README.md @@ -357,13 +357,13 @@ See [patterns.md](https://github.com/terraform-aws-modules/terraform-aws-alb/blo | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.5 | +| [aws](#requirement\_aws) | >= 6.19 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 6.5 | +| [aws](#provider\_aws) | >= 6.19 | ## Modules @@ -417,7 +417,7 @@ No modules. | [internal](#input\_internal) | If true, the LB will be internal. Defaults to `false` | `bool` | `null` | no | | [ip\_address\_type](#input\_ip\_address\_type) | The type of IP addresses used by the subnets for your load balancer. The possible values are `ipv4` and `dualstack` | `string` | `null` | no | | [ipam\_pools](#input\_ipam\_pools) | The IPAM pools to use with the load balancer |
object({
ipv4_ipam_pool_id = string
})
| `null` | no | -| [listeners](#input\_listeners) | Map of listener configurations to create |
map(object({
alpn_policy = optional(string)
certificate_arn = optional(string)
additional_certificate_arns = optional(list(string), [])
authenticate_cognito = optional(object({
authentication_request_extra_params = optional(map(string))
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
user_pool_arn = optional(string)
user_pool_client_id = optional(string)
user_pool_domain = optional(string)
}))
authenticate_oidc = optional(object({
authentication_request_extra_params = optional(map(string))
authorization_endpoint = string
client_id = string
client_secret = string
issuer = string
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
token_endpoint = string
user_info_endpoint = string
}))
fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}))
forward = optional(object({
target_group_arn = optional(string)
target_group_key = optional(string)
}))
weighted_forward = optional(object({
target_groups = optional(list(object({
target_group_arn = optional(string)
target_group_key = optional(string)
weight = optional(number)
})))
stickiness = optional(object({
duration = optional(number)
enabled = optional(bool)
}))
}))
redirect = optional(object({
host = optional(string)
path = optional(string)
port = optional(string)
protocol = optional(string)
query = optional(string)
status_code = string
}))
mutual_authentication = optional(object({
advertise_trust_store_ca_names = optional(string)
ignore_client_certificate_expiry = optional(bool)
mode = string
trust_store_arn = optional(string)
}))
order = optional(number)
port = optional(number)
protocol = optional(string)
routing_http_request_x_amzn_mtls_clientcert_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_issuer_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_leaf_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_subject_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_validity_header_name = optional(string)
routing_http_request_x_amzn_tls_cipher_suite_header_name = optional(string)
routing_http_request_x_amzn_tls_version_header_name = optional(string)
routing_http_response_access_control_allow_credentials_header_value = optional(string)
routing_http_response_access_control_allow_headers_header_value = optional(string)
routing_http_response_access_control_allow_methods_header_value = optional(string)
routing_http_response_access_control_allow_origin_header_value = optional(string)
routing_http_response_access_control_expose_headers_header_value = optional(string)
routing_http_response_access_control_max_age_header_value = optional(string)
routing_http_response_content_security_policy_header_value = optional(string)
routing_http_response_server_enabled = optional(bool)
routing_http_response_strict_transport_security_header_value = optional(string)
routing_http_response_x_content_type_options_header_value = optional(string)
routing_http_response_x_frame_options_header_value = optional(string)
ssl_policy = optional(string)
tcp_idle_timeout_seconds = optional(number)
tags = optional(map(string), {})

# Listener rules
rules = optional(map(object({
actions = list(object({
authenticate_cognito = optional(object({
authentication_request_extra_params = optional(map(string))
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
user_pool_arn = string
user_pool_client_id = string
user_pool_domain = string
}))
authenticate_oidc = optional(object({
authentication_request_extra_params = optional(map(string))
authorization_endpoint = string
client_id = string
client_secret = string
issuer = string
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
token_endpoint = string
user_info_endpoint = string
}))
fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}))
forward = optional(object({
target_group_arn = optional(string)
target_group_key = optional(string)
}))
order = optional(number)
redirect = optional(object({
host = optional(string)
path = optional(string)
port = optional(string)
protocol = optional(string)
query = optional(string)
status_code = string
}))
weighted_forward = optional(object({
stickiness = optional(object({
duration = optional(number)
enabled = optional(bool)
}))
target_groups = optional(list(object({
target_group_arn = optional(string)
target_group_key = optional(string)
weight = optional(number)
})))
}))
}))
conditions = list(object({
host_header = optional(object({
values = list(string)
}))
http_header = optional(object({
http_header_name = string
values = list(string)
}))
http_request_method = optional(object({
values = list(string)
}))
path_pattern = optional(object({
values = list(string)
}))
query_string = optional(list(object({
key = optional(string)
value = string
})))
source_ip = optional(object({
values = list(string)
}))
}))
listener_arn = optional(string)
listener_key = optional(string)
priority = optional(number)
tags = optional(map(string), {})
})), {})
}))
| `{}` | no | +| [listeners](#input\_listeners) | Map of listener configurations to create |
map(object({
alpn_policy = optional(string)
certificate_arn = optional(string)
additional_certificate_arns = optional(list(string), [])
authenticate_cognito = optional(object({
authentication_request_extra_params = optional(map(string))
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
user_pool_arn = optional(string)
user_pool_client_id = optional(string)
user_pool_domain = optional(string)
}))
authenticate_oidc = optional(object({
authentication_request_extra_params = optional(map(string))
authorization_endpoint = string
client_id = string
client_secret = string
issuer = string
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
token_endpoint = string
user_info_endpoint = string
}))
fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}))
forward = optional(object({
target_group_arn = optional(string)
target_group_key = optional(string)
}))
weighted_forward = optional(object({
target_groups = optional(list(object({
target_group_arn = optional(string)
target_group_key = optional(string)
weight = optional(number)
})))
stickiness = optional(object({
duration = optional(number)
enabled = optional(bool)
}))
}))
redirect = optional(object({
host = optional(string)
path = optional(string)
port = optional(string)
protocol = optional(string)
query = optional(string)
status_code = string
}))
mutual_authentication = optional(object({
advertise_trust_store_ca_names = optional(string)
ignore_client_certificate_expiry = optional(bool)
mode = string
trust_store_arn = optional(string)
}))
order = optional(number)
port = optional(number)
protocol = optional(string)
routing_http_request_x_amzn_mtls_clientcert_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_issuer_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_leaf_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_subject_header_name = optional(string)
routing_http_request_x_amzn_mtls_clientcert_validity_header_name = optional(string)
routing_http_request_x_amzn_tls_cipher_suite_header_name = optional(string)
routing_http_request_x_amzn_tls_version_header_name = optional(string)
routing_http_response_access_control_allow_credentials_header_value = optional(string)
routing_http_response_access_control_allow_headers_header_value = optional(string)
routing_http_response_access_control_allow_methods_header_value = optional(string)
routing_http_response_access_control_allow_origin_header_value = optional(string)
routing_http_response_access_control_expose_headers_header_value = optional(string)
routing_http_response_access_control_max_age_header_value = optional(string)
routing_http_response_content_security_policy_header_value = optional(string)
routing_http_response_server_enabled = optional(bool)
routing_http_response_strict_transport_security_header_value = optional(string)
routing_http_response_x_content_type_options_header_value = optional(string)
routing_http_response_x_frame_options_header_value = optional(string)
ssl_policy = optional(string)
tcp_idle_timeout_seconds = optional(number)
tags = optional(map(string), {})

# Listener rules
rules = optional(map(object({
actions = list(object({
authenticate_cognito = optional(object({
authentication_request_extra_params = optional(map(string))
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
user_pool_arn = string
user_pool_client_id = string
user_pool_domain = string
}))
authenticate_oidc = optional(object({
authentication_request_extra_params = optional(map(string))
authorization_endpoint = string
client_id = string
client_secret = string
issuer = string
on_unauthenticated_request = optional(string)
scope = optional(string)
session_cookie_name = optional(string)
session_timeout = optional(number)
token_endpoint = string
user_info_endpoint = string
}))
fixed_response = optional(object({
content_type = string
message_body = optional(string)
status_code = optional(string)
}))
forward = optional(object({
target_group_arn = optional(string)
target_group_key = optional(string)
}))
order = optional(number)
redirect = optional(object({
host = optional(string)
path = optional(string)
port = optional(string)
protocol = optional(string)
query = optional(string)
status_code = string
}))
weighted_forward = optional(object({
stickiness = optional(object({
duration = optional(number)
enabled = optional(bool)
}))
target_groups = optional(list(object({
target_group_arn = optional(string)
target_group_key = optional(string)
weight = optional(number)
})))
}))
}))
conditions = list(object({
host_header = optional(object({
values = optional(list(string))
regex_values = optional(list(string))
}))
http_header = optional(object({
http_header_name = string
values = optional(list(string))
regex_values = optional(list(string))
}))
http_request_method = optional(object({
values = list(string)
}))
path_pattern = optional(object({
values = optional(list(string))
regex_values = optional(list(string))
}))
query_string = optional(list(object({
key = optional(string)
value = string
})))
source_ip = optional(object({
values = list(string)
}))
}))
listener_arn = optional(string)
listener_key = optional(string)
priority = optional(number)
transform = optional(map(object({
type = optional(string)
host_header_rewrite_config = optional(object({
rewrite = optional(object({
regex = string
replace = string
}))
}))
url_rewrite_config = optional(object({
rewrite = optional(object({
regex = string
replace = string
}))
}))
})))
tags = optional(map(string), {})
})), {})
}))
| `{}` | no | | [load\_balancer\_type](#input\_load\_balancer\_type) | The type of load balancer to create. Possible values are `application`, `gateway`, or `network`. The default value is `application` | `string` | `"application"` | no | | [minimum\_load\_balancer\_capacity](#input\_minimum\_load\_balancer\_capacity) | Minimum capacity for a load balancer. Only valid for Load Balancers of type `application` or `network` |
object({
capacity_units = number
})
| `null` | no | | [name](#input\_name) | The name of the LB. This name must be unique within your AWS account, can have a maximum of 32 characters, must contain only alphanumeric characters or hyphens, and must not begin or end with a hyphen | `string` | `null` | no | diff --git a/docs/UPGRADE-10.0.md b/docs/UPGRADE-10.0.md index c568323..c88ce3c 100644 --- a/docs/UPGRADE-10.0.md +++ b/docs/UPGRADE-10.0.md @@ -19,6 +19,7 @@ Please consult the `examples` directory for reference example configurations. If - Security group rules now use a default naming scheme of `-` unless a more specific rule name is provided. - `rule.actions.type` has been replaced with `rule.actions.`. See before/after below for more details. - `query_string` supports a list of key:value pairs; type definition updated to support this (i.e. was `map(string)` and is now `list(map(string))`) +- `aws_lb_listener.ssl_policy` now defaults to `ELBSecurityPolicy-TLS13-1-3-2021-06` ### Removed diff --git a/examples/complete-alb/README.md b/examples/complete-alb/README.md index 9e0b446..94581e3 100644 --- a/examples/complete-alb/README.md +++ b/examples/complete-alb/README.md @@ -20,7 +20,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.5 | +| [aws](#requirement\_aws) | >= 6.19 | | [null](#requirement\_null) | >= 2.0 | | [random](#requirement\_random) | >= 3.6 | @@ -28,7 +28,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 6.5 | +| [aws](#provider\_aws) | >= 6.19 | | [null](#provider\_null) | >= 2.0 | | [random](#provider\_random) | >= 3.6 | diff --git a/examples/complete-alb/main.tf b/examples/complete-alb/main.tf index 392862a..29f1a12 100644 --- a/examples/complete-alb/main.tf +++ b/examples/complete-alb/main.tf @@ -93,7 +93,7 @@ module "alb" { conditions = [{ http_header = { http_header_name = "x-Gimme-Fixed-Response" - values = ["yes", "please", "right now"] + regex_values = ["^yes$", "^please$", "^right\\snow$"] } }] } @@ -125,6 +125,26 @@ module "alb" { value = "true" }] }] + + transform = { + host-header-rewrite = { + host_header_rewrite_config = { + rewrite = { + regex = "^mywebsite-(.+).com$" + replace = "test.$1.myweb.com" + } + } + } + my_other_tranform = { + type = "url-rewrite" + url_rewrite_config = { + rewrite = { + regex = "^mywebsite-(.+).net" + replace = "test.$1.myweb.net" + } + } + } + } } ex-redirect = { diff --git a/examples/complete-alb/versions.tf b/examples/complete-alb/versions.tf index 1e24c89..93f5ac5 100644 --- a/examples/complete-alb/versions.tf +++ b/examples/complete-alb/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } null = { source = "hashicorp/null" diff --git a/examples/complete-nlb/README.md b/examples/complete-nlb/README.md index 17de1f0..c3ef6ff 100644 --- a/examples/complete-nlb/README.md +++ b/examples/complete-nlb/README.md @@ -20,13 +20,13 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.5 | +| [aws](#requirement\_aws) | >= 6.19 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 6.5 | +| [aws](#provider\_aws) | >= 6.19 | ## Modules diff --git a/examples/complete-nlb/versions.tf b/examples/complete-nlb/versions.tf index 1548bda..0d5ee58 100644 --- a/examples/complete-nlb/versions.tf +++ b/examples/complete-nlb/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } } } diff --git a/examples/mutual-auth-alb/README.md b/examples/mutual-auth-alb/README.md index 7b645a4..3c59669 100644 --- a/examples/mutual-auth-alb/README.md +++ b/examples/mutual-auth-alb/README.md @@ -21,7 +21,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.5 | +| [aws](#requirement\_aws) | >= 6.19 | | [null](#requirement\_null) | >= 2.0 | | [tls](#requirement\_tls) | >= 4.0 | @@ -29,7 +29,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 6.5 | +| [aws](#provider\_aws) | >= 6.19 | | [null](#provider\_null) | >= 2.0 | | [tls](#provider\_tls) | >= 4.0 | diff --git a/examples/mutual-auth-alb/versions.tf b/examples/mutual-auth-alb/versions.tf index b4fce63..0fd680a 100644 --- a/examples/mutual-auth-alb/versions.tf +++ b/examples/mutual-auth-alb/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } null = { source = "hashicorp/null" diff --git a/main.tf b/main.tf index 45d7938..848d7c1 100644 --- a/main.tf +++ b/main.tf @@ -450,7 +450,8 @@ resource "aws_lb_listener_rule" "this" { for_each = condition.value.host_header != null ? [condition.value.host_header] : [] content { - values = host_header.value.values + values = host_header.value.values + regex_values = host_header.value.regex_values } } @@ -460,6 +461,7 @@ resource "aws_lb_listener_rule" "this" { content { http_header_name = http_header.value.http_header_name values = http_header.value.values + regex_values = http_header.value.regex_values } } @@ -475,7 +477,8 @@ resource "aws_lb_listener_rule" "this" { for_each = condition.value.path_pattern != null ? [condition.value.path_pattern] : [] content { - values = path_pattern.value.values + values = path_pattern.value.values + regex_values = path_pattern.value.regex_values } } @@ -501,6 +504,45 @@ resource "aws_lb_listener_rule" "this" { listener_arn = try(aws_lb_listener.this[each.value.listener_key].arn, each.value.listener_arn) priority = each.value.priority + dynamic "transform" { + for_each = each.value.transform != null ? each.value.transform : {} + + content { + type = coalesce(transform.value.type, transform.key) + + dynamic "host_header_rewrite_config" { + for_each = transform.value.host_header_rewrite_config != null ? [transform.value.host_header_rewrite_config] : [] + + content { + + dynamic "rewrite" { + for_each = host_header_rewrite_config.value.rewrite != null ? [host_header_rewrite_config.value.rewrite] : [] + + content { + regex = rewrite.value.regex + replace = rewrite.value.replace + } + } + } + } + dynamic "url_rewrite_config" { + for_each = transform.value.url_rewrite_config != null ? [transform.value.url_rewrite_config] : [] + + content { + + dynamic "rewrite" { + for_each = url_rewrite_config.value.rewrite != null ? [url_rewrite_config.value.rewrite] : [] + + content { + regex = rewrite.value.regex + replace = rewrite.value.replace + } + } + } + } + } + } + tags = merge( local.tags, each.value.tags, diff --git a/modules/lb_trust_store/README.md b/modules/lb_trust_store/README.md index ad27a2e..7ef4d78 100644 --- a/modules/lb_trust_store/README.md +++ b/modules/lb_trust_store/README.md @@ -30,13 +30,13 @@ module "trust_store" { | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.5 | +| [aws](#requirement\_aws) | >= 6.19 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 6.5 | +| [aws](#provider\_aws) | >= 6.19 | ## Modules diff --git a/modules/lb_trust_store/versions.tf b/modules/lb_trust_store/versions.tf index 1548bda..0d5ee58 100644 --- a/modules/lb_trust_store/versions.tf +++ b/modules/lb_trust_store/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } } } diff --git a/variables.tf b/variables.tf index e5b0b11..8ba7981 100644 --- a/variables.tf +++ b/variables.tf @@ -378,17 +378,20 @@ variable "listeners" { })) conditions = list(object({ host_header = optional(object({ - values = list(string) + values = optional(list(string)) + regex_values = optional(list(string)) })) http_header = optional(object({ http_header_name = string - values = list(string) + values = optional(list(string)) + regex_values = optional(list(string)) })) http_request_method = optional(object({ values = list(string) })) path_pattern = optional(object({ - values = list(string) + values = optional(list(string)) + regex_values = optional(list(string)) })) query_string = optional(list(object({ key = optional(string) @@ -401,7 +404,22 @@ variable "listeners" { listener_arn = optional(string) listener_key = optional(string) priority = optional(number) - tags = optional(map(string), {}) + transform = optional(map(object({ + type = optional(string) + host_header_rewrite_config = optional(object({ + rewrite = optional(object({ + regex = string + replace = string + })) + })) + url_rewrite_config = optional(object({ + rewrite = optional(object({ + regex = string + replace = string + })) + })) + }))) + tags = optional(map(string), {}) })), {}) })) default = {} diff --git a/versions.tf b/versions.tf index 1548bda..0d5ee58 100644 --- a/versions.tf +++ b/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } } } diff --git a/wrappers/lb_trust_store/versions.tf b/wrappers/lb_trust_store/versions.tf index 1548bda..0d5ee58 100644 --- a/wrappers/lb_trust_store/versions.tf +++ b/wrappers/lb_trust_store/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } } } diff --git a/wrappers/versions.tf b/wrappers/versions.tf index 1548bda..0d5ee58 100644 --- a/wrappers/versions.tf +++ b/wrappers/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 6.5" + version = ">= 6.19" } } }