diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 71da442..02bf72e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.103.0 + rev: v1.104.0 hooks: - id: terraform_fmt - id: terraform_wrapper_module_for_each diff --git a/README.md b/README.md index c93a9a1..3f400d3 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.19 | +| [aws](#requirement\_aws) | >= 6.22 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 6.19 | +| [aws](#provider\_aws) | >= 6.22 | ## 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 = 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 |
+| [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)
}))
jwt_validation = optional(object({
issuer = string
jwks_endpoint = string
additional_claim = optional(list(object({
format = string
name = string
values = list(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
}))
jwt_validation = optional(object({
issuer = string
jwks_endpoint = string
additional_claim = optional(list(object({
format = string
name = string
values = list(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/examples/complete-alb/README.md b/examples/complete-alb/README.md
index 94581e3..db20f4b 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.19 |
+| [aws](#requirement\_aws) | >= 6.22 |
| [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.19 |
+| [aws](#provider\_aws) | >= 6.22 |
| [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 29f1a12..5410edb 100644
--- a/examples/complete-alb/main.tf
+++ b/examples/complete-alb/main.tf
@@ -395,6 +395,45 @@ module "alb" {
target_group_key = "ex-instance"
}
}
+
+ ex-jwt = {
+ port = 445
+ protocol = "HTTPS"
+ certificate_arn = module.acm.acm_certificate_arn
+
+ forward = {
+ target_group_key = "ex-instance"
+ }
+
+ rules = {
+ ex-jwt = {
+ priority = 5
+
+ actions = [
+ {
+ jwt_validation = {
+ issuer = "https://${var.domain_name}"
+ jwks_endpoint = "https://${var.domain_name}/jwks.json"
+ additional_claim = [
+ { format = "space-separated-values", name = "scp", values = ["read", "write"] }
+ ]
+ }
+ },
+ {
+ forward = {
+ target_group_key = "ex-lambda-with-trigger"
+ }
+ }
+ ]
+
+ conditions = [{
+ host_header = {
+ values = ["foobar.com"]
+ }
+ }]
+ }
+ }
+ }
}
target_groups = {
diff --git a/examples/complete-alb/versions.tf b/examples/complete-alb/versions.tf
index 93f5ac5..fa6fd38 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.19"
+ version = ">= 6.22"
}
null = {
source = "hashicorp/null"
diff --git a/examples/complete-nlb/README.md b/examples/complete-nlb/README.md
index c3ef6ff..339987a 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.19 |
+| [aws](#requirement\_aws) | >= 6.22 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.19 |
+| [aws](#provider\_aws) | >= 6.22 |
## Modules
diff --git a/examples/complete-nlb/versions.tf b/examples/complete-nlb/versions.tf
index 0d5ee58..0cf1cd7 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.19"
+ version = ">= 6.22"
}
}
}
diff --git a/examples/mutual-auth-alb/README.md b/examples/mutual-auth-alb/README.md
index 3c59669..c7f807a 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.19 |
+| [aws](#requirement\_aws) | >= 6.22 |
| [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.19 |
+| [aws](#provider\_aws) | >= 6.22 |
| [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 0fd680a..e422bce 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.19"
+ version = ">= 6.22"
}
null = {
source = "hashicorp/null"
diff --git a/main.tf b/main.tf
index 2593cec..7538187 100644
--- a/main.tf
+++ b/main.tf
@@ -164,6 +164,30 @@ resource "aws_lb_listener" "this" {
}
}
+ dynamic "default_action" {
+ for_each = each.value.jwt_validation != null ? [each.value.jwt_validation] : []
+
+ content {
+ jwt_validation {
+ issuer = default_action.value.issuer
+ jwks_endpoint = default_action.value.jwks_endpoint
+
+ dynamic "additional_claim" {
+ for_each = default_action.value.additional_claim != null ? default_action.value.additional_claim : []
+
+ content {
+ format = additional_claim.value.format
+ name = additional_claim.value.name
+ values = additional_claim.value.values
+ }
+ }
+ }
+
+ order = each.value.order
+ type = "jwt-validation"
+ }
+ }
+
dynamic "default_action" {
for_each = each.value.fixed_response != null ? [each.value.fixed_response] : []
@@ -354,6 +378,35 @@ resource "aws_lb_listener_rule" "this" {
}
}
+ # JWT validation
+ dynamic "action" {
+ for_each = [for action in each.value.actions : action if action.jwt_validation != null]
+
+ content {
+ dynamic "jwt_validation" {
+ for_each = [action.value.jwt_validation]
+
+ content {
+ issuer = jwt_validation.value.issuer
+ jwks_endpoint = jwt_validation.value.jwks_endpoint
+
+ dynamic "additional_claim" {
+ for_each = jwt_validation.value.additional_claim != null ? jwt_validation.value.additional_claim : []
+
+ content {
+ format = additional_claim.value.format
+ name = additional_claim.value.name
+ values = additional_claim.value.values
+ }
+ }
+ }
+ }
+
+ order = action.value.order
+ type = "jwt-validation"
+ }
+ }
+
# Fixed response
dynamic "action" {
for_each = [for action in each.value.actions : action if action.fixed_response != null]
diff --git a/modules/lb_trust_store/README.md b/modules/lb_trust_store/README.md
index 7ef4d78..bc3ebae 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.19 |
+| [aws](#requirement\_aws) | >= 6.22 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.19 |
+| [aws](#provider\_aws) | >= 6.22 |
## Modules
diff --git a/modules/lb_trust_store/versions.tf b/modules/lb_trust_store/versions.tf
index 0d5ee58..0cf1cd7 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.19"
+ version = ">= 6.22"
}
}
}
diff --git a/variables.tf b/variables.tf
index 5d5401b..849c7f0 100644
--- a/variables.tf
+++ b/variables.tf
@@ -269,6 +269,15 @@ variable "listeners" {
target_group_arn = optional(string)
target_group_key = optional(string)
}))
+ jwt_validation = optional(object({
+ issuer = string
+ jwks_endpoint = string
+ additional_claim = optional(list(object({
+ format = string
+ name = string
+ values = list(string)
+ })))
+ }))
weighted_forward = optional(object({
target_groups = optional(list(object({
target_group_arn = optional(string)
@@ -346,6 +355,15 @@ variable "listeners" {
token_endpoint = string
user_info_endpoint = string
}))
+ jwt_validation = optional(object({
+ issuer = string
+ jwks_endpoint = string
+ additional_claim = optional(list(object({
+ format = string
+ name = string
+ values = list(string)
+ })))
+ }))
fixed_response = optional(object({
content_type = string
message_body = optional(string)
diff --git a/versions.tf b/versions.tf
index 0d5ee58..0cf1cd7 100644
--- a/versions.tf
+++ b/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.19"
+ version = ">= 6.22"
}
}
}
diff --git a/wrappers/lb_trust_store/versions.tf b/wrappers/lb_trust_store/versions.tf
index 0d5ee58..0cf1cd7 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.19"
+ version = ">= 6.22"
}
}
}
diff --git a/wrappers/versions.tf b/wrappers/versions.tf
index 0d5ee58..0cf1cd7 100644
--- a/wrappers/versions.tf
+++ b/wrappers/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.19"
+ version = ">= 6.22"
}
}
}