diff --git a/Makefile b/Makefile index 0aa5aa6..cd124a5 100644 --- a/Makefile +++ b/Makefile @@ -23,50 +23,110 @@ default: all all: $(MAKE) init $(MAKE) validate - $(MAKE) security $(MAKE) lint + $(MAKE) security $(MAKE) format $(MAKE) documentation - $(MAKE) documentation-examples - -security: - @echo "--> Running Security checks" - @tfsec . documentation: @echo "--> Generating documentation" @terraform-docs markdown table --output-file ${PWD}/README.md --output-mode inject . + $(MAKE) documentation-modules + $(MAKE) documentation-examples + +documentation-modules: + @echo "--> Generating documentation for modules" + @if [ -d modules ]; then \ + find modules -type d -mindepth 1 -maxdepth 1 -exec terraform-docs markdown table --output-file README.md --output-mode inject {} \; ; \ + fi documentation-examples: @echo "--> Generating documentation examples" - @find examples -type d -mindepth 1 -maxdepth 1 -exec terraform-docs markdown table --output-file README.md --output-mode inject {} \; + @if [ -d examples ]; then \ + find examples -type d -mindepth 1 -maxdepth 1 -exec terraform-docs markdown table --output-file README.md --output-mode inject {} \; ; \ + fi init: @echo "--> Running terraform init" @terraform init -backend=false -validate-all: - @echo "--> Running all validation checks" - $(MAKE) validate - $(MAKE) validate-examples +security: + @echo "--> Running Security checks" + @tfsec . + $(MAKE) security-modules + $(MAKE) security-examples + +security-modules: + @echo "--> Running Security checks on modules" + @if [ -d modules ]; then \ + find modules -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + echo "--> Validating $$dir"; \ + tfsec $$dir; \ + done; \ + fi + +security-examples: + @echo "--> Running Security checks on examples" + @if [ -d examples ]; then \ + find examples -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + echo "--> Validating $$dir"; \ + tfsec $$dir; \ + done; \ + fi validate: @echo "--> Running terraform validate" @terraform init -backend=false @terraform validate + $(MAKE) validate-modules + $(MAKE) validate-examples + +validate-modules: + @echo "--> Running terraform validate on modules" + @if [ -d modules ]; then \ + find modules -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + echo "--> Validating $$dir"; \ + terraform -chdir=$$dir init -backend=false; \ + terraform -chdir=$$dir validate; \ + done; \ + fi validate-examples: @echo "--> Running terraform validate on examples" - @find examples -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ - echo "--> Validating $$dir"; \ - terraform -chdir=$$dir init; \ - terraform -chdir=$$dir validate; \ - done + @if [ -d examples ]; then \ + find examples -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + echo "--> Validating $$dir"; \ + terraform -chdir=$$dir init -backend=false; \ + terraform -chdir=$$dir validate; \ + done; \ + fi lint: @echo "--> Running tflint" @tflint --init @tflint -f compact + $(MAKE) lint-modules + $(MAKE) lint-examples + +lint-modules: + @echo "--> Running tflint on modules" + @if [ -d modules ]; then \ + find modules -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + echo "--> Linting $$dir"; \ + tflint --chdir=$$dir --init; \ + tflint --chdir=$$dir -f compact; \ + done; \ + fi + +lint-examples: + @echo "--> Running tflint on examples" + @if [ -d examples ]; then \ + find examples -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + echo "--> Linting $$dir"; \ + tflint --chdir=$$dir --init; \ + tflint --chdir=$$dir -f compact; \ + done; \ + fi format: @echo "--> Running terraform fmt" diff --git a/README.md b/README.md index 0d999da..01b20bf 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,17 @@ module "connectivity" { source = "appvia/connectivity/aws" version = "0.0.2" + services = { + egress = { + network = { + availability_zones = 2 + ipam_pool_id = module.ipam_pool.id + name = "egress" + vpc_netmask = 24 + } + } + } + # insert variables here connectivity_config = { inspection = { @@ -89,14 +100,6 @@ module "connectivity" { public_netmask = 24 } } - egress = { - network = { - availability_zones = 2 - ipam_pool_id = module.ipam_pool.id - name = "egress" - vpc_netmask = 24 - } - } } } ``` @@ -124,7 +127,7 @@ The most common usage pattern here is to place resources such as CI, monitoring, Notes: -- The transit gateway must be configured so that the default association table is default routing table, hence all new attachments are placed in the untrusted routing table. +- The transit gateway must be configured so that the default association table is `workloads` routing table, hence all new attachments are placed in the untrusted routing table. - The transit gateway must be configured so that the default propagation table is the `trusted` routing table, this ensures that all traffic has a route from trusted to untrusted. - Adding a new trusted requires manual intervention, i.e the network is automatically added to the untrusted routing table, manually deleted, and then the attachment id added to the trusted attachments variable. - Any trusted attachments are automatically added to the untrusted routing table, to ensure bi-directional routing. @@ -258,7 +261,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0.7 | +| [terraform](#requirement\_terraform) | >= 1.0.0 | | [aws](#requirement\_aws) | >= 5.0.0 | ## Providers @@ -272,7 +275,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | Name | Source | Version | |------|--------|---------| | [egress\_vpc](#module\_egress\_vpc) | appvia/network/aws | 0.3.0 | -| [endpoints](#module\_endpoints) | appvia/private-endpoints/aws | 0.2.2 | +| [endpoints](#module\_endpoints) | appvia/private-endpoints/aws | 0.2.4 | | [endpoints\_vpc](#module\_endpoints\_vpc) | appvia/network/aws | 0.3.0 | | [ingress\_vpc](#module\_ingress\_vpc) | appvia/network/aws | 0.3.0 | | [inspection\_vpc](#module\_inspection\_vpc) | appvia/network/aws | 0.3.0 | @@ -290,6 +293,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [aws_ec2_transit_gateway_route.trusted_route_table](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route_table.inspection_return](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table) | resource | | [aws_ec2_transit_gateway_route_table.trusted](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table) | resource | +| [aws_ec2_transit_gateway_route_table.trusted_core](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table) | resource | | [aws_ec2_transit_gateway_route_table_association.inspection_egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | | [aws_ec2_transit_gateway_route_table_association.inspection_endpoints](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | | [aws_ec2_transit_gateway_route_table_association.inspection_inbound](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route_table_association) | resource | @@ -308,13 +312,14 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [aws_ram_principal_association.associations](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | | [aws_ram_resource_association.prefixes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | | [aws_ram_resource_share.prefixes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [amazon\_side\_asn](#input\_amazon\_side\_asn) | The ASN for the transit gateway. | `number` | n/a | yes | -| [connectivity\_config](#input\_connectivity\_config) | The type of connectivity options for the transit gateway. |
object({| n/a | yes | +| [connectivity\_config](#input\_connectivity\_config) | The type of connectivity options for the transit gateway. |
egress = optional(object({
network = object({
# Defines the configuration for an egress network.
availability_zones = optional(number, 2)
# The number of availablity zones to use for the egress network. Defaults to 2.
ipam_pool_id = optional(string, null)
# The ID of the IPAM pool to use for the egress network. Defaults to null.
name = optional(string, "egress")
# The name of the egress network. Defaults to 'egress'.
private_netmask = optional(number, 28)
# The netmask to use for the private network. Defaults to 28.
public_netmask = optional(number, 28)
# The netmask to use for the public network. Defaults to 28.
vpc_cidr = optional(string, null)
# The CIDR block to use for the VPC. Defaults to null, required when not using IPAM
vpc_netmask = optional(string, null)
# The netmask to use for the VPC. Defaults to null, required when using IPAM
})
}), null)
endpoints = optional(object({
# Defines the configuration for the endpoints network.
network = object({
# Defines the configuration for the endpoints network.
availability_zones = optional(number, 2)
# The number of availablity zones to use for the endpoints network. Defaults to 2.
ipam_pool_id = optional(string, null)
# The ID of the IPAM pool to use for the endpoints network. Defaults to null.
name = optional(string, "endpoints")
# The name of the endpoints network. Defaults to 'endpoints'.
private_netmask = optional(number, 24)
# The netmask to use for the private network. Defaults to 24, ensure space for enough aws services.
vpc_cidr = optional(string, null)
# The CIDR block to use for the VPC. Defaults to null, required when not using IPAM
vpc_netmask = optional(string, null)
# The netmask to use for the VPC. Defaults to null, required when using IPAM
})
sharing = optional(object({
# Defines the configuration for the sharing network via AWS RAM
principals = optional(list(string), [])
# The list of organizational units or accounts to share the endpoints resolvers rules with. Defaults to an empty list.
}), null)
services = optional(map(object({
# Defines the configuration for the private endpoints in the shared network.
private_dns_enabled = optional(bool, true)
# Whether private DNS is enabled. Defaults to true.
service_type = optional(string, "Interface")
# The type of service, i.e. Gateway or Interface. Defaults to 'Interface'
service = string
# The name of the service i.e. ec2, ec2messages, ssm, ssmmessages, logs, kms, secretsmanager, s3.awsamazon.com
policy = optional(string, null)
# An optional IAM policy to use for the endpoint. Defaults to null.
})), {
ec2 = {
service = "ec2"
},
ec2messages = {
service = "ec2messages"
},
ssm = {
service = "ssm"
},
ssmmessages = {
service = "ssmmessages"
},
logs = {
service = "logs"
},
kms = {
service = "kms"
},
secretsmanager = {
service = "secretsmanager"
},
s3 = {
service = "s3"
},
})
}), null)
ingress = optional(object({
# Defines the configuration for the ingress network.
network = object({
# Defines the configuration for the ingress network.
availability_zones = optional(number, 2)
# The number of availablity zones to use for the ingress network. Defaults to 2.
ipam_pool_id = optional(string, null)
# The ID of the IPAM pool to use for the ingress network. Defaults to null.
name = optional(string, "ingress")
# The name of the ingress network. Defaults to 'ingress'.
private_netmask = number
# The netmask to use for the private network. Required, ensure space for enough aws services.
public_netmask = number
# The netmask to use for the public network. Required, ensure space for enough aws services.
vpc_cidr = optional(string, null)
# The CIDR block to use for the VPC. Defaults to null, required when not using IPAM
vpc_netmask = optional(string, null)
# The netmask to use for the VPC. Defaults to null, required when using IPAM
})
}), null)
inspection = optional(object({
# Defines the configuration for the inspection network.
inbound_route_table_name = optional(string, "inbound")
# The name of the inbound route table. Defaults to 'inbound'.
network = optional(object({
# Defines the configuration for the inspection network.
availability_zones = number
# The number of availablity zones to use for the inspection network. Required. Must match the
# number of availability zones you use in the organization, due to symmetric routing requirements.
name = optional(string, "inspection")
# The name of the inspection network. Defaults to 'inspection'.
private_netmask = optional(number, 24)
# The netmask to use for the private network. Defaults to 24
vpc_cidr = optional(string, "100.64.0.0/21")
# The CIDR block to use for the VPC. Defaults to carrier-grade NAT space.
}), null)
spokes_route_table_name = optional(string, "spokes")
# The name of the spokes route table. Defaults to 'spokes'.
}), null)
trusted = optional(object({
# Defines the configuration for the trusted routing
trusted_attachments = optional(list(string), [])
# The list of transit gateway attachments to trust e.g can see all the other untrusted networks. Defaults to an empty list.
trusted_route_table_name = optional(string, "trusted")
# The name of the trusted route table. Defaults to 'trusted'.
}), null)
})
object({| n/a | yes | | [description](#input\_description) | The description of the transit gateway to provision. | `string` | n/a | yes | | [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | n/a | yes | | [enable\_dns\_support](#input\_enable\_dns\_support) | Whether DNS support is enabled. | `bool` | `true` | no | @@ -326,6 +331,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [prefix\_ram\_principals](#input\_prefix\_ram\_principals) | The list of organizational units or accounts to share the prefix lists with. | `list(string)` | `[]` | no | | [ram\_share\_name](#input\_ram\_share\_name) | The name of the RAM share to create for the transit gateway. | `string` | `"tgw-ram-share"` | no | | [ram\_share\_principals](#input\_ram\_share\_principals) | The list of organizational units or accounts to share the transit gateway with. | `list(string)` | `[]` | no | +| [services](#input\_services) | A collection of features and services associated with this connectivity domain. |
inspection_with_all = optional(object({
# The name of the inbound route table. Defaults to 'inbound'.
network = optional(object({
# Defines the configuration for the inspection network.
availability_zones = number
# The number of availablity zones to use for the inspection network. Required. Must match the
# number of availability zones you use in the organization, due to symmetric routing requirements.
name = optional(string, "inspection")
# The name of the inspection network. Defaults to 'inspection'.
private_netmask = optional(number, 24)
# The netmask to use for the private network. Defaults to 24
vpc_cidr = optional(string, "100.64.0.0/21")
# The CIDR block to use for the VPC. Defaults to carrier-grade NAT space.
}), null)
return_route_table_name = optional(string, "inspection-return")
}), null)
trusted = optional(object({
# Defines the configuration for the trusted routing
trusted_attachments = optional(list(string), [])
# The list of transit gateway attachments to trust e.g can see all the other untrusted networks. Defaults to an empty list.
trusted_route_table_name = optional(string, "trusted")
# The name of the trusted route table. Defaults to 'trusted'.
trusted_core_route_table_name = optional(string, "trusted-core")
}), null)
})
object({| `{}` | no | ## Outputs @@ -343,11 +349,15 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [ingress\_vpc\_id\_rt\_attributes\_by\_type\_by\_az](#output\_ingress\_vpc\_id\_rt\_attributes\_by\_type\_by\_az) | The route table attributes of the ingress VPC. | | [ingress\_vpc\_private\_subnet\_attributes\_by\_az](#output\_ingress\_vpc\_private\_subnet\_attributes\_by\_az) | The attributes of the ingress VPC. | | [ingress\_vpc\_public\_subnet\_attributes\_by\_az](#output\_ingress\_vpc\_public\_subnet\_attributes\_by\_az) | The attributes of the ingress VPC. | +| [inspection\_route\_inbound\_table\_id](#output\_inspection\_route\_inbound\_table\_id) | The ID of the inbound route table for inspection. | | [inspection\_vpc\_id](#output\_inspection\_vpc\_id) | The ID of the VPC that is used for inspection traffic. | | [inspection\_vpc\_id\_rt\_attributes\_by\_type\_by\_az](#output\_inspection\_vpc\_id\_rt\_attributes\_by\_type\_by\_az) | The route table attributes of the inspection VPC. | | [inspection\_vpc\_private\_subnet\_attributes\_by\_az](#output\_inspection\_vpc\_private\_subnet\_attributes\_by\_az) | The attributes of the inspection VPC. | | [inspection\_vpc\_public\_subnet\_attributes\_by\_az](#output\_inspection\_vpc\_public\_subnet\_attributes\_by\_az) | The attributes of the inspection VPC. | | [transit\_gateway\_id](#output\_transit\_gateway\_id) | The ID of the transit gateway. | +| [trusted\_core\_route\_table\_id](#output\_trusted\_core\_route\_table\_id) | The ID of the trusted core route table. | +| [trusted\_route\_table\_id](#output\_trusted\_route\_table\_id) | The ID of the trusted route table. | +| [workloads\_route\_table\_id](#output\_workloads\_route\_table\_id) | The ID of the workloads route table. | ``` diff --git a/data.tf b/data.tf new file mode 100644 index 0000000..0ab8db3 --- /dev/null +++ b/data.tf @@ -0,0 +1,3 @@ + +## Find the current region +data "aws_region" "current" {} diff --git a/endpoints.tf b/endpoints.tf index 90747ac..2137082 100644 --- a/endpoints.tf +++ b/endpoints.tf @@ -1,39 +1,40 @@ -## Provision a network for the endpoints vpc +## Provision an egress vpc if required module "endpoints_vpc" { count = local.enable_endpoints ? 1 : 0 source = "appvia/network/aws" version = "0.3.0" - availability_zones = var.connectivity_config.endpoints.network.availability_zones - enable_default_route_table_association = false - enable_default_route_table_propagation = false - enable_ipam = var.connectivity_config.endpoints.network.ipam_pool_id != null + availability_zones = var.services.endpoints.network.availability_zones + enable_default_route_table_association = local.enable_default_route_table_association + enable_default_route_table_propagation = local.enable_default_route_table_propagation + enable_ipam = var.services.endpoints.network.ipam_pool_id != null enable_transit_gateway = true - enable_transit_gateway_appliance_mode = true - ipam_pool_id = var.connectivity_config.endpoints.network.ipam_pool_id - name = var.connectivity_config.endpoints.network.name - private_subnet_netmask = var.connectivity_config.endpoints.network.private_netmask + ipam_pool_id = var.services.endpoints.network.ipam_pool_id + name = var.services.endpoints.network.name + private_subnet_netmask = var.services.endpoints.network.private_netmask tags = var.tags transit_gateway_id = module.tgw.ec2_transit_gateway_id - vpc_cidr = var.connectivity_config.endpoints.network.vpc_cidr - vpc_netmask = var.connectivity_config.endpoints.network.vpc_netmask + vpc_cidr = var.services.endpoints.network.vpc_cidr + vpc_netmask = var.services.endpoints.network.vpc_netmask } ## Provision if required the shared private endpoints module "endpoints" { count = local.enable_endpoints ? 1 : 0 source = "appvia/private-endpoints/aws" - version = "0.2.2" + version = "0.2.4" - name = var.connectivity_config.endpoints.network.name - endpoints = var.connectivity_config.endpoints.services + name = var.services.endpoints.network.name + endpoints = var.services.endpoints.services + region = local.region tags = var.tags network = { create = false + name = var.services.endpoints.network.name private_subnet_cidr_by_id = module.endpoints_vpc[0].private_subnet_cidr_by_id - transit_gateway_id = module.tgw.ec2_transit_gateway_id + vpc_dns_resolver = cidrhost(module.endpoints_vpc[0].vpc_cidr, 2) vpc_id = module.endpoints_vpc[0].vpc_id } @@ -45,6 +46,8 @@ module "endpoints" { } sharing = { - principals = var.connectivity_config.endpoints.sharing.principals + principals = var.services.endpoints.sharing.principals } + + depends_on = [module.endpoints_vpc] } diff --git a/examples/central_vpc/README.md b/examples/central_vpc/README.md deleted file mode 100644 index ef2fa69..0000000 --- a/examples/central_vpc/README.md +++ /dev/null @@ -1,25 +0,0 @@ - -## Requirements - -No requirements. - -## Providers - -No providers. - -## Modules - -No modules. - -## Resources - -No resources. - -## Inputs - -No inputs. - -## Outputs - -No outputs. - \ No newline at end of file diff --git a/examples/complete/main.tf b/examples/complete/main.tf index d791408..f7943f8 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -17,7 +17,7 @@ module "hub" { ram_share_principals = values(var.ram_principals) tags = var.tags - connectivity_config = { + services = { egress = { network = { availability_zones = 2 @@ -38,16 +38,6 @@ module "hub" { } } - inspection = { - network = { - availability_zones = 3 - vpc_cidr = "100.64.0.0/21" - name = "inspection" - private_subnet_netmask = 24 - public_subnet_netmask = 24 - } - } - endpoints = { services = { ec2messages = { @@ -73,4 +63,17 @@ module "hub" { } } } + + connectivity_config = { + inspection_with_all = { + network = { + availability_zones = 3 + vpc_cidr = "100.64.0.0/21" + name = "inspection" + private_subnet_netmask = 24 + public_subnet_netmask = 24 + } + } + + } } diff --git a/examples/inspection/README.md b/examples/inspection/README.md index 3045937..0ae4ab9 100644 --- a/examples/inspection/README.md +++ b/examples/inspection/README.md @@ -27,7 +27,7 @@ No resources. |------|-------------|------|---------|:--------:| | [asn](#input\_asn) | The ASN of the gateway. | `number` | `64512` | no | | [name](#input\_name) | The name of the transit gateway to provision. | `string` | `"main-hub"` | no | -| [tags](#input\_tags) | A map of tags to assign to the resources. | `map(string)` | `{}` | no | +| [tags](#input\_tags) | A map of tags to assign to the resources. | `map(string)` |
egress = optional(object({
network = object({
# Defines the configuration for an egress network.
availability_zones = optional(number, 2)
# The number of availablity zones to use for the egress network. Defaults to 2.
ipam_pool_id = optional(string, null)
# The ID of the IPAM pool to use for the egress network. Defaults to null.
name = optional(string, "egress")
# The name of the egress network. Defaults to 'egress'.
private_netmask = optional(number, 28)
# The netmask to use for the private network. Defaults to 28.
public_netmask = optional(number, 28)
# The netmask to use for the public network. Defaults to 28.
vpc_cidr = optional(string, null)
# The CIDR block to use for the VPC. Defaults to null, required when not using IPAM
vpc_netmask = optional(string, null)
# The netmask to use for the VPC. Defaults to null, required when using IPAM
})
}), null)
endpoints = optional(object({
# Defines the configuration for the endpoints network.
network = object({
# Defines the configuration for the endpoints network.
availability_zones = optional(number, 2)
# The number of availablity zones to use for the endpoints network. Defaults to 2.
ipam_pool_id = optional(string, null)
# The ID of the IPAM pool to use for the endpoints network. Defaults to null.
name = optional(string, "endpoints")
# The name of the endpoints network. Defaults to 'endpoints'.
private_netmask = optional(number, 24)
# The netmask to use for the private network. Defaults to 24, ensure space for enough aws services.
vpc_cidr = optional(string, null)
# The CIDR block to use for the VPC. Defaults to null, required when not using IPAM
vpc_netmask = optional(string, null)
# The netmask to use for the VPC. Defaults to null, required when using IPAM
})
sharing = optional(object({
# Defines the configuration for the sharing network via AWS RAM
principals = optional(list(string), [])
# The list of organizational units or accounts to share the endpoints resolvers rules with. Defaults to an empty list.
}), null)
services = optional(map(object({
# Defines the configuration for the private endpoints in the shared network.
private_dns_enabled = optional(bool, true)
# Whether private DNS is enabled. Defaults to true.
service_type = optional(string, "Interface")
# The type of service, i.e. Gateway or Interface. Defaults to 'Interface'
service = string
# The name of the service i.e. ec2, ec2messages, ssm, ssmmessages, logs, kms, secretsmanager, s3.awsamazon.com
policy = optional(string, null)
# An optional IAM policy to use for the endpoint. Defaults to null.
})), {
ec2messages = {
service = "ec2messages"
},
ssm = {
service = "ssm"
},
ssmmessages = {
service = "ssmmessages"
},
})
}), null)
ingress = optional(object({
# Defines the configuration for the ingress network.
network = object({
# Defines the configuration for the ingress network.
availability_zones = optional(number, 2)
# The number of availablity zones to use for the ingress network. Defaults to 2.
ipam_pool_id = optional(string, null)
# The ID of the IPAM pool to use for the ingress network. Defaults to null.
name = optional(string, "ingress")
# The name of the ingress network. Defaults to 'ingress'.
private_netmask = number
# The netmask to use for the private network. Required, ensure space for enough aws services.
public_netmask = number
# The netmask to use for the public network. Required, ensure space for enough aws services.
vpc_cidr = optional(string, null)
# The CIDR block to use for the VPC. Defaults to null, required when not using IPAM
vpc_netmask = optional(string, null)
# The netmask to use for the VPC. Defaults to null, required when using IPAM
})
}), null)
})
{| no | ## Outputs diff --git a/examples/inspection/main.tf b/examples/inspection/main.tf index ba133bf..8677a0a 100644 --- a/examples/inspection/main.tf +++ b/examples/inspection/main.tf @@ -16,14 +16,60 @@ module "hub" { enable_vpn_ecmp_support = true tags = var.tags + services = { + egress = { + network = { + availability_zones = 2 + name = "egress" + private_netmask = 24 + public_netmask = 24 + vpc_cidr = "10.20.0.0/21" + } + } + + ingress = { + network = { + availability_zones = 2 + name = "ingress" + private_netmask = 24 + public_netmask = 24 + vpc_cidr = "10.20.8.0/21" + } + } + + endpoints = { + services = { + ec2messages = { + service = "ec2messages" + }, + ssm = { + service = "ssm" + }, + ssmmessages = { + service = "ssmmessages" + }, + } + + sharing = { + principals = [] + } + + network = { + availability_zones = 2 + name = "endpoints" + private_netmask = 24 + vpc_cidr = "10.20.16.0/21" + } + } + } + connectivity_config = { - inspection = { + inspection_with_all = { ## Will be created in the hub account i.e. provider aws network = { availability_zones = 3 name = "inspection" private_netmask = 24 - public_netmask = 24 vpc_cidr = "100.64.0.0/21" } } diff --git a/examples/inspection/providers.tf b/examples/inspection/providers.tf deleted file mode 100644 index e2ec8e6..0000000 --- a/examples/inspection/providers.tf +++ /dev/null @@ -1,10 +0,0 @@ - -provider "aws" {} - -provider "aws" { - alias = "ingress" -} - -provider "aws" { - alias = "egress" -} diff --git a/examples/inspection/variables.tf b/examples/inspection/variables.tf index 5603ff6..c0c0f01 100644 --- a/examples/inspection/variables.tf +++ b/examples/inspection/variables.tf @@ -19,5 +19,8 @@ variable "asn" { variable "tags" { description = "A map of tags to assign to the resources." type = map(string) - default = {} + default = { + Environment = "test" + GitRepo = "https://github.com/appvia/terraform-aws-connectivity" + } } diff --git a/examples/trusted/README.md b/examples/trusted/README.md index 8ad94cb..0d54cc5 100644 --- a/examples/trusted/README.md +++ b/examples/trusted/README.md @@ -27,6 +27,7 @@ No resources. |------|-------------|------|---------|:--------:| | [asn](#input\_asn) | The ASN of the gateway. | `number` | `64512` | no | | [name](#input\_name) | The name of the transit gateway to provision. | `string` | `"main-hub"` | no | +| [ram\_principals](#input\_ram\_principals) | The AWS RAM principal to share the transit gateway with. | `map(string)` | `{}` | no | | [tags](#input\_tags) | A map of tags to assign to the resources. | `map(string)` | `{}` | no | | [trusted\_attachments](#input\_trusted\_attachments) | The list of trusted account IDs. | `list(string)` | `[]` | no | diff --git a/examples/trusted/main.tf b/examples/trusted/main.tf index 72bef04..ff05aa5 100644 --- a/examples/trusted/main.tf +++ b/examples/trusted/main.tf @@ -16,6 +16,50 @@ module "hub_trusted" { enable_vpn_ecmp_support = true tags = var.tags + services = { + egress = { + network = { + availability_zones = 2 + name = "egress" + private_netmask = 24 + public_netmask = 24 + vpc_cidr = "10.20.0.0/21" + } + } + + ingress = { + network = { + availability_zones = 2 + name = "ingress" + private_netmask = 24 + public_netmask = 24 + vpc_cidr = "10.20.8.0/21" + } + } + + endpoints = { + services = { + ssm = { + service = "ssm" + }, + ssmmessages = { + service = "ssmmessages" + }, + } + + sharing = { + principals = [] + } + + network = { + availability_zones = 2 + name = "endpoints" + private_netmask = 24 + vpc_cidr = "10.20.16.0/21" + } + } + } + connectivity_config = { trusted = { trusted_attachments = var.trusted_attachments diff --git a/examples/trusted/variables.tf b/examples/trusted/variables.tf index 97eacae..48d49a3 100644 --- a/examples/trusted/variables.tf +++ b/examples/trusted/variables.tf @@ -27,3 +27,9 @@ variable "tags" { type = map(string) default = {} } + +variable "ram_principals" { + description = "The AWS RAM principal to share the transit gateway with." + type = map(string) + default = {} +} diff --git a/inspection.tf b/inspection_all.tf similarity index 64% rename from inspection.tf rename to inspection_all.tf index 57f635b..d828aca 100644 --- a/inspection.tf +++ b/inspection_all.tf @@ -1,34 +1,45 @@ +# Note, this implementation creates two routing tables, return and spokes. Post creation of the spokes routing table, you must +# associate the correct routing table with the transi gateway; currently this must be done manually. +# +# - The transit gateway must be configured so that the default association table is the `inspection-inbound` routing table +# - The transit gateway must be configured so that the default propagation table is the `inspection-return` routing table +# + ## Provision the inspection vpcs if required module "inspection_vpc" { - count = local.enable_inspection ? 1 : 0 + count = local.enable_inspection_all ? 1 : 0 source = "appvia/network/aws" version = "0.3.0" - availability_zones = var.connectivity_config.inspection.network.availability_zones + availability_zones = var.connectivity_config.inspection_with_all.network.availability_zones enable_default_route_table_association = false enable_default_route_table_propagation = false enable_transit_gateway = true enable_transit_gateway_appliance_mode = true - name = var.connectivity_config.inspection.network.name - private_subnet_netmask = var.connectivity_config.inspection.network.private_netmask + name = var.connectivity_config.inspection_with_all.network.name + private_subnet_netmask = var.connectivity_config.inspection_with_all.network.private_netmask tags = var.tags transit_gateway_id = module.tgw.ec2_transit_gateway_id - vpc_cidr = var.connectivity_config.inspection.network.vpc_cidr + vpc_cidr = var.connectivity_config.inspection_with_all.network.vpc_cidr } -## We create a route table for all the spokes to propagatio into. This route table is associated with +## We create a route table for all the spokes to propagated into. This route table is associated with ## the inspection vpc attachment, and is used to return traffic to the spoke vpcs. resource "aws_ec2_transit_gateway_route_table" "inspection_return" { - count = local.enable_inspection ? 1 : 0 + count = local.enable_inspection_all ? 1 : 0 - tags = merge(var.tags, { Name = var.connectivity_config.inspection.spokes_route_table_name }) + tags = merge(var.tags, { Name = var.connectivity_config.inspection_with_all.return_route_table_name }) transit_gateway_id = module.tgw.ec2_transit_gateway_id } +# +## Setup the association the inspection vpc, and ensure the inbound route table has a default route to the inspection vpc. +# + ## We need to associated the inspection vpc attachment with the return route table. resource "aws_ec2_transit_gateway_route_table_association" "inspection_inbound" { - count = local.enable_inspection ? 1 : 0 + count = local.enable_inspection_all ? 1 : 0 replace_existing_association = true transit_gateway_attachment_id = module.inspection_vpc[0].transit_gateway_attachment_id @@ -38,69 +49,80 @@ resource "aws_ec2_transit_gateway_route_table_association" "inspection_inbound" ## The default route table is setup as the default association for all attachments; we need to ## add an default route here to funnel all traffic to the inspection vpc. resource "aws_ec2_transit_gateway_route" "inspection_inbound" { - count = local.enable_inspection ? 1 : 0 + count = local.enable_inspection_all ? 1 : 0 destination_cidr_block = "0.0.0.0/0" transit_gateway_attachment_id = module.inspection_vpc[0].transit_gateway_attachment_id transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id } +# +## Next, we need to ensure the various service associations and propagations - here setup the +## routing for the services, i.e ingress, egress, endpoints +# + ## If the egress vpc is enabled, we need to add a default route to the return traffic routing table, ## to allow traffic to egress via it. resource "aws_ec2_transit_gateway_route" "inspection_egress" { - count = local.enable_inspection && local.enable_egress ? 1 : 0 + count = local.enable_inspection_all && local.enable_egress ? 1 : 0 destination_cidr_block = "0.0.0.0/0" transit_gateway_attachment_id = module.egress_vpc[0].transit_gateway_attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.inspection_return[0].id } -## We need to associate the endpoints vpc +## ENDPOINTS (association and propagation) + +## We need to associate the endpoints vpc and propagate the routes resource "aws_ec2_transit_gateway_route_table_association" "inspection_endpoints" { - count = local.enable_inspection == true && local.enable_endpoints == true ? 1 : 0 + count = local.enable_inspection_all == true && local.enable_endpoints == true ? 1 : 0 replace_existing_association = true - transit_gateway_attachment_id = module.endpoints_vpc[0].transit_gateway_attachment_id + transit_gateway_attachment_id = local.endpoints_vpc_attachment_id transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id } -## We need to associate the ingress vpc -resource "aws_ec2_transit_gateway_route_table_association" "inspection_ingress" { - count = local.enable_inspection == true && local.enable_ingress == true ? 1 : 0 +## We need to propagate the endpoints_vpc into the return route table +resource "aws_ec2_transit_gateway_route_table_propagation" "inspection_endpoints" { + count = local.enable_inspection_all == true && local.enable_endpoints == true ? 1 : 0 - replace_existing_association = true - transit_gateway_attachment_id = module.ingress_vpc[0].transit_gateway_attachment_id - transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id + transit_gateway_attachment_id = local.endpoints_vpc_attachment_id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.inspection_return[0].id } -## We need to associate the egress vpc -resource "aws_ec2_transit_gateway_route_table_association" "inspection_egress" { - count = local.enable_inspection == true && local.enable_egress == true ? 1 : 0 +## INGRESS (association and propagation) + +## We need to associate the ingress vpc with inbound routing table +resource "aws_ec2_transit_gateway_route_table_association" "inspection_ingress" { + count = local.enable_inspection_all == true && local.enable_ingress == true ? 1 : 0 replace_existing_association = true - transit_gateway_attachment_id = module.egress_vpc[0].transit_gateway_attachment_id + transit_gateway_attachment_id = module.ingress_vpc[0].transit_gateway_attachment_id transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id } -## We need to propagate the endpoints_vpc into the return route table -resource "aws_ec2_transit_gateway_route_table_propagation" "inspection_endpoints" { - count = local.enable_inspection == true && local.enable_endpoints == true ? 1 : 0 - - transit_gateway_attachment_id = module.endpoints_vpc[0].transit_gateway_attachment_id - transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.inspection_return[0].id -} - ## We need to propagate the ingress_vpc into the return route table resource "aws_ec2_transit_gateway_route_table_propagation" "inspection_ingress" { - count = local.enable_inspection == true && local.enable_ingress == true ? 1 : 0 + count = local.enable_inspection_all == true && local.enable_ingress == true ? 1 : 0 transit_gateway_attachment_id = module.ingress_vpc[0].transit_gateway_attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.inspection_return[0].id } +## EGRESS (association and propagation) + +## We need to associate the egress vpc with the inbound routing table +resource "aws_ec2_transit_gateway_route_table_association" "inspection_egress" { + count = local.enable_inspection_all == true && local.enable_egress == true ? 1 : 0 + + replace_existing_association = true + transit_gateway_attachment_id = module.egress_vpc[0].transit_gateway_attachment_id + transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id +} + ## We need to propagate the egress_vpc into the return route spokes_route_table_name resource "aws_ec2_transit_gateway_route_table_propagation" "inspection_egress" { - count = local.enable_inspection == true && local.enable_egress == true ? 1 : 0 + count = local.enable_inspection_all == true && local.enable_egress == true ? 1 : 0 transit_gateway_attachment_id = module.egress_vpc[0].transit_gateway_attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.inspection_return[0].id diff --git a/locals.tf b/locals.tf index 0650237..8b46a03 100644 --- a/locals.tf +++ b/locals.tf @@ -1,13 +1,26 @@ locals { ## Indicates the inspection connectivity layout - enable_inspection = var.connectivity_config.inspection != null + enable_inspection_all = var.connectivity_config.inspection_with_all != null ## Indicates the trusted network connectivity layout enable_trusted = var.connectivity_config.trusted != null ## Indicates if we have egress configuration - enable_egress = var.connectivity_config.egress != null + enable_egress = var.services.egress != null ## Indicates if we have ingress configuration - enable_ingress = var.connectivity_config.ingress != null + enable_ingress = var.services.ingress != null ## Indicates if we should provision a endpoints vpc - enable_endpoints = var.connectivity_config.endpoints != null + enable_endpoints = var.services.endpoints != null + + ## The current region + region = data.aws_region.current.name + + ## The transit gateway attaccment id for the endpoints vpc + endpoints_vpc_attachment_id = local.enable_endpoints ? module.endpoints_vpc[0].transit_gateway_attachment_id : null + ## The workloads routing table for the trusted configuration + trusted_workloads_routing_table_id = local.enable_trusted ? module.tgw.ec2_transit_gateway_association_default_route_table_id : null + + ## Should we enable default propation on the vpc + enable_default_route_table_propagation = local.enable_trusted ? false : true + ## Should we enable default association on the vpc + enable_default_route_table_association = local.enable_trusted ? false : true } diff --git a/main.tf b/main.tf index 14ff974..2f5658a 100644 --- a/main.tf +++ b/main.tf @@ -1,5 +1,5 @@ -## Provision the transit gateway +## Provision the transit gateway for this region module "tgw" { source = "terraform-aws-modules/transit-gateway/aws" version = "2.12.2" @@ -29,22 +29,22 @@ module "egress_vpc" { source = "appvia/network/aws" version = "0.3.0" - availability_zones = var.connectivity_config.egress.network.availability_zones - enable_default_route_table_association = false - enable_default_route_table_propagation = false - enable_ipam = var.connectivity_config.egress.network.ipam_pool_id != null + availability_zones = var.services.egress.network.availability_zones + enable_default_route_table_association = local.enable_default_route_table_association + enable_default_route_table_propagation = local.enable_default_route_table_propagation + enable_ipam = var.services.egress.network.ipam_pool_id != null enable_nat_gateway = true enable_transit_gateway = true enable_transit_gateway_subnet_natgw = true - ipam_pool_id = var.connectivity_config.egress.network.ipam_pool_id - name = var.connectivity_config.egress.network.name + ipam_pool_id = var.services.egress.network.ipam_pool_id + name = var.services.egress.network.name nat_gateway_mode = "all_azs" - private_subnet_netmask = var.connectivity_config.egress.network.private_netmask - public_subnet_netmask = var.connectivity_config.egress.network.public_netmask + private_subnet_netmask = var.services.egress.network.private_netmask + public_subnet_netmask = var.services.egress.network.public_netmask tags = var.tags transit_gateway_id = module.tgw.ec2_transit_gateway_id - vpc_cidr = var.connectivity_config.egress.network.vpc_cidr - vpc_netmask = var.connectivity_config.egress.network.vpc_netmask + vpc_cidr = var.services.egress.network.vpc_cidr + vpc_netmask = var.services.egress.network.vpc_netmask } ## Provision an ingress vpc if required @@ -53,20 +53,20 @@ module "ingress_vpc" { source = "appvia/network/aws" version = "0.3.0" - availability_zones = var.connectivity_config.ingress.network.availability_zones - enable_default_route_table_association = false - enable_default_route_table_propagation = false - enable_ipam = var.connectivity_config.ingress.network.ipam_pool_id != null + availability_zones = var.services.ingress.network.availability_zones + enable_default_route_table_association = local.enable_default_route_table_association + enable_default_route_table_propagation = local.enable_default_route_table_propagation + enable_ipam = var.services.ingress.network.ipam_pool_id != null enable_nat_gateway = false enable_transit_gateway = true - ipam_pool_id = var.connectivity_config.ingress.network.ipam_pool_id - name = var.connectivity_config.ingress.network.name - private_subnet_netmask = var.connectivity_config.ingress.network.private_netmask - public_subnet_netmask = var.connectivity_config.ingress.network.public_netmask + ipam_pool_id = var.services.ingress.network.ipam_pool_id + name = var.services.ingress.network.name + private_subnet_netmask = var.services.ingress.network.private_netmask + public_subnet_netmask = var.services.ingress.network.public_netmask tags = var.tags transit_gateway_id = module.tgw.ec2_transit_gateway_id - vpc_cidr = var.connectivity_config.ingress.network.vpc_cidr - vpc_netmask = var.connectivity_config.ingress.network.vpc_netmask + vpc_cidr = var.services.ingress.network.vpc_cidr + vpc_netmask = var.services.ingress.network.vpc_netmask } ## Share the transit gateway with the other principals diff --git a/modules/prefix_share/.terraform.lock.hcl b/modules/prefix_share/.terraform.lock.hcl new file mode 100644 index 0000000..5021293 --- /dev/null +++ b/modules/prefix_share/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.49.0" + constraints = ">= 5.0.0" + hashes = [ + "h1:RZtXnBRpO4LNmmz0tXJQLa2heqk9VFGblFZtRCZkm/M=", + "zh:0979b07cdeffb868ea605e4bbc008adc7cccb5f3ba1d3a0b794ea3e8fff20932", + "zh:2121a0a048a1d9419df69f3561e524b7e8a6b74ba0f57bd8948799f12b6ad3a1", + "zh:573362042ba0bd18e98567a4f45d91b09eb0d223513518ba04f16a646a906403", + "zh:57be7a4d6c362be2fa586d270203f4eac1ee239816239a9503b86ebc8fa1fef0", + "zh:5c72ed211d9234edd70eac9d77c3cafc7bbf819d1c28332a6d77acf227c9a23c", + "zh:7786d1a9781f8e8c0079bf58f4ed4aeddec0caf54ad7ddcf43c47936d545a04f", + "zh:82133e7d39787ee91ed41988da71beecc2ecb900b5da94b3f3d77fbc4d4dc722", + "zh:8cdb1c154dead85be8352afd30eaf41c59249de9e7e0a8eb4ab8e625b90a4922", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:ac215fd1c3bd647ae38868940651b97a53197688daefcd70b3595c84560e5267", + "zh:c45db22356d20e431639061a72e07da5201f4937c1df6b9f03f32019facf3905", + "zh:c9ba90e62db9a4708ed1a4e094849f88ce9d44c52b49f613b30bb3f7523b8d97", + "zh:d2be3607be2209995c80dc1d66086d527de5d470f73509e813254067e8287106", + "zh:e3fa20090f3cebf3911fc7ef122bd8c0505e3330ab7d541fa945fea861205007", + "zh:ef1b9d5c0b6279323f2ecfc322db8083e141984cfe1bb2f33c0f4934fccb69e3", + ] +} diff --git a/modules/prefix_share/README.md b/modules/prefix_share/README.md new file mode 100644 index 0000000..00bd04f --- /dev/null +++ b/modules/prefix_share/README.md @@ -0,0 +1,35 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.7 | +| [aws](#requirement\_aws) | >= 5.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.0.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_ram_principal_association.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [resource\_share\_arn](#input\_resource\_share\_arn) | The ARN of the resource share | `string` | n/a | yes | +| [principals](#input\_principals) | The principal to share with | `list(string)` | `[]` | no | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index fa92cf3..410bcfd 100644 --- a/outputs.tf +++ b/outputs.tf @@ -4,6 +4,26 @@ output "connectivity_type" { value = var.connectivity_config } +output "trusted_route_table_id" { + description = "The ID of the trusted route table." + value = local.enable_trusted ? aws_ec2_transit_gateway_route_table.trusted[0].id : null +} + +output "trusted_core_route_table_id" { + description = "The ID of the trusted core route table." + value = local.enable_trusted ? aws_ec2_transit_gateway_route_table.trusted_core[0].id : null +} + +output "workloads_route_table_id" { + description = "The ID of the workloads route table." + value = local.enable_trusted ? local.trusted_workloads_routing_table_id : null +} + +output "inspection_route_inbound_table_id" { + description = "The ID of the inbound route table for inspection." + value = local.enable_inspection_all ? aws_ec2_transit_gateway_route_table.inspection_return[0].id : null +} + output "egress_vpc_id" { description = "The ID of the VPC that is used for egress traffic." value = local.enable_egress ? module.egress_vpc[0].vpc_id : null @@ -61,22 +81,22 @@ output "endpoints_vpc_id_rt_attributes_by_type_by_az" { output "inspection_vpc_id" { description = "The ID of the VPC that is used for inspection traffic." - value = local.enable_inspection ? module.inspection_vpc[0].vpc_id : null + value = local.enable_inspection_all ? module.inspection_vpc[0].vpc_id : null } output "inspection_vpc_private_subnet_attributes_by_az" { description = "The attributes of the inspection VPC." - value = local.enable_inspection ? module.inspection_vpc[0].private_subnet_attributes_by_az : null + value = local.enable_inspection_all ? module.inspection_vpc[0].private_subnet_attributes_by_az : null } output "inspection_vpc_public_subnet_attributes_by_az" { description = "The attributes of the inspection VPC." - value = local.enable_inspection ? module.inspection_vpc[0].public_subnet_attributes_by_az : null + value = local.enable_inspection_all ? module.inspection_vpc[0].public_subnet_attributes_by_az : null } output "inspection_vpc_id_rt_attributes_by_type_by_az" { description = "The route table attributes of the inspection VPC." - value = local.enable_inspection ? module.inspection_vpc[0].rt_attributes_by_type_by_az : null + value = local.enable_inspection_all ? module.inspection_vpc[0].rt_attributes_by_type_by_az : null } output "transit_gateway_id" { diff --git a/terraform.tf b/terraform.tf index 6f48074..c3db407 100644 --- a/terraform.tf +++ b/terraform.tf @@ -1,6 +1,6 @@ terraform { - required_version = ">= 1.0.7" + required_version = ">= 1.0.0" required_providers { aws = { diff --git a/trusted.tf b/trusted.tf index da0ed1e..2ddaa0e 100644 --- a/trusted.tf +++ b/trusted.tf @@ -8,6 +8,15 @@ resource "aws_ec2_transit_gateway_route_table" "trusted" { transit_gateway_id = module.tgw.ec2_transit_gateway_id } +## Provision a core trusted routing table for the transit gateway, this can be used for cloud to on-premises +## connectivity, or for trusted network connectivity. +resource "aws_ec2_transit_gateway_route_table" "trusted_core" { + count = local.enable_trusted ? 1 : 0 + + tags = merge(var.tags, { Name = var.connectivity_config.trusted.trusted_core_route_table_name }) + transit_gateway_id = module.tgw.ec2_transit_gateway_id +} + ## Associate the trusted attachments with the trusted routing table. resource "aws_ec2_transit_gateway_route_table_association" "trusted" { for_each = local.enable_trusted == true ? toset(var.connectivity_config.trusted.trusted_attachments) : toset([]) @@ -24,7 +33,7 @@ resource "aws_ec2_transit_gateway_route_table_propagation" "untrusted" { for_each = local.enable_trusted == true ? toset(var.connectivity_config.trusted.trusted_attachments) : toset([]) transit_gateway_attachment_id = each.value - transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id + transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.trusted[0].id } ## We need to add a default route to the trusted route table to egress @@ -42,7 +51,7 @@ resource "aws_ec2_transit_gateway_route" "trusted_default" { destination_cidr_block = "0.0.0.0/0" transit_gateway_attachment_id = module.egress_vpc[0].transit_gateway_attachment_id - transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id + transit_gateway_route_table_id = local.trusted_workloads_routing_table_id } ## We need to associate the endpoints vpc with the trusted routing table @@ -50,7 +59,7 @@ resource "aws_ec2_transit_gateway_route_table_association" "trusted_endpoints" { count = local.enable_trusted == true && local.enable_endpoints == true ? 1 : 0 replace_existing_association = true - transit_gateway_attachment_id = module.endpoints_vpc[0].transit_gateway_attachment_id + transit_gateway_attachment_id = local.endpoints_vpc_attachment_id transit_gateway_route_table_id = aws_ec2_transit_gateway_route_table.trusted[0].id } @@ -76,8 +85,8 @@ resource "aws_ec2_transit_gateway_route_table_association" "trusted_egress" { resource "aws_ec2_transit_gateway_route_table_propagation" "trusted_endpoints" { count = local.enable_trusted == true && local.enable_endpoints == true ? 1 : 0 - transit_gateway_attachment_id = module.endpoints_vpc[0].transit_gateway_attachment_id - transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id + transit_gateway_attachment_id = local.endpoints_vpc_attachment_id + transit_gateway_route_table_id = local.trusted_workloads_routing_table_id } ## We need to propagate the ingress_vpc into the untrusted route table @@ -85,7 +94,7 @@ resource "aws_ec2_transit_gateway_route_table_propagation" "trusted_ingress" { count = local.enable_trusted == true && local.enable_ingress == true ? 1 : 0 transit_gateway_attachment_id = module.ingress_vpc[0].transit_gateway_attachment_id - transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id + transit_gateway_route_table_id = local.trusted_workloads_routing_table_id } ## We need to propagate the egress_vpc into the untrusted route table @@ -93,5 +102,5 @@ resource "aws_ec2_transit_gateway_route_table_propagation" "trusted_egress" { count = local.enable_trusted == true && local.enable_egress == true ? 1 : 0 transit_gateway_attachment_id = module.egress_vpc[0].transit_gateway_attachment_id - transit_gateway_route_table_id = module.tgw.ec2_transit_gateway_association_default_route_table_id + transit_gateway_route_table_id = local.trusted_workloads_routing_table_id } diff --git a/variables.tf b/variables.tf index 151e7e1..f494b29 100644 --- a/variables.tf +++ b/variables.tf @@ -29,8 +29,8 @@ variable "prefix_ram_principals" { default = [] } -variable "connectivity_config" { - description = "The type of connectivity options for the transit gateway." +variable "services" { + description = "A collection of features and services associated with this connectivity domain." type = object({ egress = optional(object({ network = object({ @@ -84,9 +84,6 @@ variable "connectivity_config" { policy = optional(string, null) # An optional IAM policy to use for the endpoint. Defaults to null. })), { - ec2 = { - service = "ec2" - }, ec2messages = { service = "ec2messages" }, @@ -96,18 +93,6 @@ variable "connectivity_config" { ssmmessages = { service = "ssmmessages" }, - logs = { - service = "logs" - }, - kms = { - service = "kms" - }, - secretsmanager = { - service = "secretsmanager" - }, - s3 = { - service = "s3" - }, }) }), null) ingress = optional(object({ @@ -130,9 +115,14 @@ variable "connectivity_config" { # The netmask to use for the VPC. Defaults to null, required when using IPAM }) }), null) - inspection = optional(object({ - # Defines the configuration for the inspection network. - inbound_route_table_name = optional(string, "inbound") + }) + default = {} +} + +variable "connectivity_config" { + description = "The type of connectivity options for the transit gateway." + type = object({ + inspection_with_all = optional(object({ # The name of the inbound route table. Defaults to 'inbound'. network = optional(object({ # Defines the configuration for the inspection network. @@ -146,15 +136,16 @@ variable "connectivity_config" { vpc_cidr = optional(string, "100.64.0.0/21") # The CIDR block to use for the VPC. Defaults to carrier-grade NAT space. }), null) - spokes_route_table_name = optional(string, "spokes") - # The name of the spokes route table. Defaults to 'spokes'. + return_route_table_name = optional(string, "inspection-return") }), null) + trusted = optional(object({ # Defines the configuration for the trusted routing trusted_attachments = optional(list(string), []) # The list of transit gateway attachments to trust e.g can see all the other untrusted networks. Defaults to an empty list. trusted_route_table_name = optional(string, "trusted") # The name of the trusted route table. Defaults to 'trusted'. + trusted_core_route_table_name = optional(string, "trusted-core") }), null) }) }
"Environment": "test",
"GitRepo": "https://github.com/appvia/terraform-aws-connectivity"
}