├── .circleci └── config.yml ├── .env.docker ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Rakefile ├── az ├── main.tf ├── outputs.tf └── variables.tf ├── base ├── main.tf ├── outputs.tf └── variables.tf ├── bin ├── .covalence │ └── launcher └── covalence ├── covalence.yaml ├── data ├── environments.yaml ├── globals.yaml └── stacks │ ├── base-options.yaml │ ├── common.yaml │ ├── defaults.yaml │ ├── no-lan.yaml │ ├── overrides.yaml │ ├── peer-connect.yaml │ ├── peer-vpc.yaml │ └── vpg-attach.yaml ├── dhcp ├── main.tf ├── outputs.tf └── variables.tf ├── examples ├── basic │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── complete │ ├── main.tf │ ├── outputs.tf │ └── variables.tf └── peering │ ├── main.tf │ └── variables.tf ├── peer ├── main.tf ├── outputs.tf └── variables.tf └── vpg ├── main.tf ├── outputs.tf └── variables.tf /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | common: &common 2 | working_directory: ~/repo 3 | 4 | docker: 5 | - image: unifio/ci:3.0.411-ruby-2.4 6 | 7 | environment: 8 | AWS_REGION: 'us-east-2' 9 | TF_PLUGIN_CACHE_DIR: '/root/.terraform.d/plugin-cache' 10 | 11 | version: 2 12 | 13 | jobs: 14 | build: 15 | <<: *common 16 | 17 | steps: 18 | - checkout 19 | 20 | - run: 21 | name: Verify 22 | environment: 23 | CI_REPORTS: 'reports' 24 | COVALENCE_TEST_ENVS: 'basic,complete' 25 | command: | 26 | mkdir reports 27 | bundle exec rake ci 28 | 29 | - store_test_results: 30 | path: reports 31 | 32 | basic: 33 | <<: *common 34 | 35 | steps: 36 | - checkout 37 | 38 | - run: 39 | name: Test DMZ only configuration 40 | command: bundle exec rake basic:no-lan:apply 41 | 42 | - run: 43 | name: Test defaults 44 | command: | 45 | bundle exec rake basic:defaults:apply 46 | bundle exec rake basic:defaults:destroy 47 | 48 | - run: 49 | name: Test some base module options and expand to 3 AZs 50 | command: | 51 | bundle exec rake basic:base-options:apply 52 | 53 | - run: 54 | name: Test VPN gateway attachment 55 | command: | 56 | bundle exec rake basic:vpg-attach:apply 57 | bundle exec rake basic:vpg-attach:destroy 58 | 59 | - run: 60 | name: Clean up 61 | when: always 62 | command: | 63 | bundle exec rake basic:destroy 64 | 65 | complete: 66 | <<: *common 67 | 68 | steps: 69 | - checkout 70 | 71 | - run: 72 | name: Test more options and overrides 73 | command: | 74 | bundle exec rake complete:overrides:apply || true 75 | # Need to run twice due to frequent timing issues 76 | # see https://github.com/unifio/terraform-aws-vpc/issues/39 77 | bundle exec rake complete:overrides:apply 78 | 79 | - run: 80 | name: Test peering connection 81 | command: | 82 | bundle exec rake complete:peer-vpc:apply || true 83 | # Need to run twice due to frequent timing issues 84 | # see https://github.com/unifio/terraform-aws-vpc/issues/39 85 | bundle exec rake complete:peer-vpc:apply 86 | bundle exec rake peering:peer-connect:apply 87 | 88 | - run: 89 | name: Clean up 90 | when: always 91 | command: | 92 | bundle exec rake peering:destroy || true 93 | bundle exec rake complete:destroy 94 | 95 | workflows: 96 | version: 2 97 | 98 | vpc_module: 99 | jobs: 100 | - build 101 | - basic: 102 | requires: 103 | - build 104 | - complete: 105 | requires: 106 | - build 107 | -------------------------------------------------------------------------------- /.env.docker: -------------------------------------------------------------------------------- 1 | AWS_REGION=us-east-2 2 | CI_REPORTS=reports 3 | COVALENCE_TEST_ENVS=basic,complete 4 | CHECKPOINT_DISABLE=1 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tfstate* 2 | .terraform/ 3 | .env 4 | reports/** 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.renderWhitespace": "all", 3 | "files.associations": { 4 | "*.tpl": "hcl", 5 | "*.tf" : "terraform" 6 | }, 7 | "files.insertFinalNewline": true, 8 | "files.trimTrailingWhitespace": true, 9 | "terraform.formatOnSave": true 10 | } 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #### Consider Implementing: 2 | * full ipv6 support 3 | * vpc endpoints 4 | 5 | ## 0.3.6 (Jul 11, 2018) 6 | 7 | #### BUG FIXES: 8 | * Resolved [issue](https://github.com/unifio/terraform-aws-vpc/issues/32) caused by [terraform-provider-aws v1.25.0](https://github.com/terraform-providers/terraform-provider-aws/issues/2514). Addressed by adding a default `instance_tenancy` when one isn't supplied using a local variable. 9 | 10 | ## 0.3.5 (March 11, 2018) 11 | 12 | #### IMPROVEMENTS / NEW FEATURES: 13 | * Updated CI configuration to more reliably handle Terraform / AWS timing issues. 14 | * Added security group rule descriptions. 15 | 16 | #### BUG FIXES: 17 | * Updated az module to properly handle 0 private subnets. 18 | 19 | ## 0.3.4 (March 7, 2018) 20 | 21 | #### BACKWARDS INCOMPATIBILITIES / NOTES: 22 | * Terraform versions earlier than 0.11.0 no longer supported. 23 | * The following input variable have been changed: 24 | * az module 25 | * `dmz_cidrs` -> `dmz_cidrs_override` 26 | * `lan_cidrs` -> `lan_cidrs_override` 27 | 28 | #### IMPROVEMENTS / NEW FEATURES: 29 | * Added support for the `enable_classiclink_dns_support` parameter on the vpc resource. 30 | * Added support for the `assign_generated_ipv6_cidr_block` parameter on the vpc resource. Full ipv6 support coming in the next update. 31 | * Introduced local variables into the `az` module to better document formulation for default options. 32 | 33 | #### BUG FIXES: 34 | * Updated DHCP module outputs to suppress warnings in Terraform 0.11.0+ 35 | 36 | ## 0.3.3 (November 13, 2017) 37 | 38 | #### IMPROVEMENTS / NEW FEATURES: 39 | * Add 'enable' flag for DHCP. Default is true. This allows for stacks to include these based on variable since at this time you cannot conditionally include modules. 40 | 41 | ## 0.3.2 (May 16, 2017) 42 | 43 | #### BACKWARDS INCOMPATIBILITIES / NOTES: 44 | * The following output variables have been changed: 45 | * az module 46 | * `dmz_cidrs (string)` -> `dmz_cidrs (list)` 47 | * `dmz_ids (string)` -> `dmz_ids (list)` 48 | * `eip_nat_ids (string)` -> `eip_nat_ids (list)` 49 | * `eip_nat_ips (string)` -> `eip_nat_ips (list)` 50 | * `lan_ids (string)` -> `lan_ids (list)` 51 | * `lan_cidrs (string)` -> `lan_cidrs (list)` 52 | * `nat_ids (string)` -> `nat_ids (list)` 53 | * `rt_lan_ids (string)` -> `rt_lan_ids (list)` 54 | * The following input variable have been changed: 55 | * az module 56 | * `stack_item_fullname` now defaults to a value of `VPC Quick Start` 57 | * `stack_item_label` now defaults to a value of `qckstrt` 58 | 59 | ## 0.3.1 (April 23, 2017) 60 | 61 | #### IMPROVEMENTS / NEW FEATURES: 62 | * DHCP defaults are now more minimal and do not set values for all parameters. 63 | 64 | ## 0.3.0 (April 3, 2017) 65 | 66 | #### BACKWARDS INCOMPATIBILITIES / NOTES: 67 | * Enabled complex variable types, which are only supported in Terraform 0.7.0 and newer. 68 | * The following input variables have been removed 69 | * peer module 70 | * `multi_acct` 71 | * The following input variables have been changed: 72 | * az module 73 | * `az (string, required)` -> `azs (list, optional)` 74 | * `dmz_cidr (string, required)` -> `dmz_cidrs (list, optional)` 75 | * `lan_cidr (string, required)` -> `lan_cidrs (list, optional)` 76 | * `vgw_ids (string, optional` - > `vgw_ids (list, optional)` 77 | * dhcp module 78 | * `name_servers (string, optional)` -> `name_servers (list, optional)` 79 | * `netbios_name_servers (string, optional)` -> `netbios_name_servers (list, optional)` 80 | * `ntp_servers (string, optional)` -> `ntp_servers (list, optional)` 81 | * peer module 82 | * `peer_owner_id (string, required)` -> `accepter_owner_id (string, optional)` 83 | * `peer_vpc_id (string, required)` -> `accepter_vpc_id (string, optional)` 84 | * `vpc_id (string, required)` -> `requester_vpc_id (string, optional)` 85 | * The following output variables have been changed: 86 | * az module 87 | * `dmz_cidr (string)` -> `dmz_cidrs (string)` 88 | * `dmz_id (string)` -> `dmz_ids (string)` 89 | * `eip_nat_id (string)` -> `eip_nat_ids (string)` 90 | * `eip_nat_ip (string)` -> `eip_nat_ips (string)` 91 | * `lan_id (string)` -> `lan_ids (string)` 92 | * `lan_cidr (string)` -> `lan_cidrs (string)` 93 | * `nat_id (string)` -> `nat_ids (string)` 94 | * base module 95 | * `dmz_subnet_id (string)` -> `dmz_subnet_ids (string)` 96 | * `lan_subnet_id (string)` -> `lan_subnet_ids (string)` 97 | * `lan_rt_id (string)` -> `lan_rt_ids (string)` 98 | 99 | #### IMPROVEMENTS / NEW FEATURES: 100 | * Added conditional support for the following parameters: 101 | * az module 102 | * `azs` 103 | * `dmz_cidrs` 104 | * `enable_dmz_public_ips` 105 | * `nat_key_name` 106 | * base module 107 | * `enable_classiclink` 108 | * `enable_dns` 109 | * `enable_hostnames` 110 | * `instance_tenancy` 111 | * peer module 112 | * `accepter_allow_clasic_link_to_remote` 113 | * `accepter_allow_to_remote_classic_link` 114 | * `accepter_auto_accept` 115 | * `requester_allow_clasic_link_to_remote` 116 | * `requester_allow_to_remote_classic_link` 117 | * vpg module 118 | * `availability_zone` 119 | 120 | * Added support for AZ auto-provisioning. 121 | * Re-enabled support for EC2 based NATs. 122 | * Added conditional support for EIPs with EC2 based NATs. 123 | 124 | ## 0.2.5 (October 7, 2016) 125 | 126 | #### BACKWARDS INCOMPATIBILITIES / NOTES: 127 | * Unattached VPN gateways created by previous versions of this module will be destroyed and recreated on update due to changes in resource naming. 128 | * This module has been verified for compatiblity with Terraform 0.7.5. 129 | 130 | #### FEATURES: 131 | * Added support for establishing VPC peering connections. 132 | 133 | #### BUG FIXES: 134 | * Resolved issue where changing the attached status of a VPN gateway would result in the resource being destroyed and recreated. 135 | 136 | ## 0.2.4 (June 24, 2016) 137 | 138 | #### IMPROVEMENTS: 139 | * Added NAT gateway public IP to the AZ module outputs. 140 | 141 | ## 0.2.3 (June 8, 2016) 142 | 143 | #### IMPROVEMENTS: 144 | * Added support for VGW route propagation for routing tables. 145 | * Added support for VPG creation without VPC attachment. Necessary to avoid chicken-and-egg scenario when configuring VPC for VPG route propagation. 146 | 147 | ## 0.2.2 (June 2, 2016) 148 | 149 | #### IMPROVEMENTS: 150 | * Verified with Terraform v0.6.16. 151 | 152 | ## 0.2.1 (May 16, 2016) 153 | 154 | #### FEATURES: 155 | * Exposed subnet CIDR blocks as AZ module outputs. 156 | 157 | #### IMPROVEMENTS: 158 | * Verified with Terraform v0.6.15. 159 | * Updated formatting to HashiCorp standard. 160 | * Expanded examples to include new VPC resources. 161 | 162 | ## 0.2.0 (Apr 20, 2016) 163 | 164 | #### FEATURES: 165 | * Added support for configuring instance tenancy. 166 | * Added support for enabling ClassicLink. 167 | 168 | #### IMPROVEMENTS: 169 | * Verified with Terraform v0.6.14. 170 | * Migrated NAT features to VPC NAT gateway. 171 | 172 | ## 0.1.1 (Dec 1, 2015) 173 | 174 | #### FEATURES: 175 | * Added support for assigning Elastic IP address to each NAT instance. 176 | * Added support for disabling the provisioning of NAT instances [GH-3] 177 | * Added support for auto-recovery of NAT instances 178 | * Added support for VPC flow logs [GH-1] 179 | 180 | #### IMPROVEMENTS: 181 | * Updated template_file usage for 0.6.7 to remove deprecation warnings [GH-10] 182 | * Replaced user_data template and parameters with generic user_data param. 183 | 184 | ## 0.1.0 (Oct 21, 2015) 185 | 186 | * Initial Release 187 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform AWS VPC Stack # 2 | [![Circle CI](https://circleci.com/gh/unifio/terraform-aws-vpc/tree/master.svg?style=svg)](https://circleci.com/gh/unifio/terraform-aws-vpc/tree/master) 3 | 4 | Terraform module for deployment and management of an AWS Virtual Private Cloud (VPC) and related resources. 5 | 6 | This module is well suited to both basic and advanced use cases with very few required inputs, but the ability to configure just about every feature available. 7 | 8 | ## Requirements ## 9 | 10 | - Terraform 0.11.0 or newer 11 | - AWS provider 12 | 13 | ## Quick Start 14 | 15 | The following code will yield a fully functioning VPC environment: 16 | 17 | ```js 18 | module "vpc_base" { 19 | source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 20 | } 21 | 22 | module "az" { 23 | source = "github.com/unifio/terraform-aws-vpc?ref=master//az" 24 | 25 | vpc_id = "${module.vpc_base.vpc_id}" 26 | } 27 | ``` 28 | 29 | ## Base Module ## 30 | 31 | The Base module provisions the VPC, Internet Gateway and DMZ routing table. It additionally enables flow log capture over the entire VPC. 32 | 33 | ### Input Variables ### 34 | 35 | Name | Type | Required | Description 36 | --- | --- | --- | --- 37 | `enable_classiclink` | string | Default: `false` | Specifies whether ClassicLink is enabled for the VPC. 38 | `enable_dns` | string | Default: `true` | Specifies whether DNS resolution is supported for the VPC. 39 | `enable_hostnames` | string | Default: `true` | Specifies whether the instances launched in the VPC get DNS hostnames. 40 | `flow_log_traffic_type` | string | Default: `ALL` | The type of traffic to capture. Valid values: ACCEPT,REJECT,ALL. 41 | `instance_tenancy` | string | Default: `default` | The allowed tenancy of instances launched into the VPC. Other options at this time are `dedicated` and `host`. These will both force any instance launched into the VPC to be dedicated, regardless of the tenancy option specified when the instance is launched. See [EC2 Dedicated Instance Doc](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) for more information. 42 | `stack_item_label` | string | Default: `qckstrt` | Short form identifier for this stack. This value is used to create the "Name" tag for resources created by this stack item, and also serves as a unique key for re-use. 43 | `stack_item_fullname` | string | Default: `VPC Quick Start` | Long form descriptive name for this stack item. This value is used to create the "application" tag for resources created by this stack item. 44 | `vpc_cidr` | string | Default: `172.16.0.0/21` | The CIDR block you want the VPC to cover. 45 | `vgw_ids` | string | | A list of virtual gateways to associate with the routing tables for route propagation. 46 | 47 | ### Usage ### 48 | 49 | ```js 50 | module "vpc_base" { 51 | source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 52 | 53 | enable_dns = "true" 54 | enable_hostnames = "false" 55 | stack_item_fullname = "My Stack" 56 | stack_item_label = "mystack" 57 | vpc_cidr = "172.16.0.0/21" 58 | } 59 | ``` 60 | 61 | ### Outputs ### 62 | 63 | Name | Type | Description 64 | --- | --- | --- 65 | `flow_log_id` | string | ID of the AWS flow log. 66 | `igw_id` | string | ID of the Internet gateway. 67 | `rt_dmz_id` | string | ID of the DMZ routing table. 68 | `vpc_id` | string | ID of the VPC. 69 | 70 | ## DHCP module ## 71 | 72 | The DHCP module provisions a DHCP options resource and associates it with the specified VPC resource. 73 | 74 | ### Input Variables ### 75 | 76 | Name | Type | Required | Description 77 | --- | --- | --- | --- 78 | `domain_name` | string | | The suffix domain name to use by default when resolving non Fully Qualified Domain Names. In other words, this is what ends up being the search value in the /etc/resolv.conf file. 79 | `name_servers` | list | Default: `["AmazonProvidedDNS"]` | List of name servers to configure in /etc/resolv.conf. 80 | `netbios_name_servers` | list | | List of NETBIOS name servers. 81 | `netbios_node_type` | string | | The NetBIOS node type (1, 2, 4, or 8). AWS recommends to specify 2 since broadcast and multicast are not supported in their network. For more information about these node types, see RFC 2132. 82 | `ntp_servers` | list | | List of NTP servers to configure. 83 | `stack_item_fullname` | string | yes | Long form descriptive name for this stack item. This value is used to create the "application" tag for resources created by this stack item. 84 | `stack_item_label` | string | yes | Short form identifier for this stack. This value is used to create the "Name" tag for resources created by this stack item, and also serves as a unique key for re-use. 85 | `vpc_id` | string | yes | ID of the VPC to associate the DHCP Options Set with. 86 | 87 | ### Usage ### 88 | 89 | ```js 90 | module "vpc_base" { 91 | source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 92 | } 93 | 94 | module "dhcp" { 95 | source = "github.com/unifio/terraform-aws-vpc?ref=master//dhcp" 96 | 97 | domain_name = "mydomain.com" 98 | name_servers = ["172.16.0.2"] 99 | netbios_name_servers = ["172.16.0.2"] 100 | netbios_node_type = 2 101 | ntp_servers = ["172.16.0.2"] 102 | stack_item_fullname = "My Stack" 103 | stack_item_label = "mystack" 104 | vpc_id = "${module.vpc_base.vpc_id}" 105 | } 106 | ``` 107 | 108 | ### Outputs ### 109 | 110 | Name | Type | Description 111 | --- | --- | --- 112 | `dhcp_id` | string | ID of the DHCP Options set. 113 | 114 | ## VPG Module ## 115 | 116 | Creates a VPC VPN Gateway 117 | 118 | ### Input Variables 119 | 120 | Name | Type | Required | Description 121 | --- | --- | --- | --- 122 | `stack_item_fullname` | string | yes | Long form descriptive name for this stack item. This value is used to create the "application" tag for resources created by this stack item. 123 | `stack_item_label` | string | yes | Short form identifier for this stack. This value is used to create the "Name" tag for resources created by this stack item, and also serves as a unique key for re-use. 124 | `vpc_attach` | string | | Specifies whether the VPN gateway should be associated with a VPC. 125 | `vpc_id` | string | | The VPC to associate the VPN gateway with. 126 | 127 | ### Usage 128 | 129 | ```js 130 | module "vpc_base" { 131 | source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 132 | } 133 | 134 | module "vpg" { 135 | source = "github.com/unifio/terraform-aws-vpc?ref=master//vpg" 136 | 137 | stack_item_fullname = "My Stack" 138 | stack_item_label = "mystack" 139 | vpc_attach = "true" 140 | vpc_id = "${module.vpc_base.vpc_id}" 141 | } 142 | ``` 143 | 144 | ### Outputs ### 145 | 146 | Name | Type | Description 147 | --- | --- | --- 148 | `vpg_id` | string | ID of the newly created VPN Gateway. 149 | 150 | ## AZ Module ## 151 | 152 | The AZ module provisions subnets, routing tables and NATing. It has support for both Internet facing and private subnets, static and dynamic routing (VPN propagation) as well as gateway or EC2 based NATing. It will handle basic CIDR calculations for up to 4 availability zones and 2 private subnets per availability zone. All parameters are overidable for more advanced configurations. 153 | 154 | ### Input Variables ### 155 | 156 | Name | Type | Required | Description 157 | --- | --- | --- | --- 158 | `azs_provisioned` | string | Default: `2` | The number of availability zones to be provisioned. Either this or **azs\_provisioned\_override** must be specified. Auto-provisioning will support up to 4 AZs without the need for overrides. 159 | `azs_provisioned_override` | list | | List of availability zone letters to be provisioned. Useful in regions where not all AZs are VPC ready. Either this or **azs_provisioned** must be specified. 160 | `dmz_cidrs_override` | list | | The CIDR block(s) you want the public subnet(s) to cover. 161 | `enable_dmz_public_ips` | string | | Specify true to indicate that instances launched into the DMZ subnet should be assigned a public IP address. 162 | `lan_cidrs_override` | list | | The CIDR block(s) you want the LAN subnet(s) to cover. 163 | `lans_per_az` | string | Default: `1` | The number of private subnets to be provisioned per AZ. Auto-provisioning will support up to 2 private subnets per AZ without the need for overrides. 164 | `nat_ami_override` | string | | Custom NAT Amazon Machine Image (AMI). 165 | `nat_eips_enabled` | string | Default: `false` | Flag for specifying allocation of Elastic IPs to NATs for the purposes of whitelisting. This value is overriden to `true` when utilizing NAT gateways. 166 | `nat_gateways_enabled` | string | Default: `false` | Flag for specifying utilization of managed NAT gateways over EC2 based NAT instances. 167 | `nat_instance_type` | string | Default: `t2.nano` | NAT EC2 instance type. 168 | `nat_key_name` | string | | Name of the EC2 key pair to install on EC2 based NAT instances. 169 | `rt_dmz_id` | string | yes | The ID of the DMZ routing table. 170 | `stack_item_fullname` | string | Default: `VPC Quick Start` | Long form descriptive name for this stack item. This value is used to create the "application" tag for resources created by this stack item. 171 | `stack_item_label` | string | Default: `qckstrt` | Short form identifier for this stack. This value is used to create the "Name" tag for resources created by this stack item, and also serves as a unique key for re-use. 172 | `vgw_ids` | list | | A list of virtual gateways to associate with the routing tables for route propagation. 173 | `vpc_id` | string | yes | ID of the VPC. 174 | 175 | ### Usage ### 176 | 177 | ```js 178 | module "vpc_base" { 179 | source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 180 | } 181 | 182 | module "az" { 183 | source = "github.com/unifio/terraform-aws-vpc?ref=master//az" 184 | 185 | azs_provisioned = 2 186 | enable_dmz_public_ips = "true" 187 | rt_dmz_id = "${module.vpc_base.rt_dmz_id}" 188 | stack_item_fullname = "My Stack" 189 | stack_item_label = "mystck" 190 | vgw_ids = "${aws_vpn_gateway.vpg.id}" 191 | vpc_id = "${module.vpc_base.vpc_id}" 192 | } 193 | ``` 194 | 195 | ### Outputs ### 196 | 197 | ** The order and association of the IDs match the order of the availability zones passed to the module. 198 | 199 | Name | Type | Description 200 | --- | --- | --- 201 | `dmz_ids` | list | List of subnet IDs of the DMZ subnetworks. 202 | `lan_ids` | list | List of subnet IDs of the LAN subnetworks. 203 | `dmz_cidrs` | list | List of subnet CIDR blocks of the DMZ subnetworks. 204 | `lan_cidrs` | list | List of subnet CIDR blocks of the LAN subnetworks. 205 | `eip_nat_ids` | list | List of Elastic IP IDs for each of the NAT gateways. 206 | `nat_ids` | list | List of NAT gateways IDs. 207 | `eip_nat_ips` | list | List of NAT gateway public IPs. 208 | `rt_lan_ids` | list | List of routing table IDs for the LAN subnets. 209 | 210 | ## Peer Module ## 211 | 212 | Creates a VPC peering connection 213 | 214 | ### Input Variables 215 | 216 | Name | Type | Required | Description 217 | --- | --- | --- | --- 218 | `accepter_allow_classic_link_to_remote` | string | | Allow a local linked EC2-Classic instance to communicate with instances in a peer VPC. This enables an outbound communication from the local ClassicLink connection to the remote VPC. 219 | `accepter_allow_remote_dns` | string | Default: `false` | Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC. 220 | `accepter_allow_to_remote_classic_link` | string | | Allow a local VPC to communicate with a linked EC2-Classic instance in a peer VPC. This enables an outbound communication from the local VPC to the remote ClassicLink connection. 221 | `accepter_auto_accept` | string | | Accept the peering (both VPCs need to be in the same AWS account). 222 | `accepter_owner_id` | string | | The AWS account ID of the owner of the peer VPC. 223 | `accepter_vpc_id` | string | | The ID of the VPC with which you are creating the VPC Peering Connection. 224 | `requester_allow_classic_link_to_remote` | string | | Allow a local linked EC2-Classic instance to communicate with instances in a peer VPC. This enables an outbound communication from the local ClassicLink connection to the remote VPC. 225 | `requester_allow_remote_dns` | string | Default: `false` | Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC. 226 | `requester_allow_to_remote_classic_link` | string | | Allow a local VPC to communicate with a linked EC2-Classic instance in a peer VPC. This enables an outbound communication from the local VPC to the remote ClassicLink connection. 227 | `requester_vpc_id` | string | | The ID of the requester VPC. 228 | `stack_item_fullname` | string | yes | Long form descriptive name for this stack item. This value is used to create the "application" tag for resources created by this stack item. 229 | `stack_item_label` | string | yes | Short form identifier for this stack. This value is used to create the "Name" tag for resources created by this stack item, and also serves as a unique key for re-use. 230 | 231 | ### Usage 232 | 233 | ```js 234 | module "vpc_peer" { 235 | source = "github.com/unifio/terraform-aws-vpc?ref=master//peer" 236 | 237 | accepter_allow_remote_dns = "false" 238 | accepter_owner_id = "${var.peer_owner_id}" 239 | accepter_vpc_id = "${var.peer_vpc_id}" 240 | requester_allow_remote_dns = "true" 241 | requester_vpc_id = "${var.owner_vpc_id}" 242 | stack_item_fullname = "${var.stack_item_fullname}" 243 | stack_item_label = "${var.stack_item_label}" 244 | } 245 | ``` 246 | 247 | ### Outputs ### 248 | 249 | Name | Type | Description 250 | --- | --- | --- 251 | `peer_connection_id` | string | ID of the newly created peering connection. 252 | 253 | ## Examples ## 254 | 255 | See the [examples](examples) directory for a complete set of example source files. 256 | 257 | ## License ## 258 | 259 | MPL 2. See LICENSE for full details. 260 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake' 2 | require 'covalence/environment_tasks' 3 | require 'covalence/spec_tasks' 4 | -------------------------------------------------------------------------------- /az/main.tf: -------------------------------------------------------------------------------- 1 | # VPC availability zone 2 | 3 | ## Set Terraform version constraint 4 | terraform { 5 | required_version = "> 0.11.0" 6 | } 7 | 8 | ## Variables 9 | data "aws_region" "current" {} 10 | 11 | data "aws_availability_zones" "available" {} 12 | 13 | locals { 14 | # Calculates the number of AZs to be provisioned based on various possible inputs 15 | azs_provisioned_count = "${local.azs_provisioned_override_enabled == "true" ? length(var.azs_provisioned_override) : var.azs_provisioned}" 16 | 17 | # Check to see if availability zones are being overridden. Some AWS regions do not support VPC in all AZs and it can vary by account. 18 | azs_provisioned_override_enabled = "${length(var.azs_provisioned_override) > 0 && var.azs_provisioned_override[0] != "non_empty_list" ? "true" : "false"}" 19 | 20 | # Check to see if DMZ CIDRs are being overridden. An empty list causes problems in some of the downstream formualtion. 21 | dmz_cidrs_override_enabled = "${length(var.dmz_cidrs_override) > 0 && var.dmz_cidrs_override[0] != "non_empty_list" ? "true" : "false"}" 22 | 23 | # Check to see if elastic IPs are to be provisioned. NAT gateways require EIPs. 24 | eips_enabled_check = "${var.nat_eips_enabled == "true" || var.nat_gateways_enabled == "true" ? 1 : 0}" 25 | 26 | # Check to see if private LAN subnets are to be provisioned. 27 | lans_enabled_check = "${local.lans_per_az_checked > 0 ? 1 : 0}" 28 | 29 | # Check to see if LAN CIDRs are being overridden. An empty list causes problems in some of the downstream formualtion. 30 | lan_cidrs_override_enabled = "${length(var.lan_cidrs_override) > 0 && var.lan_cidrs_override[0] != "non_empty_list" ? "true" : "false"}" 31 | 32 | # Multiplier to be used in downstream calculation based on the number of LAN subnets per AZ. 33 | lans_multiplier = "${local.lans_per_az_checked >= 0 ? local.lans_per_az_checked : 1}" 34 | 35 | # Handles scenario where an emptry string is passed in for lans_per_az 36 | lans_per_az_checked = "${var.lans_per_az != "" ? var.lans_per_az : "1"}" 37 | 38 | # Check to see if NAT gateways are to be provisioned 39 | nat_gateways_enabled_check = "${var.nat_gateways_enabled == "true" ? 1 : 0}" 40 | 41 | # Check to see if NAT gateways are NOT to be provisioned 42 | nat_gateways_not_enabled_check = "${var.nat_gateways_enabled != "true" ? 1 : 0}" 43 | 44 | # default subnet tags 45 | default_subnet_tags = { 46 | application = "${var.stack_item_fullname}" 47 | managed_by = "terraform" 48 | } 49 | } 50 | 51 | ## Provisions DMZ resources 52 | 53 | ### Provisions subnets 54 | 55 | data "aws_vpc" "base" { 56 | id = "${var.vpc_id}" 57 | } 58 | 59 | resource "aws_subnet" "dmz" { 60 | count = "${local.azs_provisioned_count}" 61 | 62 | # Selects the first N number of AZs available for VPC use in the given region, where N is the requested number of AZs to provision. This order can be overidden by passing in an explicit list of AZ letters to be used. 63 | availability_zone = "${local.azs_provisioned_override_enabled == "true" ? "${data.aws_region.current.name}${element(var.azs_provisioned_override,count.index)}" : element(data.aws_availability_zones.available.names,count.index)}" 64 | 65 | # Provisions N number of evenly allocated address spaces from the overall VPC CIDR block, where N is the requested number of AZs to provision. Address space per subnet can be overidden by passing in an explicit list of CIDRs to be used. 66 | cidr_block = "${local.dmz_cidrs_override_enabled == "true" ? element(var.dmz_cidrs_override,count.index) : cidrsubnet(data.aws_vpc.base.cidr_block,lookup(var.az_cidrsubnet_newbits, local.azs_provisioned_count),count.index)}" 67 | map_public_ip_on_launch = "${var.enable_dmz_public_ips}" 68 | vpc_id = "${var.vpc_id}" 69 | 70 | tags = "${merge(local.default_subnet_tags, var.additional_subnet_tags, map("Name", "${var.stack_item_label}-dmz-${count.index}"))}" 71 | } 72 | 73 | ### Associates subnet with routing table 74 | resource "aws_route_table_association" "rta_dmz" { 75 | count = "${local.azs_provisioned_count}" 76 | 77 | route_table_id = "${var.rt_dmz_id}" 78 | subnet_id = "${element(aws_subnet.dmz.*.id,count.index)}" 79 | } 80 | 81 | ### Provisions NATs 82 | data "aws_ami" "nat_ami" { 83 | most_recent = true 84 | 85 | owners = ["amazon"] 86 | 87 | filter { 88 | name = "architecture" 89 | values = ["x86_64"] 90 | } 91 | 92 | filter { 93 | name = "name" 94 | values = ["amzn-ami-vpc-nat*"] 95 | } 96 | 97 | filter { 98 | name = "root-device-type" 99 | values = ["ebs"] 100 | } 101 | 102 | filter { 103 | name = "virtualization-type" 104 | values = ["hvm"] 105 | } 106 | } 107 | 108 | resource "aws_eip" "eip_nat" { 109 | count = "${local.azs_provisioned_count * local.lans_enabled_check * local.eips_enabled_check}" 110 | 111 | vpc = true 112 | } 113 | 114 | resource "aws_eip_association" "eip_nat_assoc" { 115 | count = "${local.azs_provisioned_count * local.lans_enabled_check * local.eips_enabled_check * local.nat_gateways_not_enabled_check}" 116 | 117 | allocation_id = "${element(aws_eip.eip_nat.*.id,count.index)}" 118 | instance_id = "${element(aws_instance.nat.*.id,count.index)}" 119 | } 120 | 121 | resource "aws_instance" "nat" { 122 | count = "${local.azs_provisioned_count * local.lans_enabled_check * local.nat_gateways_not_enabled_check}" 123 | 124 | ami = "${coalesce(var.nat_ami_override,data.aws_ami.nat_ami.id)}" 125 | associate_public_ip_address = true 126 | instance_type = "${var.nat_instance_type}" 127 | key_name = "${var.nat_key_name}" 128 | source_dest_check = false 129 | subnet_id = "${element(aws_subnet.dmz.*.id,count.index)}" 130 | vpc_security_group_ids = ["${element(aws_security_group.sg_nat.*.id,count.index)}"] 131 | 132 | tags { 133 | application = "${var.stack_item_fullname}" 134 | managed_by = "terraform" 135 | Name = "${var.stack_item_label}-nat-${count.index}" 136 | } 137 | } 138 | 139 | resource "aws_security_group" "sg_nat" { 140 | count = "${local.azs_provisioned_count * local.lans_enabled_check * local.nat_gateways_not_enabled_check}" 141 | 142 | description = "${var.stack_item_fullname} NAT security group" 143 | name_prefix = "${var.stack_item_label}-nat-" 144 | vpc_id = "${var.vpc_id}" 145 | 146 | egress { 147 | cidr_blocks = ["0.0.0.0/0"] 148 | description = "Egress to the Internet" 149 | from_port = 0 150 | protocol = "-1" 151 | to_port = 0 152 | } 153 | 154 | ingress { 155 | cidr_blocks = ["${local.lan_cidrs_override_enabled == "true" ? element(var.lan_cidrs_override,count.index) : cidrsubnet(data.aws_vpc.base.cidr_block,lookup(var.az_cidrsubnet_newbits, local.azs_provisioned_count * local.lans_multiplier),count.index + lookup(var.az_cidrsubnet_offset, local.azs_provisioned_count))}"] 156 | description = "Ingress from ${var.stack_item_label}-lan-${count.index}" 157 | from_port = 0 158 | protocol = "-1" 159 | to_port = 0 160 | } 161 | 162 | tags { 163 | application = "${var.stack_item_fullname}" 164 | managed_by = "terraform" 165 | Name = "${var.stack_item_label}-nat-${count.index}" 166 | } 167 | } 168 | 169 | resource "aws_nat_gateway" "nat" { 170 | count = "${local.azs_provisioned_count * local.lans_enabled_check * local.nat_gateways_enabled_check}" 171 | 172 | allocation_id = "${element(aws_eip.eip_nat.*.id,count.index)}" 173 | subnet_id = "${element(aws_subnet.dmz.*.id,count.index)}" 174 | } 175 | 176 | ### 177 | 178 | ## Provisions LAN resources 179 | 180 | ### Provisions subnet 181 | resource "aws_subnet" "lan" { 182 | count = "${local.azs_provisioned_count * local.lans_multiplier}" 183 | 184 | # Selects the first N number of AZs available for VPC use in the given region, where N is the requested number of AZs to provision. This order can be overidden by passing in an explicit list of AZ letters to be used. 185 | availability_zone = "${local.azs_provisioned_override_enabled == "true" ? "${data.aws_region.current.name}${element(var.azs_provisioned_override,count.index)}" : element(data.aws_availability_zones.available.names,count.index)}" 186 | 187 | # Provisions N number of evenly allocated address spaces from the overall VPC CIDR block, where N is the requested number of AZs to provision multiplied by the number of LAN subnets to provision per AZ. Address space per subnet can be overidden by passing in an explicit list of CIDRs to be used. 188 | cidr_block = "${local.lan_cidrs_override_enabled == "true" ? element(var.lan_cidrs_override,count.index) : cidrsubnet(data.aws_vpc.base.cidr_block,lookup(var.az_cidrsubnet_newbits, local.azs_provisioned_count * local.lans_multiplier),count.index + lookup(var.az_cidrsubnet_offset, local.azs_provisioned_count))}" 189 | vpc_id = "${var.vpc_id}" 190 | 191 | tags = "${merge(local.default_subnet_tags, var.additional_subnet_tags, map("Name", "${var.stack_item_label}-lan-${count.index}"))}" 192 | } 193 | 194 | ### Provisions routing table 195 | resource "aws_route_table" "rt_lan" { 196 | count = "${local.azs_provisioned_count * local.lans_multiplier}" 197 | 198 | propagating_vgws = ["${compact(var.vgw_ids)}"] 199 | vpc_id = "${var.vpc_id}" 200 | 201 | tags { 202 | application = "${var.stack_item_fullname}" 203 | managed_by = "terraform" 204 | Name = "${var.stack_item_label}-lan-${count.index}" 205 | } 206 | } 207 | 208 | ### Associates subnet with routing table 209 | resource "aws_route_table_association" "rta_lan" { 210 | count = "${local.azs_provisioned_count * local.lans_multiplier}" 211 | 212 | route_table_id = "${element(aws_route_table.rt_lan.*.id,count.index)}" 213 | subnet_id = "${element(aws_subnet.lan.*.id,count.index)}" 214 | } 215 | -------------------------------------------------------------------------------- /az/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output Variables 2 | 3 | ## Returns Subnet IDs 4 | output "dmz_ids" { 5 | value = ["${aws_subnet.dmz.*.id}"] 6 | } 7 | 8 | output "lan_ids" { 9 | value = ["${aws_subnet.lan.*.id}"] 10 | } 11 | 12 | ## Returns Subnet CIDR blocks 13 | output "dmz_cidrs" { 14 | value = ["${aws_subnet.dmz.*.cidr_block}"] 15 | } 16 | 17 | output "lan_cidrs" { 18 | value = ["${aws_subnet.lan.*.cidr_block}"] 19 | } 20 | 21 | ## Returns information about the NATs 22 | output "eip_nat_ids" { 23 | value = ["${aws_eip.eip_nat.*.id}"] 24 | } 25 | 26 | output "eip_nat_ips" { 27 | value = ["${aws_eip.eip_nat.*.public_ip}"] 28 | } 29 | 30 | output "nat_ids" { 31 | value = ["${compact(concat(aws_instance.nat.*.id,aws_nat_gateway.nat.*.id))}"] 32 | } 33 | 34 | ## Returns the routing table ID 35 | output "rt_lan_ids" { 36 | value = ["${aws_route_table.rt_lan.*.id}"] 37 | } 38 | -------------------------------------------------------------------------------- /az/variables.tf: -------------------------------------------------------------------------------- 1 | # Input variables 2 | 3 | ## Resource tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | description = "Long form descriptive name for this stack item. This value is used to create the 'application' resource tag for resources created by this stack item." 7 | default = "VPC Quick Start" 8 | } 9 | 10 | variable "stack_item_label" { 11 | type = "string" 12 | description = "Short form identifier for this stack. This value is used to create the 'Name' resource tag for resources created by this stack item, and also serves as a unique key for re-use." 13 | default = "qckstrt" 14 | } 15 | 16 | variable "additional_subnet_tags" { 17 | type = "map" 18 | description = "Additional tags to apply at the subnet level, if any" 19 | default = {} 20 | } 21 | 22 | ## VPC parameters 23 | variable "az_cidrsubnet_newbits" { 24 | type = "map" 25 | description = "The number of bits by which to extend the CIDR range for the given number of AZs." 26 | 27 | default = { 28 | "1" = "1" 29 | "2" = "2" 30 | "3" = "3" 31 | "4" = "3" 32 | "6" = "4" 33 | "8" = "4" 34 | } 35 | } 36 | 37 | variable "az_cidrsubnet_offset" { 38 | type = "map" 39 | description = "The number of AZs to provision for." 40 | 41 | default = { 42 | "1" = "1" 43 | "2" = "2" 44 | "3" = "4" 45 | "4" = "4" 46 | } 47 | } 48 | 49 | variable "azs_provisioned" { 50 | type = "string" 51 | description = "The number of availability zones to be provisioned." 52 | default = "2" 53 | } 54 | 55 | variable "azs_provisioned_override" { 56 | type = "list" 57 | description = "List of availability zones to be provisioned." 58 | default = ["non_empty_list"] 59 | } 60 | 61 | variable "dmz_cidrs_override" { 62 | type = "list" 63 | description = "The CIDR block(s) you want the DMZ subnet(s) to cover." 64 | default = ["non_empty_list"] 65 | } 66 | 67 | variable "enable_dmz_public_ips" { 68 | type = "string" 69 | description = "Specify true to indicate that instances launched into the DMZ subnet should be assigned a public IP address. Default is false." 70 | default = "" 71 | } 72 | 73 | variable "lan_cidrs_override" { 74 | type = "list" 75 | description = "The CIDR block(s) you want the LAN subnet(s) to cover." 76 | default = ["non_empty_list"] 77 | } 78 | 79 | variable "lans_per_az" { 80 | type = "string" 81 | description = "The number of private LAN subnets to be provisioned per AZ" 82 | default = "1" 83 | } 84 | 85 | variable "nat_ami_override" { 86 | type = "string" 87 | description = "Custom NAT Amazon machine image" 88 | default = "" 89 | } 90 | 91 | variable "nat_eips_enabled" { 92 | type = "string" 93 | description = "Flag for specifying allocation of Elastic IPs to NATs for the purposes of whitelisting. This value is overriden to 'true' when utilizing NAT gateways." 94 | default = "false" 95 | } 96 | 97 | variable "nat_gateways_enabled" { 98 | type = "string" 99 | description = "Flag for specifying utilization of managed NAT gateways over EC2 based NAT instances." 100 | default = "false" 101 | } 102 | 103 | variable "nat_instance_type" { 104 | type = "string" 105 | description = "NAT EC2 instance type" 106 | default = "t2.nano" 107 | } 108 | 109 | variable "nat_key_name" { 110 | type = "string" 111 | description = "NAT EC2 key pair name" 112 | default = "" 113 | } 114 | 115 | variable "rt_dmz_id" { 116 | type = "string" 117 | description = "The ID of the DMZ routing table" 118 | } 119 | 120 | variable "vgw_ids" { 121 | type = "list" 122 | description = "A list of virtual gateways to associate with the routing tables for route propagation." 123 | default = [] 124 | } 125 | 126 | variable "vpc_id" { 127 | type = "string" 128 | description = "The ID of the VPC" 129 | } 130 | -------------------------------------------------------------------------------- /base/main.tf: -------------------------------------------------------------------------------- 1 | # VPC base 2 | 3 | ## Set Terraform version constraint 4 | terraform { 5 | required_version = "> 0.11.0" 6 | } 7 | 8 | ## Set default instance tennancy if not provided 9 | locals { 10 | default_instance_tenancy = "${length(var.instance_tenancy) >= 1 ? "${var.instance_tenancy}" : "default"}" 11 | 12 | default_vpc_tags = { 13 | application = "${var.stack_item_fullname}" 14 | managed_by = "terraform" 15 | Name = "${var.stack_item_label}-vpc" 16 | } 17 | } 18 | 19 | ## Provisions Virtual Private Cloud (VPC) 20 | resource "aws_vpc" "vpc" { 21 | cidr_block = "${var.vpc_cidr}" 22 | instance_tenancy = "${local.default_instance_tenancy}" 23 | enable_dns_support = "${var.enable_dns}" 24 | enable_dns_hostnames = "${var.enable_hostnames}" 25 | enable_classiclink = "${var.enable_classiclink}" 26 | enable_classiclink_dns_support = "${var.enable_classiclink_dns_support}" 27 | assign_generated_ipv6_cidr_block = "${var.assign_generated_ipv6_cidr_block}" 28 | 29 | tags = "${merge(local.default_vpc_tags, var.additional_vpc_tags)}" 30 | } 31 | 32 | ## Provisions Internet gateways 33 | resource "aws_internet_gateway" "igw" { 34 | vpc_id = "${aws_vpc.vpc.id}" 35 | 36 | tags { 37 | application = "${var.stack_item_fullname}" 38 | managed_by = "terraform" 39 | Name = "${var.stack_item_label}-igw" 40 | } 41 | } 42 | 43 | ## Provisions DMZ routing table 44 | resource "aws_route_table" "rt_dmz" { 45 | propagating_vgws = ["${compact(var.vgw_ids)}"] 46 | vpc_id = "${aws_vpc.vpc.id}" 47 | 48 | tags { 49 | application = "${var.stack_item_fullname}" 50 | managed_by = "terraform" 51 | Name = "${var.stack_item_label}-dmz" 52 | } 53 | } 54 | 55 | ## Provisions VPC flow logs 56 | resource "aws_cloudwatch_log_group" "flow_log_group" { 57 | name_prefix = "${var.stack_item_label}-vpc-logs-" 58 | } 59 | 60 | data "aws_iam_policy_document" "flow_log_role" { 61 | statement { 62 | actions = ["sts:AssumeRole"] 63 | 64 | principals { 65 | type = "Service" 66 | identifiers = ["vpc-flow-logs.amazonaws.com"] 67 | } 68 | } 69 | } 70 | 71 | resource "aws_iam_role" "flow_log_role" { 72 | assume_role_policy = "${data.aws_iam_policy_document.flow_log_role.json}" 73 | name_prefix = "${var.stack_item_label}-vpc-logs-" 74 | } 75 | 76 | data "aws_iam_policy_document" "flow_log_policy" { 77 | statement { 78 | actions = [ 79 | "logs:CreateLogGroup", 80 | "logs:CreateLogStream", 81 | "logs:PutLogEvents", 82 | "logs:DescribeLogGroups", 83 | "logs:DescribeLogStreams", 84 | ] 85 | 86 | resources = ["${aws_cloudwatch_log_group.flow_log_group.arn}"] 87 | } 88 | } 89 | 90 | resource "aws_iam_role_policy" "flow_log_role_policies" { 91 | name = "logs" 92 | policy = "${data.aws_iam_policy_document.flow_log_policy.json}" 93 | role = "${aws_iam_role.flow_log_role.id}" 94 | } 95 | 96 | resource "aws_flow_log" "flow_log" { 97 | log_destination = "${aws_cloudwatch_log_group.flow_log_group.arn}" 98 | iam_role_arn = "${aws_iam_role.flow_log_role.arn}" 99 | vpc_id = "${aws_vpc.vpc.id}" 100 | traffic_type = "${var.flow_log_traffic_type}" 101 | } 102 | -------------------------------------------------------------------------------- /base/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output Variables 2 | 3 | output "flow_log_id" { 4 | value = "${aws_flow_log.flow_log.id}" 5 | } 6 | 7 | output "igw_id" { 8 | value = "${aws_internet_gateway.igw.id}" 9 | } 10 | 11 | output "rt_dmz_id" { 12 | value = "${aws_route_table.rt_dmz.id}" 13 | } 14 | 15 | output "vpc_id" { 16 | value = "${aws_vpc.vpc.id}" 17 | } 18 | 19 | output "vpc_default_security_group_id" { 20 | value = "${aws_vpc.vpc.default_security_group_id}" 21 | } 22 | -------------------------------------------------------------------------------- /base/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | description = "Long form descriptive name for this stack item. This value is used to create the 'application' resource tag for resources created by this stack item." 7 | default = "VPC Quick Start" 8 | } 9 | 10 | variable "stack_item_label" { 11 | type = "string" 12 | description = "Short form identifier for this stack. This value is used to create the 'Name' resource tag for resources created by this stack item, and also serves as a unique key for re-use." 13 | default = "qckstrt" 14 | } 15 | 16 | variable "additional_vpc_tags" { 17 | type = "map" 18 | description = "Additional tags to apply at the VPC level, if any" 19 | default = {} 20 | } 21 | 22 | ## VPC parameters 23 | variable "assign_generated_ipv6_cidr_block" { 24 | type = "string" 25 | description = "Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IP addresses, or the size of the CIDR block." 26 | default = "false" 27 | } 28 | 29 | variable "enable_classiclink" { 30 | type = "string" 31 | description = "A boolean flag to enable/disable ClassicLink for the VPC. Only valid in regions and accounts that support EC2 Classic. Defaults false." 32 | default = "" 33 | } 34 | 35 | variable "enable_classiclink_dns_support" { 36 | type = "string" 37 | description = "A boolean flag to enable/disable ClassicLink DNS Support for the VPC. Only valid in regions and accounts that support EC2 Classic." 38 | default = "false" 39 | } 40 | 41 | variable "enable_dns" { 42 | type = "string" 43 | description = "A boolean flag to enable/disable DNS support in the VPC. Defaults true." 44 | default = "" 45 | } 46 | 47 | variable "enable_hostnames" { 48 | type = "string" 49 | description = "A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false." 50 | default = "" 51 | } 52 | 53 | variable "instance_tenancy" { 54 | type = "string" 55 | description = "A tenancy option for instances launched into the VPC." 56 | default = "" 57 | } 58 | 59 | variable "vpc_cidr" { 60 | type = "string" 61 | description = "The CIDR block for the VPC." 62 | default = "172.16.0.0/21" 63 | } 64 | 65 | ## Flow log parameters 66 | variable "flow_log_traffic_type" { 67 | type = "string" 68 | description = "The type of traffic to capture. Valid values: ACCEPT,REJECT,ALL" 69 | default = "ALL" 70 | } 71 | 72 | ## Routing parameters 73 | variable "vgw_ids" { 74 | type = "list" 75 | description = "A list of virtual gateways for propagation." 76 | default = [] 77 | } 78 | -------------------------------------------------------------------------------- /bin/.covalence/launcher: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run from the source tree root 3 | cd `dirname $0` 4 | cd ../.. 5 | ### Environment Variables 6 | # Variables are used for determining CI settings 7 | # Variable precedence is as follows with the last taking 8 | # the highest precedence 9 | # 10 | # 1. Default values 11 | # 2. Exported environment variables 12 | # 3. .env.covalence loaded values 13 | # 4. bin/covalence argument switches 14 | # 15 | # source local .env.covalence file if present 16 | LOCAL_ENVFILE=${LOCAL_ENVFILE:-".env.covalence"} 17 | 18 | # If set to true will no use old docker-wrapper behavior 19 | # omitting the `rake` command 20 | DOCKER_WRAPPER=${DOCKER_WRAPPER:-} 21 | # The docker environment variable file passed to the container 22 | # Can contain multiple envfiles separated by : env1:env2:env3 23 | LOAD_ENVFILE=${LOAD_ENVFILE:-".env.docker:.env.secrets"} 24 | # AWS Credentials path to mount (defaults to data/secure/.aws) 25 | AWS_CREDENTIAL_PATH=${AWS_CREDENTIAL_PATH:-"$HOME/.aws"} 26 | # The Container home directory 27 | DOCKER_HOMEDIR=${DOCKER_HOMEDIR:-"/root"} 28 | # The docker DNS can be updated to AWS DNS 29 | DOCKER_DNS=${DOCKER_DNS:-} 30 | # If you want docker to run as specific user 31 | CONTAINER_USER_ID=${CONTAINER_USER_ID:-} 32 | # Alternative Covalence Rakefile can be specified 33 | # will add `-f Rakefile`` 34 | COVALENCE_RAKEFILE=${COVALENCE_RAKEFILE:-} 35 | # Alternative Covalence configuration can be specified 36 | COVALENCE_CONFIG=${COVALENCE_CONFIG:-"covalence.yaml"} 37 | # Environments to be included in CI 38 | COVALENCE_TEST_ENVS=${COVALENCE_TEST_ENVS:-} 39 | # The Container image to use for the ci defaults to unifio/ci latest 40 | DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-"unifio/ci"} 41 | # Enable debugging of script 42 | S_DEBUG=${S_DEBUG:-} 43 | # Dump verbose information about commands without executing them. 44 | DUMP_ENV=${DUMP_ENV:-} 45 | # Causes covalence rake -T 46 | LIST_RAKE_TASKS=${LIST_RAKE_TASKS:-} 47 | # Adds volume to docker container HOST_MNT:CONTAINER_MNT 48 | ADD_VOLUMES=${ADD_VOLUMES:-} 49 | # Can be used to change docker run behavior ie -it vs --rm 50 | DOCKER_RUN_TYPE=${DOCKER_RUN_TYPE:-"--rm"} 51 | # TEST_HOST_LOCAL is used for specifying a domain to overload 52 | # and point to the Docker host IP in the container /etc/host file 53 | # --add-host CONSUL_TEST_IP will be set automatically 54 | TEST_HOST_LOCAL=${TEST_HOST_LOCAL:-} 55 | CONSUL_TEST_IP=${CONSUL_TEST_IP:-} 56 | # Allows specifying --entrypoint= command 57 | ENTRYPOINT=${ENTRYPOINT:-} 58 | # Interactive Shell enabled 59 | INTSHELL=${INTSHELL:-} 60 | # Sets the Docker workspace to mount and set as working directory -w 61 | DOCKER_WORKSPACE=${DOCKER_WORKSPACE:-"/workspace"} 62 | # The project root directory to mount in docker workspace 63 | SRC_ROOT=${SRC_ROOT:-"$(pwd)"} 64 | # Atlas and AWS tokens if needed but defaults to .aws 65 | # For possible future use currently should be set in .env.docker 66 | #ATLAS_TOKEN=${AWS_SECRET_ACCESS_KEY:-} 67 | #AWS_ACCESS_KEY_ID=${AWS_SECRET_ACCESS_KEY:-} 68 | #AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-} 69 | 70 | # Create initial Docker Base Command 71 | DOCKER_BASE_COMMANDS[0]="docker run" 72 | ARGS=() 73 | # Check for debug statements 74 | if [[ $S_DEBUG ]]; then 75 | set -x 76 | fi 77 | 78 | # Checks if ARGS already contains the given value 79 | has_arg() { 80 | local element 81 | for element in "${@:2}"; do 82 | [ "${element}" == "${1}" ] && return 0 83 | done 84 | return 1 85 | } 86 | # Adds the given argument if not specified 87 | add_arg() { 88 | local arg="${1}" 89 | [ $# -ge 1 ] && local val="${2}" 90 | if ! has_arg "${arg}" "${DOCKER_BASE_COMMANDS[@]}"; then 91 | ARGS+=("${arg}") 92 | [ $# -ge 1 ] && ARGS+=("${val}") 93 | fi 94 | } 95 | # Adds the given argument duplicates ok. 96 | add_arg_simple() { 97 | local arg="${1}" 98 | [ $# -ge 1 ] && local val="${2}" 99 | ARGS+=("${arg}") 100 | [ $# -ge 1 ] && ARGS+=("${val}") 101 | } 102 | # get the docker host ip address. and add it to container /etc/host 103 | # for TEST_HOST_LOCAL URL provided. 104 | get_docker_host(){ 105 | if [[ $TEST_HOST_LOCAL ]]; then 106 | GET_DOCKER_HOST_IP=$(docker inspect --format '{{ .NetworkSettings.Gateway }}' $(docker ps -q | grep -m 1 "") 2>/dev/null) 107 | if [[ ${GET_DOCKER_HOST_IP} ]];then 108 | CONSUL_TEST_IP=${GET_DOCKER_HOST_IP} 109 | add_arg_simple "--add-host" "${TEST_HOST_LOCAL}:${CONSUL_TEST_IP}" 110 | fi 111 | fi 112 | } 113 | # add a volume host:docker mount. 114 | add_host_volume(){ 115 | local host_vol="${1%:*}" 116 | local dkr_vol="${1##*:}" 117 | add_arg "-v" "${host_vol}:${dkr_vol}" 118 | } 119 | 120 | # add envfiles for docker if they exist in working directory 121 | add_docker_envfiles(){ 122 | local envfiles="${1}" 123 | IFS=':' read -r -a arrenvs <<< "$envfiles" 124 | for i in "${arrenvs[@]}" 125 | do 126 | if [[ -r "${i}" ]];then 127 | add_arg "--env-file" "$(pwd)/${i}" 128 | fi 129 | done 130 | } 131 | usage () { 132 | echo "" 133 | echo "Usage : $0 [OPTIONS] [COMMANDS|task]" 134 | echo "Options:" 135 | echo " -l List available rake tasks " 136 | echo " -e FILE:FILE Envfiles for docker : separated " 137 | echo " -s FILE Local env file to source " 138 | echo " -d DNS Docker DNS " 139 | echo " -u USER Run Docker as user " 140 | echo " -O Use Wrapper without Covalence " 141 | echo " -T URL URL for Consul overload " 142 | echo " -R Leave intermediary containers " 143 | echo " -v VOL:MNT Add a volume mount to container " 144 | echo " -c AWS_DIR AWS credentials path " 145 | echo " -w DIR Host workspace to mount " 146 | echo " -E ENTRYPOINT Override entrypoint command " 147 | echo " -i DKR_IMG_NAME Docker container Image name " 148 | echo " -h View help. " 149 | echo " -r RAKEFILE Specify separate rakefile " 150 | echo " -D Turn on debug " 151 | echo " -H Environment dump " 152 | } 153 | # require at lest a task or -l to run 154 | if [ $# -lt 1 ]; then 155 | usage 156 | exit 1 157 | fi 158 | 159 | # Load local env file if provided/available 160 | # That way explicit options will overwrite 161 | # any env vars sourced in .env.covalence 162 | if [[ -r "${LOCAL_ENVFILE}" ]]; then 163 | . ./"${LOCAL_ENVFILE}" 164 | fi 165 | 166 | # Parse arguments and populate ENV vars respectively 167 | # See Environment Variable section or .env.covalence for 168 | # option details. 169 | while getopts ":le:s:d:OIT:Rv:c:w:E:i:hr:DH" opt; do 170 | case $opt in 171 | l) 172 | LIST_RAKE_TASKS=1 173 | ;; 174 | e) 175 | LOAD_ENVFILE="$OPTARG" 176 | ;; 177 | s) 178 | LOCAL_ENVFILE="$OPTARG" 179 | ;; 180 | d) 181 | DOCKER_DNS="$OPTARG" 182 | ;; 183 | u) 184 | CONTAINER_USER_ID="$OPTARG" 185 | ;; 186 | O) 187 | DOCKER_WRAPPER=1 188 | ;; 189 | T) 190 | TEST_HOST_LOCAL="$OPTARG" 191 | ;; 192 | R) 193 | DOCKER_RUN_TYPE="--it" 194 | ;; 195 | v) 196 | ADD_VOLUMES="$OPTARG" 197 | ;; 198 | c) 199 | AWS_CREDENTIAL_PATH="$OPTARG" 200 | ;; 201 | w) 202 | DOCKER_WORKSPACE="$OPTARG" 203 | ;; 204 | E) 205 | ENTRYPOINT="$OPTARG" 206 | ;; 207 | i) 208 | DOCKER_IMAGE_NAME="$OPTARG" 209 | ;; 210 | h) 211 | usage 212 | exit 0 213 | ;; 214 | D) 215 | S_DEBUG=1 216 | ;; 217 | H) 218 | DUMP_ENV=1 219 | ;; 220 | I) 221 | INTSHELL=1 222 | ;; 223 | r) 224 | COVALENCE_RAKEFILE="$OPTARG" 225 | ;; 226 | \?) 227 | set +x 228 | echo "Invalid option: -$OPTARG" >&2 229 | usage 230 | exit 1 231 | ;; 232 | :) 233 | set +x 234 | echo "Option -$OPTARG requires an argument." >&2 235 | usage 236 | exit 1 237 | ;; 238 | esac 239 | done 240 | 241 | # Get rid of processed options from Array 242 | shift "$((OPTIND-1))" 243 | USER_ARGS=("${@}") 244 | 245 | if [[ "${COVALENCE_CONFIG}" ]]; then 246 | add_arg_simple "-e" "COVALENCE_CONFIG=${COVALENCE_CONFIG}" 247 | fi 248 | 249 | if [[ "${COVALENCE_TEST_ENVS}" ]]; then 250 | add_arg_simple "-e" "COVALENCE_TEST_ENVS=${COVALENCE_TEST_ENVS}" 251 | fi 252 | 253 | # Add the --rm or --it argument to the docker command array. 254 | if [[ "${DOCKER_RUN_TYPE}" ]]; then 255 | DOCKER_BASE_COMMANDS[3]="${DOCKER_RUN_TYPE}" 256 | fi 257 | 258 | if [[ "${DOCKER_DNS}" ]]; then 259 | add_arg "--dns" "${DOCKER_DNS}" 260 | fi 261 | 262 | if [[ "${CONTAINER_USER_ID}" ]]; then 263 | DOCKER_HOMEDIR="" 264 | add_arg_simple "-e" "AWS_CONFIG_FILE=${DOCKER_HOMEDIR}/.aws/config" 265 | add_arg_simple "-e" "AWS_SHARED_CREDENTIALS_FILE=${DOCKER_HOMEDIR}/.aws/credentials" 266 | add_arg_simple "-e" "USER=user" 267 | add_arg_simple "-e" "LOCAL_USER_ID=${CONTAINER_USER_ID}" 268 | else 269 | add_arg_simple "-e" "USER=root" 270 | fi 271 | 272 | get_docker_host "$TEST_HOST_LOCAL" 273 | 274 | if [[ "$ADD_VOLUMES" ]];then 275 | add_host_volume "${ADD_VOLUMES}" 276 | fi 277 | 278 | if [[ -d "$AWS_CREDENTIAL_PATH" ]];then 279 | add_arg_simple "-v" "${AWS_CREDENTIAL_PATH}:${DOCKER_HOMEDIR}/.aws" 280 | fi 281 | 282 | if [[ -d "${SRC_ROOT}" ]];then 283 | add_arg_simple "-v" "${SRC_ROOT}:${DOCKER_WORKSPACE}" 284 | add_arg "-w" "${DOCKER_WORKSPACE}" 285 | fi 286 | 287 | if [[ "${LOAD_ENVFILE}" ]]; then 288 | add_docker_envfiles "${LOAD_ENVFILE}" 289 | fi 290 | 291 | if [[ "${ENTRYPOINT}" ]]; then 292 | ARGS+=("--entrypoint=${ENTRYPOINT}") 293 | fi 294 | if [[ $INTSHELL && ! $ENTRYPOINT ]]; then 295 | ARGS+=("--entrypoint=/bin/sh") 296 | fi 297 | # All options should be completed 298 | # Only image and task remain. 299 | 300 | if [[ $DOCKER_IMAGE_NAME ]];then 301 | if [[ $INTSHELL && $DOCKER_WRAPPER ]]; then 302 | ARGS+=("-it") 303 | fi 304 | ARGS+=("$DOCKER_IMAGE_NAME") 305 | fi 306 | 307 | #Check whether docker wrapper or covalence 308 | if [[ ! $DOCKER_WRAPPER ]]; then 309 | ARGS+=("bundle exec rake") 310 | fi 311 | 312 | if [[ -r "${COVALENCE_RAKEFILE}" && ! $DOCKER_WRAPPER ]];then 313 | add_arg "-f" "${COVALENCE_RAKEFILE}" 314 | fi 315 | 316 | if [[ $LIST_RAKE_TASKS && ! $DOCKER_WRAPPER ]];then 317 | ARGS+=("-T") 318 | fi 319 | # Merged Commands for execution 320 | DOCKER_BASE_COMMANDS=(${DOCKER_BASE_COMMANDS[@]} ${ARGS[@]} ${USER_ARGS[@]}) 321 | 322 | if [[ $DUMP_ENV ]]; then 323 | echo "DOCKER_BASE_COMMANDS that would have been executed without -H" 324 | echo "${DOCKER_BASE_COMMANDS[@]}" 325 | # echo "ARGS array" 326 | # echo "${ARGS[@]}" 327 | # echo "USER_ARGS array" 328 | # echo "${USER_ARGS[@]}" 329 | # echo "" 330 | else 331 | # Execute the commands 332 | # If we are listing, remove the rake as user won't pass that in. 333 | if [[ $LIST_RAKE_TASKS && ! $DOCKER_WRAPPER ]];then 334 | "${DOCKER_BASE_COMMANDS[@]}" | sed -e "s/^rake //" 335 | else 336 | "${DOCKER_BASE_COMMANDS[@]}" 337 | fi 338 | fi 339 | -------------------------------------------------------------------------------- /bin/covalence: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | COVALENCE_SCRIPT="https://s3.amazonaws.com/unifio-covalence/covalence?versionId=k_MRX2uIWItAsCR1YFrJWZOaDIB9FFAR" 4 | 5 | cd `dirname $0` 6 | 7 | if [[ ! -e ./.covalence/launcher ]]; then 8 | mkdir -p .covalence 9 | curl -o .covalence/launcher -s $COVALENCE_SCRIPT 10 | chmod 0755 .covalence/launcher 11 | fi 12 | 13 | bash .covalence/launcher "$@" 14 | -------------------------------------------------------------------------------- /covalence.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | :backends: 3 | - yaml 4 | 5 | :logger: noop 6 | 7 | :merge_behavior: 'deeper' 8 | 9 | :hierarchy: 10 | - "stacks/common" 11 | - "stacks/%{stack}" 12 | - 'globals' 13 | - 'environments' 14 | 15 | :yaml: 16 | :datadir: data 17 | -------------------------------------------------------------------------------- /data/environments.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Environments 3 | 4 | environments: 5 | basic: 6 | - no-lan 7 | - defaults 8 | - base-options 9 | - vpg-attach 10 | 11 | complete: 12 | - overrides 13 | - peer-vpc 14 | 15 | peering: 16 | - peer-connect 17 | -------------------------------------------------------------------------------- /data/globals.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Global variables 3 | 4 | ## Terraform 5 | tf_state_bucket: 'unifio-terraform-state' 6 | tf_state_region: "us-east-2" 7 | -------------------------------------------------------------------------------- /data/stacks/base-options.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Basic base options example 3 | 4 | ## Module 5 | base-options::module: 'examples/basic' 6 | 7 | ## State storage 8 | base-options::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::basic::vars: 16 | azs_provisioned: '3' 17 | enable_dns: 'false' 18 | enable_hostnames: 'true' 19 | nat_eips_enabled: 'true' 20 | -------------------------------------------------------------------------------- /data/stacks/common.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Common resources 3 | 4 | ## Basic example 5 | examples::basic::vars: 6 | domain_name: 'basic.example' 7 | region: 'us-east-2' 8 | stack_item_fullname: 'Basic Examples' 9 | stack_item_label: 'bsc' 10 | vpc_cidr: '172.16.0.0/21' 11 | 12 | ## Complete example 13 | examples::complete::vars: &complete_common 14 | region: 'us-east-1' 15 | stack_item_fullname: 'Complete Examples' 16 | 17 | ## Peering example 18 | examples::peering::vars: 19 | <<: *complete_common 20 | -------------------------------------------------------------------------------- /data/stacks/defaults.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Basic defaults example 3 | 4 | ## Module 5 | defaults::module: 'examples/basic' 6 | 7 | ## State storage 8 | defaults::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::basic::vars: 16 | azs_provisioned: '2' 17 | -------------------------------------------------------------------------------- /data/stacks/no-lan.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Basic no LAN example 3 | 4 | ## Module 5 | no-lan::module: 'examples/basic' 6 | 7 | ## State storage 8 | no-lan::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::basic::vars: 16 | azs_provisioned: '2' 17 | lans_per_az: '0' 18 | -------------------------------------------------------------------------------- /data/stacks/overrides.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Complete overrides example 3 | 4 | ## Module 5 | overrides::module: 'examples/complete' 6 | 7 | ## State storage 8 | overrides::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::complete::vars: 16 | domain_name: 'complete.example' 17 | enable_classiclink: 'true' 18 | # TODO: Cannot be paired with Classiclink. Update test for this. 19 | #instance_tenancy: 'dedicated' 20 | lans_per_az: '2' 21 | name_servers: 22 | - '172.16.0.2' 23 | - '172.16.1.2' 24 | - '172.16.2.2' 25 | nat_gateways_enabled: 'true' 26 | netbios_name_servers: 27 | - '172.16.0.2' 28 | - '172.16.1.2' 29 | - '172.16.2.2' 30 | ntp_servers: 31 | - '127.0.0.1' 32 | stack_item_label: 'cmpl' 33 | vpc_cidr: '172.16.0.0/21' 34 | -------------------------------------------------------------------------------- /data/stacks/peer-connect.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Complete peering connection example 3 | 4 | ## Module 5 | peer-connect::module: 'examples/peering' 6 | 7 | ## State storage 8 | peer-connect::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::peering::vars: 16 | accepter_rt_lan_ids: 17 | type: 's3.state' 18 | bucket: "%{hiera('tf_state_bucket')}" 19 | document: 'terraform-aws-vpc/complete/peer/terraform.tfstate' 20 | key: 'lan_rt_ids' 21 | accepter_vpc_cidr: '172.17.0.0/21' 22 | accepter_vpc_id: 23 | type: 's3.state' 24 | bucket: "%{hiera('tf_state_bucket')}" 25 | document: 'terraform-aws-vpc/complete/peer/terraform.tfstate' 26 | key: 'vpc_id' 27 | requester_rt_lan_ids: 28 | type: 's3.state' 29 | bucket: "%{hiera('tf_state_bucket')}" 30 | document: 'terraform-aws-vpc/complete/terraform.tfstate' 31 | key: 'lan_rt_ids' 32 | requester_vpc_cidr: '172.16.0.0/21' 33 | requester_vpc_id: 34 | type: 's3.state' 35 | bucket: "%{hiera('tf_state_bucket')}" 36 | document: 'terraform-aws-vpc/complete/terraform.tfstate' 37 | key: 'vpc_id' 38 | stack_item_label: 'cmpl' 39 | -------------------------------------------------------------------------------- /data/stacks/peer-vpc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Complete peer VPC example 3 | 4 | ## Module 5 | peer-vpc::module: 'examples/complete' 6 | 7 | ## State storage 8 | peer-vpc::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}/peer" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::complete::vars: 16 | domain_name: 'complete.example' 17 | enable_hostnames: 'true' 18 | name_servers: 19 | - '172.17.0.2' 20 | - '172.17.1.2' 21 | - '172.17.2.2' 22 | netbios_name_servers: 23 | - '172.17.0.2' 24 | - '172.17.1.2' 25 | - '172.17.2.2' 26 | ntp_servers: 27 | - '127.0.0.1' 28 | stack_item_label: 'cmpl-peer' 29 | vpc_cidr: '172.17.0.0/21' 30 | -------------------------------------------------------------------------------- /data/stacks/vpg-attach.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Basic VPG attachment example 3 | 4 | ## Module 5 | vpg-attach::module: 'examples/basic' 6 | 7 | ## State storage 8 | vpg-attach::state: 9 | - s3: 10 | bucket: "%{hiera('tf_state_bucket')}" 11 | name: "terraform-aws-vpc/%{environment}" 12 | region: "%{hiera('tf_state_region')}" 13 | 14 | ## Input variables 15 | examples::basic::vars: 16 | azs_provisioned: '3' 17 | enable_dns: 'false' 18 | enable_hostnames: 'true' 19 | nat_eips_enabled: 'true' 20 | vpc_attach: 'true' 21 | -------------------------------------------------------------------------------- /dhcp/main.tf: -------------------------------------------------------------------------------- 1 | # DHCP Options 2 | 3 | ## Set Terraform version constraint 4 | terraform { 5 | required_version = "> 0.11.0" 6 | } 7 | 8 | ## Provisions DHCP options 9 | resource "aws_vpc_dhcp_options" "dhcp" { 10 | count = "${var.enable == "true" ? "1" : "0"}" 11 | 12 | domain_name = "${var.domain_name}" 13 | domain_name_servers = ["${compact(var.name_servers)}"] 14 | netbios_name_servers = ["${compact(var.netbios_name_servers)}"] 15 | netbios_node_type = "${var.netbios_node_type}" 16 | ntp_servers = ["${compact(var.ntp_servers)}"] 17 | 18 | tags { 19 | application = "${var.stack_item_fullname}" 20 | managed_by = "terraform" 21 | Name = "${var.stack_item_label}-dhcp" 22 | } 23 | } 24 | 25 | resource "aws_vpc_dhcp_options_association" "dns_resolver" { 26 | count = "${var.enable == "true" ? "1" : "0"}" 27 | 28 | dhcp_options_id = "${aws_vpc_dhcp_options.dhcp.id}" 29 | vpc_id = "${var.vpc_id}" 30 | } 31 | -------------------------------------------------------------------------------- /dhcp/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variables 2 | 3 | output "dhcp_id" { 4 | value = "${join(",",compact(aws_vpc_dhcp_options.dhcp.*.id))}" 5 | } 6 | -------------------------------------------------------------------------------- /dhcp/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource Tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | description = "Long form descriptive name for this stack item. This value is used to create the 'application' resource tag for resources created by this stack item." 7 | } 8 | 9 | variable "stack_item_label" { 10 | type = "string" 11 | description = "Short form identifier for this stack. This value is used to create the 'Name' resource tag for resources created by this stack item, and also serves as a unique key for re-use." 12 | } 13 | 14 | ## VPC parameters 15 | variable "vpc_id" { 16 | type = "string" 17 | description = "The ID of the VPC" 18 | } 19 | 20 | ## DHCP parameters 21 | variable "domain_name" { 22 | type = "string" 23 | description = "The suffix domain name to use by default when resolving non Fully Qualified Domain Names" 24 | default = "" 25 | } 26 | 27 | variable "enable" { 28 | type = "string" 29 | description = "Determine if resources should be added. Used if you want to include conditionally in a module." 30 | default = "true" 31 | } 32 | 33 | variable "name_servers" { 34 | type = "list" 35 | description = "List of name servers to configure in '/etc/resolv.conf'" 36 | default = ["AmazonProvidedDNS"] 37 | } 38 | 39 | variable "netbios_name_servers" { 40 | type = "list" 41 | description = "List of NETBIOS name servers" 42 | default = [] 43 | } 44 | 45 | variable "netbios_node_type" { 46 | type = "string" 47 | description = "The NetBIOS node type (1, 2, 4, or 8). AWS recommends to specify 2 since broadcast and multicast are not supported in their network." 48 | default = "" 49 | } 50 | 51 | variable "ntp_servers" { 52 | type = "list" 53 | description = "List of NTP servers to configure" 54 | default = [] 55 | } 56 | -------------------------------------------------------------------------------- /examples/basic/main.tf: -------------------------------------------------------------------------------- 1 | # AWS Virtual Private Cloud 2 | 3 | ## Configures AWS provider 4 | provider "aws" { 5 | region = "${var.region}" 6 | } 7 | 8 | ## Configures base VPC 9 | module "vpc_base" { 10 | # Example GitHub source 11 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 12 | source = "../../base" 13 | 14 | enable_dns = "${var.enable_dns}" 15 | enable_hostnames = "${var.enable_hostnames}" 16 | stack_item_fullname = "${var.stack_item_fullname}" 17 | stack_item_label = "${var.stack_item_label}" 18 | vpc_cidr = "${var.vpc_cidr}" 19 | } 20 | 21 | ## Configures DHCP 22 | module "vpc_dhcp" { 23 | # Example GitHub source 24 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//dhcp" 25 | source = "../../dhcp" 26 | 27 | domain_name = "${var.domain_name}" 28 | stack_item_fullname = "${var.stack_item_fullname}" 29 | stack_item_label = "${var.stack_item_label}" 30 | vpc_id = "${module.vpc_base.vpc_id}" 31 | } 32 | 33 | ## Configures VPC Availabilty Zones 34 | module "vpc_az" { 35 | # Example GitHub source 36 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//az" 37 | source = "../../az" 38 | 39 | azs_provisioned = "${var.azs_provisioned}" 40 | enable_dmz_public_ips = "${var.enable_dmz_public_ips}" 41 | lans_per_az = "${var.lans_per_az}" 42 | nat_eips_enabled = "${var.nat_eips_enabled}" 43 | rt_dmz_id = "${module.vpc_base.rt_dmz_id}" 44 | stack_item_fullname = "${var.stack_item_fullname}" 45 | stack_item_label = "${var.stack_item_label}" 46 | vpc_id = "${module.vpc_base.vpc_id}" 47 | } 48 | 49 | ## Configures Virtual Private Gateway 50 | module "vpc_vpg" { 51 | # Example GitHub source 52 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//vpg" 53 | source = "../../vpg" 54 | 55 | stack_item_fullname = "${var.stack_item_fullname}" 56 | stack_item_label = "${var.stack_item_label}" 57 | vpc_attach = "${var.vpc_attach}" 58 | vpc_id = "${module.vpc_base.vpc_id}" 59 | } 60 | 61 | ## Configures routing 62 | resource "aws_route" "dmz-to-igw" { 63 | destination_cidr_block = "0.0.0.0/0" 64 | gateway_id = "${module.vpc_base.igw_id}" 65 | route_table_id = "${module.vpc_base.rt_dmz_id}" 66 | } 67 | 68 | resource "aws_route" "lan-to-nat" { 69 | count = "${var.azs_provisioned * var.lans_per_az}" 70 | 71 | destination_cidr_block = "0.0.0.0/0" 72 | instance_id = "${element(module.vpc_az.nat_ids,count.index)}" 73 | route_table_id = "${element(module.vpc_az.rt_lan_ids,count.index)}" 74 | } 75 | -------------------------------------------------------------------------------- /examples/basic/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output Variables 2 | 3 | output "vpc_id" { 4 | value = "${module.vpc_base.vpc_id}" 5 | } 6 | 7 | output "dmz_subnet_ids" { 8 | value = "${module.vpc_az.dmz_ids}" 9 | } 10 | 11 | output "lan_subnet_ids" { 12 | value = "${module.vpc_az.lan_ids}" 13 | } 14 | 15 | output "lan_rt_ids" { 16 | value = "${module.vpc_az.rt_lan_ids}" 17 | } 18 | -------------------------------------------------------------------------------- /examples/basic/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | } 7 | 8 | variable "stack_item_label" { 9 | type = "string" 10 | } 11 | 12 | ## VPC base parameters 13 | variable "enable_dns" { 14 | type = "string" 15 | default = "" 16 | } 17 | 18 | variable "enable_hostnames" { 19 | type = "string" 20 | default = "" 21 | } 22 | 23 | variable "region" { 24 | type = "string" 25 | } 26 | 27 | variable "vpc_cidr" { 28 | type = "string" 29 | } 30 | 31 | ## DHCP 32 | variable "domain_name" { 33 | type = "string" 34 | default = "" 35 | } 36 | 37 | ## AZ parameters 38 | variable "azs_provisioned" { 39 | type = "string" 40 | default = "" 41 | } 42 | 43 | variable "enable_dmz_public_ips" { 44 | type = "string" 45 | default = "" 46 | } 47 | 48 | variable "lans_per_az" { 49 | type = "string" 50 | default = "1" 51 | } 52 | 53 | variable "nat_eips_enabled" { 54 | type = "string" 55 | default = "" 56 | } 57 | 58 | ## VPG parameters 59 | variable "vpc_attach" { 60 | type = "string" 61 | default = "" 62 | } 63 | -------------------------------------------------------------------------------- /examples/complete/main.tf: -------------------------------------------------------------------------------- 1 | # AWS Virtual Private Cloud 2 | 3 | ## Configures AWS provider 4 | provider "aws" { 5 | region = "${var.region}" 6 | } 7 | 8 | ## Configures base VPC 9 | module "vpc_base" { 10 | # Example GitHub source 11 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//base" 12 | source = "../../base" 13 | 14 | enable_classiclink = "${var.enable_classiclink}" 15 | enable_hostnames = "${var.enable_hostnames}" 16 | instance_tenancy = "${var.instance_tenancy}" 17 | stack_item_fullname = "${var.stack_item_fullname}" 18 | stack_item_label = "${var.stack_item_label}" 19 | vpc_cidr = "${var.vpc_cidr}" 20 | } 21 | 22 | ## Configures DHCP 23 | module "vpc_dhcp" { 24 | # Example GitHub source 25 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//dhcp" 26 | source = "../../dhcp" 27 | 28 | domain_name = "${var.domain_name}" 29 | name_servers = ["${var.name_servers}"] 30 | netbios_name_servers = ["${var.netbios_name_servers}"] 31 | netbios_node_type = "${var.netbios_node_type}" 32 | ntp_servers = ["${var.ntp_servers}"] 33 | stack_item_fullname = "${var.stack_item_fullname}" 34 | stack_item_label = "${var.stack_item_label}" 35 | vpc_id = "${module.vpc_base.vpc_id}" 36 | } 37 | 38 | ## Configures ACLs 39 | resource "aws_network_acl" "acl" { 40 | vpc_id = "${module.vpc_base.vpc_id}" 41 | subnet_ids = ["${concat(module.vpc_az.lan_ids,module.vpc_az.dmz_ids)}"] 42 | 43 | tags { 44 | application = "${var.stack_item_fullname}" 45 | managed_by = "terraform" 46 | Name = "${var.stack_item_label}-acl" 47 | } 48 | } 49 | 50 | ## Configures Virtual Private Gateway 51 | module "vpc_vpg" { 52 | # Example GitHub source 53 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//vpg" 54 | source = "../../vpg" 55 | 56 | vpc_attach = "true" 57 | vpc_id = "${module.vpc_base.vpc_id}" 58 | stack_item_fullname = "${var.stack_item_fullname}" 59 | stack_item_label = "${var.stack_item_label}" 60 | } 61 | 62 | module "vpc_az" { 63 | # Example GitHub source 64 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//az" 65 | source = "../../az" 66 | 67 | azs_provisioned_override = "${var.azs_provisioned_override}" 68 | 69 | dmz_cidrs_override = ["${cidrsubnet(var.vpc_cidr,3,0)}", 70 | "${cidrsubnet(var.vpc_cidr,3,1)}", 71 | "${cidrsubnet(var.vpc_cidr,3,2)}", 72 | "${cidrsubnet(var.vpc_cidr,3,3)}", 73 | ] 74 | 75 | lan_cidrs_override = ["${cidrsubnet(var.vpc_cidr,4,8)}", 76 | "${cidrsubnet(var.vpc_cidr,4,9)}", 77 | "${cidrsubnet(var.vpc_cidr,4,10)}", 78 | "${cidrsubnet(var.vpc_cidr,4,11)}", 79 | "${cidrsubnet(var.vpc_cidr,4,12)}", 80 | "${cidrsubnet(var.vpc_cidr,4,13)}", 81 | "${cidrsubnet(var.vpc_cidr,4,14)}", 82 | "${cidrsubnet(var.vpc_cidr,4,15)}", 83 | ] 84 | 85 | lans_per_az = "${var.lans_per_az}" 86 | nat_eips_enabled = "false" 87 | nat_gateways_enabled = "${var.nat_gateways_enabled}" 88 | rt_dmz_id = "${module.vpc_base.rt_dmz_id}" 89 | stack_item_label = "${var.stack_item_label}" 90 | stack_item_fullname = "${var.stack_item_fullname}" 91 | vgw_ids = ["${module.vpc_vpg.vpg_id}"] 92 | vpc_id = "${module.vpc_base.vpc_id}" 93 | } 94 | 95 | ## Configures routing 96 | resource "aws_route" "dmz-to-igw" { 97 | destination_cidr_block = "0.0.0.0/0" 98 | gateway_id = "${module.vpc_base.igw_id}" 99 | route_table_id = "${module.vpc_base.rt_dmz_id}" 100 | } 101 | 102 | resource "aws_route" "lan-to-nat-gw" { 103 | count = "${length(var.azs_provisioned_override) * (length(var.lans_per_az) > 0 ? var.lans_per_az : "1") * signum(var.nat_gateways_enabled == "true" ? "1" : "0")}" 104 | 105 | destination_cidr_block = "0.0.0.0/0" 106 | nat_gateway_id = "${element(module.vpc_az.nat_ids,count.index)}" 107 | route_table_id = "${element(module.vpc_az.rt_lan_ids,count.index)}" 108 | } 109 | 110 | resource "aws_route" "lan-to-nat" { 111 | count = "${length(var.azs_provisioned_override) * (length(var.lans_per_az) > 0 ? var.lans_per_az : "1") * signum(var.nat_gateways_enabled == "true" ? "0" : "1")}" 112 | 113 | destination_cidr_block = "0.0.0.0/0" 114 | instance_id = "${element(module.vpc_az.nat_ids,count.index)}" 115 | route_table_id = "${element(module.vpc_az.rt_lan_ids,count.index)}" 116 | } 117 | 118 | resource "aws_vpc_endpoint" "s3-ep" { 119 | route_table_ids = ["${module.vpc_az.rt_lan_ids}"] 120 | service_name = "com.amazonaws.${var.region}.s3" 121 | vpc_id = "${module.vpc_base.vpc_id}" 122 | } 123 | -------------------------------------------------------------------------------- /examples/complete/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variables 2 | 3 | output "dmz_subnet_ids" { 4 | value = "${module.vpc_az.dmz_ids}" 5 | } 6 | 7 | output "lan_rt_ids" { 8 | value = "${module.vpc_az.rt_lan_ids}" 9 | } 10 | 11 | output "lan_subnet_ids" { 12 | value = "${module.vpc_az.lan_ids}" 13 | } 14 | 15 | output "vpc_id" { 16 | value = "${module.vpc_base.vpc_id}" 17 | } 18 | -------------------------------------------------------------------------------- /examples/complete/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource Tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | } 7 | 8 | variable "stack_item_label" { 9 | type = "string" 10 | } 11 | 12 | ## VPC Parameters 13 | variable "azs_provisioned_override" { 14 | type = "list" 15 | default = ["a", "c", "d", "e"] 16 | } 17 | 18 | variable "enable_classiclink" { 19 | type = "string" 20 | default = "" 21 | } 22 | 23 | variable "enable_hostnames" { 24 | type = "string" 25 | default = "" 26 | } 27 | 28 | variable "instance_tenancy" { 29 | type = "string" 30 | default = "" 31 | } 32 | 33 | variable "lans_per_az" { 34 | type = "string" 35 | default = "" 36 | } 37 | 38 | variable "nat_gateways_enabled" { 39 | type = "string" 40 | default = "" 41 | } 42 | 43 | variable "region" { 44 | type = "string" 45 | } 46 | 47 | variable "vpc_cidr" { 48 | type = "string" 49 | } 50 | 51 | ## DHCP 52 | variable "domain_name" { 53 | type = "string" 54 | default = "" 55 | } 56 | 57 | variable "name_servers" { 58 | type = "list" 59 | default = [] 60 | } 61 | 62 | variable "netbios_name_servers" { 63 | type = "list" 64 | default = [] 65 | } 66 | 67 | variable "netbios_node_type" { 68 | type = "string" 69 | default = "" 70 | } 71 | 72 | variable "ntp_servers" { 73 | type = "list" 74 | default = [] 75 | } 76 | -------------------------------------------------------------------------------- /examples/peering/main.tf: -------------------------------------------------------------------------------- 1 | # AWS VPC Peering Connection 2 | 3 | ## Configures AWS provider 4 | provider "aws" { 5 | region = "${var.region}" 6 | } 7 | 8 | ## Configures VPC peering connection 9 | module "vpc_peer" { 10 | # Example GitHub source 11 | #source = "github.com/unifio/terraform-aws-vpc?ref=master//peer" 12 | source = "../../peer" 13 | 14 | accepter_allow_classic_link_to_remote = "false" 15 | accepter_allow_remote_dns = "true" 16 | accepter_allow_to_remote_classic_link = "true" 17 | accepter_vpc_id = "${var.accepter_vpc_id}" 18 | requester_allow_classic_link_to_remote = "true" 19 | requester_allow_remote_dns = "false" 20 | requester_allow_to_remote_classic_link = "false" 21 | requester_vpc_id = "${var.requester_vpc_id}" 22 | stack_item_fullname = "${var.stack_item_fullname}" 23 | stack_item_label = "${var.stack_item_label}" 24 | } 25 | 26 | resource "aws_route" "requester-to-accepter" { 27 | count = "${length(var.requester_rt_lan_ids)}" 28 | 29 | destination_cidr_block = "${var.accepter_vpc_cidr}" 30 | route_table_id = "${element(var.requester_rt_lan_ids,count.index)}" 31 | vpc_peering_connection_id = "${module.vpc_peer.peer_connection_id}" 32 | } 33 | 34 | resource "aws_route" "accepter-to-requester" { 35 | count = "${length(var.accepter_rt_lan_ids)}" 36 | 37 | destination_cidr_block = "${var.requester_vpc_cidr}" 38 | route_table_id = "${element(var.accepter_rt_lan_ids,count.index)}" 39 | vpc_peering_connection_id = "${module.vpc_peer.peer_connection_id}" 40 | } 41 | -------------------------------------------------------------------------------- /examples/peering/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource Tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | description = "Long form descriptive name for this stack item. This value is used to create the 'application' resource tag for resources created by this stack item." 7 | } 8 | 9 | variable "stack_item_label" { 10 | type = "string" 11 | description = "Short form identifier for this stack. This value is used to create the 'Name' resource tag for resources created by this stack item, and also serves as a unique key for re-use." 12 | } 13 | 14 | ## Peering Parameters 15 | variable "accepter_rt_lan_ids" { 16 | type = "list" 17 | description = "The IDs of the peer VPC routing tables." 18 | } 19 | 20 | variable "accepter_vpc_cidr" { 21 | type = "string" 22 | description = "The ID of the peer VPC." 23 | } 24 | 25 | variable "accepter_vpc_id" { 26 | type = "string" 27 | description = "The ID of the VPC with which you are creating the VPC Peering Connection." 28 | } 29 | 30 | variable "region" { 31 | type = "string" 32 | } 33 | 34 | variable "requester_rt_lan_ids" { 35 | type = "list" 36 | description = "The IDs of the requesting VPC routing tables." 37 | } 38 | 39 | variable "requester_vpc_cidr" { 40 | type = "string" 41 | description = "The ID of the requester VPC." 42 | } 43 | 44 | variable "requester_vpc_id" { 45 | type = "string" 46 | description = "The ID of the requester VPC." 47 | } 48 | -------------------------------------------------------------------------------- /peer/main.tf: -------------------------------------------------------------------------------- 1 | # Peering Connection 2 | 3 | ## Set Terraform version constraint 4 | terraform { 5 | required_version = "> 0.11.0" 6 | } 7 | 8 | ## Provisions VPC peering 9 | resource "aws_vpc_peering_connection" "peer" { 10 | count = "${length(var.vpc_peering_connection_id) > 0 ? "0" : "1"}" 11 | 12 | auto_accept = "${var.accepter_region != "" ? "false" : var.auto_accept}" 13 | peer_owner_id = "${var.accepter_owner_id}" 14 | peer_region = "${var.accepter_region}" 15 | peer_vpc_id = "${var.accepter_vpc_id}" 16 | vpc_id = "${var.requester_vpc_id}" 17 | 18 | accepter { 19 | allow_classic_link_to_remote_vpc = "${var.accepter_allow_classic_link_to_remote}" 20 | allow_remote_vpc_dns_resolution = "${var.accepter_allow_remote_dns}" 21 | allow_vpc_to_remote_classic_link = "${var.accepter_allow_to_remote_classic_link}" 22 | } 23 | 24 | requester { 25 | allow_classic_link_to_remote_vpc = "${var.requester_allow_classic_link_to_remote}" 26 | allow_remote_vpc_dns_resolution = "${var.requester_allow_remote_dns}" 27 | allow_vpc_to_remote_classic_link = "${var.requester_allow_to_remote_classic_link}" 28 | } 29 | 30 | tags { 31 | application = "${var.stack_item_fullname}" 32 | managed_by = "terraform" 33 | Name = "${var.stack_item_label}-peer" 34 | } 35 | } 36 | 37 | resource "aws_vpc_peering_connection_accepter" "peer_accept" { 38 | count = "${length(var.vpc_peering_connection_id) > 0 ? "1" : "0"}" 39 | 40 | auto_accept = "${var.accepter_auto_accept}" 41 | vpc_peering_connection_id = "${var.vpc_peering_connection_id}" 42 | 43 | accepter { 44 | allow_classic_link_to_remote_vpc = "${var.accepter_allow_classic_link_to_remote}" 45 | allow_remote_vpc_dns_resolution = "${var.accepter_allow_remote_dns}" 46 | allow_vpc_to_remote_classic_link = "${var.accepter_allow_to_remote_classic_link}" 47 | } 48 | 49 | requester { 50 | allow_classic_link_to_remote_vpc = "${var.requester_allow_classic_link_to_remote}" 51 | allow_remote_vpc_dns_resolution = "${var.requester_allow_remote_dns}" 52 | allow_vpc_to_remote_classic_link = "${var.requester_allow_to_remote_classic_link}" 53 | } 54 | 55 | tags { 56 | application = "${var.stack_item_fullname}" 57 | managed_by = "terraform" 58 | Name = "${var.stack_item_label}-peer" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /peer/outputs.tf: -------------------------------------------------------------------------------- 1 | # Outputs 2 | 3 | output "peer_connection_id" { 4 | value = "${join(",",aws_vpc_peering_connection.peer.*.id)}" 5 | } 6 | -------------------------------------------------------------------------------- /peer/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource Tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | description = "Long form descriptive name for this stack item. This value is used to create the 'application' resource tag for resources created by this stack item." 7 | } 8 | 9 | variable "stack_item_label" { 10 | type = "string" 11 | description = "Short form identifier for this stack. This value is used to create the 'Name' resource tag for resources created by this stack item, and also serves as a unique key for re-use." 12 | } 13 | 14 | ## Peering parameters 15 | variable "accepter_allow_classic_link_to_remote" { 16 | type = "string" 17 | description = "Allow a local linked EC2-Classic instance to communicate with instances in a peer VPC. This enables an outbound communication from the local ClassicLink connection to the remote VPC." 18 | default = "" 19 | } 20 | 21 | variable "accepter_allow_remote_dns" { 22 | type = "string" 23 | description = "Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC." 24 | default = "false" 25 | } 26 | 27 | variable "accepter_allow_to_remote_classic_link" { 28 | type = "string" 29 | description = "Allow a local VPC to communicate with a linked EC2-Classic instance in a peer VPC. This enables an outbound communication from the local VPC to the remote ClassicLink connection." 30 | default = "" 31 | } 32 | 33 | variable "accepter_auto_accept" { 34 | type = "string" 35 | description = "Accept the peering (both VPCs need to be in the same AWS account)." 36 | default = "" 37 | } 38 | 39 | variable "accepter_owner_id" { 40 | type = "string" 41 | description = "The AWS account ID of the owner of the peer VPC." 42 | default = "" 43 | } 44 | 45 | variable "accepter_region" { 46 | type = "string" 47 | description = "The region of the accepter VPC of the VPC Peering Connection." 48 | default = "" 49 | } 50 | 51 | variable "accepter_vpc_id" { 52 | type = "string" 53 | description = "The ID of the VPC with which you are creating the VPC Peering Connection." 54 | default = "" 55 | } 56 | 57 | variable "auto_accept" { 58 | type = "string" 59 | description = "Accept the peering (both VPCs need to be in the same AWS account and region)." 60 | default = "true" 61 | } 62 | 63 | variable "requester_allow_classic_link_to_remote" { 64 | type = "string" 65 | description = "Allow a local linked EC2-Classic instance to communicate with instances in a peer VPC. This enables an outbound communication from the local ClassicLink connection to the remote VPC." 66 | default = "" 67 | } 68 | 69 | variable "requester_allow_remote_dns" { 70 | type = "string" 71 | description = "Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC." 72 | default = "false" 73 | } 74 | 75 | variable "requester_allow_to_remote_classic_link" { 76 | type = "string" 77 | description = "Allow a local VPC to communicate with a linked EC2-Classic instance in a peer VPC. This enables an outbound communication from the local VPC to the remote ClassicLink connection." 78 | default = "" 79 | } 80 | 81 | variable "requester_vpc_id" { 82 | type = "string" 83 | description = "The ID of the requester VPC." 84 | default = "" 85 | } 86 | 87 | variable "vpc_peering_connection_id" { 88 | type = "string" 89 | description = "The VPC Peering Connection ID to manage." 90 | default = "" 91 | } 92 | -------------------------------------------------------------------------------- /vpg/main.tf: -------------------------------------------------------------------------------- 1 | # Virtual Private Gateway 2 | 3 | ## Set Terraform version constraint 4 | terraform { 5 | required_version = "> 0.11.0" 6 | } 7 | 8 | ## Gateway configuration 9 | resource "aws_vpn_gateway" "vpg" { 10 | availability_zone = "${var.availability_zone}" 11 | 12 | tags { 13 | application = "${var.stack_item_fullname}" 14 | managed_by = "terraform" 15 | Name = "${var.stack_item_label}-vpg" 16 | } 17 | } 18 | 19 | resource "aws_vpn_gateway_attachment" "attach" { 20 | count = "${length(var.vpc_attach) > 0 && var.vpc_attach == "true" ? 1 : 0}" 21 | 22 | vpc_id = "${var.vpc_id}" 23 | vpn_gateway_id = "${aws_vpn_gateway.vpg.id}" 24 | } 25 | -------------------------------------------------------------------------------- /vpg/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output Variables 2 | 3 | ## Returns ID of the VPG 4 | output "vpg_id" { 5 | value = "${aws_vpn_gateway.vpg.id}" 6 | } 7 | -------------------------------------------------------------------------------- /vpg/variables.tf: -------------------------------------------------------------------------------- 1 | # Input Variables 2 | 3 | ## Resource tags 4 | variable "stack_item_fullname" { 5 | type = "string" 6 | description = "Long form descriptive name for this stack item. This value is used to create the 'application' resource tag for resources created by this stack item." 7 | } 8 | 9 | variable "stack_item_label" { 10 | type = "string" 11 | description = "Short form identifier for this stack. This value is used to create the 'Name' resource tag for resources created by this stack item, and also serves as a unique key for re-use." 12 | } 13 | 14 | ## VPC parameters 15 | variable "availability_zone" { 16 | type = "string" 17 | description = "The Availability Zone for the virtual private gateway." 18 | default = "" 19 | } 20 | 21 | variable "vpc_attach" { 22 | type = "string" 23 | description = "Specifies whether the VPG should be associated with a VPC." 24 | default = "" 25 | } 26 | 27 | variable "vpc_id" { 28 | type = "string" 29 | description = "The VPC ID to create in." 30 | default = "" 31 | } 32 | --------------------------------------------------------------------------------