diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b84d048..868fb48 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.99.4 + rev: v1.100.0 hooks: - id: terraform_fmt - id: terraform_wrapper_module_for_each @@ -24,7 +24,7 @@ repos: - '--args=--only=terraform_workspace_remote' - id: terraform_validate - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-merge-conflict - id: end-of-file-fixer diff --git a/README.md b/README.md index d85ae21..0ee9c52 100644 --- a/README.md +++ b/README.md @@ -132,21 +132,23 @@ module "alb" { actions = [ { - type = "authenticate-oidc" - authentication_request_extra_params = { - display = "page" - prompt = "login" + authenticate-oidc = { + authentication_request_extra_params = { + display = "page" + prompt = "login" + } + authorization_endpoint = "https://foobar.com/auth" + client_id = "client_id" + client_secret = "client_secret" + issuer = "https://foobar.com" + token_endpoint = "https://foobar.com/token" + user_info_endpoint = "https://foobar.com/user_info" } - authorization_endpoint = "https://foobar.com/auth" - client_id = "client_id" - client_secret = "client_secret" - issuer = "https://foobar.com" - token_endpoint = "https://foobar.com/token" - user_info_endpoint = "https://foobar.com/user_info" }, { - type = "forward" - target_group_key = "ex-instance" + forward = { + target_group_key = "ex-instance" + } } ] } @@ -178,12 +180,13 @@ module "alb" { redirect = { priority = 5000 actions = [{ - type = "redirect" - status_code = "HTTP_302" - host = "www.youtube.com" - path = "/watch" - query = "v=dQw4w9WgXcQ" - protocol = "HTTPS" + redirect = { + status_code = "HTTP_302" + host = "www.youtube.com" + path = "/watch" + query = "v=dQw4w9WgXcQ" + protocol = "HTTPS" + } }] conditions = [{ @@ -197,14 +200,16 @@ module "alb" { priority = 2 actions = [ { - type = "authenticate-cognito" - user_pool_arn = "arn:aws:cognito-idp::123456789012:userpool/test-pool" - user_pool_client_id = "6oRmFiS0JHk=" - user_pool_domain = "test-domain-com" + authenticate-cognito = { + user_pool_arn = "arn:aws:cognito-idp::123456789012:userpool/test-pool" + user_pool_client_id = "6oRmFiS0JHk=" + user_pool_domain = "test-domain-com" + } }, { - type = "forward" - target_group_key = "instance" + forward = { + target_group_key = "instance" + } } ] @@ -351,14 +356,14 @@ See [patterns.md](https://github.com/terraform-aws-modules/terraform-aws-alb/blo | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.99 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.5 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.99 | +| [aws](#provider\_aws) | >= 6.5 | ## Modules @@ -387,18 +392,18 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [access\_logs](#input\_access\_logs) | Map containing access logging configuration for load balancer | `map(string)` | `{}` | no | -| [additional\_target\_group\_attachments](#input\_additional\_target\_group\_attachments) | Map of additional target group attachments to create. Use `target_group_key` to attach to the target group created in `target_groups` | `any` | `{}` | no | +| [access\_logs](#input\_access\_logs) | Map containing access logging configuration for load balancer |
object({
bucket = string
enabled = optional(bool, true)
prefix = optional(string)
})
| `null` | no | +| [additional\_target\_group\_attachments](#input\_additional\_target\_group\_attachments) | Map of additional target group attachments to create. Use `target_group_key` to attach to the target group created in `target_groups` |
map(object({
target_group_key = string
target_id = string
target_type = optional(string)
port = optional(number)
availability_zone = optional(string)
}))
| `null` | no | | [associate\_web\_acl](#input\_associate\_web\_acl) | Indicates whether a Web Application Firewall (WAF) ACL should be associated with the load balancer | `bool` | `false` | no | -| [client\_keep\_alive](#input\_client\_keep\_alive) | Client keep alive value in seconds. The valid range is 60-604800 seconds. The default is 3600 seconds. | `number` | `null` | no | -| [connection\_logs](#input\_connection\_logs) | Map containing access logging configuration for load balancer | `map(string)` | `{}` | no | +| [client\_keep\_alive](#input\_client\_keep\_alive) | Client keep alive value in seconds. The valid range is 60-604800 seconds. The default is 3600 seconds | `number` | `null` | no | +| [connection\_logs](#input\_connection\_logs) | Map containing access logging configuration for load balancer |
object({
bucket = string
enabled = optional(bool, true)
prefix = optional(string)
})
| `null` | no | | [create](#input\_create) | Controls if resources should be created (affects nearly all resources) | `bool` | `true` | no | | [create\_security\_group](#input\_create\_security\_group) | Determines if a security group is created | `bool` | `true` | no | | [customer\_owned\_ipv4\_pool](#input\_customer\_owned\_ipv4\_pool) | The ID of the customer owned ipv4 pool to use for this load balancer | `string` | `null` | no | | [default\_port](#input\_default\_port) | Default port used across the listener and target group | `number` | `80` | no | | [default\_protocol](#input\_default\_protocol) | Default protocol used across the listener and target group | `string` | `"HTTP"` | no | | [desync\_mitigation\_mode](#input\_desync\_mitigation\_mode) | Determines how the load balancer handles requests that might pose a security risk to an application due to HTTP desync. Valid values are `monitor`, `defensive` (default), `strictest` | `string` | `null` | no | -| [dns\_record\_client\_routing\_policy](#input\_dns\_record\_client\_routing\_policy) | Indicates how traffic is distributed among the load balancer Availability Zones. Possible values are any\_availability\_zone (default), availability\_zone\_affinity, or partial\_availability\_zone\_affinity. Only valid for network type load balancers. | `string` | `null` | no | +| [dns\_record\_client\_routing\_policy](#input\_dns\_record\_client\_routing\_policy) | Indicates how traffic is distributed among the load balancer Availability Zones. Possible values are any\_availability\_zone (default), availability\_zone\_affinity, or partial\_availability\_zone\_affinity. Only valid for network type load balancers | `string` | `null` | no | | [drop\_invalid\_header\_fields](#input\_drop\_invalid\_header\_fields) | Indicates whether HTTP headers with header fields that are not valid are removed by the load balancer (`true`) or routed to targets (`false`). The default is `true`. Elastic Load Balancing requires that message header names contain only alphanumeric characters and hyphens. Only valid for Load Balancers of type `application` | `bool` | `true` | no | | [enable\_cross\_zone\_load\_balancing](#input\_enable\_cross\_zone\_load\_balancing) | If `true`, cross-zone load balancing of the load balancer will be enabled. For application load balancer this feature is always enabled (`true`) and cannot be disabled. Defaults to `true` | `bool` | `true` | no | | [enable\_deletion\_protection](#input\_enable\_deletion\_protection) | If `true`, deletion of the load balancer will be disabled via the AWS API. This will prevent Terraform from deleting the load balancer. Defaults to `true` | `bool` | `true` | no | @@ -407,31 +412,32 @@ No modules. | [enable\_waf\_fail\_open](#input\_enable\_waf\_fail\_open) | Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF. Defaults to `false` | `bool` | `null` | no | | [enable\_xff\_client\_port](#input\_enable\_xff\_client\_port) | Indicates whether the X-Forwarded-For header should preserve the source port that the client used to connect to the load balancer in `application` load balancers. Defaults to `false` | `bool` | `null` | no | | [enable\_zonal\_shift](#input\_enable\_zonal\_shift) | Whether zonal shift is enabled | `bool` | `null` | no | -| [enforce\_security\_group\_inbound\_rules\_on\_private\_link\_traffic](#input\_enforce\_security\_group\_inbound\_rules\_on\_private\_link\_traffic) | Indicates whether inbound security group rules are enforced for traffic originating from a PrivateLink. Only valid for Load Balancers of type network. The possible values are on and off. | `string` | `null` | no | +| [enforce\_security\_group\_inbound\_rules\_on\_private\_link\_traffic](#input\_enforce\_security\_group\_inbound\_rules\_on\_private\_link\_traffic) | Indicates whether inbound security group rules are enforced for traffic originating from a PrivateLink. Only valid for Load Balancers of type network. The possible values are on and off | `string` | `null` | no | | [idle\_timeout](#input\_idle\_timeout) | The time in seconds that the connection is allowed to be idle. Only valid for Load Balancers of type `application`. Default: `60` | `number` | `null` | no | | [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 | `map(string)` | `{}` | no | -| [listeners](#input\_listeners) | Map of listener configurations to create | `any` | `{}` | 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 | | [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` | `any` | `{}` | 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 | | [name\_prefix](#input\_name\_prefix) | Creates a unique name beginning with the specified prefix. Conflicts with `name` | `string` | `null` | no | | [preserve\_host\_header](#input\_preserve\_host\_header) | Indicates whether the Application Load Balancer should preserve the Host header in the HTTP request and send it to the target without any change. Defaults to `false` | `bool` | `null` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | -| [route53\_records](#input\_route53\_records) | Map of Route53 records to create. Each record map should contain `zone_id`, `name`, and `type` | `any` | `{}` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | +| [route53\_records](#input\_route53\_records) | Map of Route53 records to create. Each record map should contain `zone_id`, `name`, and `type` |
map(object({
zone_id = string
name = optional(string)
type = string
}))
| `null` | no | | [security\_group\_description](#input\_security\_group\_description) | Description of the security group created | `string` | `null` | no | -| [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | Security group egress rules to add to the security group created | `any` | `{}` | no | -| [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Security group ingress rules to add to the security group created | `any` | `{}` | no | +| [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | Security group egress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `null` | no | +| [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Security group ingress rules to add to the security group created |
map(object({
name = optional(string)

cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string, "tcp")
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
tags = optional(map(string), {})
to_port = optional(string)
}))
| `null` | no | | [security\_group\_name](#input\_security\_group\_name) | Name to use on security group created | `string` | `null` | no | | [security\_group\_tags](#input\_security\_group\_tags) | A map of additional tags to add to the security group created | `map(string)` | `{}` | no | | [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether the security group name (`security_group_name`) is used as a prefix | `bool` | `true` | no | | [security\_groups](#input\_security\_groups) | A list of security group IDs to assign to the LB | `list(string)` | `[]` | no | -| [subnet\_mapping](#input\_subnet\_mapping) | A list of subnet mapping blocks describing subnets to attach to load balancer | `list(map(string))` | `[]` | no | +| [subnet\_mapping](#input\_subnet\_mapping) | A list of subnet mapping blocks describing subnets to attach to load balancer |
list(object({
allocation_id = optional(string)
ipv6_address = optional(string)
private_ipv4_address = optional(string)
subnet_id = string
}))
| `null` | no | | [subnets](#input\_subnets) | A list of subnet IDs to attach to the LB. Subnets cannot be updated for Load Balancers of type `network`. Changing this value for load balancers of type `network` will force a recreation of the resource | `list(string)` | `null` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | -| [target\_groups](#input\_target\_groups) | Map of target group configurations to create | `any` | `{}` | no | -| [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the load balancer | `map(string)` | `{}` | no | +| [target\_groups](#input\_target\_groups) | Map of target group configurations to create |
map(object({
connection_termination = optional(bool)
deregistration_delay = optional(number)
health_check = optional(object({
enabled = optional(bool)
healthy_threshold = optional(number)
interval = optional(number)
matcher = optional(string)
path = optional(string)
port = optional(string)
protocol = optional(string)
timeout = optional(number)
unhealthy_threshold = optional(number)
}))
ip_address_type = optional(string)
lambda_multi_value_headers_enabled = optional(bool)
load_balancing_algorithm_type = optional(string)
load_balancing_anomaly_mitigation = optional(string)
load_balancing_cross_zone_enabled = optional(bool)
name = optional(string)
name_prefix = optional(string)
port = optional(number)
preserve_client_ip = optional(bool)
protocol = optional(string)
protocol_version = optional(string)
proxy_protocol_v2 = optional(bool)
slow_start = optional(number)
stickiness = optional(object({
cookie_duration = optional(number)
cookie_name = optional(string)
enabled = optional(bool)
type = string
}))
tags = optional(map(string))
target_failover = optional(list(object({
on_deregistration = string
on_unhealthy = string
})))
target_group_health = optional(object({
dns_failover = optional(object({
minimum_healthy_targets_count = optional(string)
minimum_healthy_targets_percentage = optional(string)
}))
unhealthy_state_routing = optional(object({
minimum_healthy_targets_count = optional(number)
minimum_healthy_targets_percentage = optional(string)
}))
}))
target_health_state = optional(object({
enable_unhealthy_connection_termination = bool
unhealthy_draining_interval = optional(number)
}))
target_type = optional(string)
target_id = optional(string)
vpc_id = optional(string)
# Attachment
create_attachment = optional(bool, true)
availability_zone = optional(string)
# Lambda
attach_lambda_permission = optional(bool, false)
lambda_qualifier = optional(string)
lambda_statement_id = optional(string)
lambda_action = optional(string)
lambda_principal = optional(string)
lambda_source_account = optional(string)
lambda_event_source_token = optional(string)
}))
| `null` | no | +| [timeouts](#input\_timeouts) | Create, update, and delete timeout configurations for the load balancer |
object({
create = optional(string)
update = optional(string)
delete = optional(string)
})
| `null` | no | | [vpc\_id](#input\_vpc\_id) | Identifier of the VPC where the security group will be created | `string` | `null` | no | | [web\_acl\_arn](#input\_web\_acl\_arn) | Web Application Firewall (WAF) ARN of the resource to associate with the load balancer | `string` | `null` | no | | [xff\_header\_processing\_mode](#input\_xff\_header\_processing\_mode) | Determines how the load balancer modifies the X-Forwarded-For header in the HTTP request before sending the request to the target. The possible values are `append`, `preserve`, and `remove`. Only valid for Load Balancers of type `application`. The default is `append` | `string` | `null` | no | diff --git a/docs/UPGRADE-10.0.md b/docs/UPGRADE-10.0.md new file mode 100644 index 0000000..c568323 --- /dev/null +++ b/docs/UPGRADE-10.0.md @@ -0,0 +1,103 @@ +# Upgrade from v9.x to v10.x + +Please consult the `examples` directory for reference example configurations. If you find a bug, please open an issue with supporting configuration to reproduce. + +## List of backwards incompatible changes + +- Terraform `v1.5.7` is now minimum supported version +- AWS provider `v6.5` is now minimum supported version + +## Additional changes + +### Added + +- Support for `region` parameter to specify the AWS region for the resources created if different from the provider region. + +### Modified + +- Variable definitions now contain detailed `object` types in place of the previously used `any` type. +- 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))`) + +### Removed + +- None + +### Variable and output changes + +1. Removed variables: + + - None + +2. Renamed variables: + + - None + +3. Added variables: + + - None + +4. Removed outputs: + + - None + +5. Renamed outputs: + + - None + +6. Added outputs: + + - None + +## Upgrade Migrations + +### Diff of Before vs After + +```diff + module "alb" { + source = "terraform-aws-modules/alb/aws" +- version = "9.17.0" ++ version = "10.0.0" + + listeners = { + ex-http-https-redirect = { + port = 80 + protocol = "HTTP" + redirect = { + port = "443" + protocol = "HTTPS" + status_code = "HTTP_301" + } + + rules = { + ex-fixed-response = { + priority = 3 + actions = [{ + # Same for all action types, not just `fixed_response` +- type = "fixed-response" ++ fixed_response = { + content_type = "text/plain" + status_code = 200 + message_body = "This is a fixed response" ++ } + }] + + conditions = [{ +- query_string = { ++ query_string = [{ + key = "weighted" + value = "true" +- } ++ }] + }] + } + } + } + } +} +``` + +## Terraform State Moves + +None required diff --git a/UPGRADE-5.0.md b/docs/UPGRADE-5.0.md similarity index 100% rename from UPGRADE-5.0.md rename to docs/UPGRADE-5.0.md diff --git a/UPGRADE-9.0.md b/docs/UPGRADE-9.0.md similarity index 100% rename from UPGRADE-9.0.md rename to docs/UPGRADE-9.0.md diff --git a/docs/patterns.md b/docs/patterns.md index 2cabe5d..17585c0 100644 --- a/docs/patterns.md +++ b/docs/patterns.md @@ -226,12 +226,12 @@ module "alb" { weighted_forward = { target_groups = [ { - target_group_key = "ex-lambda-with-trigger" - weight = 60 + key = "ex-lambda-with-trigger" + weight = 60 }, { - target_group_key = "ex-lambda-without-trigger" - weight = 40 + key = "ex-lambda-without-trigger" + weight = 40 } ] } @@ -257,7 +257,7 @@ module "alb" { module "lambda_with_allowed_triggers" { source = "terraform-aws-modules/lambda/aws" - version = "~> 6.0" + version = "~> 8.0" # Truncated for brevity ... @@ -271,7 +271,7 @@ module "lambda_with_allowed_triggers" { module "lambda_without_allowed_triggers" { source = "terraform-aws-modules/lambda/aws" - version = "~> 6.0" + version = "~> 8.0" # Truncated for brevity ... diff --git a/examples/complete-alb/README.md b/examples/complete-alb/README.md index 29f0c83..9e0b446 100644 --- a/examples/complete-alb/README.md +++ b/examples/complete-alb/README.md @@ -19,8 +19,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.99 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.5 | | [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) | >= 5.99 | +| [aws](#provider\_aws) | >= 6.5 | | [null](#provider\_null) | >= 2.0 | | [random](#provider\_random) | >= 3.6 | @@ -36,14 +36,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Source | Version | |------|--------|---------| -| [acm](#module\_acm) | terraform-aws-modules/acm/aws | ~> 4.0 | +| [acm](#module\_acm) | terraform-aws-modules/acm/aws | ~> 5.0 | | [alb](#module\_alb) | ../../ | n/a | | [alb\_disabled](#module\_alb\_disabled) | ../../ | n/a | -| [lambda\_with\_allowed\_triggers](#module\_lambda\_with\_allowed\_triggers) | terraform-aws-modules/lambda/aws | ~> 6.0 | -| [lambda\_without\_allowed\_triggers](#module\_lambda\_without\_allowed\_triggers) | terraform-aws-modules/lambda/aws | ~> 6.0 | -| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | -| [wildcard\_cert](#module\_wildcard\_cert) | terraform-aws-modules/acm/aws | ~> 4.0 | +| [lambda\_with\_allowed\_triggers](#module\_lambda\_with\_allowed\_triggers) | terraform-aws-modules/lambda/aws | ~> 8.0 | +| [lambda\_without\_allowed\_triggers](#module\_lambda\_without\_allowed\_triggers) | terraform-aws-modules/lambda/aws | ~> 8.0 | +| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | +| [wildcard\_cert](#module\_wildcard\_cert) | terraform-aws-modules/acm/aws | ~> 5.0 | ## Resources @@ -54,14 +54,11 @@ Note that this example may create resources which cost money. Run `terraform des | [aws_cognito_user_pool_domain.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_domain) | resource | | [aws_instance.other](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | -| [aws_vpc_ipam.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam) | resource | -| [aws_vpc_ipam_pool.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool) | resource | -| [aws_vpc_ipam_pool_cidr.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_ipam_pool_cidr) | resource | | [null_resource.download_package](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [random_string.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | -| [aws_ssm_parameter.al2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_ssm_parameter.al2023](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | ## Inputs diff --git a/examples/complete-alb/main.tf b/examples/complete-alb/main.tf index 4176781..0963b2b 100644 --- a/examples/complete-alb/main.tf +++ b/examples/complete-alb/main.tf @@ -67,14 +67,6 @@ module "alb" { prefix = "connection-logs" } - ipam_pools = { - ipv4_ipam_pool_id = aws_vpc_ipam_pool.this.id - } - - minimum_load_balancer_capacity = { - capacity_units = 10 - } - client_keep_alive = 7200 listeners = { @@ -91,10 +83,11 @@ module "alb" { ex-fixed-response = { priority = 3 actions = [{ - type = "fixed-response" - content_type = "text/plain" - status_code = 200 - message_body = "This is a fixed response" + fixed_response = { + content_type = "text/plain" + status_code = 200 + message_body = "This is a fixed response" + } }] conditions = [{ @@ -108,51 +101,55 @@ module "alb" { ex-weighted-forward = { priority = 4 actions = [{ - type = "weighted-forward" - target_groups = [ - { - target_group_key = "ex-lambda-with-trigger" - weight = 2 - }, - { - target_group_key = "ex-instance" - weight = 1 + weighted_forward = { + target_groups = [ + { + key = "ex-lambda-with-trigger" + weight = 2 + }, + { + key = "ex-instance" + weight = 1 + } + ] + stickiness = { + enabled = true + duration = 3600 } - ] - stickiness = { - enabled = true - duration = 3600 } }] conditions = [{ - query_string = { + query_string = [{ key = "weighted" value = "true" - } + }] }] } ex-redirect = { priority = 5000 actions = [{ - type = "redirect" - status_code = "HTTP_302" - host = "www.youtube.com" - path = "/watch" - query = "v=dQw4w9WgXcQ" - protocol = "HTTPS" + redirect = { + status_code = "HTTP_302" + host = "www.youtube.com" + path = "/watch" + query = "v=dQw4w9WgXcQ" + protocol = "HTTPS" + } }] conditions = [{ - query_string = [{ - key = "video" - value = "random" + query_string = [ + { + key = "video" + value = "random" }, { key = "image" value = "next" - }] + } + ] }] } } @@ -200,17 +197,19 @@ module "alb" { ex-cognito = { actions = [ { - type = "authenticate-cognito" - on_unauthenticated_request = "authenticate" - session_cookie_name = "session-${local.name}" - session_timeout = 3600 - user_pool_arn = aws_cognito_user_pool.this.arn - user_pool_client_id = aws_cognito_user_pool_client.this.id - user_pool_domain = aws_cognito_user_pool_domain.this.domain + authenticate_cognito = { + on_unauthenticated_request = "authenticate" + session_cookie_name = "session-${local.name}" + session_timeout = 3600 + user_pool_arn = aws_cognito_user_pool.this.arn + user_pool_client_id = aws_cognito_user_pool_client.this.id + user_pool_domain = aws_cognito_user_pool_domain.this.domain + } }, { - type = "forward" - target_group_key = "ex-instance" + forward = { + target_group_key = "ex-instance" + } } ] @@ -224,10 +223,11 @@ module "alb" { ex-fixed-response = { priority = 3 actions = [{ - type = "fixed-response" - content_type = "text/plain" - status_code = 200 - message_body = "This is a fixed response" + fixed_response = { + content_type = "text/plain" + status_code = 200 + message_body = "This is a fixed response" + } }] conditions = [{ @@ -241,28 +241,29 @@ module "alb" { ex-weighted-forward = { priority = 4 actions = [{ - type = "weighted-forward" - target_groups = [ - { - target_group_key = "ex-instance" - weight = 2 - }, - { - target_group_key = "ex-lambda-with-trigger" - weight = 1 + weighted_forward = { + target_groups = [ + { + target_group_key = "ex-instance" + weight = 2 + }, + { + target_group_key = "ex-lambda-with-trigger" + weight = 1 + } + ] + stickiness = { + enabled = true + duration = 3600 } - ] - stickiness = { - enabled = true - duration = 3600 } }] conditions = [{ - query_string = { + query_string = [{ key = "weighted" value = "true" - }, + }], path_pattern = { values = ["/some/path"] } @@ -272,19 +273,20 @@ module "alb" { ex-redirect = { priority = 5000 actions = [{ - type = "redirect" - status_code = "HTTP_302" - host = "www.youtube.com" - path = "/watch" - query = "v=dQw4w9WgXcQ" - protocol = "HTTPS" + redirect = { + status_code = "HTTP_302" + host = "www.youtube.com" + path = "/watch" + query = "v=dQw4w9WgXcQ" + protocol = "HTTPS" + } }] conditions = [{ - query_string = { + query_string = [{ key = "video" value = "random" - } + }] }] } } @@ -318,21 +320,23 @@ module "alb" { actions = [ { - type = "authenticate-oidc" - authentication_request_extra_params = { - display = "page" - prompt = "login" + authenticate_oidc = { + authentication_request_extra_params = { + display = "page" + prompt = "login" + } + authorization_endpoint = "https://${var.domain_name}/auth" + client_id = "client_id" + client_secret = "client_secret" + issuer = "https://${var.domain_name}" + token_endpoint = "https://${var.domain_name}/token" + user_info_endpoint = "https://${var.domain_name}/user_info" } - authorization_endpoint = "https://${var.domain_name}/auth" - client_id = "client_id" - client_secret = "client_secret" - issuer = "https://${var.domain_name}" - token_endpoint = "https://${var.domain_name}/token" - user_info_endpoint = "https://${var.domain_name}/user_info" }, { - type = "forward" - target_group_key = "ex-lambda-with-trigger" + forward = { + target_group_key = "ex-lambda-with-trigger" + } } ] @@ -367,53 +371,6 @@ module "alb" { target_group_key = "ex-instance" } } - - ex-response-headers = { - port = "443" - protocol = "HTTPS" - ssl_policy = "ELBSecurityPolicy-TLS13-1-2-Res-2021-06" - certificate_arn = module.acm.acm_certificate_arn - - fixed_response = { - content_type = "text/plain" - message_body = "Fixed message" - status_code = "200" - } - - routing_http_response_server_enabled = false - routing_http_response_strict_transport_security_header_value = "max-age=31536000; includeSubDomains; preload" - routing_http_response_access_control_allow_origin_header_value = "https://example.com" - routing_http_response_access_control_allow_methods_header_value = "TRACE,GET" - routing_http_response_access_control_allow_headers_header_value = "Accept-Language,Content-Language" - routing_http_response_access_control_allow_credentials_header_value = "true" - routing_http_response_access_control_expose_headers_header_value = "Cache-Control" - routing_http_response_access_control_max_age_header_value = 86400 - routing_http_response_content_security_policy_header_value = "*" - routing_http_response_x_content_type_options_header_value = "nosniff" - routing_http_response_x_frame_options_header_value = "SAMEORIGIN" - } - - ex-request-headers = { - port = "443" - protocol = "HTTPS" - ssl_policy = "ELBSecurityPolicy-TLS13-1-2-Res-2021-06" - certificate_arn = module.acm.acm_certificate_arn - - fixed_response = { - content_type = "text/plain" - message_body = "Fixed message" - status_code = "200" - } - - routing_http_request_x_amzn_tls_version_header_name = "X-Amzn-Tls-Version-Custom" - routing_http_request_x_amzn_tls_cipher_suite_header_name = "X-Amzn-Tls-Cipher-Suite-Custom" - routing_http_request_x_amzn_mtls_clientcert_header_name = "X-Amzn-Mtls-Clientcert-Custom" - routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name = "X-Amzn-Mtls-Clientcert-Serial-Number-Custom" - routing_http_request_x_amzn_mtls_clientcert_issuer_header_name = "X-Amzn-Mtls-Clientcert-Issuer-Custom" - routing_http_request_x_amzn_mtls_clientcert_subject_header_name = "X-Amzn-Mtls-Clientcert-Subject-Custom" - routing_http_request_x_amzn_mtls_clientcert_validity_header_name = "X-Amzn-Mtls-Clientcert-Validity-Custom" - routing_http_request_x_amzn_mtls_clientcert_leaf_header_name = "X-Amzn-Mtls-Clientcert-Leaf-Custom" - } } target_groups = { @@ -508,7 +465,7 @@ module "alb_disabled" { ################################################################################ locals { - package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python3.8-zip/existing_package.zip" + package_url = "https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-lambda/master/examples/fixtures/python-zip/existing_package.zip" downloaded = "downloaded_package_${md5(local.package_url)}.zip" } @@ -524,12 +481,12 @@ resource "null_resource" "download_package" { module "lambda_with_allowed_triggers" { source = "terraform-aws-modules/lambda/aws" - version = "~> 6.0" + version = "~> 8.0" function_name = "${local.name}-with-allowed-triggers" description = "My awesome lambda function (with allowed triggers)" handler = "index.lambda_handler" - runtime = "python3.8" + runtime = "python3.13" publish = true create_package = false @@ -547,12 +504,12 @@ module "lambda_with_allowed_triggers" { module "lambda_without_allowed_triggers" { source = "terraform-aws-modules/lambda/aws" - version = "~> 6.0" + version = "~> 8.0" function_name = "${local.name}-without-allowed-triggers" description = "My awesome lambda function (without allowed triggers)" handler = "index.lambda_handler" - runtime = "python3.8" + runtime = "python3.13" publish = true create_package = false @@ -570,7 +527,7 @@ module "lambda_without_allowed_triggers" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr @@ -588,32 +545,38 @@ data "aws_route53_zone" "this" { module "acm" { source = "terraform-aws-modules/acm/aws" - version = "~> 4.0" + version = "~> 5.0" + + domain_name = var.domain_name + zone_id = data.aws_route53_zone.this.id + validation_method = "DNS" - domain_name = var.domain_name - zone_id = data.aws_route53_zone.this.id + tags = local.tags } module "wildcard_cert" { source = "terraform-aws-modules/acm/aws" - version = "~> 4.0" + version = "~> 5.0" + + domain_name = "*.${var.domain_name}" + zone_id = data.aws_route53_zone.this.id + validation_method = "DNS" - domain_name = "*.${var.domain_name}" - zone_id = data.aws_route53_zone.this.id + tags = local.tags } -data "aws_ssm_parameter" "al2" { - name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" +data "aws_ssm_parameter" "al2023" { + name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64" } resource "aws_instance" "this" { - ami = data.aws_ssm_parameter.al2.value + ami = data.aws_ssm_parameter.al2023.value instance_type = "t3.nano" subnet_id = element(module.vpc.private_subnets, 0) } resource "aws_instance" "other" { - ami = data.aws_ssm_parameter.al2.value + ami = data.aws_ssm_parameter.al2023.value instance_type = "t3.nano" subnet_id = element(module.vpc.private_subnets, 0) } @@ -649,7 +612,7 @@ resource "aws_cognito_user_pool_domain" "this" { module "log_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" + version = "~> 5.0" bucket_prefix = "${local.name}-logs-" acl = "log-delivery-write" @@ -668,28 +631,3 @@ module "log_bucket" { tags = local.tags } - -################################################################## -# AWS VPC IPAM -################################################################## - -resource "aws_vpc_ipam" "this" { - operating_regions { - region_name = local.region - } -} - -resource "aws_vpc_ipam_pool" "this" { - address_family = "ipv4" - ipam_scope_id = aws_vpc_ipam.this.public_default_scope_id - locale = local.region - allocation_default_netmask_length = 30 - - public_ip_source = "amazon" - aws_service = "ec2" -} - -resource "aws_vpc_ipam_pool_cidr" "this" { - ipam_pool_id = aws_vpc_ipam_pool.this.id - netmask_length = 30 -} diff --git a/examples/complete-alb/versions.tf b/examples/complete-alb/versions.tf index 52c762c..1e24c89 100644 --- a/examples/complete-alb/versions.tf +++ b/examples/complete-alb/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } null = { source = "hashicorp/null" diff --git a/examples/complete-nlb/README.md b/examples/complete-nlb/README.md index 72592ac..17de1f0 100644 --- a/examples/complete-nlb/README.md +++ b/examples/complete-nlb/README.md @@ -19,23 +19,23 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.99 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.5 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.99 | +| [aws](#provider\_aws) | >= 6.5 | ## Modules | Name | Source | Version | |------|--------|---------| -| [acm](#module\_acm) | terraform-aws-modules/acm/aws | ~> 4.0 | -| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | +| [acm](#module\_acm) | terraform-aws-modules/acm/aws | ~> 5.0 | +| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 | | [nlb](#module\_nlb) | ../../ | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources @@ -45,7 +45,7 @@ Note that this example may create resources which cost money. Run `terraform des | [aws_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | -| [aws_ssm_parameter.al2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_ssm_parameter.al2023](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | ## Inputs diff --git a/examples/complete-nlb/main.tf b/examples/complete-nlb/main.tf index 8ebc301..a0ebbce 100644 --- a/examples/complete-nlb/main.tf +++ b/examples/complete-nlb/main.tf @@ -177,7 +177,7 @@ module "nlb" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr @@ -195,10 +195,13 @@ data "aws_route53_zone" "this" { module "acm" { source = "terraform-aws-modules/acm/aws" - version = "~> 4.0" + version = "~> 5.0" + + domain_name = var.domain_name + zone_id = data.aws_route53_zone.this.id + validation_method = "DNS" - domain_name = var.domain_name - zone_id = data.aws_route53_zone.this.id + tags = local.tags } resource "aws_eip" "this" { @@ -207,19 +210,19 @@ resource "aws_eip" "this" { domain = "vpc" } -data "aws_ssm_parameter" "al2" { - name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" +data "aws_ssm_parameter" "al2023" { + name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64" } resource "aws_instance" "this" { - ami = data.aws_ssm_parameter.al2.value + ami = data.aws_ssm_parameter.al2023.value instance_type = "t3.nano" subnet_id = element(module.vpc.private_subnets, 0) } module "log_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" + version = "~> 5.0" bucket_prefix = "${local.name}-logs-" acl = "log-delivery-write" diff --git a/examples/complete-nlb/versions.tf b/examples/complete-nlb/versions.tf index 57efb00..1548bda 100644 --- a/examples/complete-nlb/versions.tf +++ b/examples/complete-nlb/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } } } diff --git a/examples/mutual-auth-alb/README.md b/examples/mutual-auth-alb/README.md index 6cd81ed..7b645a4 100644 --- a/examples/mutual-auth-alb/README.md +++ b/examples/mutual-auth-alb/README.md @@ -20,8 +20,8 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.99 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.5 | | [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) | >= 5.99 | +| [aws](#provider\_aws) | >= 6.5 | | [null](#provider\_null) | >= 2.0 | | [tls](#provider\_tls) | >= 4.0 | @@ -37,14 +37,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Source | Version | |------|--------|---------| -| [acm](#module\_acm) | terraform-aws-modules/acm/aws | ~> 4.0 | +| [acm](#module\_acm) | terraform-aws-modules/acm/aws | ~> 5.0 | | [alb](#module\_alb) | ../../ | n/a | -| [ca\_cert\_object](#module\_ca\_cert\_object) | terraform-aws-modules/s3-bucket/aws//modules/object | n/a | -| [certificate\_bucket](#module\_certificate\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | -| [crl\_object](#module\_crl\_object) | terraform-aws-modules/s3-bucket/aws//modules/object | n/a | -| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | +| [ca\_cert\_object](#module\_ca\_cert\_object) | terraform-aws-modules/s3-bucket/aws//modules/object | ~> 5.0 | +| [certificate\_bucket](#module\_certificate\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 | +| [crl\_object](#module\_crl\_object) | terraform-aws-modules/s3-bucket/aws//modules/object | ~> 5.0 | +| [log\_bucket](#module\_log\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 5.0 | | [trust\_store](#module\_trust\_store) | ../../modules/lb_trust_store | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 6.0 | ## Resources @@ -62,7 +62,7 @@ Note that this example may create resources which cost money. Run `terraform des | [tls_self_signed_cert.root_ca](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/self_signed_cert) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | -| [aws_ssm_parameter.al2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | +| [aws_ssm_parameter.al2023](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | ## Inputs diff --git a/examples/mutual-auth-alb/main.tf b/examples/mutual-auth-alb/main.tf index 2370d26..261073c 100644 --- a/examples/mutual-auth-alb/main.tf +++ b/examples/mutual-auth-alb/main.tf @@ -96,10 +96,11 @@ module "alb" { priority = 3 actions = [ { - type = "fixed-response" - content_type = "text/plain" - status_code = 200 - message_body = "This is a fixed response" + fixed_response = { + content_type = "text/plain" + status_code = 200 + message_body = "This is a fixed response" + } } ] conditions = [{ @@ -184,7 +185,7 @@ module "trust_store" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 5.0" + version = "~> 6.0" name = local.name cidr = local.vpc_cidr @@ -196,19 +197,19 @@ module "vpc" { tags = local.tags } -data "aws_ssm_parameter" "al2" { - name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" +data "aws_ssm_parameter" "al2023" { + name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64" } resource "aws_instance" "this" { - ami = data.aws_ssm_parameter.al2.value + ami = data.aws_ssm_parameter.al2023.value instance_type = "t3.nano" subnet_id = element(module.vpc.private_subnets, 0) } module "log_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" + version = "~> 5.0" bucket_prefix = "${local.name}-logs-" acl = "log-delivery-write" @@ -234,10 +235,13 @@ data "aws_route53_zone" "this" { module "acm" { source = "terraform-aws-modules/acm/aws" - version = "~> 4.0" + version = "~> 5.0" + + domain_name = "*.${var.domain_name}" + zone_id = data.aws_route53_zone.this.id + validation_method = "DNS" - domain_name = "*.${var.domain_name}" - zone_id = data.aws_route53_zone.this.id + tags = local.tags } resource "null_resource" "generate_crl" { @@ -253,7 +257,7 @@ resource "null_resource" "generate_crl" { module "certificate_bucket" { source = "terraform-aws-modules/s3-bucket/aws" - version = "~> 3.0" + version = "~> 5.0" bucket_prefix = "${local.name}-certificate-" force_destroy = true @@ -262,7 +266,8 @@ module "certificate_bucket" { } module "ca_cert_object" { - source = "terraform-aws-modules/s3-bucket/aws//modules/object" + source = "terraform-aws-modules/s3-bucket/aws//modules/object" + version = "~> 5.0" bucket = module.certificate_bucket.s3_bucket_id key = "ca_cert/RootCA.pem" @@ -273,7 +278,8 @@ module "ca_cert_object" { } module "crl_object" { - source = "terraform-aws-modules/s3-bucket/aws//modules/object" + source = "terraform-aws-modules/s3-bucket/aws//modules/object" + version = "~> 5.0" bucket = module.certificate_bucket.s3_bucket_id key = "crl/crl.pem" diff --git a/examples/mutual-auth-alb/versions.tf b/examples/mutual-auth-alb/versions.tf index ed93d64..b4fce63 100644 --- a/examples/mutual-auth-alb/versions.tf +++ b/examples/mutual-auth-alb/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } null = { source = "hashicorp/null" diff --git a/main.tf b/main.tf index f23b561..45d7938 100644 --- a/main.tf +++ b/main.tf @@ -1,4 +1,6 @@ -data "aws_partition" "current" {} +data "aws_partition" "current" { + count = local.create ? 1 : 0 +} locals { create = var.create && var.putin_khuylo @@ -12,42 +14,30 @@ locals { resource "aws_lb" "this" { count = local.create ? 1 : 0 + region = var.region + dynamic "access_logs" { - for_each = length(var.access_logs) > 0 ? [var.access_logs] : [] + for_each = var.access_logs != null ? [var.access_logs] : [] content { bucket = access_logs.value.bucket - enabled = try(access_logs.value.enabled, true) - prefix = try(access_logs.value.prefix, null) - } - } - - dynamic "connection_logs" { - for_each = length(var.connection_logs) > 0 ? [var.connection_logs] : [] - content { - bucket = connection_logs.value.bucket - enabled = try(connection_logs.value.enabled, true) - prefix = try(connection_logs.value.prefix, null) + enabled = access_logs.value.enabled + prefix = access_logs.value.prefix } } - dynamic "ipam_pools" { - for_each = length(var.ipam_pools) > 0 ? [var.ipam_pools] : [] - - content { - ipv4_ipam_pool_id = ipam_pools.value.ipv4_ipam_pool_id - } - } + client_keep_alive = var.client_keep_alive - dynamic "minimum_load_balancer_capacity" { - for_each = length(var.minimum_load_balancer_capacity) > 0 ? [var.minimum_load_balancer_capacity] : [] + dynamic "connection_logs" { + for_each = var.connection_logs != null ? [var.connection_logs] : [] content { - capacity_units = minimum_load_balancer_capacity.value.capacity_units + bucket = connection_logs.value.bucket + enabled = connection_logs.value.enabled + prefix = connection_logs.value.prefix } } - client_keep_alive = var.client_keep_alive customer_owned_ipv4_pool = var.customer_owned_ipv4_pool desync_mitigation_mode = var.desync_mitigation_mode dns_record_client_routing_policy = var.dns_record_client_routing_policy @@ -63,19 +53,37 @@ resource "aws_lb" "this" { idle_timeout = var.idle_timeout internal = var.internal ip_address_type = var.ip_address_type - load_balancer_type = var.load_balancer_type - name = var.name - name_prefix = var.name_prefix - preserve_host_header = var.preserve_host_header - security_groups = var.create_security_group ? concat([aws_security_group.this[0].id], var.security_groups) : var.security_groups + + dynamic "ipam_pools" { + for_each = var.ipam_pools != null ? [var.ipam_pools] : [] + + content { + ipv4_ipam_pool_id = ipam_pools.value.ipv4_ipam_pool_id + } + } + + load_balancer_type = var.load_balancer_type + + dynamic "minimum_load_balancer_capacity" { + for_each = var.minimum_load_balancer_capacity != null ? [var.minimum_load_balancer_capacity] : [] + + content { + capacity_units = minimum_load_balancer_capacity.value.capacity_units + } + } + + name = var.name + name_prefix = var.name_prefix + preserve_host_header = var.preserve_host_header + security_groups = var.create_security_group ? concat([aws_security_group.this[0].id], var.security_groups) : var.security_groups dynamic "subnet_mapping" { - for_each = var.subnet_mapping + for_each = var.subnet_mapping != null ? var.subnet_mapping : [] content { - allocation_id = lookup(subnet_mapping.value, "allocation_id", null) - ipv6_address = lookup(subnet_mapping.value, "ipv6_address", null) - private_ipv4_address = lookup(subnet_mapping.value, "private_ipv4_address", null) + allocation_id = subnet_mapping.value.allocation_id + ipv6_address = subnet_mapping.value.ipv6_address + private_ipv4_address = subnet_mapping.value.private_ipv4_address subnet_id = subnet_mapping.value.subnet_id } } @@ -84,10 +92,14 @@ resource "aws_lb" "this" { tags = local.tags xff_header_processing_mode = var.xff_header_processing_mode - timeouts { - create = try(var.timeouts.create, null) - update = try(var.timeouts.update, null) - delete = try(var.timeouts.delete, null) + dynamic "timeouts" { + for_each = var.timeouts != null ? [var.timeouts] : [] + + content { + create = timeouts.value.create + update = timeouts.value.update + delete = timeouts.value.delete + } } lifecycle { @@ -104,162 +116,167 @@ resource "aws_lb" "this" { resource "aws_lb_listener" "this" { for_each = { for k, v in var.listeners : k => v if local.create } - alpn_policy = try(each.value.alpn_policy, null) - certificate_arn = try(each.value.certificate_arn, null) + region = var.region + + alpn_policy = each.value.alpn_policy + certificate_arn = each.value.certificate_arn dynamic "default_action" { - for_each = try([each.value.authenticate_cognito], []) + for_each = each.value.authenticate_cognito != null ? [each.value.authenticate_cognito] : [] content { authenticate_cognito { - authentication_request_extra_params = try(default_action.value.authentication_request_extra_params, null) - on_unauthenticated_request = try(default_action.value.on_unauthenticated_request, null) - scope = try(default_action.value.scope, null) - session_cookie_name = try(default_action.value.session_cookie_name, null) - session_timeout = try(default_action.value.session_timeout, null) + authentication_request_extra_params = default_action.value.authentication_request_extra_params + on_unauthenticated_request = default_action.value.on_unauthenticated_request + scope = default_action.value.scope + session_cookie_name = default_action.value.session_cookie_name + session_timeout = default_action.value.session_timeout user_pool_arn = default_action.value.user_pool_arn user_pool_client_id = default_action.value.user_pool_client_id user_pool_domain = default_action.value.user_pool_domain } - order = try(default_action.value.order, null) + order = each.value.order type = "authenticate-cognito" } } dynamic "default_action" { - for_each = try([each.value.authenticate_oidc], []) + for_each = each.value.authenticate_oidc != null ? [each.value.authenticate_oidc] : [] content { authenticate_oidc { - authentication_request_extra_params = try(default_action.value.authentication_request_extra_params, null) + authentication_request_extra_params = default_action.value.authentication_request_extra_params authorization_endpoint = default_action.value.authorization_endpoint client_id = default_action.value.client_id client_secret = default_action.value.client_secret issuer = default_action.value.issuer - on_unauthenticated_request = try(default_action.value.on_unauthenticated_request, null) - scope = try(default_action.value.scope, null) - session_cookie_name = try(default_action.value.session_cookie_name, null) - session_timeout = try(default_action.value.session_timeout, null) + on_unauthenticated_request = default_action.value.on_unauthenticated_request + scope = default_action.value.scope + session_cookie_name = default_action.value.session_cookie_name + session_timeout = default_action.value.session_timeout token_endpoint = default_action.value.token_endpoint user_info_endpoint = default_action.value.user_info_endpoint } - order = try(default_action.value.order, null) + order = each.value.order type = "authenticate-oidc" } } dynamic "default_action" { - for_each = try([each.value.fixed_response], []) + for_each = each.value.fixed_response != null ? [each.value.fixed_response] : [] content { fixed_response { content_type = default_action.value.content_type - message_body = try(default_action.value.message_body, null) - status_code = try(default_action.value.status_code, null) + message_body = default_action.value.message_body + status_code = default_action.value.status_code } - order = try(default_action.value.order, null) + order = each.value.order type = "fixed-response" } } dynamic "default_action" { - for_each = try([each.value.forward], []) + for_each = each.value.forward != null ? [each.value.forward] : [] content { - order = try(default_action.value.order, null) - target_group_arn = length(try(default_action.value.target_groups, [])) > 0 ? null : try(default_action.value.arn, aws_lb_target_group.this[default_action.value.target_group_key].arn, null) + order = each.value.order + target_group_arn = try(aws_lb_target_group.this[default_action.value.target_group_key].arn, default_action.value.target_group_arn) type = "forward" } } dynamic "default_action" { - for_each = try([each.value.weighted_forward], []) + for_each = each.value.weighted_forward != null ? [each.value.weighted_forward] : [] content { forward { dynamic "target_group" { - for_each = try(default_action.value.target_groups, []) + for_each = default_action.value.target_groups != null ? default_action.value.target_groups : [] content { - arn = try(target_group.value.arn, aws_lb_target_group.this[target_group.value.target_group_key].arn, null) - weight = try(target_group.value.weight, null) + arn = try(aws_lb_target_group.this[target_group.value.target_group_key].arn, target_group.value.target_group_arn) + weight = target_group.value.weight } } dynamic "stickiness" { - for_each = try([default_action.value.stickiness], []) + for_each = default_action.value.stickiness != null ? [default_action.value.stickiness] : [] content { - duration = try(stickiness.value.duration, 60) - enabled = try(stickiness.value.enabled, null) + duration = stickiness.value.duration + enabled = stickiness.value.enabled } } } - order = try(default_action.value.order, null) + order = each.value.order type = "forward" } } dynamic "default_action" { - for_each = try([each.value.redirect], []) + for_each = each.value.redirect != null ? [each.value.redirect] : [] content { - order = try(default_action.value.order, null) - redirect { - host = try(default_action.value.host, null) - path = try(default_action.value.path, null) - port = try(default_action.value.port, null) - protocol = try(default_action.value.protocol, null) - query = try(default_action.value.query, null) + host = default_action.value.host + path = default_action.value.path + port = default_action.value.port + protocol = default_action.value.protocol + query = default_action.value.query status_code = default_action.value.status_code } - type = "redirect" + order = each.value.order + type = "redirect" } } + load_balancer_arn = aws_lb.this[0].arn + dynamic "mutual_authentication" { - for_each = try([each.value.mutual_authentication], []) + for_each = each.value.mutual_authentication != null ? [each.value.mutual_authentication] : [] + content { + advertise_trust_store_ca_names = mutual_authentication.value.advertise_trust_store_ca_names + ignore_client_certificate_expiry = mutual_authentication.value.ignore_client_certificate_expiry mode = mutual_authentication.value.mode - trust_store_arn = try(mutual_authentication.value.trust_store_arn, null) - ignore_client_certificate_expiry = try(mutual_authentication.value.ignore_client_certificate_expiry, null) - advertise_trust_store_ca_names = try(mutual_authentication.value.advertise_trust_store_ca_names, null) + trust_store_arn = mutual_authentication.value.trust_store_arn } } - routing_http_response_server_enabled = try(each.value.routing_http_response_server_enabled, null) - routing_http_response_strict_transport_security_header_value = try(each.value.routing_http_response_strict_transport_security_header_value, null) - routing_http_response_access_control_allow_origin_header_value = try(each.value.routing_http_response_access_control_allow_origin_header_value, null) - routing_http_response_access_control_allow_methods_header_value = try(each.value.routing_http_response_access_control_allow_methods_header_value, null) - routing_http_response_access_control_allow_headers_header_value = try(each.value.routing_http_response_access_control_allow_headers_header_value, null) - routing_http_response_access_control_allow_credentials_header_value = try(each.value.routing_http_response_access_control_allow_credentials_header_value, null) - routing_http_response_access_control_expose_headers_header_value = try(each.value.routing_http_response_access_control_expose_headers_header_value, null) - routing_http_response_access_control_max_age_header_value = try(each.value.routing_http_response_access_control_max_age_header_value, null) - routing_http_response_content_security_policy_header_value = try(each.value.routing_http_response_content_security_policy_header_value, null) - routing_http_response_x_content_type_options_header_value = try(each.value.routing_http_response_x_content_type_options_header_value, null) - routing_http_response_x_frame_options_header_value = try(each.value.routing_http_response_x_frame_options_header_value, null) - - routing_http_request_x_amzn_tls_version_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_tls_version_header_name, null) : null - routing_http_request_x_amzn_tls_cipher_suite_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_tls_cipher_suite_header_name, null) : null - routing_http_request_x_amzn_mtls_clientcert_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_mtls_clientcert_header_name, null) : null - routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name, null) : null - routing_http_request_x_amzn_mtls_clientcert_issuer_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_mtls_clientcert_issuer_header_name, null) : null - routing_http_request_x_amzn_mtls_clientcert_subject_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_mtls_clientcert_subject_header_name, null) : null - routing_http_request_x_amzn_mtls_clientcert_validity_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_mtls_clientcert_validity_header_name, null) : null - routing_http_request_x_amzn_mtls_clientcert_leaf_header_name = try(each.value.protocol, var.default_protocol, null) == "HTTPS" ? try(each.value.routing_http_request_x_amzn_mtls_clientcert_leaf_header_name, null) : null - - load_balancer_arn = aws_lb.this[0].arn - port = try(each.value.port, var.default_port) - protocol = try(each.value.protocol, var.default_protocol) - ssl_policy = contains(["HTTPS", "TLS"], try(each.value.protocol, var.default_protocol)) ? try(each.value.ssl_policy, "ELBSecurityPolicy-TLS13-1-2-Res-2021-06") : try(each.value.ssl_policy, null) - tcp_idle_timeout_seconds = try(each.value.tcp_idle_timeout_seconds, null) - tags = merge(local.tags, try(each.value.tags, {})) + port = coalesce(each.value.port, var.default_port) + protocol = coalesce(each.value.protocol, var.default_protocol) + routing_http_request_x_amzn_mtls_clientcert_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_mtls_clientcert_header_name : null + routing_http_request_x_amzn_mtls_clientcert_issuer_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_mtls_clientcert_issuer_header_name : null + routing_http_request_x_amzn_mtls_clientcert_leaf_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_mtls_clientcert_leaf_header_name : null + routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_mtls_clientcert_serial_number_header_name : null + routing_http_request_x_amzn_mtls_clientcert_subject_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_mtls_clientcert_subject_header_name : null + routing_http_request_x_amzn_mtls_clientcert_validity_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_mtls_clientcert_validity_header_name : null + routing_http_request_x_amzn_tls_cipher_suite_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_tls_cipher_suite_header_name : null + routing_http_request_x_amzn_tls_version_header_name = coalesce(each.value.protocol, var.default_protocol) == "HTTPS" ? each.value.routing_http_request_x_amzn_tls_version_header_name : null + routing_http_response_access_control_allow_credentials_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_access_control_allow_credentials_header_value : null + routing_http_response_access_control_allow_headers_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_access_control_allow_headers_header_value : null + routing_http_response_access_control_allow_methods_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_access_control_allow_methods_header_value : null + routing_http_response_access_control_allow_origin_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_access_control_allow_origin_header_value : null + routing_http_response_access_control_expose_headers_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_access_control_expose_headers_header_value : null + routing_http_response_access_control_max_age_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_access_control_max_age_header_value : null + routing_http_response_content_security_policy_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_content_security_policy_header_value : null + routing_http_response_server_enabled = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_server_enabled : null + routing_http_response_strict_transport_security_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_strict_transport_security_header_value : null + routing_http_response_x_content_type_options_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_x_content_type_options_header_value : null + routing_http_response_x_frame_options_header_value = contains(["HTTP", "HTTPS"], coalesce(each.value.protocol, var.default_protocol)) ? each.value.routing_http_response_x_frame_options_header_value : null + ssl_policy = contains(["HTTPS", "TLS"], coalesce(each.value.protocol, var.default_protocol)) ? coalesce(each.value.ssl_policy, "ELBSecurityPolicy-TLS13-1-3-2021-06") : each.value.ssl_policy + tcp_idle_timeout_seconds = coalesce(each.value.protocol, var.default_protocol) == "TCP" ? each.value.tcp_idle_timeout_seconds : null + + tags = merge( + local.tags, + each.value.tags, + ) } ################################################################################ @@ -270,7 +287,7 @@ locals { # This allows rules to be specified under the listener definition listener_rules = flatten([ for listener_key, listener_values in var.listeners : [ - for rule_key, rule_values in lookup(listener_values, "rules", {}) : + for rule_key, rule_values in listener_values.rules : merge(rule_values, { listener_key = listener_key rule_key = rule_key @@ -282,202 +299,197 @@ locals { resource "aws_lb_listener_rule" "this" { for_each = { for v in local.listener_rules : "${v.listener_key}/${v.rule_key}" => v if local.create } - listener_arn = try(each.value.listener_arn, aws_lb_listener.this[each.value.listener_key].arn) - priority = try(each.value.priority, null) + region = var.region + # Authenticate OIDC dynamic "action" { - for_each = [for action in each.value.actions : action if action.type == "authenticate-cognito"] + for_each = [for action in each.value.actions : action if action.authenticate_cognito != null] content { - type = "authenticate-cognito" - order = try(action.value.order, null) + dynamic "authenticate_cognito" { + for_each = [action.value.authenticate_cognito] - authenticate_cognito { - authentication_request_extra_params = try(action.value.authentication_request_extra_params, null) - on_unauthenticated_request = try(action.value.on_unauthenticated_request, null) - scope = try(action.value.scope, null) - session_cookie_name = try(action.value.session_cookie_name, null) - session_timeout = try(action.value.session_timeout, null) - user_pool_arn = action.value.user_pool_arn - user_pool_client_id = action.value.user_pool_client_id - user_pool_domain = action.value.user_pool_domain + content { + authentication_request_extra_params = authenticate_cognito.value.authentication_request_extra_params + on_unauthenticated_request = authenticate_cognito.value.on_unauthenticated_request + scope = authenticate_cognito.value.scope + session_cookie_name = authenticate_cognito.value.session_cookie_name + session_timeout = authenticate_cognito.value.session_timeout + user_pool_arn = authenticate_cognito.value.user_pool_arn + user_pool_client_id = authenticate_cognito.value.user_pool_client_id + user_pool_domain = authenticate_cognito.value.user_pool_domain + } } + + order = action.value.order + type = "authenticate-cognito" } } + # Authenticate OIDC dynamic "action" { - for_each = [for action in each.value.actions : action if action.type == "authenticate-oidc"] + for_each = [for action in each.value.actions : action if action.authenticate_oidc != null] content { - type = "authenticate-oidc" - order = try(action.value.order, null) + dynamic "authenticate_oidc" { + for_each = [action.value.authenticate_oidc] - authenticate_oidc { - authentication_request_extra_params = try(action.value.authentication_request_extra_params, null) - authorization_endpoint = action.value.authorization_endpoint - client_id = action.value.client_id - client_secret = action.value.client_secret - issuer = action.value.issuer - on_unauthenticated_request = try(action.value.on_unauthenticated_request, null) - scope = try(action.value.scope, null) - session_cookie_name = try(action.value.session_cookie_name, null) - session_timeout = try(action.value.session_timeout, null) - token_endpoint = action.value.token_endpoint - user_info_endpoint = action.value.user_info_endpoint + content { + authentication_request_extra_params = authenticate_oidc.value.authentication_request_extra_params + authorization_endpoint = authenticate_oidc.value.authorization_endpoint + client_id = authenticate_oidc.value.client_id + client_secret = authenticate_oidc.value.client_secret + issuer = authenticate_oidc.value.issuer + on_unauthenticated_request = authenticate_oidc.value.on_unauthenticated_request + scope = authenticate_oidc.value.scope + session_cookie_name = authenticate_oidc.value.session_cookie_name + session_timeout = authenticate_oidc.value.session_timeout + token_endpoint = authenticate_oidc.value.token_endpoint + user_info_endpoint = authenticate_oidc.value.user_info_endpoint + } } + + order = action.value.order + type = "authenticate-oidc" } } + # Fixed response dynamic "action" { - for_each = [for action in each.value.actions : action if action.type == "redirect"] + for_each = [for action in each.value.actions : action if action.fixed_response != null] content { - type = "redirect" - order = try(action.value.order, null) + dynamic "fixed_response" { + for_each = [action.value.fixed_response] - redirect { - host = try(action.value.host, null) - path = try(action.value.path, null) - port = try(action.value.port, null) - protocol = try(action.value.protocol, null) - query = try(action.value.query, null) - status_code = action.value.status_code + content { + content_type = fixed_response.value.content_type + message_body = fixed_response.value.message_body + status_code = fixed_response.value.status_code + } } + + order = action.value.order + type = "fixed-response" } } + # Forward dynamic "action" { - for_each = [for action in each.value.actions : action if action.type == "fixed-response"] + for_each = [for action in each.value.actions : action if action.forward != null] content { - type = "fixed-response" - order = try(action.value.order, null) - - fixed_response { - content_type = action.value.content_type - message_body = try(action.value.message_body, null) - status_code = try(action.value.status_code, null) - } + order = action.value.order + target_group_arn = try(aws_lb_target_group.this[action.value.forward.target_group_key].arn, action.value.forward.target_group_arn) + type = "forward" } } + # Redirect dynamic "action" { - for_each = [for action in each.value.actions : action if action.type == "forward"] + for_each = [for action in each.value.actions : action if action.redirect != null] content { - type = "forward" - order = try(action.value.order, null) - target_group_arn = try(action.value.target_group_arn, aws_lb_target_group.this[action.value.target_group_key].arn, null) + dynamic "redirect" { + for_each = [action.value.redirect] + + content { + host = redirect.value.host + path = redirect.value.path + port = redirect.value.port + protocol = redirect.value.protocol + query = redirect.value.query + status_code = redirect.value.status_code + } + } + + order = action.value.order + type = "redirect" } } + # Weighted forward dynamic "action" { - for_each = [for action in each.value.actions : action if action.type == "weighted-forward"] + for_each = [for action in each.value.actions : action if action.weighted_forward != null] content { - type = "forward" - order = try(action.value.order, null) + dynamic "forward" { + for_each = [action.value.weighted_forward] - forward { - dynamic "target_group" { - for_each = try(action.value.target_groups, []) + content { + dynamic "stickiness" { + for_each = forward.value.stickiness != null ? [forward.value.stickiness] : [] - content { - arn = try(target_group.value.arn, aws_lb_target_group.this[target_group.value.target_group_key].arn) - weight = try(target_group.value.weight, null) + content { + duration = stickiness.value.duration + enabled = stickiness.value.enabled + } } - } - dynamic "stickiness" { - for_each = try([action.value.stickiness], []) + dynamic "target_group" { + for_each = forward.value.target_groups - content { - enabled = try(stickiness.value.enabled, null) - duration = try(stickiness.value.duration, 60) + content { + arn = try(aws_lb_target_group.this[target_group.value.target_group_key].arn, target_group.value.target_group_arn) + weight = target_group.value.weight + } } } } + + order = action.value.order + type = "forward" } } dynamic "condition" { - for_each = [for condition in each.value.conditions : condition if contains(keys(condition), "host_header")] + for_each = each.value.conditions content { dynamic "host_header" { - for_each = try([condition.value.host_header], []) + for_each = condition.value.host_header != null ? [condition.value.host_header] : [] content { values = host_header.value.values } } - } - } - dynamic "condition" { - for_each = [for condition in each.value.conditions : condition if contains(keys(condition), "http_header")] - - content { dynamic "http_header" { - for_each = try([condition.value.http_header], []) + for_each = condition.value.http_header != null ? [condition.value.http_header] : [] content { http_header_name = http_header.value.http_header_name values = http_header.value.values } } - } - } - - dynamic "condition" { - for_each = [for condition in each.value.conditions : condition if contains(keys(condition), "http_request_method")] - content { dynamic "http_request_method" { - for_each = try([condition.value.http_request_method], []) + for_each = condition.value.http_request_method != null ? [condition.value.http_request_method] : [] content { values = http_request_method.value.values } } - } - } - - dynamic "condition" { - for_each = [for condition in each.value.conditions : condition if contains(keys(condition), "path_pattern")] - content { dynamic "path_pattern" { - for_each = try([condition.value.path_pattern], []) + for_each = condition.value.path_pattern != null ? [condition.value.path_pattern] : [] content { values = path_pattern.value.values } } - } - } - dynamic "condition" { - for_each = [for condition in each.value.conditions : condition if contains(keys(condition), "query_string")] - - content { dynamic "query_string" { - for_each = try(flatten([condition.value.query_string]), []) + for_each = condition.value.query_string != null ? condition.value.query_string : [] content { - key = try(query_string.value.key, null) + key = query_string.value.key value = query_string.value.value } } - } - } - - dynamic "condition" { - for_each = [for condition in each.value.conditions : condition if contains(keys(condition), "source_ip")] - content { dynamic "source_ip" { - for_each = try([condition.value.source_ip], []) + for_each = condition.value.source_ip != null ? [condition.value.source_ip] : [] content { values = source_ip.value.values @@ -486,7 +498,13 @@ resource "aws_lb_listener_rule" "this" { } } - tags = merge(local.tags, try(each.value.tags, {})) + listener_arn = try(aws_lb_listener.this[each.value.listener_key].arn, each.value.listener_arn) + priority = each.value.priority + + tags = merge( + local.tags, + each.value.tags, + ) } ################################################################################ @@ -504,18 +522,20 @@ locals { # towards the front of the list are updated/removed. However, we need to have # unique keys on the resulting map and we can't have computed values (i.e. cert ARN) # in the key so we are using the array index as part of the key. - for idx, cert_arn in lookup(listener_values, "additional_certificate_arns", []) : + for idx, cert_arn in listener_values.additional_certificate_arns : "${listener_key}/${idx}" => { listener_key = listener_key certificate_arn = cert_arn } - } if length(lookup(listener_values, "additional_certificate_arns", [])) > 0 + } if length(listener_values.additional_certificate_arns) > 0 })...) } resource "aws_lb_listener_certificate" "this" { for_each = { for k, v in local.additional_certs : k => v if local.create } + region = var.region + listener_arn = aws_lb_listener.this[each.value.listener_key].arn certificate_arn = each.value.certificate_arn } @@ -525,54 +545,56 @@ resource "aws_lb_listener_certificate" "this" { ################################################################################ resource "aws_lb_target_group" "this" { - for_each = { for k, v in var.target_groups : k => v if local.create } + for_each = local.create && var.target_groups != null ? var.target_groups : {} - connection_termination = try(each.value.connection_termination, null) - deregistration_delay = try(each.value.deregistration_delay, null) + region = var.region + + connection_termination = each.value.connection_termination + deregistration_delay = each.value.deregistration_delay dynamic "health_check" { - for_each = try([each.value.health_check], []) + for_each = each.value.health_check != null ? [each.value.health_check] : [] content { - enabled = try(health_check.value.enabled, null) - healthy_threshold = try(health_check.value.healthy_threshold, null) - interval = try(health_check.value.interval, null) - matcher = try(health_check.value.matcher, null) - path = try(health_check.value.path, null) - port = try(health_check.value.port, null) - protocol = try(health_check.value.protocol, null) - timeout = try(health_check.value.timeout, null) - unhealthy_threshold = try(health_check.value.unhealthy_threshold, null) + enabled = health_check.value.enabled + healthy_threshold = health_check.value.healthy_threshold + interval = health_check.value.interval + matcher = health_check.value.matcher + path = health_check.value.path + port = health_check.value.port + protocol = health_check.value.protocol + timeout = health_check.value.timeout + unhealthy_threshold = health_check.value.unhealthy_threshold } } - ip_address_type = try(each.value.ip_address_type, null) - lambda_multi_value_headers_enabled = try(each.value.lambda_multi_value_headers_enabled, null) - load_balancing_algorithm_type = try(each.value.load_balancing_algorithm_type, null) - load_balancing_anomaly_mitigation = try(each.value.load_balancing_anomaly_mitigation, null) - load_balancing_cross_zone_enabled = try(each.value.load_balancing_cross_zone_enabled, null) - name = try(each.value.name, null) - name_prefix = try(each.value.name_prefix, null) - port = try(each.value.target_type, null) == "lambda" ? null : try(each.value.port, var.default_port) - preserve_client_ip = try(each.value.preserve_client_ip, null) - protocol = try(each.value.target_type, null) == "lambda" ? null : try(each.value.protocol, var.default_protocol) - protocol_version = try(each.value.protocol_version, null) - proxy_protocol_v2 = try(each.value.proxy_protocol_v2, null) - slow_start = try(each.value.slow_start, null) + ip_address_type = each.value.ip_address_type + lambda_multi_value_headers_enabled = each.value.lambda_multi_value_headers_enabled + load_balancing_algorithm_type = each.value.load_balancing_algorithm_type + load_balancing_anomaly_mitigation = each.value.load_balancing_anomaly_mitigation + load_balancing_cross_zone_enabled = each.value.load_balancing_cross_zone_enabled + name = each.value.name + name_prefix = each.value.name_prefix + port = each.value.target_type == "lambda" ? null : coalesce(each.value.port, var.default_port) + preserve_client_ip = each.value.preserve_client_ip + protocol = each.value.target_type == "lambda" ? null : coalesce(each.value.protocol, var.default_protocol) + protocol_version = each.value.protocol_version + proxy_protocol_v2 = each.value.proxy_protocol_v2 + slow_start = each.value.slow_start dynamic "stickiness" { - for_each = try([each.value.stickiness], []) + for_each = each.value.stickiness != null ? [each.value.stickiness] : [] content { - cookie_duration = try(stickiness.value.cookie_duration, null) - cookie_name = try(stickiness.value.cookie_name, null) - enabled = try(stickiness.value.enabled, true) - type = var.load_balancer_type == "network" ? "source_ip" : stickiness.value.type + cookie_duration = stickiness.value.cookie_duration + cookie_name = stickiness.value.cookie_name + enabled = stickiness.value.enabled + type = stickiness.value.type } } dynamic "target_failover" { - for_each = try(each.value.target_failover, []) + for_each = each.value.target_failover != null ? each.value.target_failover : [] content { on_deregistration = target_failover.value.on_deregistration @@ -581,42 +603,45 @@ resource "aws_lb_target_group" "this" { } dynamic "target_group_health" { - for_each = try([each.value.target_group_health], []) + for_each = each.value.target_group_health != null ? [each.value.target_group_health] : [] content { - dynamic "dns_failover" { - for_each = try([target_group_health.value.dns_failover], []) + for_each = target_group_health.value.dns_failover != null ? [target_group_health.value.dns_failover] : [] content { - minimum_healthy_targets_count = try(dns_failover.value.minimum_healthy_targets_count, null) - minimum_healthy_targets_percentage = try(dns_failover.value.minimum_healthy_targets_percentage, null) + minimum_healthy_targets_count = dns_failover.value.minimum_healthy_targets_count + minimum_healthy_targets_percentage = dns_failover.value.minimum_healthy_targets_percentage } } dynamic "unhealthy_state_routing" { - for_each = try([target_group_health.value.unhealthy_state_routing], []) + for_each = target_group_health.value.unhealthy_state_routing != null ? [target_group_health.value.unhealthy_state_routing] : [] content { - minimum_healthy_targets_count = try(unhealthy_state_routing.value.minimum_healthy_targets_count, null) - minimum_healthy_targets_percentage = try(unhealthy_state_routing.value.minimum_healthy_targets_percentage, null) + minimum_healthy_targets_count = unhealthy_state_routing.value.minimum_healthy_targets_count + minimum_healthy_targets_percentage = unhealthy_state_routing.value.minimum_healthy_targets_percentage } } } } dynamic "target_health_state" { - for_each = try([each.value.target_health_state], []) + for_each = each.value.target_health_state != null ? [each.value.target_health_state] : [] + content { - enable_unhealthy_connection_termination = try(target_health_state.value.enable_unhealthy_connection_termination, true) - unhealthy_draining_interval = try(target_health_state.value.unhealthy_draining_interval, null) + enable_unhealthy_connection_termination = target_health_state.value.enable_unhealthy_connection_termination + unhealthy_draining_interval = target_health_state.value.unhealthy_draining_interval } } - target_type = try(each.value.target_type, null) - vpc_id = try(each.value.vpc_id, var.vpc_id) + target_type = each.value.target_type + vpc_id = coalesce(each.value.vpc_id, var.vpc_id) - tags = merge(local.tags, try(each.value.tags, {})) + tags = merge( + local.tags, + each.value.tags, + ) lifecycle { create_before_destroy = true @@ -628,23 +653,27 @@ resource "aws_lb_target_group" "this" { ################################################################################ resource "aws_lb_target_group_attachment" "this" { - for_each = { for k, v in var.target_groups : k => v if local.create && lookup(v, "create_attachment", true) } + for_each = local.create && var.target_groups != null ? { for k, v in var.target_groups : k => v if v.create_attachment } : {} + + region = var.region target_group_arn = aws_lb_target_group.this[each.key].arn target_id = each.value.target_id - port = try(each.value.target_type, null) == "lambda" ? null : try(each.value.port, var.default_port) - availability_zone = try(each.value.availability_zone, null) + port = each.value.target_type == "lambda" ? null : coalesce(each.value.port, var.default_port) + availability_zone = each.value.availability_zone depends_on = [aws_lambda_permission.this] } resource "aws_lb_target_group_attachment" "additional" { - for_each = { for k, v in var.additional_target_group_attachments : k => v if local.create } + for_each = local.create && var.additional_target_group_attachments != null ? var.additional_target_group_attachments : {} + + region = var.region target_group_arn = aws_lb_target_group.this[each.value.target_group_key].arn target_id = each.value.target_id - port = try(each.value.target_type, null) == "lambda" ? null : try(each.value.port, var.default_port) - availability_zone = try(each.value.availability_zone, null) + port = each.value.target_type == "lambda" ? null : coalesce(each.value.port, var.default_port) + availability_zone = each.value.availability_zone depends_on = [aws_lambda_permission.this] } @@ -659,25 +688,27 @@ resource "aws_lb_target_group_attachment" "additional" { # lambda_function_name, the 6th index is taken from the function ARN format below # arn:aws:lambda:::function:my-function-name: locals { - lambda_target_groups = { + lambda_target_groups = var.target_groups != null ? { for k, v in var.target_groups : (k) => merge(v, { lambda_function_name = split(":", v.target_id)[6] }) - if try(v.attach_lambda_permission, false) - } + if v.attach_lambda_permission + } : {} } resource "aws_lambda_permission" "this" { for_each = { for k, v in local.lambda_target_groups : k => v if local.create } + region = var.region + function_name = each.value.lambda_function_name - qualifier = try(each.value.lambda_qualifier, null) + qualifier = each.value.lambda_qualifier - statement_id = try(each.value.lambda_statement_id, "AllowExecutionFromLb") - action = try(each.value.lambda_action, "lambda:InvokeFunction") - principal = try(each.value.lambda_principal, "elasticloadbalancing.${data.aws_partition.current.dns_suffix}") + statement_id = coalesce(each.value.lambda_statement_id, "AllowExecutionFromLb") + action = coalesce(each.value.lambda_action, "lambda:InvokeFunction") + principal = coalesce(each.value.lambda_principal, "elasticloadbalancing.${try(data.aws_partition.current[0].dns_suffix, "")}") source_arn = aws_lb_target_group.this[each.key].arn - source_account = try(each.value.lambda_source_account, null) - event_source_token = try(each.value.lambda_event_source_token, null) + source_account = each.value.lambda_source_account + event_source_token = each.value.lambda_event_source_token } ################################################################################ @@ -692,6 +723,8 @@ locals { resource "aws_security_group" "this" { count = local.create_security_group ? 1 : 0 + region = var.region + name = var.security_group_use_name_prefix ? null : local.security_group_name name_prefix = var.security_group_use_name_prefix ? "${local.security_group_name}-" : null description = coalesce(var.security_group_description, "Security group for ${local.security_group_name} ${var.load_balancer_type} load balancer") @@ -704,42 +737,48 @@ resource "aws_security_group" "this" { } } -resource "aws_vpc_security_group_egress_rule" "this" { - for_each = { for k, v in var.security_group_egress_rules : k => v if local.create_security_group } - - # Required - security_group_id = aws_security_group.this[0].id - ip_protocol = try(each.value.ip_protocol, "tcp") - - # Optional - cidr_ipv4 = lookup(each.value, "cidr_ipv4", null) - cidr_ipv6 = lookup(each.value, "cidr_ipv6", null) - description = try(each.value.description, null) - from_port = try(each.value.from_port, null) - prefix_list_id = lookup(each.value, "prefix_list_id", null) - referenced_security_group_id = lookup(each.value, "referenced_security_group_id", null) - to_port = try(each.value.to_port, null) - - tags = merge(local.tags, var.security_group_tags, try(each.value.tags, {})) +resource "aws_vpc_security_group_ingress_rule" "this" { + for_each = local.create_security_group && var.security_group_ingress_rules != null ? var.security_group_ingress_rules : {} + + region = var.region + + cidr_ipv4 = each.value.cidr_ipv4 + cidr_ipv6 = each.value.cidr_ipv6 + description = each.value.description + from_port = each.value.from_port + ip_protocol = each.value.ip_protocol + prefix_list_id = each.value.prefix_list_id + referenced_security_group_id = each.value.referenced_security_group_id + security_group_id = aws_security_group.this[0].id + tags = merge( + var.tags, + var.security_group_tags, + { "Name" = coalesce(each.value.name, "${local.security_group_name}-${each.key}") }, + each.value.tags + ) + to_port = try(coalesce(each.value.to_port, each.value.from_port), null) } -resource "aws_vpc_security_group_ingress_rule" "this" { - for_each = { for k, v in var.security_group_ingress_rules : k => v if local.create_security_group } - - # Required - security_group_id = aws_security_group.this[0].id - ip_protocol = try(each.value.ip_protocol, "tcp") - - # Optional - cidr_ipv4 = lookup(each.value, "cidr_ipv4", null) - cidr_ipv6 = lookup(each.value, "cidr_ipv6", null) - description = try(each.value.description, null) - from_port = try(each.value.from_port, null) - prefix_list_id = lookup(each.value, "prefix_list_id", null) - referenced_security_group_id = lookup(each.value, "referenced_security_group_id", null) - to_port = try(each.value.to_port, null) - - tags = merge(local.tags, var.security_group_tags, try(each.value.tags, {})) +resource "aws_vpc_security_group_egress_rule" "this" { + for_each = local.create_security_group && var.security_group_egress_rules != null ? var.security_group_egress_rules : {} + + region = var.region + + cidr_ipv4 = each.value.cidr_ipv4 + cidr_ipv6 = each.value.cidr_ipv6 + description = each.value.description + from_port = try(coalesce(each.value.from_port, each.value.to_port), null) + ip_protocol = each.value.ip_protocol + prefix_list_id = each.value.prefix_list_id + referenced_security_group_id = each.value.referenced_security_group_id + security_group_id = aws_security_group.this[0].id + tags = merge( + var.tags, + var.security_group_tags, + { "Name" = coalesce(each.value.name, "${local.security_group_name}-${each.key}") }, + each.value.tags + ) + to_port = each.value.to_port } ################################################################################ @@ -747,10 +786,10 @@ resource "aws_vpc_security_group_ingress_rule" "this" { ################################################################################ resource "aws_route53_record" "this" { - for_each = { for k, v in var.route53_records : k => v if var.create } + for_each = var.create && var.route53_records != null ? var.route53_records : {} zone_id = each.value.zone_id - name = try(each.value.name, each.key) + name = coalesce(each.value.name, each.key) type = each.value.type alias { @@ -767,6 +806,8 @@ resource "aws_route53_record" "this" { resource "aws_wafv2_web_acl_association" "this" { count = var.associate_web_acl ? 1 : 0 + region = var.region + resource_arn = aws_lb.this[0].arn web_acl_arn = var.web_acl_arn } diff --git a/modules/lb_trust_store/README.md b/modules/lb_trust_store/README.md index ae5b045..ad27a2e 100644 --- a/modules/lb_trust_store/README.md +++ b/modules/lb_trust_store/README.md @@ -29,14 +29,14 @@ module "trust_store" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.99 | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.5 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.99 | +| [aws](#provider\_aws) | >= 6.5 | ## Modules @@ -60,7 +60,8 @@ No modules. | [create\_trust\_store\_revocation](#input\_create\_trust\_store\_revocation) | Whether to create a trust store revocation for use with an application load balancer. | `bool` | `false` | no | | [name](#input\_name) | Name of the trust store. If omitted, Terraform will assign a random, unique name. This name must be unique per region, per 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 | | [name\_prefix](#input\_name\_prefix) | Creates a unique name beginning with the specified prefix. Conflicts with `name`. Cannot be longer than 6 characters. | `string` | `null` | no | -| [revocation\_lists](#input\_revocation\_lists) | Map of revocation list configurations. | `any` | `{}` | no | +| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no | +| [revocation\_lists](#input\_revocation\_lists) | Map of revocation list configurations. |
map(object({
revocations_s3_bucket = string
revocations_s3_key = string
revocations_s3_object_version = optional(string)
}))
| `null` | no | | [tags](#input\_tags) | Map of tags to assign to the resource. | `map(string)` | `{}` | no | ## Outputs diff --git a/modules/lb_trust_store/main.tf b/modules/lb_trust_store/main.tf index 1009aee..89aa395 100644 --- a/modules/lb_trust_store/main.tf +++ b/modules/lb_trust_store/main.tf @@ -1,19 +1,32 @@ +################################################################################ +# Trust Store +################################################################################ + resource "aws_lb_trust_store" "this" { count = var.create ? 1 : 0 + region = var.region + ca_certificates_bundle_s3_bucket = var.ca_certificates_bundle_s3_bucket ca_certificates_bundle_s3_key = var.ca_certificates_bundle_s3_key ca_certificates_bundle_s3_object_version = var.ca_certificates_bundle_s3_object_version name_prefix = var.name_prefix != null ? "${var.name_prefix}-" : null name = var.name != null ? var.name : null - tags = var.tags + + tags = var.tags } +################################################################################ +# Trust Store Revocation(s) +################################################################################ + resource "aws_lb_trust_store_revocation" "this" { - for_each = { for k, v in var.revocation_lists : k => v if var.create && var.create_trust_store_revocation } + for_each = var.create && var.create_trust_store_revocation && var.revocation_lists != null ? var.revocation_lists : {} + + region = var.region trust_store_arn = aws_lb_trust_store.this[0].arn revocations_s3_bucket = each.value.revocations_s3_bucket revocations_s3_key = each.value.revocations_s3_key - revocations_s3_object_version = try(each.value.revocations_s3_object_version, null) + revocations_s3_object_version = each.value.revocations_s3_object_version } diff --git a/modules/lb_trust_store/variables.tf b/modules/lb_trust_store/variables.tf index 4f6fb58..fe60420 100644 --- a/modules/lb_trust_store/variables.tf +++ b/modules/lb_trust_store/variables.tf @@ -4,6 +4,22 @@ variable "create" { default = true } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + +variable "tags" { + description = "Map of tags to assign to the resource." + type = map(string) + default = {} +} + +################################################################################ +# Trust Store +################################################################################ + variable "ca_certificates_bundle_s3_bucket" { description = "S3 bucket name holding the client certificate CA bundle." type = string @@ -40,14 +56,16 @@ variable "create_trust_store_revocation" { default = false } +################################################################################ +# Trust Store Revocation(s) +################################################################################ + variable "revocation_lists" { description = "Map of revocation list configurations." - type = any - default = {} -} - -variable "tags" { - description = "Map of tags to assign to the resource." - type = map(string) - default = {} + type = map(object({ + revocations_s3_bucket = string + revocations_s3_key = string + revocations_s3_object_version = optional(string) + })) + default = null } diff --git a/modules/lb_trust_store/versions.tf b/modules/lb_trust_store/versions.tf index 57efb00..1548bda 100644 --- a/modules/lb_trust_store/versions.tf +++ b/modules/lb_trust_store/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } } } diff --git a/variables.tf b/variables.tf index 9b3c725..5fefb12 100644 --- a/variables.tf +++ b/variables.tf @@ -4,6 +4,12 @@ variable "create" { default = true } +variable "region" { + description = "Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration" + type = string + default = null +} + variable "tags" { description = "A map of tags to add to all resources" type = map(string) @@ -16,28 +22,30 @@ variable "tags" { variable "access_logs" { description = "Map containing access logging configuration for load balancer" - type = map(string) - default = {} -} - -variable "connection_logs" { - description = "Map containing access logging configuration for load balancer" - type = map(string) - default = {} -} - -variable "ipam_pools" { - description = "The IPAM pools to use with the load balancer" - type = map(string) - default = {} + type = object({ + bucket = string + enabled = optional(bool, true) + prefix = optional(string) + }) + default = null } variable "client_keep_alive" { - description = "Client keep alive value in seconds. The valid range is 60-604800 seconds. The default is 3600 seconds." + description = "Client keep alive value in seconds. The valid range is 60-604800 seconds. The default is 3600 seconds" type = number default = null } +variable "connection_logs" { + description = "Map containing access logging configuration for load balancer" + type = object({ + bucket = string + enabled = optional(bool, true) + prefix = optional(string) + }) + default = null +} + variable "customer_owned_ipv4_pool" { description = "The ID of the customer owned ipv4 pool to use for this load balancer" type = string @@ -51,7 +59,7 @@ variable "desync_mitigation_mode" { } variable "dns_record_client_routing_policy" { - description = "Indicates how traffic is distributed among the load balancer Availability Zones. Possible values are any_availability_zone (default), availability_zone_affinity, or partial_availability_zone_affinity. Only valid for network type load balancers." + description = "Indicates how traffic is distributed among the load balancer Availability Zones. Possible values are any_availability_zone (default), availability_zone_affinity, or partial_availability_zone_affinity. Only valid for network type load balancers" type = string default = null } @@ -104,6 +112,12 @@ variable "enable_zonal_shift" { default = null } +variable "enforce_security_group_inbound_rules_on_private_link_traffic" { + description = "Indicates whether inbound security group rules are enforced for traffic originating from a PrivateLink. Only valid for Load Balancers of type network. The possible values are on and off" + type = string + default = null +} + variable "idle_timeout" { description = "The time in seconds that the connection is allowed to be idle. Only valid for Load Balancers of type `application`. Default: `60`" type = number @@ -122,22 +136,26 @@ variable "ip_address_type" { default = null } +variable "ipam_pools" { + description = "The IPAM pools to use with the load balancer" + type = object({ + ipv4_ipam_pool_id = string + }) + default = null +} + variable "load_balancer_type" { description = "The type of load balancer to create. Possible values are `application`, `gateway`, or `network`. The default value is `application`" type = string default = "application" } -variable "enforce_security_group_inbound_rules_on_private_link_traffic" { - description = "Indicates whether inbound security group rules are enforced for traffic originating from a PrivateLink. Only valid for Load Balancers of type network. The possible values are on and off." - type = string - default = null -} - variable "minimum_load_balancer_capacity" { description = "Minimum capacity for a load balancer. Only valid for Load Balancers of type `application` or `network`" - type = any - default = {} + type = object({ + capacity_units = number + }) + default = null } variable "name" { @@ -166,8 +184,13 @@ variable "security_groups" { variable "subnet_mapping" { description = "A list of subnet mapping blocks describing subnets to attach to load balancer" - type = list(map(string)) - default = [] + type = list(object({ + allocation_id = optional(string) + ipv6_address = optional(string) + private_ipv4_address = optional(string) + subnet_id = string + })) + default = null } variable "subnets" { @@ -184,8 +207,12 @@ variable "xff_header_processing_mode" { variable "timeouts" { description = "Create, update, and delete timeout configurations for the load balancer" - type = map(string) - default = {} + type = object({ + create = optional(string) + update = optional(string) + delete = optional(string) + }) + default = null } ################################################################################ @@ -206,8 +233,178 @@ variable "default_protocol" { variable "listeners" { description = "Map of listener configurations to create" - type = any - default = {} + type = 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), {}) + })), {}) + })) + default = {} } ################################################################################ @@ -216,14 +413,86 @@ variable "listeners" { variable "target_groups" { description = "Map of target group configurations to create" - type = any - default = {} + type = map(object({ + connection_termination = optional(bool) + deregistration_delay = optional(number) + health_check = optional(object({ + enabled = optional(bool) + healthy_threshold = optional(number) + interval = optional(number) + matcher = optional(string) + path = optional(string) + port = optional(string) + protocol = optional(string) + timeout = optional(number) + unhealthy_threshold = optional(number) + })) + ip_address_type = optional(string) + lambda_multi_value_headers_enabled = optional(bool) + load_balancing_algorithm_type = optional(string) + load_balancing_anomaly_mitigation = optional(string) + load_balancing_cross_zone_enabled = optional(bool) + name = optional(string) + name_prefix = optional(string) + port = optional(number) + preserve_client_ip = optional(bool) + protocol = optional(string) + protocol_version = optional(string) + proxy_protocol_v2 = optional(bool) + slow_start = optional(number) + stickiness = optional(object({ + cookie_duration = optional(number) + cookie_name = optional(string) + enabled = optional(bool) + type = string + })) + tags = optional(map(string)) + target_failover = optional(list(object({ + on_deregistration = string + on_unhealthy = string + }))) + target_group_health = optional(object({ + dns_failover = optional(object({ + minimum_healthy_targets_count = optional(string) + minimum_healthy_targets_percentage = optional(string) + })) + unhealthy_state_routing = optional(object({ + minimum_healthy_targets_count = optional(number) + minimum_healthy_targets_percentage = optional(string) + })) + })) + target_health_state = optional(object({ + enable_unhealthy_connection_termination = bool + unhealthy_draining_interval = optional(number) + })) + target_type = optional(string) + target_id = optional(string) + vpc_id = optional(string) + # Attachment + create_attachment = optional(bool, true) + availability_zone = optional(string) + # Lambda + attach_lambda_permission = optional(bool, false) + lambda_qualifier = optional(string) + lambda_statement_id = optional(string) + lambda_action = optional(string) + lambda_principal = optional(string) + lambda_source_account = optional(string) + lambda_event_source_token = optional(string) + })) + default = null } variable "additional_target_group_attachments" { description = "Map of additional target group attachments to create. Use `target_group_key` to attach to the target group created in `target_groups`" - type = any - default = {} + type = map(object({ + target_group_key = string + target_id = string + target_type = optional(string) + port = optional(number) + availability_zone = optional(string) + })) + default = null } ################################################################################ @@ -262,14 +531,38 @@ variable "vpc_id" { variable "security_group_ingress_rules" { description = "Security group ingress rules to add to the security group created" - type = any - default = {} + type = map(object({ + name = optional(string) + + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + tags = optional(map(string), {}) + to_port = optional(string) + })) + default = null } variable "security_group_egress_rules" { description = "Security group egress rules to add to the security group created" - type = any - default = {} + type = map(object({ + name = optional(string) + + cidr_ipv4 = optional(string) + cidr_ipv6 = optional(string) + description = optional(string) + from_port = optional(string) + ip_protocol = optional(string, "tcp") + prefix_list_id = optional(string) + referenced_security_group_id = optional(string) + tags = optional(map(string), {}) + to_port = optional(string) + })) + default = null } variable "security_group_tags" { @@ -284,8 +577,12 @@ variable "security_group_tags" { variable "route53_records" { description = "Map of Route53 records to create. Each record map should contain `zone_id`, `name`, and `type`" - type = any - default = {} + type = map(object({ + zone_id = string + name = optional(string) + type = string + })) + default = null } ################################################################################ diff --git a/versions.tf b/versions.tf index 57efb00..1548bda 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } } } diff --git a/wrappers/lb_trust_store/main.tf b/wrappers/lb_trust_store/main.tf index 5cccc4c..97e7efc 100644 --- a/wrappers/lb_trust_store/main.tf +++ b/wrappers/lb_trust_store/main.tf @@ -10,6 +10,7 @@ module "wrapper" { create_trust_store_revocation = try(each.value.create_trust_store_revocation, var.defaults.create_trust_store_revocation, false) name = try(each.value.name, var.defaults.name, null) name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null) - revocation_lists = try(each.value.revocation_lists, var.defaults.revocation_lists, {}) + region = try(each.value.region, var.defaults.region, null) + revocation_lists = try(each.value.revocation_lists, var.defaults.revocation_lists, null) tags = try(each.value.tags, var.defaults.tags, {}) } diff --git a/wrappers/lb_trust_store/versions.tf b/wrappers/lb_trust_store/versions.tf index 57efb00..1548bda 100644 --- a/wrappers/lb_trust_store/versions.tf +++ b/wrappers/lb_trust_store/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } } } diff --git a/wrappers/main.tf b/wrappers/main.tf index b280e9a..d226a9d 100644 --- a/wrappers/main.tf +++ b/wrappers/main.tf @@ -3,11 +3,11 @@ module "wrapper" { for_each = var.items - access_logs = try(each.value.access_logs, var.defaults.access_logs, {}) - additional_target_group_attachments = try(each.value.additional_target_group_attachments, var.defaults.additional_target_group_attachments, {}) + access_logs = try(each.value.access_logs, var.defaults.access_logs, null) + additional_target_group_attachments = try(each.value.additional_target_group_attachments, var.defaults.additional_target_group_attachments, null) associate_web_acl = try(each.value.associate_web_acl, var.defaults.associate_web_acl, false) client_keep_alive = try(each.value.client_keep_alive, var.defaults.client_keep_alive, null) - connection_logs = try(each.value.connection_logs, var.defaults.connection_logs, {}) + connection_logs = try(each.value.connection_logs, var.defaults.connection_logs, null) create = try(each.value.create, var.defaults.create, true) create_security_group = try(each.value.create_security_group, var.defaults.create_security_group, true) customer_owned_ipv4_pool = try(each.value.customer_owned_ipv4_pool, var.defaults.customer_owned_ipv4_pool, null) @@ -27,27 +27,28 @@ module "wrapper" { idle_timeout = try(each.value.idle_timeout, var.defaults.idle_timeout, null) internal = try(each.value.internal, var.defaults.internal, null) ip_address_type = try(each.value.ip_address_type, var.defaults.ip_address_type, null) - ipam_pools = try(each.value.ipam_pools, var.defaults.ipam_pools, {}) + ipam_pools = try(each.value.ipam_pools, var.defaults.ipam_pools, null) listeners = try(each.value.listeners, var.defaults.listeners, {}) load_balancer_type = try(each.value.load_balancer_type, var.defaults.load_balancer_type, "application") - minimum_load_balancer_capacity = try(each.value.minimum_load_balancer_capacity, var.defaults.minimum_load_balancer_capacity, {}) + minimum_load_balancer_capacity = try(each.value.minimum_load_balancer_capacity, var.defaults.minimum_load_balancer_capacity, null) name = try(each.value.name, var.defaults.name, null) name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null) preserve_host_header = try(each.value.preserve_host_header, var.defaults.preserve_host_header, null) putin_khuylo = try(each.value.putin_khuylo, var.defaults.putin_khuylo, true) - route53_records = try(each.value.route53_records, var.defaults.route53_records, {}) + region = try(each.value.region, var.defaults.region, null) + route53_records = try(each.value.route53_records, var.defaults.route53_records, null) security_group_description = try(each.value.security_group_description, var.defaults.security_group_description, null) - security_group_egress_rules = try(each.value.security_group_egress_rules, var.defaults.security_group_egress_rules, {}) - security_group_ingress_rules = try(each.value.security_group_ingress_rules, var.defaults.security_group_ingress_rules, {}) + security_group_egress_rules = try(each.value.security_group_egress_rules, var.defaults.security_group_egress_rules, null) + security_group_ingress_rules = try(each.value.security_group_ingress_rules, var.defaults.security_group_ingress_rules, null) security_group_name = try(each.value.security_group_name, var.defaults.security_group_name, null) security_group_tags = try(each.value.security_group_tags, var.defaults.security_group_tags, {}) security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.defaults.security_group_use_name_prefix, true) security_groups = try(each.value.security_groups, var.defaults.security_groups, []) - subnet_mapping = try(each.value.subnet_mapping, var.defaults.subnet_mapping, []) + subnet_mapping = try(each.value.subnet_mapping, var.defaults.subnet_mapping, null) subnets = try(each.value.subnets, var.defaults.subnets, null) tags = try(each.value.tags, var.defaults.tags, {}) - target_groups = try(each.value.target_groups, var.defaults.target_groups, {}) - timeouts = try(each.value.timeouts, var.defaults.timeouts, {}) + target_groups = try(each.value.target_groups, var.defaults.target_groups, null) + timeouts = try(each.value.timeouts, var.defaults.timeouts, null) vpc_id = try(each.value.vpc_id, var.defaults.vpc_id, null) web_acl_arn = try(each.value.web_acl_arn, var.defaults.web_acl_arn, null) xff_header_processing_mode = try(each.value.xff_header_processing_mode, var.defaults.xff_header_processing_mode, null) diff --git a/wrappers/versions.tf b/wrappers/versions.tf index 57efb00..1548bda 100644 --- a/wrappers/versions.tf +++ b/wrappers/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.5.7" required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.99" + version = ">= 6.5" } } }