├── .circleci
└── config.yml
├── .github
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .terraform-version
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── examples
├── basic_usage.tf
├── custom_azs.tf
└── vpn_provided.tf
├── main.tf
├── outputs.tf
├── tests
├── test1
│ └── main.tf
├── test2
│ └── main.tf
└── test3
│ └── main.tf
└── variables.tf
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | test:
4 | docker:
5 | - image: 891714082543.dkr.ecr.us-west-2.amazonaws.com/rackspace-tf-toolbox
6 | working_directory: ~/
7 | steps:
8 | - attach_workspace:
9 | at: ~/workspace
10 | - checkout:
11 | path: ~/branches/${CIRCLE_BRANCH}
12 | - run:
13 | name: Run Test
14 | command: MODULE_CI_JOB='test' python3 orchestrate.py
15 | - run:
16 | name: destroy
17 | command: cd ~ && ~/bin/destroy.sh && ~/bin/destroy_s3_buckets.sh # must succeed or we have something to clean up manually
18 | when: always
19 | - persist_to_workspace:
20 | root: ~/workspace
21 | paths:
22 | - plan_results/*
23 | - artifacts/*
24 | check_destruction:
25 | docker:
26 | - image: 891714082543.dkr.ecr.us-west-2.amazonaws.com/rackspace-tf-toolbox
27 | working_directory: ~/
28 | steps:
29 | - attach_workspace:
30 | at: ~/workspace
31 | - checkout:
32 | path: ~/module
33 | - run:
34 | name: Check Destruction
35 | command: MODULE_CI_JOB='check_destruction' python3 orchestrate.py
36 | - store_artifacts:
37 | path: ~/workspace/artifacts
38 |
39 |
40 | workflows:
41 | version: 2
42 | build_and_test:
43 | jobs:
44 | - test:
45 | filters:
46 | branches:
47 | ignore: master
48 | - check_destruction:
49 | requires:
50 | - test
51 | filters:
52 | branches:
53 | ignore: master
54 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ##### Corresponding Issue(s):
2 | - PRs should have a corresponding issue. If no issue exists, provide details in the **Reason for Change(s)** section
3 |
4 | ##### Summary of change(s):
5 |
6 | ##### Reason for Change(s):
7 |
8 | - If a bug, describe error scenario, including expected behavior and actual behavior.
9 |
10 | - If an enhancement, describe the use case and the perceived benefit(s).
11 |
12 | ##### Will the change trigger resource destruction or replacement? If yes, please provide justification:
13 |
14 | ##### Does this update/change involve issues with other external modules? If so, please describe the scenario.
15 |
16 | ##### If input variables or output variables have changed or has been added, have you updated the README?
17 |
18 | ##### Do examples need to be updated based on changes?
19 |
20 | ##### Note to the PR requester about Closing PR's
21 | Please message the person that opened the issue when auto closing it on slack, as well as any other stake holders of deep interest. Only close the issue if you believe that the issue is fully resolved with this PR.
22 |
23 | #### This PR may auto close the issue associated with it. If you feel the issue is not resolved please reopen the issue.
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Local .terraform directories
2 | **/.terraform/*
3 |
4 | # .tfstate files
5 | *.tfstate
6 | *.tfstate.*
7 |
8 | # .tfvars files
9 | *.tfvars
10 |
11 | # .terraform.lock.hcl -- not currently using
12 | .terraform.lock.hcl
13 |
14 | # Plans
15 | *.plans
16 |
17 | # Secrets
18 | secrets.tf
19 |
20 | # Mac
21 | .DS_Store
22 |
23 | # Idea
24 | .idea/*
--------------------------------------------------------------------------------
/.terraform-version:
--------------------------------------------------------------------------------
1 | 1.1.9
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | This document is a set of guidelines to contribute to the [Rackspace](https://www.rackspace.com) [Terraform](https://www.terraform.io/) modules. These modules were created to enable and empower our Managed Infrastructure as Code product. While these modules are designed for Rackspace environments, we hope they may be of use to the community at large.
4 |
5 | ## Reporting issues
6 |
7 | Rackspace customers should open a normal Rackspace support ticket to report any problems or feedback for these modules. Our support Rackers will then work with you and our product team to address those issues.
8 |
9 | ## Submitting Changes
10 |
11 | Pull requests are welcome. Currently our CI solution cannot run against pull requests from forks. Despite this, these submissions are still welcome. All pull requests will be evaluated against Rackspace best practices, and after approval, will be migrated to a branch for testing.
12 |
13 | For significant or critical features, a new test should be created, or if appropriate, and existing test should be updated. This will serve to ensure the any failures related to the feature are caught.
14 |
15 | When submitting a pull request please explain the changes in detail, and try to minimize the scope to related changes. For example, changes resolving separate bugs should be broken out into separate pull requests. If there are relevant documentation or references, such as terraform bug reports, links to those references are greatly appreciated.
16 |
17 | ## Testing
18 |
19 | Pull requests must pass a linting and build test prior to acceptance. This test ensures all submissions will produce a stable and working deployment. In addition, our CI jobs will run a check_destruction test to help determine if any breaking changes will occur with this change. This test will show a failed result if breaking changes are detected, but this will not prevent the submission from being approved.
20 |
21 | ## Coding and Style guidelines
22 |
23 | All submissions should comply with the coding and style guides outlined at [General Terraform Style Guide](https://manage.rackspace.com/aws/docs/product-guide/miac/terraform-standards.html#general-terraform-style-guide) and [Rackspace Module Standards](https://manage.rackspace.com/aws/docs/product-guide/miac/terraform-standards.html#rackspace-module-). CI testing will run and flag code that does not meet these defined standards whenever possible.
24 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2018 Rackspace, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # aws-terraform-vpc\_basenetwork
2 |
3 | This module sets up basic network components for an account in a specific region. Optionally it will setup a basic VPN gateway and VPC flow logs.
4 |
5 | ## Basic Usage
6 |
7 | ```HCL
8 | module "vpc" {
9 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork//?ref=v0.12.2"
10 |
11 | vpc_name = "MyVPC"
12 | }
13 | ```
14 |
15 | Full working references are available at [examples](examples)
16 | ## Default Resources
17 |
18 | By default only `vpc_name` is required to be set. Unless changed `aws_region` defaults to `us-west-2` and will need to be updated for other regions. `source` will also need to be declared depending on where the module lives. Given default settings the following resources are created:
19 |
20 | - VPC Flow Logs
21 | - 2 AZs with public/private subnets from the list of 3 static CIDRs ranges available for each as defaults
22 | - Public/private subnets with the count related to custom\_azs if defined or region AZs automatically calculated by Terraform otherwise
23 | - NAT Gateways will be created in each AZ's first public subnet
24 | - EIPs will be created in all public subnets for NAT gateways to use
25 | - Route Tables, including routes to NAT gateways if applicable
26 |
27 | ## Terraform 0.12 upgrade
28 |
29 | Several changes were required while adding terraform 0.12 compatibility. The following changes should be
30 | made when upgrading from a previous release to version 0.12.0 or higher.
31 |
32 | ### Module variables
33 |
34 | The following module variables were updated to better meet current Rackspace style guides:
35 |
36 | - `custom_tags` -> `tags`
37 | - `vpc_name` -> `name`
38 |
39 | ## Requirements
40 |
41 | | Name | Version |
42 | |------|---------|
43 | | terraform | >= 0.13 |
44 | | aws | >= 4.0 |
45 |
46 | ## Providers
47 |
48 | | Name | Version |
49 | |------|---------|
50 | | aws | >= 4.0 |
51 |
52 | ## Modules
53 |
54 | No Modules.
55 |
56 | ## Resources
57 |
58 | | Name |
59 | |------|
60 | | [aws_availability_zones](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/data-sources/availability_zones) |
61 | | [aws_cloudwatch_log_group](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/cloudwatch_log_group) |
62 | | [aws_eip](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/eip) |
63 | | [aws_flow_log](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/flow_log) |
64 | | [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/iam_role) |
65 | | [aws_iam_role_policy](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/iam_role_policy) |
66 | | [aws_internet_gateway](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/internet_gateway) |
67 | | [aws_nat_gateway](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/nat_gateway) |
68 | | [aws_region](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/data-sources/region) |
69 | | [aws_route](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/route) |
70 | | [aws_route_table](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/route_table) |
71 | | [aws_route_table_association](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/route_table_association) |
72 | | [aws_s3_bucket](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/s3_bucket) |
73 | | [aws_s3_bucket_acl](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/s3_bucket_acl) |
74 | | [aws_s3_bucket_lifecycle_configuration](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/s3_bucket_lifecycle_configuration) |
75 | | [aws_s3_bucket_server_side_encryption_configuration](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/s3_bucket_server_side_encryption_configuration) |
76 | | [aws_subnet](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/subnet) |
77 | | [aws_vpc](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/vpc) |
78 | | [aws_vpc_dhcp_options](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/vpc_dhcp_options) |
79 | | [aws_vpc_dhcp_options_association](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/vpc_dhcp_options_association) |
80 | | [aws_vpn_gateway](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/vpn_gateway) |
81 | | [aws_vpn_gateway_route_propagation](https://registry.terraform.io/providers/hashicorp/aws/4.0/docs/resources/vpn_gateway_route_propagation) |
82 |
83 | ## Inputs
84 |
85 | | Name | Description | Type | Default | Required |
86 | |------|-------------|------|---------|:--------:|
87 | | az\_count | Number of AZs to utilize for the subnets | `number` | `2` | no |
88 | | build\_flow\_logs | Whether or not to build flow log components in Cloudwatch Logs | `bool` | `false` | no |
89 | | build\_igw | Whether or not to build an internet gateway. If disabled, no public subnets or route tables, internet gateway, or NAT Gateways will be created. | `bool` | `true` | no |
90 | | build\_nat\_gateways | Whether or not to build a NAT gateway per AZ. if `build_igw` is set to false, this value is ignored. | `bool` | `true` | no |
91 | | build\_s3\_flow\_logs | Whether or not to build flow log components in s3 | `bool` | `false` | no |
92 | | build\_vpn | Whether or not to build a VPN gateway | `bool` | `false` | no |
93 | | cidr\_range | CIDR range for the VPC | `string` | `"172.18.0.0/19"` | no |
94 | | cloudwatch\_flowlog\_retention | The number of days to retain flowlogs in CLoudwatch Logs. Valid values are: [0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]. A value of `0` will retain indefinitely. | `number` | `14` | no |
95 | | custom\_azs | A list of AZs that VPC resources will reside in | `list(string)` | `[]` | no |
96 | | default\_tenancy | Default tenancy for instances. Either multi-tenant (default) or single-tenant (dedicated) | `string` | `"default"` | no |
97 | | domain\_name | Custom domain name for the VPC | `string` | `""` | no |
98 | | domain\_name\_servers | Array of custom domain name servers | `list(string)` |
[
"AmazonProvidedDNS"
]
| no |
99 | | enable\_dns\_hostnames | Whether or not to enable DNS hostnames for the VPC | `bool` | `true` | no |
100 | | enable\_dns\_support | Whether or not to enable DNS support for the VPC | `bool` | `true` | no |
101 | | environment | Application environment for which this network is being created. e.g. Development/Production | `string` | `"Development"` | no |
102 | | logging\_bucket\_access\_control | Define ACL for Bucket from one of the [canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl): private, public-read, public-read-write, aws-exec-read, authenticated-read, log-delivery-write | `string` | `"private"` | no |
103 | | logging\_bucket\_encryption | Enable default bucket encryption. i.e. AES256 or aws:kms | `string` | `"AES256"` | no |
104 | | logging\_bucket\_encryption\_kms\_mster\_key | The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse\_algorithm as aws:kms. | `string` | `""` | no |
105 | | logging\_bucket\_force\_destroy | Whether all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable. ie. true | `bool` | `false` | no |
106 | | logging\_bucket\_name | Bucket name to store s3 flow logs. If empty, a random bucket name is generated. Use in conjuction with `build_s3_flow_logs` | `string` | `""` | no |
107 | | logging\_bucket\_prefix | The prefix for the location in the S3 bucket. If you don't specify a prefix, the access logs are stored in the root of the bucket. | `string` | `""` | no |
108 | | name | Name prefix for the VPC and related resources | `string` | n/a | yes |
109 | | private\_cidr\_ranges | An array of CIDR ranges to use for private subnets | `list(string)` | [
"172.18.16.0/22",
"172.18.20.0/22",
"172.18.24.0/22"
]
| no |
110 | | private\_subnet\_names | Text that will be included in generated name for private subnets. Given the default value of `["Private"]`, subnet
names in the form \"-Private\", e.g. \"MyVpc-Public2\" will be produced. Otherwise, given a
list of names with length the same as the value of `az_count`, the first `az_count` subnets will be named using
the first string in the list, the second `az_count` subnets will be named using the second string, and so on. | `list(string)` | [
"Private"
]
| no |
111 | | private\_subnet\_tags | A list of maps containing tags to be applied to private subnets. List should either be the same length as the number of AZs to apply different tags per set of subnets, or a length of 1 to apply the same tags across all private subnets. | `list(map(string))` | [
{}
]
| no |
112 | | private\_subnets\_per\_az | Number of private subnets to create in each AZ. NOTE: This value, when multiplied by the value of `az_count`,
should not exceed the length of the `private_cidr_ranges` list! | `number` | `1` | no |
113 | | public\_cidr\_ranges | An array of CIDR ranges to use for public subnets | `list(string)` | [
"172.18.0.0/22",
"172.18.4.0/22",
"172.18.8.0/22"
]
| no |
114 | | public\_subnet\_names | Text that will be included in generated name for public subnets. Given the default value of `["Public"]`, subnet
names in the form \"-Public\", e.g. \"MyVpc-Public1\" will be produced. Otherwise, given a
list of names with length the same as the value of `az_count`, the first `az_count` subnets will be named using
the first string in the list, the second `az_count` subnets will be named using the second string, and so on. | `list(string)` | [
"Public"
]
| no |
115 | | public\_subnet\_tags | A list of maps containing tags to be applied to public subnets. List should either be the same length as the number of AZs to apply different tags per set of subnets, or a length of 1 to apply the same tags across all public subnets. | `list(map(string))` | [
{}
]
| no |
116 | | public\_subnets\_per\_az | Number of public subnets to create in each AZ. NOTE: This value, when multiplied by the value of `az_count`,
should not exceed the length of the `public_cidr_ranges` list! | `number` | `1` | no |
117 | | s3\_flowlog\_retention | The number of days to retain flowlogs in s3. A value of `0` will retain indefinitely. | `number` | `14` | no |
118 | | single\_nat | Deploy VPC in single NAT mode. | `bool` | `false` | no |
119 | | spoke\_vpc | Whether or not the VPN gateway is a spoke of a Transit VPC | `bool` | `false` | no |
120 | | tags | Optional tags to be applied on top of the base tags on all resources | `map(string)` | `{}` | no |
121 |
122 | ## Outputs
123 |
124 | | Name | Description |
125 | |------|-------------|
126 | | default\_sg | The ID of the default SG for the VPC |
127 | | flowlog\_log\_group\_arn | The ARN of the flow log CloudWatch log group if one was created |
128 | | flowlog\_log\_group\_name | The name of the flow log CloudWatch log group if one was created |
129 | | internet\_gateway | The ID of the Internet Gateway |
130 | | nat\_gateway | The ID of the NAT Gateway if one was created |
131 | | nat\_gateway\_ids | The ID of the NAT Gateway if one was created |
132 | | nat\_gateway\_private\_ips | The private IPs of the NAT Gateway if one was created |
133 | | nat\_gateway\_public\_ips | The public IPs of the NAT Gateway if one was created |
134 | | private\_route\_tables | The IDs for the private route tables |
135 | | private\_subnets | The IDs for the private subnets |
136 | | public\_route\_tables | The IDs for the public route tables |
137 | | public\_subnets | The IDs of the public subnets |
138 | | vpc\_id | The ID of the VPC |
139 | | vpn\_gateway | The ID of the VPN gateway if one was created |
140 |
--------------------------------------------------------------------------------
/examples/basic_usage.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.0"
8 | }
9 | }
10 | }
11 |
12 | provider "aws" {
13 | region = "us-west-2"
14 | }
15 |
16 | module "vpc" {
17 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork//?ref=v0.12.9"
18 |
19 | name = "MyVPC"
20 | }
21 |
--------------------------------------------------------------------------------
/examples/custom_azs.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.0"
8 | }
9 | }
10 | }
11 |
12 | provider "aws" {
13 | region = "us-west-2"
14 | }
15 |
16 | module "vpc" {
17 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork//?ref=v0.12.9"
18 |
19 | name = "MyVPC"
20 | custom_azs = ["us-west-2a", "us-west-2b"]
21 |
22 | cidr_range = "10.0.0.0/19"
23 | public_cidr_ranges = ["10.0.4.0/22", "10.0.8.0/22"]
24 | public_subnets_per_az = 1
25 | private_cidr_ranges = ["10.0.12.0/22", "10.0.16.0/22"]
26 | private_subnets_per_az = 1
27 | }
28 |
--------------------------------------------------------------------------------
/examples/vpn_provided.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.13"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.0"
8 | }
9 | }
10 | }
11 |
12 | provider "aws" {
13 | region = "us-west-2"
14 | }
15 |
16 | module "vpc" {
17 | source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork//?ref=v0.12.9"
18 |
19 | name = "MyVPC"
20 | build_vpn = true
21 | spoke_vpc = true
22 | }
23 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | /**
2 | * # aws-terraform-vpc_basenetwork
3 | *
4 | * This module sets up basic network components for an account in a specific region. Optionally it will setup a basic VPN gateway and VPC flow logs.
5 | *
6 | * ## Basic Usage
7 | *
8 | * ```HCL
9 | * module "vpc" {
10 | * source = "git@github.com:rackspace-infrastructure-automation/aws-terraform-vpc_basenetwork//?ref=v0.12.2"
11 | *
12 | * vpc_name = "MyVPC"
13 | * }
14 | * ```
15 | *
16 | * Full working references are available at [examples](examples)
17 | * ## Default Resources
18 | *
19 | * By default only `vpc_name` is required to be set. Unless changed `aws_region` defaults to `us-west-2` and will need to be updated for other regions. `source` will also need to be declared depending on where the module lives. Given default settings the following resources are created:
20 | *
21 | * - VPC Flow Logs
22 | * - 2 AZs with public/private subnets from the list of 3 static CIDRs ranges available for each as defaults
23 | * - Public/private subnets with the count related to custom_azs if defined or region AZs automatically calculated by Terraform otherwise
24 | * - NAT Gateways will be created in each AZ's first public subnet
25 | * - EIPs will be created in all public subnets for NAT gateways to use
26 | * - Route Tables, including routes to NAT gateways if applicable
27 | *
28 | * ## Terraform 0.12 upgrade
29 | *
30 | * Several changes were required while adding terraform 0.12 compatibility. The following changes should be
31 | * made when upgrading from a previous release to version 0.12.0 or higher.
32 | *
33 | * ### Module variables
34 | *
35 | * The following module variables were updated to better meet current Rackspace style guides:
36 | *
37 | * - `custom_tags` -> `tags`
38 | * - `vpc_name` -> `name`
39 | */
40 |
41 | terraform {
42 | required_version = ">= 0.13"
43 |
44 | required_providers {
45 | aws = {
46 | source = "hashicorp/aws"
47 | version = ">= 4.0"
48 | }
49 | }
50 | }
51 |
52 | locals {
53 | default_domain_name = data.aws_region.current.name == "us-east-1" ? "ec2.internal" : format("%s.compute.internal", data.aws_region.current.name)
54 | domain_name = var.domain_name == "" ? local.default_domain_name : var.domain_name
55 |
56 | base_tags = {
57 | ServiceProvider = "Rackspace"
58 | Environment = var.environment
59 | }
60 |
61 | single_nat_tag = {
62 | true = {
63 | HA = "Disabled"
64 | }
65 |
66 | false = {}
67 | }
68 |
69 | nat_count = var.single_nat ? 1 : var.az_count
70 |
71 | tags = merge(
72 | var.tags,
73 | local.base_tags,
74 | )
75 |
76 | azs = slice(
77 | coalescelist(var.custom_azs, data.aws_availability_zones.available.names),
78 | 0,
79 | var.az_count,
80 | )
81 | }
82 |
83 | data "aws_availability_zones" "available" {}
84 |
85 | data "aws_region" "current" {}
86 |
87 | #############
88 | # Basic VPC
89 | #############
90 |
91 | resource "aws_vpc" "vpc" {
92 | cidr_block = var.cidr_range
93 | enable_dns_hostnames = var.enable_dns_hostnames
94 | enable_dns_support = var.enable_dns_support
95 | instance_tenancy = var.default_tenancy
96 |
97 | tags = merge(
98 | local.tags,
99 | local.single_nat_tag[var.single_nat],
100 | {
101 | Name = var.name
102 | },
103 | )
104 |
105 | lifecycle {
106 | create_before_destroy = true
107 | }
108 | }
109 |
110 | resource "aws_vpc_dhcp_options" "dhcp_options" {
111 | domain_name = local.domain_name
112 | domain_name_servers = var.domain_name_servers
113 |
114 | tags = merge(
115 | local.tags,
116 | {
117 | Name = "${var.name}-DHCPOptions"
118 | },
119 | )
120 | }
121 |
122 | resource "aws_vpc_dhcp_options_association" "dhcp_options_association" {
123 | dhcp_options_id = aws_vpc_dhcp_options.dhcp_options.id
124 | vpc_id = aws_vpc.vpc.id
125 | }
126 |
127 | resource "aws_internet_gateway" "igw" {
128 | count = var.build_igw ? 1 : 0
129 |
130 | vpc_id = aws_vpc.vpc.id
131 |
132 | tags = merge(
133 | local.tags,
134 | {
135 | Name = format("%s-IGW", var.name)
136 | },
137 | )
138 | }
139 |
140 | #############
141 | # NAT Gateway
142 | #############
143 |
144 | resource "aws_eip" "nat_eip" {
145 | count = var.build_nat_gateways && var.build_igw ? local.nat_count : 0
146 |
147 | domain = "vpc"
148 |
149 | tags = merge(
150 | local.tags,
151 | {
152 | Name = format("%s-NATEIP%d", var.name, count.index + 1)
153 | },
154 | )
155 |
156 | depends_on = [aws_internet_gateway.igw]
157 | }
158 |
159 | resource "aws_nat_gateway" "nat" {
160 | count = var.build_nat_gateways && var.build_igw ? local.nat_count : 0
161 |
162 | allocation_id = element(aws_eip.nat_eip.*.id, count.index)
163 | subnet_id = element(aws_subnet.public_subnet.*.id, count.index)
164 |
165 | tags = merge(
166 | local.tags,
167 | local.single_nat_tag[var.single_nat],
168 | {
169 | Name = format("%s-NATGW%d", var.name, count.index + 1)
170 | },
171 | )
172 |
173 | depends_on = [aws_internet_gateway.igw]
174 | }
175 |
176 | #############
177 | # Subnets
178 | #############
179 |
180 | resource "aws_subnet" "public_subnet" {
181 | count = var.build_igw ? var.az_count * var.public_subnets_per_az : 0
182 |
183 | availability_zone = element(local.azs, count.index)
184 | cidr_block = var.public_cidr_ranges[count.index]
185 | map_public_ip_on_launch = true
186 | vpc_id = aws_vpc.vpc.id
187 |
188 | tags = merge(
189 | var.public_subnet_tags[length(var.public_subnet_tags) == 1 ? 0 : floor(count.index / var.az_count)],
190 | local.tags,
191 | local.single_nat_tag[var.single_nat],
192 | {
193 | Name = format(
194 | "%s-%s%d",
195 | var.name,
196 | element(var.public_subnet_names, floor(count.index / var.az_count)),
197 | count.index % var.az_count + 1,
198 | )
199 | },
200 | )
201 | }
202 |
203 | resource "aws_subnet" "private_subnet" {
204 | count = var.az_count * var.private_subnets_per_az
205 |
206 | availability_zone = element(local.azs, count.index)
207 | cidr_block = var.private_cidr_ranges[count.index]
208 | map_public_ip_on_launch = false
209 | vpc_id = aws_vpc.vpc.id
210 |
211 | tags = merge(
212 | var.private_subnet_tags[length(var.private_subnet_tags) == 1 ? 0 : floor(count.index / var.az_count)],
213 | local.tags,
214 | local.single_nat_tag[var.single_nat],
215 | {
216 | Name = format(
217 | "%s-%s%d",
218 | var.name,
219 | element(var.private_subnet_names, floor(count.index / var.az_count)),
220 | count.index % var.az_count + 1,
221 | )
222 | },
223 | )
224 | }
225 |
226 | #########################
227 | # Route Tables and Routes
228 | #########################
229 |
230 | resource "aws_route_table" "public_route_table" {
231 | count = var.build_igw ? 1 : 0
232 |
233 | vpc_id = aws_vpc.vpc.id
234 |
235 | tags = merge(
236 | local.tags,
237 | {
238 | Name = format("%s-PublicRouteTable", var.name)
239 | },
240 | )
241 | }
242 |
243 | resource "aws_route_table" "private_route_table" {
244 | count = var.az_count
245 |
246 | vpc_id = aws_vpc.vpc.id
247 |
248 | tags = merge(
249 | local.tags,
250 | local.single_nat_tag[var.single_nat],
251 | {
252 | Name = format("%s-PrivateRouteTable%d", var.name, count.index + 1)
253 | },
254 | )
255 | }
256 |
257 | resource "aws_route" "public_routes" {
258 | count = var.build_igw ? 1 : 0
259 |
260 | destination_cidr_block = "0.0.0.0/0"
261 | gateway_id = aws_internet_gateway.igw[0].id
262 | route_table_id = aws_route_table.public_route_table[0].id
263 | }
264 |
265 | resource "aws_route" "private_routes" {
266 | count = var.build_nat_gateways && var.build_igw ? var.az_count : 0
267 |
268 | destination_cidr_block = "0.0.0.0/0"
269 | nat_gateway_id = element(aws_nat_gateway.nat.*.id, count.index)
270 | route_table_id = element(aws_route_table.private_route_table.*.id, count.index)
271 | }
272 |
273 | resource "aws_route_table_association" "public_route_association" {
274 | count = var.build_igw ? var.az_count * var.public_subnets_per_az : 0
275 |
276 | route_table_id = aws_route_table.public_route_table[0].id
277 | subnet_id = element(aws_subnet.public_subnet.*.id, count.index)
278 | }
279 |
280 | resource "aws_route_table_association" "private_route_association" {
281 | count = var.az_count * var.private_subnets_per_az
282 |
283 | route_table_id = element(aws_route_table.private_route_table.*.id, count.index)
284 | subnet_id = element(aws_subnet.private_subnet.*.id, count.index)
285 | }
286 |
287 | #####
288 | # VPN
289 | #####
290 |
291 | resource "aws_vpn_gateway" "vpn_gateway" {
292 | count = var.build_vpn ? 1 : 0
293 |
294 | vpc_id = aws_vpc.vpc.id
295 |
296 | tags = merge(
297 | local.tags,
298 | {
299 | Name = format("%s-VPNGateway", var.name)
300 | "transitvpc:spoke" = var.spoke_vpc
301 | },
302 | )
303 | }
304 |
305 | resource "aws_vpn_gateway_route_propagation" "vpn_routes_public" {
306 | count = var.build_vpn ? 1 : 0
307 |
308 | route_table_id = aws_route_table.public_route_table[0].id
309 | vpn_gateway_id = aws_vpn_gateway.vpn_gateway[0].id
310 | }
311 |
312 | resource "aws_vpn_gateway_route_propagation" "vpn_routes_private" {
313 | count = var.build_vpn ? length(var.private_cidr_ranges) : 0
314 |
315 | route_table_id = element(aws_route_table.private_route_table.*.id, count.index)
316 | vpn_gateway_id = aws_vpn_gateway.vpn_gateway[0].id
317 | }
318 |
319 | ###########
320 | # Flow Logs
321 | ###########
322 |
323 | resource "aws_flow_log" "s3_vpc_log" {
324 | count = var.build_s3_flow_logs ? 1 : 0
325 |
326 | log_destination = aws_s3_bucket.vpc_log_bucket[0].arn
327 | log_destination_type = "s3"
328 | traffic_type = "ALL"
329 | vpc_id = aws_vpc.vpc.id
330 | }
331 |
332 | resource "aws_s3_bucket" "vpc_log_bucket" {
333 | count = var.build_s3_flow_logs ? 1 : 0
334 |
335 | bucket = var.logging_bucket_name
336 | force_destroy = var.logging_bucket_force_destroy
337 | tags = local.tags
338 |
339 | }
340 |
341 | resource "aws_s3_bucket_acl" "private_acl" {
342 | count = var.build_s3_flow_logs ? 1 : 0
343 |
344 | bucket = aws_s3_bucket.vpc_log_bucket[count.index]
345 | acl = var.logging_bucket_access_control
346 | }
347 |
348 | resource "aws_s3_bucket_server_side_encryption_configuration" "s3_sse" {
349 | count = var.build_s3_flow_logs ? 1 : 0
350 |
351 | bucket = aws_s3_bucket.vpc_log_bucket[count.index]
352 | rule {
353 | apply_server_side_encryption_by_default {
354 | kms_master_key_id = var.logging_bucket_encryption_kms_mster_key
355 | sse_algorithm = var.logging_bucket_encryption
356 | }
357 | }
358 | }
359 |
360 | resource "aws_s3_bucket_lifecycle_configuration" "s3_lifecycle" {
361 | count = var.build_s3_flow_logs ? 1 : 0
362 |
363 | bucket = aws_s3_bucket.vpc_log_bucket[count.index]
364 | rule {
365 | id = "Expiration"
366 | status = "Enabled"
367 | prefix = var.logging_bucket_prefix
368 | expiration {
369 | days = var.s3_flowlog_retention
370 | }
371 | }
372 | }
373 |
374 | resource "aws_flow_log" "cw_vpc_log" {
375 | count = var.build_flow_logs ? 1 : 0
376 |
377 | iam_role_arn = aws_iam_role.flowlog_role[0].arn
378 | log_destination = aws_cloudwatch_log_group.flowlog_group[0].arn
379 | traffic_type = "ALL"
380 | vpc_id = aws_vpc.vpc.id
381 | }
382 |
383 | resource "aws_cloudwatch_log_group" "flowlog_group" {
384 | count = var.build_flow_logs ? 1 : 0
385 |
386 | name = "${var.name}-FlowLogs"
387 | retention_in_days = var.cloudwatch_flowlog_retention
388 | }
389 |
390 | resource "aws_iam_role" "flowlog_role" {
391 | count = var.build_flow_logs ? 1 : 0
392 |
393 | name = "${var.name}-FlowLogsRole"
394 |
395 | assume_role_policy = <-Private\", e.g. \"MyVpc-Public2\" will be produced. Otherwise, given a
147 | list of names with length the same as the value of `az_count`, the first `az_count` subnets will be named using
148 | the first string in the list, the second `az_count` subnets will be named using the second string, and so on.
149 | EOF
150 |
151 | type = list(string)
152 | default = ["Private"]
153 | }
154 |
155 | variable "private_subnet_tags" {
156 | description = "A list of maps containing tags to be applied to private subnets. List should either be the same length as the number of AZs to apply different tags per set of subnets, or a length of 1 to apply the same tags across all private subnets."
157 | type = list(map(string))
158 |
159 | default = [{}]
160 | }
161 |
162 | variable "private_subnets_per_az" {
163 | description = <-Public\", e.g. \"MyVpc-Public1\" will be produced. Otherwise, given a
187 | list of names with length the same as the value of `az_count`, the first `az_count` subnets will be named using
188 | the first string in the list, the second `az_count` subnets will be named using the second string, and so on.
189 | EOF
190 |
191 | type = list(string)
192 | default = ["Public"]
193 | }
194 |
195 | variable "public_subnet_tags" {
196 | description = "A list of maps containing tags to be applied to public subnets. List should either be the same length as the number of AZs to apply different tags per set of subnets, or a length of 1 to apply the same tags across all public subnets."
197 | type = list(map(string))
198 |
199 | default = [{}]
200 | }
201 |
202 | variable "public_subnets_per_az" {
203 | description = <