├── .config ├── .checkov.yml ├── .mdlrc ├── .terraform-docs.yaml ├── .tflint.hcl ├── .tfsec.yml ├── .tfsec │ ├── launch_configuration_imdsv2_tfchecks.json │ ├── launch_template_imdsv2_tfchecks.json │ ├── no_launch_config_tfchecks.json │ ├── sg_no_embedded_egress_rules_tfchecks.json │ └── sg_no_embedded_ingress_rules_tfchecks.json ├── functional_tests │ ├── post-entrypoint-helpers.sh │ └── pre-entrypoint-helpers.sh └── static_tests │ ├── post-entrypoint-helpers.sh │ └── pre-entrypoint-helpers.sh ├── .copier-answers.yml ├── .gitignore ├── .header.md ├── .pre-commit-config.yaml ├── .project_automation ├── deprecation │ └── entrypoint.sh ├── deprovision │ └── entrypoint.sh ├── functional_tests │ ├── Dockerfile │ ├── entrypoint.sh │ └── functional_tests.sh ├── init │ └── noop.sh ├── provision │ └── entrypoint.sh ├── publication │ ├── Dockerfile │ └── entrypoint.sh ├── static_tests │ ├── Dockerfile │ ├── entrypoint.sh │ └── static_tests.sh └── update │ └── noop.sh ├── .project_config.yml ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE.txt ├── README.md ├── VERSION ├── data.tf ├── examples ├── basic │ ├── .header.md │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── dns_configuration │ ├── .header.md │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── ram_share │ ├── .header.md │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variablest.tf ├── service │ ├── .header.md │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── service_network │ ├── .header.md │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf └── target_groups │ ├── .header.md │ ├── README.md │ ├── function.py │ ├── lambda_function.zip │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── main.tf ├── modules ├── listener_rules │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── listeners │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf └── targets │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ └── variables.tf ├── outputs.tf ├── providers.tf ├── tests ├── 01_mandatory.tftest.hcl ├── 02_service.tftest.hcl ├── 03_target_groups.tftest.hcl ├── 04_ram_share.tftest.hcl └── 05_dns_configuration.tftest.hcl └── variables.tf /.config/.checkov.yml: -------------------------------------------------------------------------------- 1 | download-external-modules: True 2 | evaluate-variables: True 3 | file: 4 | - 'tf.json' 5 | framework: 6 | - terraform_plan 7 | skip-check: 8 | - CKV2_GCP* 9 | - CKV_AZURE* 10 | - CKV2_AZURE* 11 | repo-root-for-plan-enrichment: 12 | - '.' 13 | summary-position: bottom 14 | output: 'cli' 15 | compact: True 16 | quiet: True -------------------------------------------------------------------------------- /.config/.mdlrc: -------------------------------------------------------------------------------- 1 | # Ignoring the following rules 2 | # MD007 Unordered list indentation 3 | # MD013 Line length 4 | # MD029 Ordered list item prefix 5 | # MD055 Table row doesn't begin/end with pipes 6 | # MD057 Table has missing or invalid header separation (second row) 7 | rules "~MD007", "~MD013", "~MD029", "~MD055", "~MD057" -------------------------------------------------------------------------------- /.config/.terraform-docs.yaml: -------------------------------------------------------------------------------- 1 | formatter: markdown 2 | header-from: .header.md 3 | settings: 4 | anchor: true 5 | color: true 6 | default: true 7 | escape: true 8 | html: true 9 | indent: 2 10 | required: true 11 | sensitive: true 12 | type: true 13 | 14 | sort: 15 | enabled: true 16 | by: required 17 | 18 | output: 19 | file: README.md 20 | mode: replace 21 | -------------------------------------------------------------------------------- /.config/.tflint.hcl: -------------------------------------------------------------------------------- 1 | # https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/module-inspection.md 2 | # borrowed & modified indefinitely from https://github.com/ksatirli/building-infrastructure-you-can-mostly-trust/blob/main/.tflint.hcl 3 | 4 | plugin "aws" { 5 | enabled = true 6 | version = "0.22.1" 7 | source = "github.com/terraform-linters/tflint-ruleset-aws" 8 | } 9 | 10 | config { 11 | module = true 12 | force = false 13 | } 14 | 15 | rule "terraform_required_providers" { 16 | enabled = true 17 | } 18 | 19 | rule "terraform_required_version" { 20 | enabled = true 21 | } 22 | 23 | rule "terraform_naming_convention" { 24 | enabled = true 25 | format = "snake_case" 26 | } 27 | 28 | rule "terraform_typed_variables" { 29 | enabled = true 30 | } 31 | 32 | rule "terraform_unused_declarations" { 33 | enabled = true 34 | } 35 | 36 | rule "terraform_comment_syntax" { 37 | enabled = true 38 | } 39 | 40 | rule "terraform_deprecated_index" { 41 | enabled = true 42 | } 43 | 44 | rule "terraform_deprecated_interpolation" { 45 | enabled = true 46 | } 47 | 48 | rule "terraform_documented_outputs" { 49 | enabled = true 50 | } 51 | 52 | rule "terraform_documented_variables" { 53 | enabled = true 54 | } 55 | 56 | rule "terraform_module_pinned_source" { 57 | enabled = true 58 | } 59 | 60 | rule "terraform_standard_module_structure" { 61 | enabled = true 62 | } 63 | 64 | rule "terraform_workspace_remote" { 65 | enabled = true 66 | } 67 | -------------------------------------------------------------------------------- /.config/.tfsec.yml: -------------------------------------------------------------------------------- 1 | { 2 | "minimum_severity": "MEDIUM" 3 | } -------------------------------------------------------------------------------- /.config/.tfsec/launch_configuration_imdsv2_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS002", 5 | "description": "Check to IMDSv2 is required on EC2 instances created by this Launch Template", 6 | "impact": "Instance metadata service can be interacted with freely", 7 | "resolution": "Enable HTTP token requirement for IMDS", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_launch_configuration" 13 | ], 14 | "severity": "CRITICAL", 15 | "matchSpec": { 16 | "action": "isPresent", 17 | "name": "metadata_options", 18 | "subMatch": { 19 | "action": "and", 20 | "predicateMatchSpec": [ 21 | { 22 | "action": "equals", 23 | "name": "http_tokens", 24 | "value": "required" 25 | 26 | } 27 | ] 28 | } 29 | }, 30 | 31 | "errorMessage": "is missing `metadata_options` block - it is required with `http_tokens` set to `required` to make Instance Metadata Service more secure.", 32 | "relatedLinks": [ 33 | "https://tfsec.dev/docs/aws/ec2/enforce-http-token-imds#aws/ec2", 34 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration#metadata-options", 35 | "https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.config/.tfsec/launch_template_imdsv2_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS001", 5 | "description": "Check to IMDSv2 is required on EC2 instances created by this Launch Template", 6 | "impact": "Instance metadata service can be interacted with freely", 7 | "resolution": "Enable HTTP token requirement for IMDS", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_launch_template" 13 | ], 14 | "severity": "CRITICAL", 15 | "matchSpec": { 16 | "action": "isPresent", 17 | "name": "metadata_options", 18 | "subMatch": { 19 | "action": "and", 20 | "predicateMatchSpec": [ 21 | { 22 | "action": "equals", 23 | "name": "http_tokens", 24 | "value": "required" 25 | 26 | } 27 | ] 28 | } 29 | }, 30 | 31 | "errorMessage": "is missing `metadata_options` block - it is required with `http_tokens` set to `required` to make Instance Metadata Service more secure.", 32 | "relatedLinks": [ 33 | "https://tfsec.dev/docs/aws/ec2/enforce-http-token-imds#aws/ec2", 34 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#metadata-options", 35 | "https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.config/.tfsec/no_launch_config_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS003", 5 | "description": "Use `aws_launch_template` over `aws_launch_configuration", 6 | "impact": "Launch configurations are not capable of versions", 7 | "resolution": "Convert resource type and attributes to `aws_launch_template`", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_launch_configuration" 13 | ], 14 | "severity": "MEDIUM", 15 | "matchSpec": { 16 | "action": "notPresent", 17 | "name": "image_id" 18 | }, 19 | 20 | "errorMessage": "should be changed to `aws_launch_template` since the functionality is the same but templates can be versioned.", 21 | "relatedLinks": [ 22 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template", 23 | "https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service" 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.config/.tfsec/sg_no_embedded_egress_rules_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS005", 5 | "description": "Security group rules should be defined with `aws_security_group_rule` instead of embedded.", 6 | "impact": "Embedded security group rules can cause issues during configuration updates.", 7 | "resolution": "Move `egress` rules to `aws_security_group_rule` and attach to `aws_security_group`.", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_security_group" 13 | ], 14 | "severity": "MEDIUM", 15 | "matchSpec": { 16 | "action": "notPresent", 17 | "name": "egress" 18 | }, 19 | 20 | "errorMessage": "`egress` rules should be moved to `aws_security_group_rule` and attached to `aws_security_group` instead of embedded.", 21 | "relatedLinks": [ 22 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule", 23 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group" 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.config/.tfsec/sg_no_embedded_ingress_rules_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS004", 5 | "description": "Security group rules should be defined with `aws_security_group_rule` instead of embedded.", 6 | "impact": "Embedded security group rules can cause issues during configuration updates.", 7 | "resolution": "Move `ingress` rules to `aws_security_group_rule` and attach to `aws_security_group`.", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_security_group" 13 | ], 14 | "severity": "MEDIUM", 15 | "matchSpec": { 16 | "action": "notPresent", 17 | "name": "ingress" 18 | }, 19 | 20 | "errorMessage": "`ingress` rules should be moved to `aws_security_group_rule` and attached to `aws_security_group` instead of embedded.", 21 | "relatedLinks": [ 22 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule", 23 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group" 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.config/functional_tests/post-entrypoint-helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## NOTE: this script runs at the end of functional test 3 | ## Use this to load any configurations after the functional test 4 | ## TIPS: avoid modifying the .project_automation/functional_test/entrypoint.sh 5 | ## migrate any customization you did on entrypoint.sh to this helper script 6 | echo "Executing Post-Entrypoint Helpers" -------------------------------------------------------------------------------- /.config/functional_tests/pre-entrypoint-helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## NOTE: this script runs at the start of functional test 3 | ## use this to load any configuration before the functional test 4 | ## TIPS: avoid modifying the .project_automation/functional_test/entrypoint.sh 5 | ## migrate any customization you did on entrypoint.sh to this helper script 6 | echo "Executing Pre-Entrypoint Helpers" -------------------------------------------------------------------------------- /.config/static_tests/post-entrypoint-helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## NOTE: this script runs at the end of static test 3 | ## Use this to load any configurations after the static test 4 | ## TIPS: avoid modifying the .project_automation/static_test/entrypoint.sh 5 | ## migrate any customization you did on entrypoint.sh to this helper script 6 | echo "Executing Post-Entrypoint Helpers" -------------------------------------------------------------------------------- /.config/static_tests/pre-entrypoint-helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ## NOTE: this script runs at the start of static test 3 | ## use this to load any configuration before the static test 4 | ## TIPS: avoid modifying the .project_automation/static_test/entrypoint.sh 5 | ## migrate any customization you did on entrypoint.sh to this helper script 6 | echo "Executing Pre-Entrypoint Helpers" -------------------------------------------------------------------------------- /.copier-answers.yml: -------------------------------------------------------------------------------- 1 | # This file is auto-generated, changes will be overwritten 2 | _commit: v0.1.4 3 | _src_path: /task/0712f39c-082e-11f0-b3ed-fab5e18b6448/projecttype 4 | starting_version: v0.0.0 5 | version_file: VERSION 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | plan.out 3 | plan.out.json 4 | 5 | # Local .terraform directories 6 | **/.terraform/* 7 | 8 | # .tfstate files 9 | *.tfstate 10 | *.tfstate.* 11 | 12 | # Crash log files 13 | crash.log 14 | 15 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as 16 | # password, private keys, and other secrets. These should not be part of version 17 | # control as they are data points which are potentially sensitive and subject 18 | # to change depending on the environment. 19 | # 20 | *.tfvars 21 | 22 | # Ignore override files as they are usually used to override resources locally and so 23 | # are not checked in 24 | override.tf 25 | override.tf.json 26 | *_override.tf 27 | *_override.tf.json 28 | 29 | # Include override files you do wish to add to version control using negated pattern 30 | # 31 | # !example_override.tf 32 | 33 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 34 | # example: *tfplan* 35 | 36 | # Ignore CLI configuration files 37 | .terraformrc 38 | terraform.rc 39 | .terraform.lock.hcl 40 | 41 | go.mod 42 | go.sum 43 | 44 | .DS_Store 45 | -------------------------------------------------------------------------------- /.header.md: -------------------------------------------------------------------------------- 1 | # Amazon VPC Lattice Module 2 | 3 | This module can be used to deploy resources from [Amazon VPC Lattice](https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-service-network.html). VPC Lattice is a fully managed application networking service that you use to connect, secure, and monitor all your services across multiple accounts and virtual private clouds (VPCs). 4 | 5 | This module handles all the different resources you can use with VPC Lattice: Service Network, Service, Listeners, Listener Rules, Target Groups (and targets), and Associations (Service or VPC). You have the freedom to create the combination of resources you need, so in multi-AWS Account environments you can make use of the module as many times as needed (different providers) to create your application network architecture. 6 | 7 | ## Usage 8 | 9 | ### VPC Lattice service network (var.service_network) 10 | 11 | A [VPC Lattice service network](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-networks.html) is a logical boundary for a collection of services. It is the central place of connectivity where consumers (located in a VPC) and producers (target groups) are connected to allow service consumption. In addition, it provides a central place for access control via [IAM auth policies](https://docs.aws.amazon.com/vpc-lattice/latest/ug/auth-policies.html), and visibility by enabling [logs](https://docs.aws.amazon.com/vpc-lattice/latest/ug/monitoring-access-logs.html). 12 | 13 | When creating a service network in the module, the following attributes are expected: 14 | 15 | - `name` = (Optional|string) VPC Lattice service network name. This attribute creates a **new** service network using the specified name. **This attribute and `identifier` cannot be set at the same time.** 16 | - `auth_type` = (Optional|string) Type of IAM policy to apply in the service network. Allowed values are `NONE` (default) and `AWS_IAM`. 17 | - `auth_policy` = (Optional|any) Auth policy. The policy string in JSON must not contain newlines or blank lines. The auth policy resource will be created only if `auth_type` is set to `AWS_IAM`. 18 | - `identifier` = (Optional|string) The ID or ARN of an **existing** service network. If you are working in multi-AWS account environments, ARN is compulsory. **This attribute and `name` cannot be set at the same time.** 19 | - `access_log_cloudwatch` = (Optional|string) Amazon CloudWatch log group ARN to configure as service network's access log destination. 20 | - `access_log_s3` = (Optional|string) Amazon S3 bucket ARN to configure as service network's access log destination. 21 | - `access_log_firehose` = (Optional|string) Data Firehose delivery stream ARN to configure as service network's access log destination. 22 | 23 | You can share VPC Lattice service networks using AWS RAM with this module. Check the section [Sharing VPC Lattice resources](#sharing-vpc-lattice-resources) for more information. 24 | 25 | **Examples** of use can be found in the [/examples/service_network](./examples/service_network/) folder. 26 | 27 | #### VPC associations (var.vpc_associations) 28 | 29 | When you associate a VPC with a service network, it enables all the resources within that VPC to be clients and communicate with other services associated to that same service network. You can make use of Security Groups to control the access of the VPC association, allowing some traffic segmentation before the traffic arrives to the Service Network. 30 | 31 | You can create more than 1 VPC association with this module, as this variable expects a map of objects with the following attributes: 32 | 33 | - `vpc_id` = (string) ID of the VPC. 34 | - `security_group_ids` = (Optional|list(string)) List of Security Group IDs to associate with the VPC association. 35 | 36 | #### Access Logs for VPC Lattice service networks 37 | 38 | You can enable [access logs](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-network-monitoring.html) for VPC Lattice service networks and specify the destination resource for your logs. VPC Lattice can send logs to the following resources: **CloudWatch Log groups**, **Firehose delivery streams**, and **S3 buckets**. You can configure the three destinations at the same time (`access_log_cloudwatch`, `access_log_s3`, `access_log_firehose`), but you cannot configure the same destination type twice. 39 | 40 | ### VPC Lattice service (var.services) 41 | 42 | A [VPC Lattice service](https://docs.aws.amazon.com/vpc-lattice/latest/ug/services.html) is an independently deployable unit of software that delivers a specific task or function. It can run on instances, containers, or as serverless functions within an AWS Account or a VPC. A service has a [listener](https://docs.aws.amazon.com/vpc-lattice/latest/ug/listeners.html) that uses **rules** you can configure to help route traffic to your targets. 43 | 44 | You can create 1 or more VPC Lattice services using the module, as this variable expects a **map of objects** with the following attributes: 45 | 46 | - `identifier` = (Optional|string) ID or ARN of the VPC Lattice service (if it was created outside this module). **This attribute and `name` cannot be set at the same time.** 47 | - `name` = (Optional|string) VPC Lattice service's name - to create a new resource. **This attribute and `identifier` cannot be set at the same time.** 48 | - `auth_type` = (Optional|string) Type of IAM policy. Either `NONE` (default) or `AWS_IAM`. 49 | - `auth_policy` = (Optional|any) Auth policy. The policy string in JSON must not contain newlines or blank lines. The auth policy resource will be created only if `auth_type` is set to `AWS_IAM`. 50 | - `certificate_arn` = (Optional|string) **When configuring a HTTPS listener** AWS Certificate Manager certificate's ARN. 51 | - `custom_domain_name` = (Optional|string) Custom domain name for the service. 52 | - `listeners` = (Optional|map(string)) VPC Lattice listeners (and rules) to configure in the service - more information about its definition below. 53 | - `hosted_zone_id` = (Optional|string) Amazon Route 53 hosted zone ID to configure Alias records when configuring custom domain names. Check the section [Amazon Route 53 DNS configuration](#amazon-route-53-dns-configuration) for more information. 54 | - `access_log_cloudwatch` = (Optional|string) Amazon CloudWatch log group ARN to configure as service network's access log destination. 55 | - `access_log_s3` = (Optional|string) Amazon S3 bucket ARN to configure as service network's access log destination. 56 | - `access_log_firehose` = (Optional|string) Data Firehose delivery stream ARN to configure as service network's access log destination. 57 | 58 | The attribute `listeners` (you can define 1 or more) supports the following: 59 | 60 | - `name` = (Optional|string) Listener's name. If this attribute is not defined, the key will be used as name. 61 | - `port` = (Optional|number) Listener's port. You can specify a value from 1 to 65535. If not defined, the default values are 80 for `HTTP` and 443 for `HTTPS`. 62 | - `protocol` = (string) Listener's protocol. 63 | - `default_action` = (map(any)) Default action block for the default listener rule - more information about its definition below. 64 | - `rules` = (Optional|any) Rules to define in a listener to determine how the service routes requests to its registered targets - more information about its definition below. 65 | 66 | The attribute `default_action` *- map(any) -* supports the following: 67 | 68 | - `type` = (string) Default action to apply in the listener. Allowed values are `fixed_response` and `forward`. 69 | - `status_code` = (Optional|number) Custom HTTP status codd to return. **To define if the default_action type is `fixed-response`**. 70 | - `target_groups` = (Optional|map(string)) Map of target groups to use in the listener's default action. **To define if the default_action type is `forward`**. The map expects the following: 71 | - `target_group_identifier` = (string) Target group identifier. **The key of each target group should map the key you defined in var.target_groups**. 72 | - `weight` = (Optional|number) Determines how requests are distributed to the target group. Only required if you specify multiple target groups for a forward action. 73 | 74 | The attribute `rules` (you can define 1 or more) supports the following: 75 | 76 | - `name` = (Optional|string)Listener Rule's name. If not defined, the key will be use as name. 77 | - `priority` = (number) The priority assigned to the rule. Each rule for a specific listener must have a unique priority. The lower the number the higher the priority. 78 | - `http_match_method` = (Optional|string) The HTTP method type. 79 | - `path_match` = (Optional|map(any)) The path match. **This attribute and `header_matches` cannot be set at the same time.** 80 | - `case_sensitive` = (Optional|bool) Indicates whether the match is case sensitive. Defaults to false. 81 | - `exact` = (Optional|string) Specifies an exact type match. 82 | - `prefix` = (Optional|string) Specifies a prefix type match. Matches the value with the prefix. 83 | - `headers_match` = (Optional|map(any)) The header matches. Matches incoming requests with rule based on request header value before applying rule action. **This attribute and `path_match` cannot be set at the same time.** 84 | - `case_sensitive` = (Optional|bool) Indicates whether the match is case sensitive. Defaults to false. 85 | - `name` = (Optional|string) The name of the header. 86 | - `exact` = (Optional|string) Specifies an exact type match. 87 | - `prefix` = (Optional|string) Specifies a prefix type match. Matches the value with the prefix. 88 | - `action_fixedresponse` = (Optional|map(string)) Describes the rule action that returns a custom HTTP response. **This attribute and `action_forward` cannot be set at the same time.** 89 | - `status_code` = (Optional|string) The HTTP response code. 90 | - `action_forward` = (Optional|map(string)) The forward action. Traffic that matches the rule is forwarded to the specified target groups. **This attribute and `action_fixedresponse` cannot be set at the same time.** 91 | - `target_groups` = (Optional|map(any)) The target groups. You can define more than 1 target group. **The key of each target group should map the key you defined in var.target_groups**. 92 | - `weight` = (Optional|number) With forward actions, you can assign a weight that controls the prioritization and selection of each target group. 93 | 94 | You can share VPC Lattice services using AWS RAM with this module. Check the section [Sharing VPC Lattice resources](#sharing-vpc-lattice-resources) for more information. 95 | 96 | **Examples** of use can be found in the [/examples/service](./examples/service/) folder. Note that all the target groups used in the examples will be empty. In the [Target groups](#target-groups-vartarget_groups) section you will find more information about how to define the different target types. 97 | 98 | #### VPC Lattice service associations 99 | 100 | When a VPC Lattice service network is created or referenced using the module, a [VPC Lattice service association](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-associations.html) is created automatically for each VPC Lattice service created/referenced in the module. 101 | 102 | #### Access Logs for VPC Lattice services 103 | 104 | You can enable [access logs](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-monitoring.html) for VPC Lattice services and specify the destination resource for your logs. VPC Lattice can send logs to the following resources: **CloudWatch Log groups**, **Firehose delivery streams**, and **S3 buckets**. You can configure the three destinations at the same time (`access_log_cloudwatch`, `access_log_s3`, `access_log_firehose`) for each VPC Lattice service configured under `var.services`, but you cannot configure the same destination type twice. 105 | 106 | ### Target Groups (var.target_groups) 107 | 108 | A [Target group](https://docs.aws.amazon.com/vpc-lattice/latest/ug/target-groups.html) is a collection of targets, or compute resources that run your application or service. Targets in VPC Lattice can be Amazon EC2 instances, IP addresses, AWS Lambda functions, Application Load Balancers, Amazon ECS tasks or Kubernetes Pods. 109 | 110 | You can create 1 or more target groups with this module, as this variable expects a **map of objects** with the following attributes: 111 | 112 | - `name` = (Optional|string) Target group's name. If not provided, the key of the map will be used as name. 113 | - `type` = (string) The type of target group. Valid Values are `IP`, `LAMBDA`, `INSTANCE`, `ALB`. 114 | - `config` = (Optional|map(any)) Target group configuration - more information about its definition below. If type is set to `LAMBDA`, this parameter should not be specified. 115 | - `health_check` = (Optional|map(any)) Health check configuration - more information about its definition below. If type is set to `LAMBDA` or `ALB`, this parameter should not be specified. 116 | - `targets` = (Optional|map(any)) Targets to associate to the target group. If `type` is equals to `LAMBDA` or `ALB`, only one target can be defined. More information about its definition below. 117 | 118 | **The key used for each of the target group definitions is the one expected when defining the listeners and rules (var.services)**, so make sure these values are unique. 119 | 120 | The `config` attribute *- map(any) -* supports the following: 121 | 122 | - `port` = (number) Port on which the targets are listening. Not supported if type is set to `LAMBDA`. 123 | - `protocol` = (string) Protocol to use for routing traffic to the targets. Valid values: `HTTP` and `HTTPS`. Not supported if type is set to `LAMBDA`. 124 | - `vpc_identifier` = (string) VPC ID. Not supported if type is set to `LAMBDA`. 125 | - `ip_address_type` = (Optional|string) IP address type for the target group. Valid values: `IPV4` and `IPV6`. Not supported if type is set to `LAMBDA` or `ALB`. 126 | - `protocol_version` = (Optional|string) Protocol version. Valid values: `HTTP1` (default), `HTTP2`, `GRPC`. Not supported if type is set to `LAMBDA`. 127 | - `lambda_event_structure_version` = (Optional|string) The version of the event structure that the Lambda function receives. Valid values: `V1`and `V2` (default). Supported only if type is set to `LAMBDA`. 128 | 129 | The `health_check` attribute *- map(any) -* supports the following: 130 | 131 | - `enabled` = (Optional|bool) Whether health checks are enabled. Valid values: `true` (default) and `false`. 132 | - `health_check_interval_seconds` = (Optional|number) The approximate amount of time, in seconds, between health checks of an individual target. The range is 5-300 seconds. The default is 30 seconds. 133 | - `health_check_timeout_seconds` = (Optional|number) The amount of time, in seconds, to wait before reporting a target as unhealthy. The range is 1-120 seconds. The default is 5 seconds. 134 | - `healthy_threshold_count` = (Optional|number) The number of consecutive successful health checks required before considering an unhealthy target healthy. The range is 2-10. The default is 5. 135 | - `matcher` = (Optional|list(string)) List of HTTP codes to use when checking for a successful response from a target. 136 | - `path` = (Optional|string) The destination for health checks on the targets. If the protocol version is HTTP/1.1 or HTTP/2, specify a valid URI (for example, /path?query). The default path is /. Health checks are not supported if the protocol version is gRPC, however, you can choose HTTP/1.1 or HTTP/2 and specify a valid URI. 137 | - `port` = (Optional|number) The port used when performing health checks on targets. The default setting is the port that a target receives traffic on. 138 | - `protocol` = (Optional|string) The protocol used when performing health checks on targets. The possible protocols are `HTTP` and `HTTPS`. 139 | - `protocol_version` = (Optional|string) The protocol version used when performing health checks on targets. The possible protocol versions are `HTTP1` (default) and `HTTP2`. 140 | - `unhealthy_threshold_count` = (Optional|number) The number of consecutive failed health checks required before considering a target unhealthy. The range is 2-10. The default is 2. 141 | 142 | The `targets` attribute *- map(any) -* supports the following: 143 | 144 | - `id` = (Required|string) The ID of the target. If the target type of the target group is INSTANCE, this is an instance ID. If the target type is IP , this is an IP address. If the target type is LAMBDA, this is the ARN of the Lambda function. If the target type is ALB, this is the ARN of the Application Load Balancer. 145 | - `port` = (Optional|number) The port on which the target is listening. For HTTP, the default is 80. For HTTPS, the default is 443. Attribute not needed with target type of `LAMBDA`. 146 | 147 | **Examples** of use can be found in the [/examples/target_groups](./examples/target_groups/) folder. You will find an example for each target supported in this module. 148 | 149 | ### Sharing VPC Lattice resources (var.ram_share) 150 | 151 | With [AWS Resource Access Manager](https://aws.amazon.com/ram/) (RAM), you can share VPC Lattice service networks and services. With this module, you can use the variable `var.ram_share` to share VPC Lattice resources. The variable supports the following attributes: 152 | 153 | - `resources_share_arn` = (Optional|string) ARN of an **existing** RAM Resource Share to use to associate principals and VPC Lattice resources. **This attribute and `resource_share_name` cannot be set at the same time.** 154 | - `resources_share_name` = (Optional|string) Name of the RAM Resource Share resource. This attribute creates a **new** resource using the specified name. **This attribute and `resources_share_arn` cannot be set at the same time.** 155 | - `allow_external_principals` = (Optional|boolean) Indicates whether principals outside your organization can be associated with a resource share. **This attribute is allowed only when `resources_share_name` is provided.** 156 | - `principals` = (Optional|list(string)) List of AWS principals to associated the resources with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN. 157 | - `share_service_network` = (Optional|boolean) Indicates whether a created VPC Lattice service network should be associated or not. Defaults to `true`. 158 | - `share_services` = (Optional|list(string)) List of created VPC Lattice services to share. You should use the services' keys defined in `var.services`. 159 | 160 | **Examples** of use can be found in the [/examples/ram_share](./examples/ram_share/) folder. 161 | 162 | ### Amazon Route 53 DNS configuration 163 | 164 | VPC Lattice leverages [Domain Name System (DNS)](https://aws.amazon.com/route53/what-is-dns/) for service discovery, so each VPC Lattice service is easily identifiable through its service-managed or custom domain names. When a new Amazon VPC Lattice service is created, a service-managed domain name is generated. This domain name is publicly resolvable and resolves either to an IPv4 link-local address or an IPv6 unique-local address. So, a consumer application using this service-managed domain name does not require any extra DNS configuration for the service-to-service communication (provided the VPC Lattice configuration allows connectivity). However, it’s more likely that you will use your own custom domain names. 165 | 166 | When using custom domain names for Amazon VPC Lattice services, an [alias](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html) (for Amazon Route 53 hosted zones) have to be created to map the custom domain name with the service-managed domain name. In multi-service environments, the creation of the DNS resolution configuration can create heavy operational overhead. 167 | 168 | This module supports the creation of alias records (both A and AAAA) in Route 53 hosted zones specified in two locations: 169 | 170 | - By using the variable `var.dns_configuration` (Optional|map(string)), you can specify a "global" hosted zone ID (attribute `hosted_zone_id`) to configure the Alias record of each VPC Lattice service created/referenced with a custom domain name configured. 171 | - By using the attribute `hosted_zone_id` under each VPC Lattice service configured (`var.services`) you can create the Alias record for the provided Hosted Zone ID only for that specific service. 172 | - A Hosted Zone ID referenced in a service definition overrides the configuration done in `var.dns_configuration`. 173 | 174 | **The module only supports the DNS configuration if the Hosted Zone and VPC Lattice service are in the same AWS Account**. For multi-Account environments, please check the [Guidance for Amazon VPC Lattice Automated DNS Configuration on AWS](https://aws.amazon.com/solutions/guidance/amazon-vpc-lattice-automated-dns-configuration-on-aws/). This Guidance Solution follows an event-driven architecture to communicate AWS Accounts and configure DNS records when Hosted Zones and VPC Lattice services are in different AWS Accounts. 175 | 176 | **Examples** of use can be found in the [/examples/dns_configuration](./examples/dns_configuration/) folder. 177 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fail_fast: false 3 | minimum_pre_commit_version: "2.6.0" 4 | repos: 5 | - 6 | repo: https://github.com/terraform-docs/terraform-docs 7 | # To update run: 8 | # pre-commit autoupdate --freeze 9 | rev: 212db41760d7fc45d736d5eb94a483d0d2a12049 # frozen: v0.16.0 10 | hooks: 11 | - id: terraform-docs-go 12 | args: 13 | - "--config=.config/.terraform-docs.yaml" 14 | - "--lockfile=false" 15 | - "--recursive" 16 | - "--recursive-path=examples/" 17 | - "./" -------------------------------------------------------------------------------- /.project_automation/deprecation/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 4 | # managed and local tasks always use these variables for the project and project type path 5 | PROJECT_PATH=${BASE_PATH}/project 6 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 7 | -------------------------------------------------------------------------------- /.project_automation/deprovision/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 4 | # managed and local tasks always use these variables for the project and project type path 5 | PROJECT_PATH=${BASE_PATH}/project 6 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 7 | -------------------------------------------------------------------------------- /.project_automation/functional_tests/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:4.0 2 | ENV TERRAFORM_VERSION=1.7.4 3 | RUN cd /tmp && \ 4 | wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ 5 | unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin && chmod 755 /usr/local/bin/terraform -------------------------------------------------------------------------------- /.project_automation/functional_tests/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## WARNING: DO NOT modify the content of entrypoint.sh 4 | # Use ./config/functional_tests/pre-entrypoint-helpers.sh or ./config/functional_tests/post-entrypoint-helpers.sh 5 | # to load any customizations or additional configurations 6 | 7 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 8 | # managed and local tasks always use these variables for the project and project type path 9 | PROJECT_PATH=${BASE_PATH}/project 10 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 11 | 12 | #********** helper functions ************* 13 | pre_entrypoint() { 14 | if [ -f ${PROJECT_PATH}/.config/functional_tests/pre-entrypoint-helpers.sh ]; then 15 | echo "Pre-entrypoint helper found" 16 | source ${PROJECT_PATH}/.config/functional_tests/pre-entrypoint-helpers.sh 17 | echo "Pre-entrypoint helper loaded" 18 | else 19 | echo "Pre-entrypoint helper not found - skipped" 20 | fi 21 | } 22 | post_entrypoint() { 23 | if [ -f ${PROJECT_PATH}/.config/functional_tests/post-entrypoint-helpers.sh ]; then 24 | echo "Post-entrypoint helper found" 25 | source ${PROJECT_PATH}/.config/functional_tests/post-entrypoint-helpers.sh 26 | echo "Post-entrypoint helper loaded" 27 | else 28 | echo "Post-entrypoint helper not found - skipped" 29 | fi 30 | } 31 | 32 | #********** Pre-entrypoint helper ************* 33 | pre_entrypoint 34 | 35 | #********** Functional Test ************* 36 | /bin/bash ${PROJECT_PATH}/.project_automation/functional_tests/functional_tests.sh 37 | if [ $? -eq 0 ] 38 | then 39 | echo "Functional test completed" 40 | EXIT_CODE=0 41 | else 42 | echo "Functional test failed" 43 | EXIT_CODE=1 44 | fi 45 | 46 | #********** Post-entrypoint helper ************* 47 | post_entrypoint 48 | 49 | #********** Exit Code ************* 50 | exit $EXIT_CODE -------------------------------------------------------------------------------- /.project_automation/functional_tests/functional_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 4 | # managed and local tasks always use these variables for the project and project type path 5 | PROJECT_PATH=${BASE_PATH}/project 6 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 7 | 8 | echo "Starting Functional Tests" 9 | cd ${PROJECT_PATH} 10 | 11 | #********** Terraform Test ********** 12 | 13 | # Look up the mandatory test file 14 | MANDATORY_TEST_PATH="./tests/01_mandatory.tftest.hcl" 15 | if test -f ${MANDATORY_TEST_PATH}; then 16 | echo "File ${MANDATORY_TEST_PATH} is found, resuming test" 17 | # Run Terraform test 18 | terraform init 19 | terraform test 20 | else 21 | echo "File ${MANDATORY_TEST_PATH} not found. You must include at least one test run in file ${MANDATORY_TEST_PATH}" 22 | (exit 1) 23 | fi 24 | 25 | if [ $? -eq 0 ]; then 26 | echo "Terraform Test Successfull" 27 | else 28 | echo "Terraform Test Failed" 29 | exit 1 30 | fi 31 | 32 | echo "End of Functional Tests" -------------------------------------------------------------------------------- /.project_automation/init/noop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Not Supported!" 3 | -------------------------------------------------------------------------------- /.project_automation/provision/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 4 | # managed and local tasks always use these variables for the project and project type path 5 | PROJECT_PATH=${BASE_PATH}/project 6 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 7 | -------------------------------------------------------------------------------- /.project_automation/publication/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:4.0 2 | RUN yum install -y yum-utils && yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && yum install -y gh 3 | RUN pip install awscli 4 | -------------------------------------------------------------------------------- /.project_automation/publication/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 4 | # managed and local tasks always use these variables for the project and project type path 5 | PROJECT_PATH=${BASE_PATH}/project 6 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 7 | 8 | echo "[STAGE: Publication]" 9 | VERSION=$(cat VERSION) 10 | echo $VERSION 11 | BRANCH=main 12 | EXISTING_GIT_VERSION="$(git tag -l)" 13 | 14 | if [[ $(echo $EXISTING_GIT_VERSION | grep $VERSION) ]] 15 | then 16 | echo "version exists skipping release creation hint: Bump version in VERSION file" 17 | else 18 | echo "creating new version" 19 | gh release create ${VERSION} --target ${BRANCH} --generate-notes 20 | fi 21 | -------------------------------------------------------------------------------- /.project_automation/static_tests/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:4.0 2 | ENV TERRAFORM_VERSION=1.7.4 3 | RUN cd /tmp && \ 4 | wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ 5 | unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/local/bin && chmod 755 /usr/local/bin/terraform 6 | 7 | ENV TFLINT_VERSION=v0.45.0 8 | 9 | RUN cd /tmp && \ 10 | wget https://github.com/terraform-linters/tflint/releases/download/${TFLINT_VERSION}/tflint_linux_amd64.zip && \ 11 | unzip tflint_linux_amd64.zip -d /usr/local/bin && chmod 755 /usr/local/bin/tflint 12 | 13 | RUN mkdir -p ~/.tflint.d/plugins 14 | 15 | ENV TFLINT_VERSION=v0.22.1 16 | 17 | RUN wget -O /tmp/tflint-ruleset-aws.zip https://github.com/terraform-linters/tflint-ruleset-aws/releases/download/${TFLINT_VERSION}/tflint-ruleset-aws_darwin_arm64.zip \ 18 | && unzip /tmp/tflint-ruleset-aws.zip -d ~/.tflint.d/plugins \ 19 | && rm /tmp/tflint-ruleset-aws.zip 20 | 21 | RUN curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash 22 | 23 | RUN pip3 install checkov 24 | 25 | RUN gem install mdl 26 | 27 | ENV TERRAFORM_DOCS_VERSION=v0.16.0 28 | RUN wget https://github.com/terraform-docs/terraform-docs/releases/download/${TERRAFORM_DOCS_VERSION}/terraform-docs-${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz && \ 29 | tar -C /usr/local/bin -xzf terraform-docs-${TERRAFORM_DOCS_VERSION}-linux-amd64.tar.gz && chmod +x /usr/local/bin/terraform-docs -------------------------------------------------------------------------------- /.project_automation/static_tests/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## WARNING: DO NOT modify the content of entrypoint.sh 4 | # Use ./config/static_tests/pre-entrypoint-helpers.sh or ./config/static_tests/post-entrypoint-helpers.sh 5 | # to load any customizations or additional configurations 6 | 7 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 8 | # managed and local tasks always use these variables for the project and project type path 9 | PROJECT_PATH=${BASE_PATH}/project 10 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 11 | 12 | #********** helper functions ************* 13 | pre_entrypoint() { 14 | if [ -f ${PROJECT_PATH}/.config/static_tests/pre-entrypoint-helpers.sh ]; then 15 | echo "Pre-entrypoint helper found" 16 | source ${PROJECT_PATH}/.config/static_tests/pre-entrypoint-helpers.sh 17 | echo "Pre-entrypoint helper loaded" 18 | else 19 | echo "Pre-entrypoint helper not found - skipped" 20 | fi 21 | } 22 | post_entrypoint() { 23 | if [ -f ${PROJECT_PATH}/.config/static_tests/post-entrypoint-helpers.sh ]; then 24 | echo "Post-entrypoint helper found" 25 | source ${PROJECT_PATH}/.config/static_tests/post-entrypoint-helpers.sh 26 | echo "Post-entrypoint helper loaded" 27 | else 28 | echo "Post-entrypoint helper not found - skipped" 29 | fi 30 | } 31 | 32 | #********** Pre-entrypoint helper ************* 33 | pre_entrypoint 34 | 35 | #********** Static Test ************* 36 | /bin/bash ${PROJECT_PATH}/.project_automation/static_tests/static_tests.sh 37 | if [ $? -eq 0 ] 38 | then 39 | echo "Static test completed" 40 | EXIT_CODE=0 41 | else 42 | echo "Static test failed" 43 | EXIT_CODE=1 44 | fi 45 | 46 | #********** Post-entrypoint helper ************* 47 | post_entrypoint 48 | 49 | #********** Exit Code ************* 50 | exit $EXIT_CODE 51 | -------------------------------------------------------------------------------- /.project_automation/static_tests/static_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## NOTE: paths may differ when running in a managed task. To ensure behavior is consistent between 4 | # managed and local tasks always use these variables for the project and project type path 5 | PROJECT_PATH=${BASE_PATH}/project 6 | PROJECT_TYPE_PATH=${BASE_PATH}/projecttype 7 | 8 | echo "Starting Static Tests" 9 | 10 | #********** Terraform Validate ************* 11 | cd ${PROJECT_PATH} 12 | terraform init 13 | terraform validate 14 | if [ $? -eq 0 ] 15 | then 16 | echo "Success - Terraform validate" 17 | else 18 | echo "Failure - Terraform validate" 19 | exit 1 20 | fi 21 | 22 | #********** tflint ******************** 23 | echo 'Starting tflint' 24 | tflint --init --config ${PROJECT_PATH}/.config/.tflint.hcl 25 | MYLINT=$(tflint --force --config ${PROJECT_PATH}/.config/.tflint.hcl) 26 | if [ -z "$MYLINT" ] 27 | then 28 | echo "Success - tflint found no linting issues!" 29 | else 30 | echo "Failure - tflint found linting issues!" 31 | echo "$MYLINT" 32 | exit 1 33 | fi 34 | 35 | #********** tfsec ********************* 36 | echo 'Starting tfsec' 37 | MYTFSEC=$(tfsec . --config-file ${PROJECT_PATH}/.config/.tfsec.yml --custom-check-dir ${PROJECT_PATH}/.config/.tfsec) 38 | if [[ $MYTFSEC == *"No problems detected!"* ]]; 39 | then 40 | echo "Success - tfsec found no security issues!" 41 | echo "$MYTFSEC" 42 | else 43 | echo "Failure - tfsec found security issues!" 44 | echo "$MYTFSEC" 45 | exit 1 46 | fi 47 | 48 | #********** Checkov Analysis ************* 49 | echo "Running Checkov Analysis" 50 | checkov --config-file ${PROJECT_PATH}/.config/.checkov.yml 51 | if [ $? -eq 0 ] 52 | then 53 | echo "Success - Checkov found no issues!" 54 | else 55 | echo "Failure - Checkov found issues!" 56 | exit 1 57 | fi 58 | 59 | #********** Markdown Lint ************** 60 | echo 'Starting markdown lint' 61 | MYMDL=$(mdl --config ${PROJECT_PATH}/.config/.mdlrc .header.md examples/*/.header.md) 62 | if [ -z "$MYMDL" ] 63 | then 64 | echo "Success - markdown lint found no linting issues!" 65 | else 66 | echo "Failure - markdown lint found linting issues!" 67 | echo "$MYMDL" 68 | exit 1 69 | fi 70 | 71 | #********** Terraform Docs ************* 72 | echo 'Starting terraform-docs' 73 | TDOCS="$(terraform-docs --config ${PROJECT_PATH}/.config/.terraform-docs.yaml --lockfile=false ./)" 74 | git add -N README.md 75 | GDIFF="$(git diff --compact-summary)" 76 | if [ -z "$GDIFF" ] 77 | then 78 | echo "Success - Terraform Docs creation verified!" 79 | else 80 | echo "Failure - Terraform Docs creation failed, ensure you have precommit installed and running before submitting the Pull Request. TIPS: false error may occur if you have unstaged files in your repo" 81 | echo "$GDIFF" 82 | exit 1 83 | fi 84 | 85 | #*************************************** 86 | echo "End of Static Tests" -------------------------------------------------------------------------------- /.project_automation/update/noop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Not Supported!" 3 | -------------------------------------------------------------------------------- /.project_config.yml: -------------------------------------------------------------------------------- 1 | version: "1.0.0" 2 | 3 | init: 4 | entrypoint: .project_automation/init/noop.sh 5 | update: 6 | entrypoint: .project_automation/update/noop.sh 7 | static_tests: 8 | dockerfile: .project_automation/static_tests/Dockerfile 9 | entrypoint: .project_automation/static_tests/entrypoint.sh 10 | functional_tests: 11 | github_permissions: 12 | contents: write 13 | dockerfile: .project_automation/functional_tests/Dockerfile 14 | entrypoint: .project_automation/functional_tests/entrypoint.sh 15 | publication: 16 | github_permissions: 17 | contents: write 18 | dockerfile: .project_automation/publication/Dockerfile 19 | entrypoint: .project_automation/publication/entrypoint.sh 20 | deprecation: 21 | entrypoint: .project_automation/deprecation/entrypoint.sh 22 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @aws-ia/aws-ia -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Creating modules for Terraform 2 | 3 | This repository contains code for an application that is published using the Application Builder Platform (ABP). 4 | 5 | ## Module Standards 6 | 7 | For best practices and information on developing with Terraform, see the [I&A Module Standards](https://aws-ia.github.io/standards-terraform/) 8 | 9 | ## Contributing Code 10 | 11 | In order to contibute code to this repository, you must submit a *[Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)*. To do so, you must *[fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo)* this repostiory, make your changes in your forked version and submit a *Pull Request*. 12 | 13 | ## Writing Documentation 14 | 15 | > :bangbang: **Do not manually update README.md**. 16 | 17 | README.md is automatically generated by pulling in content from other files. For instructions, including a fill-in-the-blank content template, see [Create readmes for Terraform-based Partner Solutions.](https://aws-ia-us-west-2.s3.us-west-2.amazonaws.com/docs/content/index.html#/lessons/8rpYWWL59M7dcS-NsjYmaISUu-L_UqEv) 18 | 19 | 20 | ## Checks and Validation 21 | 22 | Pull Requests (PRs) submitted against this repository undergo a series of static and functional checks. 23 | 24 | > :exclamation: Note: Failures during funtional or static checks will prevent a pull request from being accepted. 25 | 26 | It is a best practice to perform these checks locally prior to submitting a pull request. 27 | 28 | ## Checks Performed 29 | - TFLint 30 | - tfsec 31 | - Markdown Lint 32 | - Checkov 33 | - Terratest 34 | 35 | > :bangbang: The readme.md file will be created after all checks have completed successfuly, it is recommended that you install terraform-docs locally in order to preview your readme.md file prior to publication. 36 | 37 | ## Install the required tools 38 | 39 | Prerequisites: 40 | - [Python](https://docs.python.org/3/using/index.html) 41 | - [Pip](https://pip.pypa.io/en/stable/installation/) 42 | - [golang](https://go.dev/doc/install) (for macos you can use `brew`) 43 | - [tflint](https://github.com/terraform-linters/tflint) 44 | - [tfsec](https://aquasecurity.github.io/tfsec/v1.0.11/) 45 | - [Markdown Lint](https://github.com/markdownlint/markdownlint) 46 | - [Checkov](https://www.checkov.io/2.Basics/Installing%20Checkov.html) 47 | - [terraform-docs](https://github.com/terraform-docs/terraform-docs) 48 | - [coreutils](https://www.gnu.org/software/coreutils/) 49 | 50 | ## Performing Checks manually 51 | 52 | Preparation 53 | ``` 54 | terraform init 55 | terraform validate 56 | ``` 57 | ## Checks 58 | 59 | ### tflint 60 | ``` 61 | tflint --init 62 | tflint 63 | ``` 64 | ### tfsec 65 | ``` 66 | tfsec . 67 | ``` 68 | ### Markdown Lint 69 | ``` 70 | mdl .header.md 71 | ``` 72 | ### Checkov 73 | ``` 74 | terraform init 75 | terraform plan -out tf.plan 76 | terraform show -json tf.plan > tf.json 77 | checkov 78 | ``` 79 | ### Terratest 80 | 81 | Include tests to validate your examples/<> root modules, at a minimum. This can be accomplished with usually only slight modifications to the [boilerplate test provided in this template](./test/examples\_basic\_test.go) 82 | 83 | ``` 84 | # from the root of the repository 85 | cd test 86 | go mod init github.com/aws-ia/terraform-project-ephemeral 87 | go mod tidy 88 | go install github.com/gruntwork-io/terratest/modules/terraform 89 | go test -timeout 45m 90 | ``` 91 | 92 | ## Documentation 93 | 94 | ### terraform-docs 95 | 96 | ``` 97 | # from the root of the repository 98 | terraform-docs --lockfile=false ./ 99 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at 4 | 5 | http://aws.amazon.com/apache2.0/ 6 | 7 | or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Amazon VPC Lattice Module 3 | 4 | This module can be used to deploy resources from [Amazon VPC Lattice](https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-service-network.html). VPC Lattice is a fully managed application networking service that you use to connect, secure, and monitor all your services across multiple accounts and virtual private clouds (VPCs). 5 | 6 | This module handles all the different resources you can use with VPC Lattice: Service Network, Service, Listeners, Listener Rules, Target Groups (and targets), and Associations (Service or VPC). You have the freedom to create the combination of resources you need, so in multi-AWS Account environments you can make use of the module as many times as needed (different providers) to create your application network architecture. 7 | 8 | ## Usage 9 | 10 | ### VPC Lattice service network (var.service\_network) 11 | 12 | A [VPC Lattice service network](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-networks.html) is a logical boundary for a collection of services. It is the central place of connectivity where consumers (located in a VPC) and producers (target groups) are connected to allow service consumption. In addition, it provides a central place for access control via [IAM auth policies](https://docs.aws.amazon.com/vpc-lattice/latest/ug/auth-policies.html), and visibility by enabling [logs](https://docs.aws.amazon.com/vpc-lattice/latest/ug/monitoring-access-logs.html). 13 | 14 | When creating a service network in the module, the following attributes are expected: 15 | 16 | - `name` = (Optional|string) VPC Lattice service network name. This attribute creates a **new** service network using the specified name. **This attribute and `identifier` cannot be set at the same time.** 17 | - `auth_type` = (Optional|string) Type of IAM policy to apply in the service network. Allowed values are `NONE` (default) and `AWS_IAM`. 18 | - `auth_policy` = (Optional|any) Auth policy. The policy string in JSON must not contain newlines or blank lines. The auth policy resource will be created only if `auth_type` is set to `AWS_IAM`. 19 | - `identifier` = (Optional|string) The ID or ARN of an **existing** service network. If you are working in multi-AWS account environments, ARN is compulsory. **This attribute and `name` cannot be set at the same time.** 20 | - `access_log_cloudwatch` = (Optional|string) Amazon CloudWatch log group ARN to configure as service network's access log destination. 21 | - `access_log_s3` = (Optional|string) Amazon S3 bucket ARN to configure as service network's access log destination. 22 | - `access_log_firehose` = (Optional|string) Data Firehose delivery stream ARN to configure as service network's access log destination. 23 | 24 | You can share VPC Lattice service networks using AWS RAM with this module. Check the section [Sharing VPC Lattice resources](#sharing-vpc-lattice-resources) for more information. 25 | 26 | **Examples** of use can be found in the [/examples/service\_network](./examples/service\_network/) folder. 27 | 28 | #### VPC associations (var.vpc\_associations) 29 | 30 | When you associate a VPC with a service network, it enables all the resources within that VPC to be clients and communicate with other services associated to that same service network. You can make use of Security Groups to control the access of the VPC association, allowing some traffic segmentation before the traffic arrives to the Service Network. 31 | 32 | You can create more than 1 VPC association with this module, as this variable expects a map of objects with the following attributes: 33 | 34 | - `vpc_id` = (string) ID of the VPC. 35 | - `security_group_ids` = (Optional|list(string)) List of Security Group IDs to associate with the VPC association. 36 | 37 | #### Access Logs for VPC Lattice service networks 38 | 39 | You can enable [access logs](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-network-monitoring.html) for VPC Lattice service networks and specify the destination resource for your logs. VPC Lattice can send logs to the following resources: **CloudWatch Log groups**, **Firehose delivery streams**, and **S3 buckets**. You can configure the three destinations at the same time (`access_log_cloudwatch`, `access_log_s3`, `access_log_firehose`), but you cannot configure the same destination type twice. 40 | 41 | ### VPC Lattice service (var.services) 42 | 43 | A [VPC Lattice service](https://docs.aws.amazon.com/vpc-lattice/latest/ug/services.html) is an independently deployable unit of software that delivers a specific task or function. It can run on instances, containers, or as serverless functions within an AWS Account or a VPC. A service has a [listener](https://docs.aws.amazon.com/vpc-lattice/latest/ug/listeners.html) that uses **rules** you can configure to help route traffic to your targets. 44 | 45 | You can create 1 or more VPC Lattice services using the module, as this variable expects a **map of objects** with the following attributes: 46 | 47 | - `identifier` = (Optional|string) ID or ARN of the VPC Lattice service (if it was created outside this module). **This attribute and `name` cannot be set at the same time.** 48 | - `name` = (Optional|string) VPC Lattice service's name - to create a new resource. **This attribute and `identifier` cannot be set at the same time.** 49 | - `auth_type` = (Optional|string) Type of IAM policy. Either `NONE` (default) or `AWS_IAM`. 50 | - `auth_policy` = (Optional|any) Auth policy. The policy string in JSON must not contain newlines or blank lines. The auth policy resource will be created only if `auth_type` is set to `AWS_IAM`. 51 | - `certificate_arn` = (Optional|string) **When configuring a HTTPS listener** AWS Certificate Manager certificate's ARN. 52 | - `custom_domain_name` = (Optional|string) Custom domain name for the service. 53 | - `listeners` = (Optional|map(string)) VPC Lattice listeners (and rules) to configure in the service - more information about its definition below. 54 | - `hosted_zone_id` = (Optional|string) Amazon Route 53 hosted zone ID to configure Alias records when configuring custom domain names. Check the section [Amazon Route 53 DNS configuration](#amazon-route-53-dns-configuration) for more information. 55 | - `access_log_cloudwatch` = (Optional|string) Amazon CloudWatch log group ARN to configure as service network's access log destination. 56 | - `access_log_s3` = (Optional|string) Amazon S3 bucket ARN to configure as service network's access log destination. 57 | - `access_log_firehose` = (Optional|string) Data Firehose delivery stream ARN to configure as service network's access log destination. 58 | 59 | The attribute `listeners` (you can define 1 or more) supports the following: 60 | 61 | - `name` = (Optional|string) Listener's name. If this attribute is not defined, the key will be used as name. 62 | - `port` = (Optional|number) Listener's port. You can specify a value from 1 to 65535. If not defined, the default values are 80 for `HTTP` and 443 for `HTTPS`. 63 | - `protocol` = (string) Listener's protocol. 64 | - `default_action` = (map(any)) Default action block for the default listener rule - more information about its definition below. 65 | - `rules` = (Optional|any) Rules to define in a listener to determine how the service routes requests to its registered targets - more information about its definition below. 66 | 67 | The attribute `default_action` *- map(any) -* supports the following: 68 | 69 | - `type` = (string) Default action to apply in the listener. Allowed values are `fixed_response` and `forward`. 70 | - `status_code` = (Optional|number) Custom HTTP status codd to return. **To define if the default\_action type is `fixed-response`**. 71 | - `target_groups` = (Optional|map(string)) Map of target groups to use in the listener's default action. **To define if the default\_action type is `forward`**. The map expects the following: 72 | - `target_group_identifier` = (string) Target group identifier. **The key of each target group should map the key you defined in var.target\_groups**. 73 | - `weight` = (Optional|number) Determines how requests are distributed to the target group. Only required if you specify multiple target groups for a forward action. 74 | 75 | The attribute `rules` (you can define 1 or more) supports the following: 76 | 77 | - `name` = (Optional|string)Listener Rule's name. If not defined, the key will be use as name. 78 | - `priority` = (number) The priority assigned to the rule. Each rule for a specific listener must have a unique priority. The lower the number the higher the priority. 79 | - `http_match_method` = (Optional|string) The HTTP method type. 80 | - `path_match` = (Optional|map(any)) The path match. **This attribute and `header_matches` cannot be set at the same time.** 81 | - `case_sensitive` = (Optional|bool) Indicates whether the match is case sensitive. Defaults to false. 82 | - `exact` = (Optional|string) Specifies an exact type match. 83 | - `prefix` = (Optional|string) Specifies a prefix type match. Matches the value with the prefix. 84 | - `headers_match` = (Optional|map(any)) The header matches. Matches incoming requests with rule based on request header value before applying rule action. **This attribute and `path_match` cannot be set at the same time.** 85 | - `case_sensitive` = (Optional|bool) Indicates whether the match is case sensitive. Defaults to false. 86 | - `name` = (Optional|string) The name of the header. 87 | - `exact` = (Optional|string) Specifies an exact type match. 88 | - `prefix` = (Optional|string) Specifies a prefix type match. Matches the value with the prefix. 89 | - `action_fixedresponse` = (Optional|map(string)) Describes the rule action that returns a custom HTTP response. **This attribute and `action_forward` cannot be set at the same time.** 90 | - `status_code` = (Optional|string) The HTTP response code. 91 | - `action_forward` = (Optional|map(string)) The forward action. Traffic that matches the rule is forwarded to the specified target groups. **This attribute and `action_fixedresponse` cannot be set at the same time.** 92 | - `target_groups` = (Optional|map(any)) The target groups. You can define more than 1 target group. **The key of each target group should map the key you defined in var.target\_groups**. 93 | - `weight` = (Optional|number) With forward actions, you can assign a weight that controls the prioritization and selection of each target group. 94 | 95 | You can share VPC Lattice services using AWS RAM with this module. Check the section [Sharing VPC Lattice resources](#sharing-vpc-lattice-resources) for more information. 96 | 97 | **Examples** of use can be found in the [/examples/service](./examples/service/) folder. Note that all the target groups used in the examples will be empty. In the [Target groups](#target-groups-vartarget\_groups) section you will find more information about how to define the different target types. 98 | 99 | #### VPC Lattice service associations 100 | 101 | When a VPC Lattice service network is created or referenced using the module, a [VPC Lattice service association](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-associations.html) is created automatically for each VPC Lattice service created/referenced in the module. 102 | 103 | #### Access Logs for VPC Lattice services 104 | 105 | You can enable [access logs](https://docs.aws.amazon.com/vpc-lattice/latest/ug/service-monitoring.html) for VPC Lattice services and specify the destination resource for your logs. VPC Lattice can send logs to the following resources: **CloudWatch Log groups**, **Firehose delivery streams**, and **S3 buckets**. You can configure the three destinations at the same time (`access_log_cloudwatch`, `access_log_s3`, `access_log_firehose`) for each VPC Lattice service configured under `var.services`, but you cannot configure the same destination type twice. 106 | 107 | ### Target Groups (var.target\_groups) 108 | 109 | A [Target group](https://docs.aws.amazon.com/vpc-lattice/latest/ug/target-groups.html) is a collection of targets, or compute resources that run your application or service. Targets in VPC Lattice can be Amazon EC2 instances, IP addresses, AWS Lambda functions, Application Load Balancers, Amazon ECS tasks or Kubernetes Pods. 110 | 111 | You can create 1 or more target groups with this module, as this variable expects a **map of objects** with the following attributes: 112 | 113 | - `name` = (Optional|string) Target group's name. If not provided, the key of the map will be used as name. 114 | - `type` = (string) The type of target group. Valid Values are `IP`, `LAMBDA`, `INSTANCE`, `ALB`. 115 | - `config` = (Optional|map(any)) Target group configuration - more information about its definition below. If type is set to `LAMBDA`, this parameter should not be specified. 116 | - `health_check` = (Optional|map(any)) Health check configuration - more information about its definition below. If type is set to `LAMBDA` or `ALB`, this parameter should not be specified. 117 | - `targets` = (Optional|map(any)) Targets to associate to the target group. If `type` is equals to `LAMBDA` or `ALB`, only one target can be defined. More information about its definition below. 118 | 119 | **The key used for each of the target group definitions is the one expected when defining the listeners and rules (var.services)**, so make sure these values are unique. 120 | 121 | The `config` attribute *- map(any) -* supports the following: 122 | 123 | - `port` = (number) Port on which the targets are listening. Not supported if type is set to `LAMBDA`. 124 | - `protocol` = (string) Protocol to use for routing traffic to the targets. Valid values: `HTTP` and `HTTPS`. Not supported if type is set to `LAMBDA`. 125 | - `vpc_identifier` = (string) VPC ID. Not supported if type is set to `LAMBDA`. 126 | - `ip_address_type` = (Optional|string) IP address type for the target group. Valid values: `IPV4` and `IPV6`. Not supported if type is set to `LAMBDA` or `ALB`. 127 | - `protocol_version` = (Optional|string) Protocol version. Valid values: `HTTP1` (default), `HTTP2`, `GRPC`. Not supported if type is set to `LAMBDA`. 128 | - `lambda_event_structure_version` = (Optional|string) The version of the event structure that the Lambda function receives. Valid values: `V1`and `V2` (default). Supported only if type is set to `LAMBDA`. 129 | 130 | The `health_check` attribute *- map(any) -* supports the following: 131 | 132 | - `enabled` = (Optional|bool) Whether health checks are enabled. Valid values: `true` (default) and `false`. 133 | - `health_check_interval_seconds` = (Optional|number) The approximate amount of time, in seconds, between health checks of an individual target. The range is 5-300 seconds. The default is 30 seconds. 134 | - `health_check_timeout_seconds` = (Optional|number) The amount of time, in seconds, to wait before reporting a target as unhealthy. The range is 1-120 seconds. The default is 5 seconds. 135 | - `healthy_threshold_count` = (Optional|number) The number of consecutive successful health checks required before considering an unhealthy target healthy. The range is 2-10. The default is 5. 136 | - `matcher` = (Optional|list(string)) List of HTTP codes to use when checking for a successful response from a target. 137 | - `path` = (Optional|string) The destination for health checks on the targets. If the protocol version is HTTP/1.1 or HTTP/2, specify a valid URI (for example, /path?query). The default path is /. Health checks are not supported if the protocol version is gRPC, however, you can choose HTTP/1.1 or HTTP/2 and specify a valid URI. 138 | - `port` = (Optional|number) The port used when performing health checks on targets. The default setting is the port that a target receives traffic on. 139 | - `protocol` = (Optional|string) The protocol used when performing health checks on targets. The possible protocols are `HTTP` and `HTTPS`. 140 | - `protocol_version` = (Optional|string) The protocol version used when performing health checks on targets. The possible protocol versions are `HTTP1` (default) and `HTTP2`. 141 | - `unhealthy_threshold_count` = (Optional|number) The number of consecutive failed health checks required before considering a target unhealthy. The range is 2-10. The default is 2. 142 | 143 | The `targets` attribute *- map(any) -* supports the following: 144 | 145 | - `id` = (Required|string) The ID of the target. If the target type of the target group is INSTANCE, this is an instance ID. If the target type is IP , this is an IP address. If the target type is LAMBDA, this is the ARN of the Lambda function. If the target type is ALB, this is the ARN of the Application Load Balancer. 146 | - `port` = (Optional|number) The port on which the target is listening. For HTTP, the default is 80. For HTTPS, the default is 443. Attribute not needed with target type of `LAMBDA`. 147 | 148 | **Examples** of use can be found in the [/examples/target\_groups](./examples/target\_groups/) folder. You will find an example for each target supported in this module. 149 | 150 | ### Sharing VPC Lattice resources (var.ram\_share) 151 | 152 | With [AWS Resource Access Manager](https://aws.amazon.com/ram/) (RAM), you can share VPC Lattice service networks and services. With this module, you can use the variable `var.ram_share` to share VPC Lattice resources. The variable supports the following attributes: 153 | 154 | - `resources_share_arn` = (Optional|string) ARN of an **existing** RAM Resource Share to use to associate principals and VPC Lattice resources. **This attribute and `resource_share_name` cannot be set at the same time.** 155 | - `resources_share_name` = (Optional|string) Name of the RAM Resource Share resource. This attribute creates a **new** resource using the specified name. **This attribute and `resources_share_arn` cannot be set at the same time.** 156 | - `allow_external_principals` = (Optional|boolean) Indicates whether principals outside your organization can be associated with a resource share. **This attribute is allowed only when `resources_share_name` is provided.** 157 | - `principals` = (Optional|list(string)) List of AWS principals to associated the resources with. Possible values are an AWS account ID, an AWS Organizations Organization ARN, or an AWS Organizations Organization Unit ARN. 158 | - `share_service_network` = (Optional|boolean) Indicates whether a created VPC Lattice service network should be associated or not. Defaults to `true`. 159 | - `share_services` = (Optional|list(string)) List of created VPC Lattice services to share. You should use the services' keys defined in `var.services`. 160 | 161 | **Examples** of use can be found in the [/examples/ram\_share](./examples/ram\_share/) folder. 162 | 163 | ### Amazon Route 53 DNS configuration 164 | 165 | VPC Lattice leverages [Domain Name System (DNS)](https://aws.amazon.com/route53/what-is-dns/) for service discovery, so each VPC Lattice service is easily identifiable through its service-managed or custom domain names. When a new Amazon VPC Lattice service is created, a service-managed domain name is generated. This domain name is publicly resolvable and resolves either to an IPv4 link-local address or an IPv6 unique-local address. So, a consumer application using this service-managed domain name does not require any extra DNS configuration for the service-to-service communication (provided the VPC Lattice configuration allows connectivity). However, it’s more likely that you will use your own custom domain names. 166 | 167 | When using custom domain names for Amazon VPC Lattice services, an [alias](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html) (for Amazon Route 53 hosted zones) have to be created to map the custom domain name with the service-managed domain name. In multi-service environments, the creation of the DNS resolution configuration can create heavy operational overhead. 168 | 169 | This module supports the creation of alias records (both A and AAAA) in Route 53 hosted zones specified in two locations: 170 | 171 | - By using the variable `var.dns_configuration` (Optional|map(string)), you can specify a "global" hosted zone ID (attribute `hosted_zone_id`) to configure the Alias record of each VPC Lattice service created/referenced with a custom domain name configured. 172 | - By using the attribute `hosted_zone_id` under each VPC Lattice service configured (`var.services`) you can create the Alias record for the provided Hosted Zone ID only for that specific service. 173 | - A Hosted Zone ID referenced in a service definition overrides the configuration done in `var.dns_configuration`. 174 | 175 | **The module only supports the DNS configuration if the Hosted Zone and VPC Lattice service are in the same AWS Account**. For multi-Account environments, please check the [Guidance for Amazon VPC Lattice Automated DNS Configuration on AWS](https://aws.amazon.com/solutions/guidance/amazon-vpc-lattice-automated-dns-configuration-on-aws/). This Guidance Solution follows an event-driven architecture to communicate AWS Accounts and configure DNS records when Hosted Zones and VPC Lattice services are in different AWS Accounts. 176 | 177 | **Examples** of use can be found in the [/examples/dns\_configuration](./examples/dns\_configuration/) folder. 178 | 179 | ## Requirements 180 | 181 | | Name | Version | 182 | |------|---------| 183 | | [terraform](#requirement\_terraform) | >= 1.3.0 | 184 | | [aws](#requirement\_aws) | >= 4.66.0 | 185 | 186 | ## Providers 187 | 188 | | Name | Version | 189 | |------|---------| 190 | | [aws](#provider\_aws) | >= 4.66.0 | 191 | 192 | ## Modules 193 | 194 | | Name | Source | Version | 195 | |------|--------|---------| 196 | | [listeners](#module\_listeners) | ./modules/listeners | n/a | 197 | | [tags](#module\_tags) | aws-ia/label/aws | 0.0.6 | 198 | | [targets](#module\_targets) | ./modules/targets | n/a | 199 | 200 | ## Resources 201 | 202 | | Name | Type | 203 | |------|------| 204 | | [aws_ram_principal_association.ram_principal_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_principal_association) | resource | 205 | | [aws_ram_resource_association.ram_service_network_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | 206 | | [aws_ram_resource_association.ram_services_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | 207 | | [aws_ram_resource_share.ram_resource_share](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | 208 | | [aws_route53_record.custom_domain_name_a_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | 209 | | [aws_route53_record.custom_domain_name_aaaa_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | 210 | | [aws_vpclattice_access_log_subscription.service_cloudwatch_access_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_access_log_subscription) | resource | 211 | | [aws_vpclattice_access_log_subscription.service_firehose_access_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_access_log_subscription) | resource | 212 | | [aws_vpclattice_access_log_subscription.service_network_cloudwatch_access_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_access_log_subscription) | resource | 213 | | [aws_vpclattice_access_log_subscription.service_network_firehose_access_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_access_log_subscription) | resource | 214 | | [aws_vpclattice_access_log_subscription.service_network_s3_access_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_access_log_subscription) | resource | 215 | | [aws_vpclattice_access_log_subscription.service_s3_access_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_access_log_subscription) | resource | 216 | | [aws_vpclattice_auth_policy.service_auth_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_auth_policy) | resource | 217 | | [aws_vpclattice_auth_policy.service_network_auth_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_auth_policy) | resource | 218 | | [aws_vpclattice_service.lattice_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service) | resource | 219 | | [aws_vpclattice_service_network.lattice_service_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service_network) | resource | 220 | | [aws_vpclattice_service_network_service_association.lattice_service_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service_network_service_association) | resource | 221 | | [aws_vpclattice_service_network_vpc_association.lattice_vpc_association](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service_network_vpc_association) | resource | 222 | | [aws_vpclattice_target_group.lambda_lattice_target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_target_group) | resource | 223 | | [aws_vpclattice_target_group.lattice_target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_target_group) | resource | 224 | | [aws_vpclattice_service.lattice_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpclattice_service) | data source | 225 | 226 | ## Inputs 227 | 228 | | Name | Description | Type | Default | Required | 229 | |------|-------------|------|---------|:--------:| 230 | | [dns\_configuration](#input\_dns\_configuration) | Amazon Route 53 DNS configuration. For VPC Lattice services with custom domain name configured, you can indicate the Hosted Zone ID to create the corresponding Alias record (IPv4 and IPv6) pointing to the VPC Lattice-generated domain name.
You can override the Hosted Zone to configure the Alias record by configuring the `hosted_zone_id` attribute under each service definition (`var.services`).
This configuration is only supported if both the VPC Lattice service and the Route 53 Hosted Zone are in the same account. More information about the variable format and multi-Account support can be found in the "Amazon Route 53 DNS configuration" section of the README. | `map(string)` | `{}` | no | 231 | | [ram\_share](#input\_ram\_share) | Configuration of the resources to share using AWS Resource Access Manager (RAM). VPC Lattice service networks and services can be shared using RAM.
More information about the format of this variable can be found in the "Sharing VPC Lattice resources" section of the README. | `any` | `{}` | no | 232 | | [service\_network](#input\_service\_network) | Amazon VPC Lattice service network information. You can either create a new service network or reference a current one (to associate VPC Lattice services or VPCs). Setting the `name` attribute will create a **new** service network, while using the attribute `identifier` will reference an **existing** service network.
More information about the format of this variable can be found in the "Usage - VPC Lattice service network" section of the README. | `any` | `{}` | no | 233 | | [services](#input\_services) | Definition of the VPC Lattice Services to create. You can use this module to either create only Lattice services (not associated with any service network), or associated with a service network (if you create one or provide an identifier). You can define 1 or more Service using this module.
More information about the format of this variable can be found in the "Usage - VPC Lattice service" section of the README. | `any` | `{}` | no | 234 | | [tags](#input\_tags) | Tags to apply to all the resources created in this module. | `map(string)` | `{}` | no | 235 | | [target\_groups](#input\_target\_groups) | Definitions of the Target Groups to create. You can define 1 or more Target Groups using this module.
More information about the format of this variable can be found in the "Usage - Target Groups" section of the README. | `any` | `{}` | no | 236 | | [vpc\_associations](#input\_vpc\_associations) | VPC Lattice VPC associations. You can define 1 or more VPC associations using this module.
More information about the format of this variable can be found in the "Usage - VPC association" section of the README. |
map(object({
vpc_id = optional(string)
security_group_ids = optional(list(string))
}))
| `{}` | no | 237 | 238 | ## Outputs 239 | 240 | | Name | Description | 241 | |------|-------------| 242 | | [listeners\_by\_service](#output\_listeners\_by\_service) | VPC Lattice Listener and Rules. Per Lattice Service, each Listener is composed by the following attributes:
- `attributes` = Full output of **aws\_vpclattice\_listener**.
- `rules` = Full output of **aws\_vpclattice\_listener\_rule**. | 243 | | [ram\_resource\_share](#output\_ram\_resource\_share) | AWS Resource Access Manager resource share. Full output of **aws\_ram\_resource\_share**. | 244 | | [service\_network](#output\_service\_network) | VPC Lattice resource attributes. Full output of **aws\_vpclattice\_service\_network**. | 245 | | [service\_network\_log\_subscriptions](#output\_service\_network\_log\_subscriptions) | VPC Lattice service network access log subscriptions. The output is composed by the following attributes:
- `cloudwatch` = Full output of **aws\_vpclattice\_access\_log\_subscription**.
- `s3` = Full output of **aws\_vpclattice\_access\_log\_subscription**.
- `firehose` = Full output of **aws\_vpclattice\_access\_log\_subscription**. | 246 | | [services](#output\_services) | VPC Lattice Services. The output is composed by the following attributes (per Service created):
- `attributes` = Full output of **aws\_vpclattice\_service**.
- `service_network_association` = Full output of **aws\_vpclattice\_service\_network\_service\_association**.
- `log_subscriptions` = *The output is composed by the following attributes:*
- `cloudwatch` = Full output of **aws\_vpclattice\_access\_log\_subscription**.
- `s3` = Full output of **aws\_vpclattice\_access\_log\_subscription**.
- `firehose` = Full output of **aws\_vpclattice\_access\_log\_subscription**. | 247 | | [target\_groups](#output\_target\_groups) | VPC Lattice Target Groups. Full output of **aws\_vpclattice\_target\_group**. | 248 | | [vpc\_associations](#output\_vpc\_associations) | VPC Lattice VPC associations. Full output of **aws\_vpclattice\_service\_network\_vpc\_association**. | 249 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v1.0.0 2 | -------------------------------------------------------------------------------- /data.tf: -------------------------------------------------------------------------------- 1 | # --- root/data.tf --- 2 | 3 | locals { 4 | # ---------- VPC Lattice Service Network variables ----------- 5 | # Determine if a Service Network should be created 6 | create_service_network = contains(keys(var.service_network), "name") 7 | # Service Network identifier 8 | service_network = local.create_service_network ? aws_vpclattice_service_network.lattice_service_network[0].id : try(var.service_network.identifier, null) 9 | # Service Network ARN 10 | service_network_arn = local.create_service_network ? aws_vpclattice_service_network.lattice_service_network[0].arn : try(var.service_network.identifier, null) 11 | # Checking if Service Network identifier was provided by the user 12 | sn_identifier_provided = contains(keys(var.service_network), "identifier") 13 | # Checking if Service Network auth policy should be created 14 | sn_auth_policy = (try(var.service_network.auth_type, "NONE") == "AWS_IAM") && (contains(keys(var.service_network), "auth_policy")) 15 | # Checking the access log destinations for the service network 16 | sn_access_log_cloudwatch = contains(keys(var.service_network), "access_log_cloudwatch") 17 | sn_access_log_s3 = contains(keys(var.service_network), "access_log_s3") 18 | sn_access_log_firehose = contains(keys(var.service_network), "access_log_firehose") 19 | 20 | # ---------- VPC Lattice Service variables --------- 21 | # Service Association - if Service Network is created or passed 22 | create_service_association = local.create_service_network || local.sn_identifier_provided 23 | # Checking if a global Private Hosted Zone has been defined 24 | global_phz = contains(keys(var.dns_configuration), "hosted_zone_id") 25 | # Obtaining a map of VPC Lattice services that require the creation of DNS configuration 26 | services_with_dns_config = local.global_phz ? var.services : { for k, v in var.services : k => v if contains(keys(v), "hosted_zone_id") } 27 | 28 | # ---------- VPC Lattice Target Groups ---------- 29 | # We create a map of target group IDs 30 | target_group_ids = merge( 31 | try({ for k, v in aws_vpclattice_target_group.lambda_lattice_target_group : k => v.id }, {}), 32 | try({ for k, v in aws_vpclattice_target_group.lattice_target_group : k => v.id }, {}), 33 | ) 34 | 35 | # ---------- AWS RAM SHARE ---------- 36 | # Determining if a RAM resource share has to be created 37 | create_ram_resource_share = contains(keys(var.ram_share), "resource_share_name") 38 | # Determining if any RAM share configuration has to be created 39 | config_ram_share = length(keys(var.ram_share)) > 0 40 | # Getting RAM resource share ARN 41 | resource_share_arn = local.create_ram_resource_share ? aws_ram_resource_share.ram_resource_share[0].arn : try(var.ram_share.resource_share_arn, null) 42 | # Determining if the service network needs to be shared 43 | share_service_network = local.config_ram_share ? local.create_service_network && try(var.ram_share.share_service_network, true) : false 44 | # Default of var.ram_share.share_services - if not defined, all the created services will be included 45 | share_services = try(var.ram_share.share_services, keys(var.services)) 46 | # Support RAM share of services managed by the module as well as external ones 47 | ram_services_association_resources = { 48 | for svc in local.share_services : 49 | svc => lookup( 50 | aws_vpclattice_service.lattice_service, 51 | svc, 52 | lookup( 53 | data.aws_vpclattice_service.lattice_service, 54 | svc, 55 | null 56 | ) 57 | ) 58 | } 59 | # Move var.ram_share.principals from list(string) to map(string) 60 | principals_map = { for index, principal in try(var.ram_share.principals, []) : index => principal } 61 | } 62 | 63 | # Sanitizes tags for aws provider 64 | module "tags" { 65 | source = "aws-ia/label/aws" 66 | version = "0.0.6" 67 | 68 | tags = var.tags 69 | } -------------------------------------------------------------------------------- /examples/basic/.header.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-amazon-vpc-lattice-module/0679e9cb22c33019185c01683dcadcd48c835fda/examples/basic/.header.md -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Requirements 3 | 4 | | Name | Version | 5 | |------|---------| 6 | | [terraform](#requirement\_terraform) | >= 0.14.0 | 7 | | [aws](#requirement\_aws) | >= 3.72.0 | 8 | | [awscc](#requirement\_awscc) | >= 0.11.0 | 9 | 10 | ## Providers 11 | 12 | No providers. 13 | 14 | ## Modules 15 | 16 | No modules. 17 | 18 | ## Resources 19 | 20 | No resources. 21 | 22 | ## Inputs 23 | 24 | No inputs. 25 | 26 | ## Outputs 27 | 28 | No outputs. 29 | -------------------------------------------------------------------------------- /examples/basic/main.tf: -------------------------------------------------------------------------------- 1 | ##################################################################################### 2 | # Terraform module examples are meant to show an _example_ on how to use a module 3 | # per use-case. The code below should not be copied directly but referenced in order 4 | # to build your own root module that invokes this module 5 | ##################################################################################### 6 | -------------------------------------------------------------------------------- /examples/basic/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-amazon-vpc-lattice-module/0679e9cb22c33019185c01683dcadcd48c835fda/examples/basic/outputs.tf -------------------------------------------------------------------------------- /examples/basic/providers.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.14.0" 3 | required_providers { 4 | aws = { 5 | source = "hashicorp/aws" 6 | version = ">= 3.72.0" 7 | } 8 | awscc = { 9 | source = "hashicorp/awscc" 10 | version = ">= 0.11.0" 11 | } 12 | } 13 | } 14 | 15 | provider "awscc" { 16 | user_agent = [{ 17 | product_name = "terraform-awscc-" 18 | product_version = "0.0.1" 19 | comment = "V1/AWS-D69B4015/" 20 | }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/basic/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-amazon-vpc-lattice-module/0679e9cb22c33019185c01683dcadcd48c835fda/examples/basic/variables.tf -------------------------------------------------------------------------------- /examples/dns_configuration/.header.md: -------------------------------------------------------------------------------- 1 | # Amazon VPC Lattice - Example: DNS configuration 2 | 3 | This example shows how you can use the VPC Lattice module to configure DNS resolution (creation of Alias records) when creation VPC Lattice services with custom domain names. This example creates the following: 4 | 5 | * Two Amazon Route 53 private hosted zones, and one VPC (needed for the configuration of the hosted zone as *private*). 6 | * Eight VPC Lattice services with basic configuration (without listeners or targets). 7 | * When configured, the custom domain name provided in each service's definition will create an Alias record either in the *global* Private Hosted Zone (defined in `var.dns_configuration.private_hosted_zone_id`) or in the *specific* PHZ (defined in the attribute `private_hosted_zone_id` under the service's configuration in `var.services`). 8 | -------------------------------------------------------------------------------- /examples/dns_configuration/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Amazon VPC Lattice - Example: DNS configuration 3 | 4 | This example shows how you can use the VPC Lattice module to configure DNS resolution (creation of Alias records) when creation VPC Lattice services with custom domain names. This example creates the following: 5 | 6 | * Two Amazon Route 53 private hosted zones, and one VPC (needed for the configuration of the hosted zone as *private*). 7 | * Eight VPC Lattice services with basic configuration (without listeners or targets). 8 | * When configured, the custom domain name provided in each service's definition will create an Alias record either in the *global* Private Hosted Zone (defined in `var.dns_configuration.private_hosted_zone_id`) or in the *specific* PHZ (defined in the attribute `private_hosted_zone_id` under the service's configuration in `var.services`). 9 | 10 | ## Requirements 11 | 12 | | Name | Version | 13 | |------|---------| 14 | | [terraform](#requirement\_terraform) | >= 1.3.0 | 15 | | [aws](#requirement\_aws) | >= 4.66.0 | 16 | 17 | ## Providers 18 | 19 | | Name | Version | 20 | |------|---------| 21 | | [aws](#provider\_aws) | >= 4.66.0 | 22 | 23 | ## Modules 24 | 25 | | Name | Source | Version | 26 | |------|--------|---------| 27 | | [dns\_resolution\_example1](#module\_dns\_resolution\_example1) | ../.. | n/a | 28 | | [dns\_resolution\_example3](#module\_dns\_resolution\_example3) | ../.. | n/a | 29 | 30 | ## Resources 31 | 32 | | Name | Type | 33 | |------|------| 34 | | [aws_route53_zone.global_private_hosted_zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource | 35 | | [aws_route53_zone.specific_private_hosted_zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone) | resource | 36 | | [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) | resource | 37 | | [aws_vpclattice_service.service2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service) | resource | 38 | | [aws_vpclattice_service.service4](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service) | resource | 39 | | [aws_vpclattice_service.service6](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service) | resource | 40 | 41 | ## Inputs 42 | 43 | | Name | Description | Type | Default | Required | 44 | |------|-------------|------|---------|:--------:| 45 | | [aws\_region](#input\_aws\_region) | AWS Region to use. | `string` | `"eu-west-1"` | no | 46 | 47 | ## Outputs 48 | 49 | No outputs. 50 | -------------------------------------------------------------------------------- /examples/dns_configuration/main.tf: -------------------------------------------------------------------------------- 1 | # --- examples/dns_configuration/main.tf --- 2 | 3 | # Private Hosted Zones 4 | resource "aws_route53_zone" "global_private_hosted_zone" { 5 | name = "global.com" 6 | 7 | vpc { 8 | vpc_id = aws_vpc.vpc.id 9 | } 10 | } 11 | 12 | resource "aws_route53_zone" "specific_private_hosted_zone" { 13 | name = "specific.com" 14 | 15 | vpc { 16 | vpc_id = aws_vpc.vpc.id 17 | } 18 | } 19 | 20 | resource "aws_vpc" "vpc" { 21 | cidr_block = "10.0.0.0/24" 22 | } 23 | 24 | module "dns_resolution_example1" { 25 | source = "../.." 26 | 27 | dns_configuration = { 28 | hosted_zone_id = aws_route53_zone.global_private_hosted_zone.id 29 | } 30 | 31 | services = { 32 | # EXAMPLE 1: VPC Lattice service created by the module and Alias record created in the "global" PHZ 33 | service1 = { 34 | name = "service1" 35 | auth_type = "NONE" 36 | custom_domain_name = "service1.global.com" 37 | } 38 | 39 | # EXAMPLE 2: VPC Lattice service created outside the module and Alias record created in the "global" PHZ 40 | service2 = { 41 | identifier = aws_vpclattice_service.service2.arn 42 | } 43 | 44 | # EXAMPLE 3: VPC Lattice service created by the module and Alias record created in the "specific" PHZ 45 | service3 = { 46 | name = "service3" 47 | auth_type = "NONE" 48 | custom_domain_name = "service3.specific.com" 49 | hosted_zone_id = aws_route53_zone.specific_private_hosted_zone.id 50 | } 51 | 52 | # EXAMPLE 4: VPC Lattice service created outside the module and Alias record created in the "specific" PHZ 53 | service4 = { 54 | identifier = aws_vpclattice_service.service4.arn 55 | hosted_zone_id = aws_route53_zone.specific_private_hosted_zone.id 56 | } 57 | } 58 | } 59 | 60 | resource "aws_vpclattice_service" "service2" { 61 | name = "service2" 62 | auth_type = "NONE" 63 | custom_domain_name = "service2.global.com" 64 | } 65 | 66 | resource "aws_vpclattice_service" "service4" { 67 | name = "service4" 68 | auth_type = "NONE" 69 | custom_domain_name = "service4.global.com" 70 | } 71 | 72 | module "dns_resolution_example3" { 73 | source = "../.." 74 | 75 | services = { 76 | # EXAMPLE 5: VPC Lattice service created by the module (no Alias record created) 77 | service5 = { 78 | name = "service7" 79 | auth_type = "NONE" 80 | } 81 | 82 | # EXAMPLE 5: VPC Lattice service created outside the module and Alias record created in the "specific" PHZ 83 | service6 = { 84 | identifier = aws_vpclattice_service.service6.arn 85 | hosted_zone_id = aws_route53_zone.specific_private_hosted_zone.id 86 | } 87 | } 88 | } 89 | 90 | resource "aws_vpclattice_service" "service6" { 91 | name = "service8" 92 | auth_type = "NONE" 93 | custom_domain_name = "service6.specific.com" 94 | } -------------------------------------------------------------------------------- /examples/dns_configuration/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- examples/dns_configuration/outputs.tf --- -------------------------------------------------------------------------------- /examples/dns_configuration/providers.tf: -------------------------------------------------------------------------------- 1 | # --- examples/dns_configuration/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } 12 | 13 | # Provider definition 14 | provider "aws" { 15 | region = var.aws_region 16 | } -------------------------------------------------------------------------------- /examples/dns_configuration/variables.tf: -------------------------------------------------------------------------------- 1 | # --- examples/dns_configuration/variables.tf --- 2 | 3 | variable "aws_region" { 4 | type = string 5 | description = "AWS Region to use." 6 | default = "eu-west-1" 7 | } -------------------------------------------------------------------------------- /examples/ram_share/.header.md: -------------------------------------------------------------------------------- 1 | # Amazon VPC Lattice - Example: AWS RAM share 2 | 3 | This example shows how you can use the VPC Lattice module to share service networks and services using [AWS Resource Access Manager](https://aws.amazon.com/ram/) RAM. The example creates the following: 4 | 5 | * 1 VPC Lattice service network. 6 | * 3 VPC Lattice services - basic configuration (without listeners or targets). 7 | * 2 RAM shares. One is sharing the service network, and the other one is sharing 2 out of the 3 VPC Lattice services created. 8 | 9 | **NOTE**: Given we automate these examples before merging new PRs, there's an [AWS Systems Manager parameter](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) data source configured to obtain an Account ID from a parameter configured in the AWS Account we use for the automated tests. Take that into account when doing your own tests, and please remember to keep this configuration when doing any PR to this repository. 10 | 11 | In the `outputs.tf` file, you can see an example on how to obtain the information about the RAM share created (if applicable). 12 | -------------------------------------------------------------------------------- /examples/ram_share/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Amazon VPC Lattice - Example: AWS RAM share 3 | 4 | This example shows how you can use the VPC Lattice module to share service networks and services using [AWS Resource Access Manager](https://aws.amazon.com/ram/) RAM. The example creates the following: 5 | 6 | * 1 VPC Lattice service network. 7 | * 3 VPC Lattice services - basic configuration (without listeners or targets). 8 | * 2 RAM shares. One is sharing the service network, and the other one is sharing 2 out of the 3 VPC Lattice services created. 9 | 10 | **NOTE**: Given we automate these examples before merging new PRs, there's an [AWS Systems Manager parameter](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) data source configured to obtain an Account ID from a parameter configured in the AWS Account we use for the automated tests. Take that into account when doing your own tests, and please remember to keep this configuration when doing any PR to this repository. 11 | 12 | In the `outputs.tf` file, you can see an example on how to obtain the information about the RAM share created (if applicable). 13 | 14 | ## Requirements 15 | 16 | | Name | Version | 17 | |------|---------| 18 | | [terraform](#requirement\_terraform) | >= 1.3.0 | 19 | | [aws](#requirement\_aws) | >= 4.66.0 | 20 | 21 | ## Providers 22 | 23 | | Name | Version | 24 | |------|---------| 25 | | [aws](#provider\_aws) | >= 4.66.0 | 26 | 27 | ## Modules 28 | 29 | | Name | Source | Version | 30 | |------|--------|---------| 31 | | [vpclattice\_service\_network\_share](#module\_vpclattice\_service\_network\_share) | ../.. | n/a | 32 | | [vpclattice\_services\_share](#module\_vpclattice\_services\_share) | ../.. | n/a | 33 | 34 | ## Resources 35 | 36 | | Name | Type | 37 | |------|------| 38 | | [aws_ram_resource_share.vpclattice_resource_share](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_share) | resource | 39 | | [aws_ssm_parameter.account_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter) | data source | 40 | 41 | ## Inputs 42 | 43 | | Name | Description | Type | Default | Required | 44 | |------|-------------|------|---------|:--------:| 45 | | [aws\_region](#input\_aws\_region) | AWS Region to use. | `string` | `"eu-west-1"` | no | 46 | 47 | ## Outputs 48 | 49 | No outputs. 50 | -------------------------------------------------------------------------------- /examples/ram_share/main.tf: -------------------------------------------------------------------------------- 1 | # --- examples/ram_share/main.tf --- 2 | 3 | # Obtaining the AWS Account ID to share the resources with. 4 | # If you are testing outside the module automation, either change this value with an AWS Account you own, or create a Parameter with this value 5 | data "aws_ssm_parameter" "account_id" { 6 | name = "account_id_share" 7 | } 8 | 9 | module "vpclattice_service_network_share" { 10 | source = "../.." 11 | 12 | service_network = { 13 | name = "service-network" 14 | auth_type = "NONE" 15 | } 16 | 17 | ram_share = { 18 | resource_share_name = "service-network-resource-share" 19 | allow_external_principals = true 20 | principals = [data.aws_ssm_parameter.account_id.value] 21 | } 22 | } 23 | 24 | module "vpclattice_services_share" { 25 | source = "../.." 26 | 27 | services = { 28 | service1 = { 29 | name = "service1" 30 | auth_type = "NONE" 31 | } 32 | service2 = { 33 | name = "service2" 34 | auth_type = "NONE" 35 | } 36 | service3 = { 37 | name = "service3" 38 | auth_type = "NONE" 39 | } 40 | } 41 | 42 | ram_share = { 43 | resource_share_arn = aws_ram_resource_share.vpclattice_resource_share.arn 44 | principals = [data.aws_ssm_parameter.account_id.value] 45 | share_services = ["service1", "service2"] 46 | } 47 | } 48 | 49 | resource "aws_ram_resource_share" "vpclattice_resource_share" { 50 | name = "services-resource-share" 51 | allow_external_principals = true 52 | } 53 | 54 | -------------------------------------------------------------------------------- /examples/ram_share/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- examples/ram_share/outputs.tf --- -------------------------------------------------------------------------------- /examples/ram_share/providers.tf: -------------------------------------------------------------------------------- 1 | # --- examples/ram_share/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } 12 | 13 | # Provider definition 14 | provider "aws" { 15 | region = var.aws_region 16 | } -------------------------------------------------------------------------------- /examples/ram_share/variablest.tf: -------------------------------------------------------------------------------- 1 | # --- examples/ram_share/variables.tf --- 2 | 3 | variable "aws_region" { 4 | type = string 5 | description = "AWS Region to use." 6 | default = "eu-west-1" 7 | } -------------------------------------------------------------------------------- /examples/service/.header.md: -------------------------------------------------------------------------------- 1 | # Amazon VPC Lattice - VPC Lattice service examples 2 | 3 | This example shows how you can use the VPC Lattice module to create VPC Lattice services. The following examples are covered: 4 | 5 | 1. VPC Lattice service configured with a custom domain name and no auth policy. Access logs are configured for CloudWatch logs, S3, and Data Firehose. 6 | 2. VPC Lattice service configured with auth type "AWS_IAM". 7 | 3. VPC Lattice services associated to a service network. 8 | 4. VPC Lattice service with HTTP listener. 9 | * Default action fixed-response (404) 10 | * Rule 1 (priority 10) - If prefix "/lambda", sends all the traffic to *target1* 11 | * Rule 2 (priority 20) - If header "target = instance", sends a fixed-response (404) 12 | 5. VPC Lattice service with HTTPS listener (forward default action) 13 | 14 | In the `outputs.tf` file, you can see an example on how to obtain VPC Lattice service attributes, associations' information, access log subscriptions' information, listeners and rules. 15 | -------------------------------------------------------------------------------- /examples/service/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Amazon VPC Lattice - VPC Lattice service examples 3 | 4 | This example shows how you can use the VPC Lattice module to create VPC Lattice services. The following examples are covered: 5 | 6 | 1. VPC Lattice service configured with a custom domain name and no auth policy. Access logs are configured for CloudWatch logs, S3, and Data Firehose. 7 | 2. VPC Lattice service configured with auth type "AWS\_IAM". 8 | 3. VPC Lattice services associated to a service network. 9 | 4. VPC Lattice service with HTTP listener. 10 | * Default action fixed-response (404) 11 | * Rule 1 (priority 10) - If prefix "/lambda", sends all the traffic to *target1* 12 | * Rule 2 (priority 20) - If header "target = instance", sends a fixed-response (404) 13 | 5. VPC Lattice service with HTTPS listener (forward default action) 14 | 15 | In the `outputs.tf` file, you can see an example on how to obtain VPC Lattice service attributes, associations' information, access log subscriptions' information, listeners and rules. 16 | 17 | ## Requirements 18 | 19 | | Name | Version | 20 | |------|---------| 21 | | [terraform](#requirement\_terraform) | >= 1.3.0 | 22 | | [aws](#requirement\_aws) | >= 4.66.0 | 23 | 24 | ## Providers 25 | 26 | | Name | Version | 27 | |------|---------| 28 | | [aws](#provider\_aws) | >= 4.66.0 | 29 | | [random](#provider\_random) | n/a | 30 | 31 | ## Modules 32 | 33 | | Name | Source | Version | 34 | |------|--------|---------| 35 | | [service\_associations](#module\_service\_associations) | ../.. | n/a | 36 | | [service\_auth](#module\_service\_auth) | ../.. | n/a | 37 | | [service\_customdomainname\_noauth](#module\_service\_customdomainname\_noauth) | ../.. | n/a | 38 | | [service\_httplistener](#module\_service\_httplistener) | ../.. | n/a | 39 | | [service\_httpslistener](#module\_service\_httpslistener) | ../.. | n/a | 40 | | [service\_network](#module\_service\_network) | ../.. | n/a | 41 | 42 | ## Resources 43 | 44 | | Name | Type | 45 | |------|------| 46 | | [aws_cloudwatch_log_group.service_network_loggroup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | 47 | | [aws_iam_role.firehose_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | 48 | | [aws_kinesis_firehose_delivery_stream.service_network_deliverystream](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_firehose_delivery_stream) | resource | 49 | | [aws_s3_bucket.service_network_logbucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | 50 | | [random_string.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | 51 | | [aws_iam_policy_document.firehose_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 52 | 53 | ## Inputs 54 | 55 | | Name | Description | Type | Default | Required | 56 | |------|-------------|------|---------|:--------:| 57 | | [aws\_region](#input\_aws\_region) | AWS Region to use. | `string` | `"eu-west-1"` | no | 58 | 59 | ## Outputs 60 | 61 | | Name | Description | 62 | |------|-------------| 63 | | [service\_attributes](#output\_service\_attributes) | VPC Lattice Service ID. | 64 | | [service\_listener\_rules](#output\_service\_listener\_rules) | VPC Lattice listener rules. | 65 | | [service\_listeners](#output\_service\_listeners) | VPC Lattice listeners. | 66 | | [service\_log\_subscriptions](#output\_service\_log\_subscriptions) | VPC Lattice service log subscriptions. | 67 | | [service\_sn\_association](#output\_service\_sn\_association) | VPC Lattice service association. | 68 | -------------------------------------------------------------------------------- /examples/service/main.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service/main.tf --- 2 | 3 | # EXAMPLE 1: VPC Lattice service configured with a custom domain name and no auth policy 4 | module "service_customdomainname_noauth" { 5 | source = "../.." 6 | 7 | services = { 8 | service1 = { 9 | name = "service-noauth" 10 | auth_type = "NONE" 11 | custom_domain_name = "example.domain.net" 12 | access_log_cloudwatch = aws_cloudwatch_log_group.service_network_loggroup.arn 13 | access_log_s3 = aws_s3_bucket.service_network_logbucket.arn 14 | access_log_firehose = aws_kinesis_firehose_delivery_stream.service_network_deliverystream.arn 15 | } 16 | } 17 | } 18 | 19 | # EXAMPLE 2: VPC Lattice service configured with auth type "AWS_IAM" 20 | module "service_auth" { 21 | source = "../.." 22 | 23 | services = { 24 | service1 = { 25 | name = "service-auth" 26 | auth_type = "AWS_IAM" 27 | auth_policy = jsonencode({ 28 | Version = "2012-10-17" 29 | Statement = [ 30 | { 31 | Action = "*" 32 | Effect = "Allow" 33 | Principal = "*" 34 | Resource = "*" 35 | Condition = { 36 | StringNotEqualsIgnoreCase = { 37 | "aws:PrincipalType" = "anonymous" 38 | } 39 | } 40 | } 41 | ] 42 | }) 43 | } 44 | } 45 | } 46 | 47 | # EXAMPLE 3: VPC Lattice services associated to a service network 48 | module "service_network" { 49 | source = "../.." 50 | 51 | service_network = { 52 | name = "sn-service-associations" 53 | } 54 | } 55 | 56 | module "service_associations" { 57 | source = "../.." 58 | 59 | service_network = { 60 | identifier = module.service_network.service_network.id 61 | } 62 | 63 | services = { 64 | service1 = { 65 | name = "service1" 66 | } 67 | service2 = { 68 | name = "service2" 69 | } 70 | } 71 | } 72 | 73 | # EXAMPLE 4: VPC Lattice service with HTTP listener (2 listener rules) 74 | # - Default action fixed-response (404) 75 | # - Rule1 (priority 10) - If prefix /lambda, sends all the traffic to target1 76 | # - Rule2 (priority 20) - If header "target = instance", sends a fixed-response (404) 77 | module "service_httplistener" { 78 | source = "../.." 79 | 80 | services = { 81 | myservice = { 82 | name = "service-httplistener" 83 | listeners = { 84 | http_listener = { 85 | name = "httplistener" 86 | port = 80 87 | protocol = "HTTP" 88 | default_action_fixedresponse = { status_code = 404 } 89 | rules = { 90 | rule1 = { 91 | priority = 10 92 | path_match = { prefix = "/lambda" } 93 | action_forward = { 94 | target_groups = { 95 | target1 = { weight = 100 } 96 | } 97 | } 98 | } 99 | rule2 = { 100 | priority = 20 101 | header_matches = { 102 | name = "target" 103 | exact = "instance" 104 | } 105 | action_fixedresponse = { status_code = 404 } 106 | } 107 | } 108 | } 109 | } 110 | } 111 | } 112 | 113 | target_groups = { 114 | target1 = { type = "LAMBDA" } 115 | } 116 | } 117 | 118 | # EXAMPLE 5: VPC Lattice with HTTPS listener (forward default action) 119 | module "service_httpslistener" { 120 | source = "../.." 121 | 122 | services = { 123 | myservice = { 124 | name = "service-httpslistener" 125 | auth_type = "NONE" 126 | 127 | listeners = { 128 | https_listener = { 129 | name = "httpslistener" 130 | port = 443 131 | protocol = "HTTPS" 132 | default_action_forward = { 133 | target_groups = { 134 | target2 = { weight = 50 } 135 | target3 = { weight = 50 } 136 | } 137 | } 138 | } 139 | } 140 | } 141 | } 142 | 143 | target_groups = { 144 | target2 = { type = "LAMBDA" } 145 | target3 = { type = "LAMBDA" } 146 | } 147 | } 148 | 149 | # ---------- SUPPORT RESOURCES ---------- 150 | # Generate random string (for resources' names) 151 | resource "random_string" "random" { 152 | length = 8 153 | special = false 154 | upper = false 155 | } 156 | 157 | # S3 Bucket 158 | resource "aws_s3_bucket" "service_network_logbucket" { 159 | bucket = "sn-logbucket-${random_string.random.result}" 160 | force_destroy = true 161 | } 162 | 163 | # CloudWatch Log Group 164 | resource "aws_cloudwatch_log_group" "service_network_loggroup" { 165 | name = "sn_loggroup-${random_string.random.result}" 166 | retention_in_days = 0 167 | } 168 | 169 | # Firehose Delivery Stream 170 | resource "aws_kinesis_firehose_delivery_stream" "service_network_deliverystream" { 171 | name = "sn-loggroup-firehose-${random_string.random.result}" 172 | destination = "extended_s3" 173 | 174 | extended_s3_configuration { 175 | role_arn = aws_iam_role.firehose_role.arn 176 | bucket_arn = aws_s3_bucket.service_network_logbucket.arn 177 | } 178 | } 179 | 180 | # IAM Role (for Firehose Delivery Stream) 181 | data "aws_iam_policy_document" "firehose_assume_role" { 182 | statement { 183 | effect = "Allow" 184 | 185 | principals { 186 | type = "Service" 187 | identifiers = ["firehose.amazonaws.com"] 188 | } 189 | 190 | actions = ["sts:AssumeRole"] 191 | } 192 | } 193 | 194 | resource "aws_iam_role" "firehose_role" { 195 | name = "firehose_test_role" 196 | assume_role_policy = data.aws_iam_policy_document.firehose_assume_role.json 197 | } -------------------------------------------------------------------------------- /examples/service/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service/outputs.tf --- 2 | 3 | output "service_attributes" { 4 | description = "VPC Lattice Service ID." 5 | value = { for k, v in module.service_customdomainname_noauth.services : k => v.attributes } 6 | } 7 | 8 | output "service_sn_association" { 9 | description = "VPC Lattice service association." 10 | value = { for k, v in module.service_associations.services : k => v.service_network_association } 11 | } 12 | 13 | output "service_listeners" { 14 | description = "VPC Lattice listeners." 15 | value = { 16 | http_listener = module.service_httplistener.listeners_by_service.myservice.http_listener.attributes 17 | https_listener = { for k, v in module.service_httpslistener.listeners_by_service : k => { for i, j in v : i => j.attributes.listener_id } } 18 | } 19 | } 20 | 21 | output "service_listener_rules" { 22 | description = "VPC Lattice listener rules." 23 | value = module.service_httplistener.listeners_by_service.myservice.http_listener.rules 24 | } 25 | 26 | output "service_log_subscriptions" { 27 | description = "VPC Lattice service log subscriptions." 28 | value = { for k, v in module.service_customdomainname_noauth.services.service1.log_subscriptions : k => v.arn } 29 | } -------------------------------------------------------------------------------- /examples/service/providers.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } 12 | 13 | # Provider definition 14 | provider "aws" { 15 | region = var.aws_region 16 | } -------------------------------------------------------------------------------- /examples/service/variables.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service/variables.tf --- 2 | 3 | variable "aws_region" { 4 | type = string 5 | description = "AWS Region to use." 6 | default = "eu-west-1" 7 | } 8 | -------------------------------------------------------------------------------- /examples/service_network/.header.md: -------------------------------------------------------------------------------- 1 | # Amazon VPC Lattice - VPC Lattice service network examples 2 | 3 | This example shows how you can use the VPC Lattice module to create VPC Lattice service networks and VPC associations. The following examples are covered: 4 | 5 | 1. VPC Lattice service network without auth policy configured. Access logs are configured for CloudWatch logs, S3, and Data Firehose. 6 | 2. VPC Lattice service network with auth policy configured. 7 | 3. VPC Lattice service network created outside the module and referenced in the module. 8 | 4. VPC Lattice service network VPC associations. 9 | 10 | In the `outputs.tf` file, you can see an example on how to obtain the VPC Lattice service network ID and ARN, access logs subscription information, and VPC associations' ID. 11 | -------------------------------------------------------------------------------- /examples/service_network/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Amazon VPC Lattice - VPC Lattice service network examples 3 | 4 | This example shows how you can use the VPC Lattice module to create VPC Lattice service networks and VPC associations. The following examples are covered: 5 | 6 | 1. VPC Lattice service network without auth policy configured. Access logs are configured for CloudWatch logs, S3, and Data Firehose. 7 | 2. VPC Lattice service network with auth policy configured. 8 | 3. VPC Lattice service network created outside the module and referenced in the module. 9 | 4. VPC Lattice service network VPC associations. 10 | 11 | In the `outputs.tf` file, you can see an example on how to obtain the VPC Lattice service network ID and ARN, access logs subscription information, and VPC associations' ID. 12 | 13 | ## Requirements 14 | 15 | | Name | Version | 16 | |------|---------| 17 | | [terraform](#requirement\_terraform) | >= 1.3.0 | 18 | | [aws](#requirement\_aws) | >= 4.66.0 | 19 | 20 | ## Providers 21 | 22 | | Name | Version | 23 | |------|---------| 24 | | [aws](#provider\_aws) | >= 4.66.0 | 25 | | [random](#provider\_random) | n/a | 26 | 27 | ## Modules 28 | 29 | | Name | Source | Version | 30 | |------|--------|---------| 31 | | [vpclattice\_service\_network\_referenced](#module\_vpclattice\_service\_network\_referenced) | ../.. | n/a | 32 | | [vpclattice\_service\_network\_with\_policy](#module\_vpclattice\_service\_network\_with\_policy) | ../.. | n/a | 33 | | [vpclattice\_service\_network\_without\_policy](#module\_vpclattice\_service\_network\_without\_policy) | ../.. | n/a | 34 | | [vpclattice\_vpc\_associations](#module\_vpclattice\_vpc\_associations) | ../.. | n/a | 35 | | [vpcs](#module\_vpcs) | aws-ia/vpc/aws | 4.4.4 | 36 | 37 | ## Resources 38 | 39 | | Name | Type | 40 | |------|------| 41 | | [aws_cloudwatch_log_group.service_network_loggroup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | 42 | | [aws_iam_role.firehose_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | 43 | | [aws_kinesis_firehose_delivery_stream.service_network_deliverystream](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_firehose_delivery_stream) | resource | 44 | | [aws_s3_bucket.service_network_logbucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | 45 | | [aws_vpclattice_service_network.external_service_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpclattice_service_network) | resource | 46 | | [random_string.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | 47 | | [aws_iam_policy_document.firehose_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 48 | 49 | ## Inputs 50 | 51 | | Name | Description | Type | Default | Required | 52 | |------|-------------|------|---------|:--------:| 53 | | [aws\_region](#input\_aws\_region) | AWS Region to use. | `string` | `"eu-west-1"` | no | 54 | | [vpcs](#input\_vpcs) | VPCs to create. | `map(any)` |
{
"vpc1": {
"cidr_block": "10.0.0.0/24",
"number_azs": 2
},
"vpc2": {
"cidr_block": "10.0.1.0/24",
"number_azs": 2
}
}
| no | 55 | 56 | ## Outputs 57 | 58 | | Name | Description | 59 | |------|-------------| 60 | | [service\_network](#output\_service\_network) | VPC Lattice service network (full output). | 61 | | [service\_network\_arn](#output\_service\_network\_arn) | VPC Lattice service network ARN. | 62 | | [service\_network\_id](#output\_service\_network\_id) | VPC Lattice service network ID. | 63 | | [service\_network\_log\_subscriptions](#output\_service\_network\_log\_subscriptions) | VPC Lattice service network log subscriptions. | 64 | | [vpc\_associations](#output\_vpc\_associations) | VPC Lattice VPC association IDs. | 65 | -------------------------------------------------------------------------------- /examples/service_network/main.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service_network/main.tf --- 2 | 3 | # Example 1: VPC Lattice service network created without auth policy 4 | module "vpclattice_service_network_without_policy" { 5 | source = "../.." 6 | 7 | service_network = { 8 | name = "service-network-without-policy" 9 | auth_type = "NONE" 10 | access_log_cloudwatch = aws_cloudwatch_log_group.service_network_loggroup.arn 11 | access_log_s3 = aws_s3_bucket.service_network_logbucket.arn 12 | access_log_firehose = aws_kinesis_firehose_delivery_stream.service_network_deliverystream.arn 13 | } 14 | } 15 | 16 | # Example 2: VPC Lattice service network created with auth policy 17 | module "vpclattice_service_network_with_policy" { 18 | source = "../.." 19 | 20 | service_network = { 21 | name = "service-network-with-policy" 22 | auth_type = "AWS_IAM" 23 | auth_policy = jsonencode({ 24 | Version = "2012-10-17" 25 | Statement = [ 26 | { 27 | Action = "*" 28 | Effect = "Allow" 29 | Principal = "*" 30 | Resource = "*" 31 | Condition = { 32 | StringNotEqualsIgnoreCase = { 33 | "aws:PrincipalType" = "anonymous" 34 | } 35 | } 36 | } 37 | ] 38 | }) 39 | } 40 | } 41 | 42 | # Example 3: VPC Lattice service network reference (created outside the module) 43 | resource "aws_vpclattice_service_network" "external_service_network" { 44 | name = "external-service-network" 45 | auth_type = "NONE" 46 | } 47 | 48 | module "vpclattice_service_network_referenced" { 49 | source = "../.." 50 | 51 | service_network = { 52 | identifier = aws_vpclattice_service_network.external_service_network.id 53 | } 54 | } 55 | 56 | # Example 4: VPC Lattice service network VPC association 57 | module "vpclattice_vpc_associations" { 58 | source = "../.." 59 | 60 | service_network = { 61 | identifier = aws_vpclattice_service_network.external_service_network.id 62 | } 63 | 64 | vpc_associations = { for k, v in module.vpcs : k => { 65 | vpc_id = v.vpc_attributes.id 66 | } } 67 | } 68 | 69 | # ---------- SUPPORT RESOURCES ---------- 70 | # Generate random string (for resources' names) 71 | resource "random_string" "random" { 72 | length = 8 73 | special = false 74 | upper = false 75 | } 76 | 77 | # S3 Bucket 78 | resource "aws_s3_bucket" "service_network_logbucket" { 79 | bucket = "sn-logbucket-${random_string.random.result}" 80 | force_destroy = true 81 | } 82 | 83 | # CloudWatch Log Group 84 | resource "aws_cloudwatch_log_group" "service_network_loggroup" { 85 | name = "sn_loggroup-${random_string.random.result}" 86 | retention_in_days = 0 87 | } 88 | 89 | # Firehose Delivery Stream 90 | resource "aws_kinesis_firehose_delivery_stream" "service_network_deliverystream" { 91 | name = "sn-loggroup-firehose-${random_string.random.result}" 92 | destination = "extended_s3" 93 | 94 | extended_s3_configuration { 95 | role_arn = aws_iam_role.firehose_role.arn 96 | bucket_arn = aws_s3_bucket.service_network_logbucket.arn 97 | } 98 | } 99 | 100 | # IAM Role (for Firehose Delivery Stream) 101 | data "aws_iam_policy_document" "firehose_assume_role" { 102 | statement { 103 | effect = "Allow" 104 | 105 | principals { 106 | type = "Service" 107 | identifiers = ["firehose.amazonaws.com"] 108 | } 109 | 110 | actions = ["sts:AssumeRole"] 111 | } 112 | } 113 | 114 | resource "aws_iam_role" "firehose_role" { 115 | name = "firehose_test_role" 116 | assume_role_policy = data.aws_iam_policy_document.firehose_assume_role.json 117 | } 118 | 119 | # VPCs 120 | module "vpcs" { 121 | for_each = var.vpcs 122 | source = "aws-ia/vpc/aws" 123 | version = "4.4.4" 124 | 125 | name = each.key 126 | cidr_block = each.value.cidr_block 127 | az_count = each.value.number_azs 128 | 129 | subnets = { 130 | workload = { netmask = 28 } 131 | } 132 | } -------------------------------------------------------------------------------- /examples/service_network/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service_network/outputs.tf --- 2 | 3 | output "service_network_id" { 4 | description = "VPC Lattice service network ID." 5 | value = module.vpclattice_service_network_without_policy.service_network.id 6 | } 7 | 8 | output "service_network_arn" { 9 | description = "VPC Lattice service network ARN." 10 | value = module.vpclattice_service_network_without_policy.service_network.arn 11 | } 12 | 13 | output "service_network_log_subscriptions" { 14 | description = "VPC Lattice service network log subscriptions." 15 | value = module.vpclattice_service_network_without_policy.service_network_log_subscriptions 16 | } 17 | 18 | output "service_network" { 19 | description = "VPC Lattice service network (full output)." 20 | value = module.vpclattice_service_network_with_policy.service_network 21 | } 22 | 23 | output "vpc_associations" { 24 | description = "VPC Lattice VPC association IDs." 25 | value = { for k, v in module.vpclattice_vpc_associations.vpc_associations : k => v.id } 26 | } -------------------------------------------------------------------------------- /examples/service_network/providers.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service_network/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } 12 | 13 | # Provider definition 14 | provider "aws" { 15 | region = var.aws_region 16 | } -------------------------------------------------------------------------------- /examples/service_network/variables.tf: -------------------------------------------------------------------------------- 1 | # --- examples/service_network/variables.tf --- 2 | 3 | variable "aws_region" { 4 | type = string 5 | description = "AWS Region to use." 6 | default = "eu-west-1" 7 | } 8 | 9 | variable "vpcs" { 10 | type = map(any) 11 | description = "VPCs to create." 12 | default = { 13 | vpc1 = { 14 | cidr_block = "10.0.0.0/24" 15 | number_azs = 2 16 | } 17 | vpc2 = { 18 | cidr_block = "10.0.1.0/24" 19 | number_azs = 2 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /examples/target_groups/.header.md: -------------------------------------------------------------------------------- 1 | # Amazon VPC Lattice - Example: Target Groups creation 2 | 3 | This example shows how you can use the VPC Lattice module to only create Target Groups and Target associations. In the `outputs.tf` file, you can see an example on how to obtain the Target Group ID. 4 | -------------------------------------------------------------------------------- /examples/target_groups/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Amazon VPC Lattice - Example: Target Groups creation 3 | 4 | This example shows how you can use the VPC Lattice module to only create Target Groups and Target associations. In the `outputs.tf` file, you can see an example on how to obtain the Target Group ID. 5 | 6 | ## Requirements 7 | 8 | | Name | Version | 9 | |------|---------| 10 | | [terraform](#requirement\_terraform) | >= 1.3.0 | 11 | | [aws](#requirement\_aws) | >= 4.66.0 | 12 | 13 | ## Providers 14 | 15 | | Name | Version | 16 | |------|---------| 17 | | [archive](#provider\_archive) | n/a | 18 | | [aws](#provider\_aws) | >= 4.66.0 | 19 | 20 | ## Modules 21 | 22 | | Name | Source | Version | 23 | |------|--------|---------| 24 | | [vpc](#module\_vpc) | aws-ia/vpc/aws | 4.4.4 | 25 | | [vpclattice\_target\_groups](#module\_vpclattice\_target\_groups) | ../.. | n/a | 26 | 27 | ## Resources 28 | 29 | | Name | Type | 30 | |------|------| 31 | | [aws_iam_policy.lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | 32 | | [aws_iam_policy_attachment.lambda_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) | resource | 33 | | [aws_iam_role.lambda_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | 34 | | [aws_lambda_function.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | 35 | | [archive_file.python_lambda_package](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | 36 | | [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 37 | | [aws_iam_policy_document.lambda_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 38 | 39 | ## Inputs 40 | 41 | | Name | Description | Type | Default | Required | 42 | |------|-------------|------|---------|:--------:| 43 | | [aws\_region](#input\_aws\_region) | AWS Region to use. | `string` | `"eu-west-1"` | no | 44 | 45 | ## Outputs 46 | 47 | | Name | Description | 48 | |------|-------------| 49 | | [target\_groups](#output\_target\_groups) | Target Group IDs. | 50 | -------------------------------------------------------------------------------- /examples/target_groups/function.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | def lambda_handler(event, context): 4 | # TODO implement 5 | return { 6 | 'statusCode': 200, 7 | 'body': json.dumps('Hello from Lambda!') 8 | } -------------------------------------------------------------------------------- /examples/target_groups/lambda_function.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-amazon-vpc-lattice-module/0679e9cb22c33019185c01683dcadcd48c835fda/examples/target_groups/lambda_function.zip -------------------------------------------------------------------------------- /examples/target_groups/main.tf: -------------------------------------------------------------------------------- 1 | # --- examples/target_groups/main.tf --- 2 | 3 | module "vpclattice_target_groups" { 4 | source = "../.." 5 | 6 | target_groups = { 7 | lambdatarget = { 8 | type = "LAMBDA" 9 | targets = { 10 | mylambda = { id = aws_lambda_function.lambda.arn } 11 | } 12 | } 13 | 14 | iptarget = { 15 | type = "IP" 16 | config = { 17 | port = 80 18 | protocol = "HTTP" 19 | vpc_identifier = module.vpc.vpc_attributes.id 20 | ip_address_type = "IPV4" 21 | protocol_version = "HTTP1" 22 | } 23 | health_check = { 24 | enabled = false 25 | } 26 | targets = { 27 | ip1 = { 28 | id = "10.0.0.10" 29 | port = 80 30 | } 31 | ip2 = { 32 | id = "10.0.0.20" 33 | port = 80 34 | } 35 | ip3 = { 36 | id = "10.0.0.30" 37 | port = 80 38 | } 39 | } 40 | } 41 | 42 | albtarget = { 43 | type = "ALB" 44 | config = { 45 | port = 443 46 | protocol = "HTTPS" 47 | vpc_identifier = module.vpc.vpc_attributes.id 48 | protocol_version = "HTTP2" 49 | } 50 | } 51 | } 52 | } 53 | 54 | # VPC - to create IP targets 55 | module "vpc" { 56 | source = "aws-ia/vpc/aws" 57 | version = "4.4.4" 58 | 59 | name = "vpc" 60 | cidr_block = "10.0.0.0/24" 61 | az_count = 2 62 | 63 | subnets = { 64 | workload = { netmask = 28 } 65 | } 66 | } 67 | 68 | # AWS Lambda Function and Role 69 | resource "aws_lambda_function" "lambda" { 70 | function_name = "mylambda" 71 | filename = "lambda_function.zip" 72 | source_code_hash = data.archive_file.python_lambda_package.output_base64sha256 73 | 74 | role = aws_iam_role.lambda_role.arn 75 | runtime = "python3.10" 76 | handler = "lambda_function.lambda_handler" 77 | } 78 | 79 | data "archive_file" "python_lambda_package" { 80 | type = "zip" 81 | source_file = "${path.module}/function.py" 82 | output_path = "lambda_function.zip" 83 | } 84 | 85 | resource "aws_iam_role" "lambda_role" { 86 | name = "lambda-route53-role" 87 | path = "/" 88 | 89 | assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json 90 | } 91 | 92 | data "aws_iam_policy_document" "lambda_assume_role_policy" { 93 | statement { 94 | effect = "Allow" 95 | actions = ["sts:AssumeRole"] 96 | principals { 97 | type = "Service" 98 | identifiers = ["lambda.amazonaws.com"] 99 | } 100 | } 101 | } 102 | 103 | resource "aws_iam_policy" "lambda_policy" { 104 | name = "lambda_policy" 105 | path = "/" 106 | description = "IAM policy for logging from a lambda" 107 | 108 | policy = data.aws_iam_policy_document.lambda_policy_document.json 109 | } 110 | 111 | data "aws_iam_policy_document" "lambda_policy_document" { 112 | statement { 113 | sid = "LambdaLogging" 114 | effect = "Allow" 115 | actions = [ 116 | "logs:CreateLogGroup", 117 | "logs:CreateLogStream", 118 | "logs:PutLogEvents" 119 | ] 120 | resources = ["arn:aws:logs:*:*:*"] 121 | } 122 | } 123 | 124 | resource "aws_iam_policy_attachment" "lambda_policy_attachment" { 125 | name = "lambda-logging-policy-attachment" 126 | roles = [aws_iam_role.lambda_role.id] 127 | policy_arn = aws_iam_policy.lambda_policy.arn 128 | } -------------------------------------------------------------------------------- /examples/target_groups/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- examples/target_groups/outputs.tf --- 2 | 3 | output "target_groups" { 4 | description = "Target Group IDs." 5 | value = { for k, v in module.vpclattice_target_groups.target_groups : k => v.id } 6 | } -------------------------------------------------------------------------------- /examples/target_groups/providers.tf: -------------------------------------------------------------------------------- 1 | # --- examples/target_groups/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } 12 | 13 | # Provider definition 14 | provider "aws" { 15 | region = var.aws_region 16 | } -------------------------------------------------------------------------------- /examples/target_groups/variables.tf: -------------------------------------------------------------------------------- 1 | # --- examples/target_groups/variables.tf --- 2 | 3 | variable "aws_region" { 4 | type = string 5 | description = "AWS Region to use." 6 | default = "eu-west-1" 7 | } 8 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | # --- root/main.tf --- 2 | 3 | # ---------- VPC LATTICE SERVICE NETWORK ---------- 4 | resource "aws_vpclattice_service_network" "lattice_service_network" { 5 | count = local.create_service_network ? 1 : 0 6 | 7 | name = var.service_network.name 8 | auth_type = try(var.service_network.auth_type, "NONE") 9 | 10 | tags = module.tags.tags_aws 11 | } 12 | 13 | # Auth policy 14 | resource "aws_vpclattice_auth_policy" "service_network_auth_policy" { 15 | count = local.sn_auth_policy ? 1 : 0 16 | 17 | resource_identifier = local.service_network_arn 18 | policy = var.service_network.auth_policy 19 | } 20 | 21 | # Access log subscription 22 | resource "aws_vpclattice_access_log_subscription" "service_network_cloudwatch_access_log" { 23 | count = local.create_service_network && local.sn_access_log_cloudwatch ? 1 : 0 24 | 25 | resource_identifier = local.service_network_arn 26 | destination_arn = try(var.service_network.access_log_cloudwatch, null) 27 | } 28 | 29 | resource "aws_vpclattice_access_log_subscription" "service_network_s3_access_log" { 30 | count = local.create_service_network && local.sn_access_log_s3 ? 1 : 0 31 | 32 | resource_identifier = local.service_network_arn 33 | destination_arn = try(var.service_network.access_log_s3, null) 34 | } 35 | 36 | resource "aws_vpclattice_access_log_subscription" "service_network_firehose_access_log" { 37 | count = local.create_service_network && local.sn_access_log_firehose ? 1 : 0 38 | 39 | resource_identifier = local.service_network_arn 40 | destination_arn = try(var.service_network.access_log_firehose, null) 41 | } 42 | 43 | # ---------- VPC LATTICE VPC ASSOCIATIONS ---------- 44 | resource "aws_vpclattice_service_network_vpc_association" "lattice_vpc_association" { 45 | for_each = var.vpc_associations 46 | 47 | vpc_identifier = each.value.vpc_id 48 | service_network_identifier = local.service_network 49 | security_group_ids = try(each.value.security_group_ids, null) 50 | 51 | tags = module.tags.tags_aws 52 | } 53 | 54 | # ---------- VPC LATTICE SERVICES ---------- 55 | # VPC Lattice Service 56 | resource "aws_vpclattice_service" "lattice_service" { 57 | for_each = { 58 | for k, v in var.services : k => v 59 | if try(v.name, null) != null 60 | } 61 | 62 | name = each.value.name 63 | auth_type = try(each.value.auth_type, "NONE") 64 | certificate_arn = try(each.value.certificate_arn, null) 65 | custom_domain_name = try(each.value.custom_domain_name, null) 66 | 67 | tags = module.tags.tags_aws 68 | } 69 | 70 | # Auth policy 71 | resource "aws_vpclattice_auth_policy" "service_auth_policy" { 72 | for_each = { 73 | for k, v in var.services : k => v 74 | if(try(v.auth_type, "NONE") == "AWS_IAM") && (try(v.auth_policy, null) != null) 75 | } 76 | 77 | resource_identifier = try(aws_vpclattice_service.lattice_service[each.key].arn, each.value.identifier) 78 | policy = each.value.auth_policy 79 | } 80 | 81 | # VPC Lattice Service Association (only if service network is created or provided) 82 | resource "aws_vpclattice_service_network_service_association" "lattice_service_association" { 83 | for_each = { 84 | for k, v in var.services : k => v 85 | if local.create_service_association 86 | } 87 | 88 | service_identifier = try(each.value.identifier, aws_vpclattice_service.lattice_service[each.key].id) 89 | service_network_identifier = local.service_network 90 | 91 | tags = module.tags.tags_aws 92 | } 93 | 94 | # Data Source: Lattice Service. Used to obtain the information of the Services not created by the module, but its identifier was passed in var.services 95 | data "aws_vpclattice_service" "lattice_service" { 96 | for_each = { for k, v in var.services : k => v if contains(keys(v), "identifier") } 97 | 98 | service_identifier = each.value.identifier 99 | } 100 | 101 | # Access log subscription (only if VPC Lattice service is created - not referenced) 102 | resource "aws_vpclattice_access_log_subscription" "service_cloudwatch_access_log" { 103 | for_each = { 104 | for k, v in var.services : k => v 105 | if contains(keys(v), "access_log_cloudwatch") && try(v.name, null) != null 106 | } 107 | 108 | resource_identifier = try(aws_vpclattice_service.lattice_service[each.key].arn, null) 109 | destination_arn = try(each.value.access_log_cloudwatch, null) 110 | } 111 | 112 | resource "aws_vpclattice_access_log_subscription" "service_s3_access_log" { 113 | for_each = { 114 | for k, v in var.services : k => v 115 | if contains(keys(v), "access_log_s3") && try(v.name, null) != null 116 | } 117 | 118 | resource_identifier = try(aws_vpclattice_service.lattice_service[each.key].arn, null) 119 | destination_arn = try(each.value.access_log_s3, null) 120 | } 121 | 122 | resource "aws_vpclattice_access_log_subscription" "service_firehose_access_log" { 123 | for_each = { 124 | for k, v in var.services : k => v 125 | if contains(keys(v), "access_log_firehose") && try(v.name, null) != null 126 | } 127 | 128 | resource_identifier = try(aws_vpclattice_service.lattice_service[each.key].arn, null) 129 | destination_arn = try(each.value.access_log_firehose, null) 130 | } 131 | 132 | # ---------- AMAZON ROUTE 53 DNS CONFIGURATION ---------- 133 | # Alias record (IPv4) 134 | resource "aws_route53_record" "custom_domain_name_a_record" { 135 | for_each = local.services_with_dns_config 136 | 137 | zone_id = try(each.value.hosted_zone_id, var.dns_configuration.hosted_zone_id) 138 | name = try(var.services[each.key].custom_domain_name, data.aws_vpclattice_service.lattice_service[each.key].custom_domain_name) 139 | type = "A" 140 | 141 | alias { 142 | name = try(aws_vpclattice_service.lattice_service[each.key].dns_entry[0].domain_name, data.aws_vpclattice_service.lattice_service[each.key].dns_entry[0].domain_name) 143 | zone_id = try(aws_vpclattice_service.lattice_service[each.key].dns_entry[0].hosted_zone_id, data.aws_vpclattice_service.lattice_service[each.key].dns_entry[0].hosted_zone_id) 144 | evaluate_target_health = false 145 | } 146 | } 147 | 148 | # Alias record (IPv6) 149 | resource "aws_route53_record" "custom_domain_name_aaaa_record" { 150 | for_each = local.services_with_dns_config 151 | 152 | zone_id = try(each.value.hosted_zone_id, var.dns_configuration.hosted_zone_id) 153 | name = try(var.services[each.key].custom_domain_name, data.aws_vpclattice_service.lattice_service[each.key].custom_domain_name) 154 | type = "AAAA" 155 | 156 | alias { 157 | name = try(aws_vpclattice_service.lattice_service[each.key].dns_entry[0].domain_name, data.aws_vpclattice_service.lattice_service[each.key].dns_entry[0].domain_name) 158 | zone_id = try(aws_vpclattice_service.lattice_service[each.key].dns_entry[0].hosted_zone_id, data.aws_vpclattice_service.lattice_service[each.key].dns_entry[0].hosted_zone_id) 159 | evaluate_target_health = false 160 | } 161 | } 162 | 163 | # ---------- VPC LATTICE TARGET GROUPS ---------- 164 | # AWS Lambda Target Group (without config attribute) 165 | resource "aws_vpclattice_target_group" "lambda_lattice_target_group" { 166 | for_each = { 167 | for k, v in var.target_groups : k => v 168 | if v.type == "LAMBDA" 169 | } 170 | 171 | name = try(each.value.name, each.key) 172 | type = each.value.type 173 | 174 | config { 175 | lambda_event_structure_version = try(each.value.config.lambda_event_structure_version, "V2") 176 | } 177 | 178 | tags = module.tags.tags_aws 179 | } 180 | 181 | # Other Target Groups 182 | resource "aws_vpclattice_target_group" "lattice_target_group" { 183 | for_each = { 184 | for k, v in var.target_groups : k => v 185 | if v.type != "LAMBDA" 186 | } 187 | 188 | name = try(each.value.name, each.key) 189 | type = each.value.type 190 | 191 | config { 192 | port = try(each.value.config.port, null) 193 | protocol = try(each.value.config.protocol, null) 194 | vpc_identifier = try(each.value.config.vpc_identifier, null) 195 | ip_address_type = try(each.value.config.ip_address_type, null) 196 | protocol_version = try(each.value.config.protocol_version, null) 197 | 198 | dynamic "health_check" { 199 | for_each = each.value.type != "ALB" ? each.value.health_check[*] : [] 200 | 201 | content { 202 | enabled = try(health_check.value.enabled, true) 203 | health_check_interval_seconds = try(health_check.value.health_check_interval_seconds, null) 204 | health_check_timeout_seconds = try(health_check.value.health_check_timeout_seconds, null) 205 | healthy_threshold_count = try(health_check.value.healthy_threshold_count, null) 206 | path = try(health_check.value.path, null) 207 | port = try(health_check.value.port, null) 208 | protocol = try(health_check.value.protocol, null) 209 | protocol_version = try(health_check.value.protocol_version, null) 210 | unhealthy_threshold_count = try(health_check.value.unhealthy_threshold_count, null) 211 | 212 | matcher { 213 | value = try(each.value.health_check.matcher, null) 214 | } 215 | } 216 | } 217 | } 218 | 219 | tags = module.tags.tags_aws 220 | } 221 | 222 | # VPC Lattice Targets 223 | module "targets" { 224 | for_each = { 225 | for k, v in var.target_groups : k => v 226 | if contains(keys(v), "targets") 227 | } 228 | source = "./modules/targets" 229 | 230 | target_type = each.value.type 231 | target_group_identifier = try(aws_vpclattice_target_group.lambda_lattice_target_group[each.key].arn, aws_vpclattice_target_group.lattice_target_group[each.key].arn) 232 | targets = each.value.targets 233 | } 234 | 235 | # ---------- LISTENERS AND RULES ---------- 236 | # VPC Lattice Listeners - rules are handled inside the "listeners" module 237 | module "listeners" { 238 | source = "./modules/listeners" 239 | for_each = var.services 240 | 241 | listener_information = try(each.value.listeners, {}) 242 | service_identifier = try(each.value.identifier, aws_vpclattice_service.lattice_service[each.key].id) 243 | target_groups = local.target_group_ids 244 | tags = module.tags.tags_aws 245 | } 246 | 247 | # ---------- AWS RESOURCE ACCESS MANAGER ---------- 248 | # Create AWS RAM Resource Share (if name provided) 249 | resource "aws_ram_resource_share" "ram_resource_share" { 250 | count = local.create_ram_resource_share ? 1 : 0 251 | 252 | name = var.ram_share.resource_share_name 253 | allow_external_principals = try(var.ram_share.allow_external_principals, false) 254 | 255 | tags = module.tags.tags_aws 256 | } 257 | 258 | # AWS RAM principal association 259 | resource "aws_ram_principal_association" "ram_principal_association" { 260 | for_each = { 261 | for k, v in local.principals_map : k => v 262 | if local.config_ram_share 263 | } 264 | 265 | principal = each.value 266 | resource_share_arn = local.resource_share_arn 267 | } 268 | 269 | # AWS RAM resource association - VPC Lattice service network 270 | resource "aws_ram_resource_association" "ram_service_network_association" { 271 | count = local.share_service_network ? 1 : 0 272 | 273 | resource_arn = aws_vpclattice_service_network.lattice_service_network[0].arn 274 | resource_share_arn = local.resource_share_arn 275 | } 276 | 277 | # AWS RAM resource association - VPC Lattice services 278 | resource "aws_ram_resource_association" "ram_services_association" { 279 | count = local.config_ram_share ? length(local.share_services) : 0 280 | 281 | resource_arn = local.ram_services_association_resources[local.share_services[count.index]].arn 282 | resource_share_arn = local.resource_share_arn 283 | } -------------------------------------------------------------------------------- /modules/listener_rules/main.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listener_rules/main.tf --- 2 | 3 | # VPC Lattice Listener Rules 4 | resource "aws_vpclattice_listener_rule" "lattice_listener_rule" { 5 | for_each = var.listener_rules 6 | 7 | name = try(each.value.name, each.key) 8 | listener_identifier = var.listener_identifier 9 | service_identifier = var.service_identifier 10 | priority = each.value.priority 11 | 12 | match { 13 | http_match { 14 | method = try(each.value.http_match_method, null) 15 | 16 | # Dynamic block - header_matches 17 | dynamic "header_matches" { 18 | for_each = try(each.value.header_matches[*], []) 19 | content { 20 | case_sensitive = try(header_matches.value.case_sensitive, false) 21 | name = header_matches.value.name 22 | 23 | match { 24 | contains = try(header_matches.value.contains, null) 25 | exact = try(header_matches.value.exact, null) 26 | prefix = try(header_matches.value.prefix, null) 27 | } 28 | } 29 | } 30 | 31 | # Dynamic block - path_match 32 | dynamic "path_match" { 33 | for_each = try(each.value.path_match[*], []) 34 | content { 35 | case_sensitive = try(path_match.value.case_sensitive, false) 36 | 37 | match { 38 | exact = try(path_match.value.exact, null) 39 | prefix = try(path_match.value.prefix, null) 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | # Dynamic block - action = fixed_response 47 | dynamic "action" { 48 | for_each = try(each.value.action_fixedresponse[*], []) 49 | content { 50 | fixed_response { 51 | status_code = action.value.status_code 52 | } 53 | } 54 | } 55 | 56 | # Dynamic block - action = forward 57 | dynamic "action" { 58 | for_each = try(each.value.action_forward[*], []) 59 | content { 60 | forward { 61 | dynamic "target_groups" { 62 | for_each = try(action.value.target_groups, []) 63 | content { 64 | target_group_identifier = var.target_groups[target_groups.key] 65 | weight = target_groups.value.weight 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | tags = var.tags 73 | } -------------------------------------------------------------------------------- /modules/listener_rules/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listener_rules/outputs.tf --- 2 | 3 | output "rules" { 4 | description = "Listener rules created." 5 | value = aws_vpclattice_listener_rule.lattice_listener_rule 6 | } -------------------------------------------------------------------------------- /modules/listener_rules/providers.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listener_rules/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /modules/listener_rules/variables.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listener_rules/variables.tf --- 2 | 3 | variable "listener_rules" { 4 | type = any 5 | description = "Listener rules to create." 6 | } 7 | 8 | variable "listener_identifier" { 9 | type = string 10 | description = "VPC Lattice Listener identifier." 11 | } 12 | 13 | variable "service_identifier" { 14 | type = string 15 | description = "VPC Lattice Service identifier." 16 | } 17 | 18 | variable "target_groups" { 19 | type = map(string) 20 | description = "VPC Lattice target group identifiers." 21 | } 22 | 23 | variable "tags" { 24 | type = map(string) 25 | description = "Tags to configure in the resources created." 26 | } -------------------------------------------------------------------------------- /modules/listeners/main.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listeners/main.tf --- 2 | 3 | # VPC Lattice Listener 4 | resource "aws_vpclattice_listener" "lattice_listener" { 5 | for_each = var.listener_information 6 | 7 | name = try(each.value.name, each.key) 8 | port = try(each.value.port, null) 9 | protocol = each.value.protocol 10 | service_arn = can(regex("^svc-", var.service_identifier)) ? null : var.service_identifier 11 | service_identifier = can(regex("^svc-", var.service_identifier)) ? var.service_identifier : null 12 | 13 | # Dynamic block for default_action = fixed_response. 14 | dynamic "default_action" { 15 | for_each = try(each.value.default_action_fixedresponse[*], []) 16 | content { 17 | fixed_response { 18 | status_code = default_action.value.status_code 19 | } 20 | } 21 | } 22 | 23 | # Dynamic block for default_action = forward. 24 | dynamic "default_action" { 25 | for_each = try(each.value.default_action_forward[*], []) 26 | content { 27 | forward { 28 | dynamic "target_groups" { 29 | for_each = try(default_action.value.target_groups, []) 30 | content { 31 | target_group_identifier = var.target_groups[target_groups.key] 32 | weight = target_groups.value.weight 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | tags = var.tags 40 | } 41 | 42 | # VPC Lattice Listener rules 43 | module "rules" { 44 | source = "../../modules/listener_rules" 45 | for_each = { 46 | for k, v in aws_vpclattice_listener.lattice_listener : k => v.listener_id 47 | if try(var.listener_information[k].rules, null) != null 48 | } 49 | 50 | listener_rules = var.listener_information[each.key].rules 51 | listener_identifier = each.value 52 | service_identifier = var.service_identifier 53 | target_groups = var.target_groups 54 | tags = var.tags 55 | } -------------------------------------------------------------------------------- /modules/listeners/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listeners/outputs.tf --- 2 | 3 | output "listeners" { 4 | description = "VPC Lattice Listeners created." 5 | value = { for k, v in aws_vpclattice_listener.lattice_listener : k => { 6 | attributes = v 7 | rules = try(module.rules[k].rules, null) 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /modules/listeners/providers.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listeners/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /modules/listeners/variables.tf: -------------------------------------------------------------------------------- 1 | # --- modules/listeners/variables.tf --- 2 | 3 | variable "listener_information" { 4 | type = any 5 | description = "Information about the VPC Lattice Listener to create." 6 | } 7 | 8 | variable "service_identifier" { 9 | type = string 10 | description = "VPC Lattice Service identifier." 11 | } 12 | 13 | variable "target_groups" { 14 | type = map(string) 15 | description = "VPC Lattice target group identifiers." 16 | } 17 | 18 | variable "tags" { 19 | type = map(string) 20 | description = "Tags to configure in the resources created." 21 | } -------------------------------------------------------------------------------- /modules/targets/main.tf: -------------------------------------------------------------------------------- 1 | # --- modules/targets/main.tf --- 2 | 3 | # VPC Lattice Target Group attachment 4 | resource "aws_vpclattice_target_group_attachment" "target_attachment" { 5 | for_each = var.targets 6 | 7 | target_group_identifier = var.target_group_identifier 8 | 9 | target { 10 | id = try(each.value.id, null) 11 | port = try(each.value.port, null) 12 | } 13 | } 14 | 15 | # AWS Lambda permission (only if LAMDBA type) 16 | resource "aws_lambda_permission" "lambda_target_vpclattice" { 17 | for_each = { 18 | for k, v in var.targets : k => v 19 | if var.target_type == "LAMBDA" 20 | } 21 | 22 | statement_id = "AllowExecutionFromVpcLattice" 23 | action = "lambda:InvokeFunction" 24 | function_name = split(":", each.value.id)[6] 25 | principal = "vpc-lattice.amazonaws.com" 26 | source_arn = var.target_group_identifier 27 | } -------------------------------------------------------------------------------- /modules/targets/outputs.tf: -------------------------------------------------------------------------------- 1 | # --- modules/targets/outputs.tf --- -------------------------------------------------------------------------------- /modules/targets/providers.tf: -------------------------------------------------------------------------------- 1 | # --- modules/targets/providers.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /modules/targets/variables.tf: -------------------------------------------------------------------------------- 1 | # --- modules/targets/variables.tf --- 2 | 3 | variable "target_type" { 4 | type = string 5 | description = "Target type." 6 | } 7 | 8 | variable "target_group_identifier" { 9 | type = string 10 | description = "Target group identifier." 11 | } 12 | 13 | variable "targets" { 14 | type = map(any) 15 | description = "Targets information - for the target group attachment." 16 | } -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | # --- root/outputs.tf --- 2 | 3 | output "service_network" { 4 | value = try(aws_vpclattice_service_network.lattice_service_network[0], null) 5 | description = <<-EOF 6 | VPC Lattice resource attributes. Full output of **aws_vpclattice_service_network**. 7 | EOF 8 | } 9 | 10 | output "service_network_log_subscriptions" { 11 | value = { 12 | cloudwatch = try(aws_vpclattice_access_log_subscription.service_network_cloudwatch_access_log[0], null) 13 | s3 = try(aws_vpclattice_access_log_subscription.service_network_s3_access_log[0], null) 14 | firehose = try(aws_vpclattice_access_log_subscription.service_network_firehose_access_log[0], null) 15 | } 16 | description = <<-EOF 17 | VPC Lattice service network access log subscriptions. The output is composed by the following attributes: 18 | - `cloudwatch` = Full output of **aws_vpclattice_access_log_subscription**. 19 | - `s3` = Full output of **aws_vpclattice_access_log_subscription**. 20 | - `firehose` = Full output of **aws_vpclattice_access_log_subscription**. 21 | EOF 22 | } 23 | 24 | output "vpc_associations" { 25 | value = try(aws_vpclattice_service_network_vpc_association.lattice_vpc_association, null) 26 | description = <<-EOF 27 | VPC Lattice VPC associations. Full output of **aws_vpclattice_service_network_vpc_association**. 28 | EOF 29 | } 30 | 31 | output "services" { 32 | value = { for k, v in var.services : k => { 33 | attributes = try(aws_vpclattice_service.lattice_service[k], data.aws_vpclattice_service.lattice_service[k]) 34 | service_network_association = try(aws_vpclattice_service_network_service_association.lattice_service_association[k], null) 35 | log_subscriptions = { 36 | cloudwatch = try(aws_vpclattice_access_log_subscription.service_cloudwatch_access_log[k], null) 37 | s3 = try(aws_vpclattice_access_log_subscription.service_s3_access_log[k], null) 38 | firehose = try(aws_vpclattice_access_log_subscription.service_firehose_access_log[k], null) 39 | } 40 | } } 41 | description = <<-EOF 42 | VPC Lattice Services. The output is composed by the following attributes (per Service created): 43 | - `attributes` = Full output of **aws_vpclattice_service**. 44 | - `service_network_association` = Full output of **aws_vpclattice_service_network_service_association**. 45 | - `log_subscriptions` = *The output is composed by the following attributes:* 46 | - `cloudwatch` = Full output of **aws_vpclattice_access_log_subscription**. 47 | - `s3` = Full output of **aws_vpclattice_access_log_subscription**. 48 | - `firehose` = Full output of **aws_vpclattice_access_log_subscription**. 49 | EOF 50 | } 51 | 52 | output "target_groups" { 53 | value = { for k, v in var.target_groups : k => try(aws_vpclattice_target_group.lambda_lattice_target_group[k], try(aws_vpclattice_target_group.lattice_target_group[k], null)) } 54 | description = <<-EOF 55 | VPC Lattice Target Groups. Full output of **aws_vpclattice_target_group**. 56 | EOF 57 | } 58 | 59 | output "listeners_by_service" { 60 | value = try({ for k, v in module.listeners : k => v.listeners }, null) 61 | description = <<-EOF 62 | VPC Lattice Listener and Rules. Per Lattice Service, each Listener is composed by the following attributes: 63 | - `attributes` = Full output of **aws_vpclattice_listener**. 64 | - `rules` = Full output of **aws_vpclattice_listener_rule**. 65 | EOF 66 | } 67 | 68 | output "ram_resource_share" { 69 | value = try(aws_ram_resource_share.ram_resource_share[0], null) 70 | description = <<-EOF 71 | AWS Resource Access Manager resource share. Full output of **aws_ram_resource_share**. 72 | EOF 73 | } -------------------------------------------------------------------------------- /providers.tf: -------------------------------------------------------------------------------- 1 | # --- root/variables.tf --- 2 | 3 | terraform { 4 | required_version = ">= 1.3.0" 5 | required_providers { 6 | aws = { 7 | source = "hashicorp/aws" 8 | version = ">= 4.66.0" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/01_mandatory.tftest.hcl: -------------------------------------------------------------------------------- 1 | ## NOTE: This is the minimum mandatory test 2 | # run at least one test using the ./examples directory as your module source 3 | # create additional *.tftest.hcl for your own unit / integration tests 4 | # use tests/*.auto.tfvars to add non-default variables 5 | 6 | run "mandatory_plan_basic" { 7 | command = plan 8 | module { 9 | source = "./examples/service_network" 10 | } 11 | } 12 | 13 | run "mandatory_apply_basic" { 14 | command = apply 15 | module { 16 | source = "./examples/service_network" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/02_service.tftest.hcl: -------------------------------------------------------------------------------- 1 | 2 | run "plan_service" { 3 | command = plan 4 | module { 5 | source = "./examples/service" 6 | } 7 | } 8 | 9 | run "apply_service" { 10 | command = apply 11 | module { 12 | source = "./examples/service" 13 | } 14 | } -------------------------------------------------------------------------------- /tests/03_target_groups.tftest.hcl: -------------------------------------------------------------------------------- 1 | 2 | run "plan_target_groups" { 3 | command = plan 4 | module { 5 | source = "./examples/target_groups" 6 | } 7 | } 8 | 9 | run "apply_target_groups" { 10 | command = apply 11 | module { 12 | source = "./examples/target_groups" 13 | } 14 | } -------------------------------------------------------------------------------- /tests/04_ram_share.tftest.hcl: -------------------------------------------------------------------------------- 1 | 2 | run "plan_ram_share" { 3 | command = plan 4 | module { 5 | source = "./examples/ram_share" 6 | } 7 | } 8 | 9 | run "apply_ram_share" { 10 | command = apply 11 | module { 12 | source = "./examples/ram_share" 13 | } 14 | } -------------------------------------------------------------------------------- /tests/05_dns_configuration.tftest.hcl: -------------------------------------------------------------------------------- 1 | 2 | run "plan_ram_share" { 3 | command = plan 4 | module { 5 | source = "./examples/dns_configuration" 6 | } 7 | } 8 | 9 | run "apply_ram_share" { 10 | command = apply 11 | module { 12 | source = "./examples/dns_configuration" 13 | } 14 | } -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | # --- root/variables.tf --- 2 | 3 | variable "service_network" { 4 | type = any 5 | description = <<-EOF 6 | Amazon VPC Lattice service network information. You can either create a new service network or reference a current one (to associate VPC Lattice services or VPCs). Setting the `name` attribute will create a **new** service network, while using the attribute `identifier` will reference an **existing** service network. 7 | More information about the format of this variable can be found in the "Usage - VPC Lattice service network" section of the README. 8 | EOF 9 | 10 | default = {} 11 | 12 | validation { 13 | error_message = "Invalid key in any of the definitions for var.service_network. Valid options include: \"name\", \"auth_type\", \"auth_policy\", \"identifier\", \"access_log_cloudwatch\", \"access_log_s3\", \"access_log_firehose\"." 14 | condition = length(setsubtract(keys(try(var.service_network, {})), [ 15 | "name", 16 | "auth_type", 17 | "auth_policy", 18 | "identifier", 19 | "access_log_cloudwatch", 20 | "access_log_s3", 21 | "access_log_firehose" 22 | ])) == 0 23 | } 24 | 25 | validation { 26 | error_message = "You should define either the `name` of a new VPC Lattice service network or its `identifier`, not both attributes." 27 | condition = length(setintersection(keys(try(var.service_network, {})), ["name", "identifier"])) != 2 28 | } 29 | } 30 | 31 | variable "vpc_associations" { 32 | type = map(object({ 33 | vpc_id = optional(string) 34 | security_group_ids = optional(list(string)) 35 | })) 36 | description = <<-EOF 37 | VPC Lattice VPC associations. You can define 1 or more VPC associations using this module. 38 | More information about the format of this variable can be found in the "Usage - VPC association" section of the README. 39 | EOF 40 | 41 | default = {} 42 | } 43 | 44 | variable "services" { 45 | type = any 46 | description = <<-EOF 47 | Definition of the VPC Lattice Services to create. You can use this module to either create only Lattice services (not associated with any service network), or associated with a service network (if you create one or provide an identifier). You can define 1 or more Service using this module. 48 | More information about the format of this variable can be found in the "Usage - VPC Lattice service" section of the README. 49 | EOF 50 | 51 | default = {} 52 | 53 | validation { 54 | error_message = "Invalid key in any of the definitions for var.services. Valid options include: \"identifier\", \"name\", \"auth_type\", \"auth_policy\", \"certificate_arn\", \"custom_domain_name\", \"listeners\", \"hosted_zone_id\", \"access_log_cloudwatch\", \"access_log_s3\", and \"access_log_firehose\"." 55 | condition = alltrue([ 56 | for service in try(var.services, {}) : length(setsubtract(keys(try(service, {})), [ 57 | "identifier", 58 | "name", 59 | "auth_type", 60 | "auth_policy", 61 | "certificate_arn", 62 | "custom_domain_name", 63 | "listeners", 64 | "hosted_zone_id", 65 | "access_log_cloudwatch", 66 | "access_log_s3", 67 | "access_log_firehose" 68 | ])) == 0 69 | ]) 70 | } 71 | } 72 | 73 | variable "target_groups" { 74 | type = any 75 | description = <<-EOF 76 | Definitions of the Target Groups to create. You can define 1 or more Target Groups using this module. 77 | More information about the format of this variable can be found in the "Usage - Target Groups" section of the README. 78 | EOF 79 | 80 | default = {} 81 | 82 | validation { 83 | error_message = "Invalid key in any of the definitions for var.target_groups. Valid options include: \"name\", \"type\", \"config\", \"health_check\", \"targets\"." 84 | condition = alltrue([ 85 | for tg in try(var.target_groups, {}) : length(setsubtract(keys(try(tg, {})), [ 86 | "name", 87 | "type", 88 | "config", 89 | "health_check", 90 | "targets" 91 | ])) == 0 92 | ]) 93 | } 94 | } 95 | 96 | variable "ram_share" { 97 | type = any 98 | description = <<-EOF 99 | Configuration of the resources to share using AWS Resource Access Manager (RAM). VPC Lattice service networks and services can be shared using RAM. 100 | More information about the format of this variable can be found in the "Sharing VPC Lattice resources" section of the README. 101 | EOF 102 | 103 | default = {} 104 | 105 | validation { 106 | error_message = "Invalid key in any of the definitions for var.ram_share. Valid options include: \"resource_share_arn\", \"resource_share_name\", \"allow_external_principals\", \"principals\", \"share_service_network\", \"share_services\"." 107 | condition = length(setsubtract(keys(var.ram_share), [ 108 | "resource_share_arn", 109 | "resource_share_name", 110 | "allow_external_principals", 111 | "principals", 112 | "share_service_network", 113 | "share_services" 114 | ])) == 0 115 | } 116 | } 117 | 118 | variable "dns_configuration" { 119 | type = map(string) 120 | description = <<-EOF 121 | Amazon Route 53 DNS configuration. For VPC Lattice services with custom domain name configured, you can indicate the Hosted Zone ID to create the corresponding Alias record (IPv4 and IPv6) pointing to the VPC Lattice-generated domain name. 122 | You can override the Hosted Zone to configure the Alias record by configuring the `hosted_zone_id` attribute under each service definition (`var.services`). 123 | This configuration is only supported if both the VPC Lattice service and the Route 53 Hosted Zone are in the same account. More information about the variable format and multi-Account support can be found in the "Amazon Route 53 DNS configuration" section of the README. 124 | EOF 125 | default = {} 126 | 127 | validation { 128 | error_message = "Invalid key in any of the definitions for var.dns_configuration. Valid options include: \"hosted_zone_id\"." 129 | condition = length(setsubtract(keys(var.dns_configuration), [ 130 | "hosted_zone_id" 131 | ])) == 0 132 | } 133 | } 134 | 135 | variable "tags" { 136 | description = "Tags to apply to all the resources created in this module." 137 | type = map(string) 138 | 139 | default = {} 140 | } 141 | --------------------------------------------------------------------------------