From fb647f61f9d73a9b57aa41f7271bec9f80779b03 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 20:04:43 -0500 Subject: [PATCH 1/5] Module - AWS Amplify (#85) * feat: add aws amplify module * chore: terraform fmt and terraform-docs * ignore jscpd in the github actions test workflow --------- Co-authored-by: zachreborn --- .github/workflows/test.yml | 1 + .jscpd.json | 5 +- modules/aws/amplify/README.md | 212 +++++++++++++++++++++++++++++ modules/aws/amplify/main.tf | 137 +++++++++++++++++++ modules/aws/amplify/outputs.tf | 4 + modules/aws/amplify/variables.tf | 222 +++++++++++++++++++++++++++++++ 6 files changed, 577 insertions(+), 4 deletions(-) create mode 100755 modules/aws/amplify/README.md create mode 100755 modules/aws/amplify/main.tf create mode 100755 modules/aws/amplify/outputs.tf create mode 100755 modules/aws/amplify/variables.tf diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2545c0620..6a511dda2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,6 +59,7 @@ jobs: uses: super-linter/super-linter@v7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VALIDATE_JSCPD: false VALIDATE_MARKDOWN: false VALIDATE_MARKDOWN_PRETTIER: false VALIDATE_NATURAL_LANGUAGE: false diff --git a/.jscpd.json b/.jscpd.json index c5c45d5ff..6a733d434 100644 --- a/.jscpd.json +++ b/.jscpd.json @@ -1,8 +1,5 @@ { "ignore": [ - "**/*.md" - ], - "pattern": [ - "**/*.tf" + "**/README.md" ] } \ No newline at end of file diff --git a/modules/aws/amplify/README.md b/modules/aws/amplify/README.md new file mode 100755 index 000000000..e9810e066 --- /dev/null +++ b/modules/aws/amplify/README.md @@ -0,0 +1,212 @@ + + + + + + + + +[![Contributors][contributors-shield]][contributors-url] +[![Forks][forks-shield]][forks-url] +[![Stargazers][stars-shield]][stars-url] +[![Issues][issues-shield]][issues-url] +[![MIT License][license-shield]][license-url] +[![LinkedIn][linkedin-shield]][linkedin-url] + + +
+
+ + Logo + + +

Amplify

+

+ This module created and manages an Amplify app, branches, and domain associations. Amplify is a continuous deployment and hosting service for modern web applications. For more information, see the AWS Amplify documentation. +
+ Explore the docs » +
+
+ Zachary Hill + · + Report Bug + · + Request Feature +

+
+ + +
+ Table of Contents +
    +
  1. Usage
  2. +
  3. Requirements
  4. +
  5. Providers
  6. +
  7. Modules
  8. +
  9. Resources
  10. +
  11. Inputs
  12. +
  13. Outputs
  14. +
  15. License
  16. +
  17. Contact
  18. +
  19. Acknowledgments
  20. +
+
+ + + +## Usage + +### Simple Example + +``` +module "example_website" { + source = "github.com/zachreborn/terraform-modules//modules/aws/amplify" + + description = "example Website - Based on Astro" + name = "example_astro_website" + repository = "https://github.com/example/example_astro_website" + branches = { + main = { + domain_name = "example.org" + framework = "Astro" + stage = "PRODUCTION" + sub_domains = ["www"] + }, + staging = { + basic_auth_credentials = var.example_basic_auth_credentials + domain_name = "staging.example.org" + enable_basic_auth = true + framework = "Astro" + }, + dev = { + basic_auth_credentials = var.example_basic_auth_credentials + domain_name = "dev.example.org" + enable_basic_auth = true + framework = "Astro" + } + } + + custom_rules = [ + { + source = "/<*>" + status = "404-200" + target = "/404" + } + ] +} +``` + +_For more examples, please refer to the [Documentation](https://github.com/zachreborn/terraform-modules)_ + +

(back to top)

+ + + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aws](#requirement\_aws) | >= 4.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.0.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_amplify_app.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/amplify_app) | resource | +| [aws_amplify_branch.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/amplify_branch) | resource | +| [aws_amplify_domain_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/amplify_domain_association) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [access\_token](#input\_access\_token) | Access token for the Amplify App. | `string` | `null` | no | +| [auto\_branch\_creation\_config](#input\_auto\_branch\_creation\_config) | Auto branch creation config for the Amplify App. |
map(object({
basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password".
build_spec = optional(string) # Build spec for the branch.
enable_auto_build = optional(bool) # Enable auto build for the branch.
enable_basic_auth = optional(bool) # Enable basic auth for the branch.
enable_performance_mode = optional(bool) # Enable performance mode for the branch.
enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch.
environment_variables = optional(map(string)) # Map of environment variables for the branch.
framework = optional(string) # The framework for the branch.
pull_request_environment_name = optional(string) # The name of the pull request environment.
stage = optional(string) # Description of the stage. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST.
}))
| `null` | no | +| [auto\_branch\_creation\_patterns](#input\_auto\_branch\_creation\_patterns) | Patterns for auto branch creation. | `list(string)` | `null` | no | +| [basic\_auth\_credentials](#input\_basic\_auth\_credentials) | Basic auth credentials for the Amplify App. Must be input as 'username:password'. | `string` | `null` | no | +| [branches](#input\_branches) | A map of branches for the Amplify App. The key becomes the branch name and the value is an object of branch attributes or settings. |
map(object({
basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password".
certificate_type = optional(string, "AMPLIFY_MANAGED") # The certificate type for the domain association. Valid values are AMPLIFY_MANAGED or CUSTOM.
custom_certificate_arn = optional(string) # The ARN for the custom certificate.
description = optional(string) # The description of the branch.
display_name = optional(string) # The display name of the branch. This gets used as the default domain prefix.
domain_name = string # The domain name for the domain association.
enable_auto_build = optional(bool, true) # Enable auto build for the branch.
enable_auto_sub_domain = optional(bool, false) # Enable auto sub domain for the domain association.
enable_basic_auth = optional(bool) # Enable basic auth for the branch.
enable_certificate = optional(bool, true) # Enable certificate for the domain association.
enable_notification = optional(bool) # Enable notification for the branch.
enable_performance_mode = optional(bool) # Enable performance mode for the branch.
enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch.
environment_variables = optional(map(string)) # Map of environment variables for the branch.
framework = optional(string) # The framework for the branch.
pull_request_environment_name = optional(string) # The name of the pull request environment.
stage = optional(string) # The stage for the branch. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST.
sub_domains = optional(set(string)) # A list of sub domains to associate with the branch.
ttl = optional(number) # The TTL for the branch.
wait_for_verification = optional(bool, true) # Wait for verification for the domain association.
}))
| n/a | yes | +| [build\_spec](#input\_build\_spec) | Build spec for the Amplify App. | `string` | `null` | no | +| [cache\_config\_type](#input\_cache\_config\_type) | Cache config type for the Amplify App. Valid values are AMPLIFY\_MANAGED, AMPLIFY\_MANAGED\_NO\_COOKIES, | `string` | `"AMPLIFY_MANAGED"` | no | +| [custom\_headers](#input\_custom\_headers) | Custom headers string for the Amplify App. | `string` | `null` | no | +| [custom\_rules](#input\_custom\_rules) | List of custom rules for the Amplify App. |
list(object({
condition = optional(string) # Condition for a URL redirect or rewrite.
source = string # Source pattern for URL redirect or rewrite.
status = optional(string) # Status code for URL redirect or rewrite. Valid values are 200, 301, 302, 404, 404-200.
target = string # Target pattern for URL redirect or rewrite.
}))
| `null` | no | +| [description](#input\_description) | Description of the Amplify App. | `string` | `null` | no | +| [enable\_auto\_branch\_creation](#input\_enable\_auto\_branch\_creation) | Enable auto branch creation for the Amplify App. | `bool` | `false` | no | +| [enable\_basic\_auth](#input\_enable\_basic\_auth) | Enable basic auth for the Amplify App. | `bool` | `false` | no | +| [enable\_branch\_auto\_build](#input\_enable\_branch\_auto\_build) | Enable branch auto build for the Amplify App. | `bool` | `false` | no | +| [enable\_branch\_auto\_deletion](#input\_enable\_branch\_auto\_deletion) | Enable branch auto deletion for the Amplify App. | `bool` | `false` | no | +| [environment\_variables](#input\_environment\_variables) | Environment variables in a map for the Amplify App. | `map(string)` | `null` | no | +| [iam\_service\_role\_arn](#input\_iam\_service\_role\_arn) | IAM service role ARN for the Amplify App. | `string` | `null` | no | +| [name](#input\_name) | Name of the Amplify App. | `string` | n/a | yes | +| [oauth\_token](#input\_oauth\_token) | OAuth token for the Amplify App. | `string` | `null` | no | +| [platform](#input\_platform) | Platform for the Amplify App. Options are WEB or WEB\_COMPUTE. | `string` | `"WEB"` | no | +| [repository](#input\_repository) | Repository for the Amplify App. This could be hosted in AWS Code Commit, Bitbucket, GitHub, GitLab, etc. | `string` | `null` | no | +| [tags](#input\_tags) | Tags for the Amplify App. | `map(string)` |
{
"created_by": "terraform",
"environment": "prod",
"terraform": "true"
}
| no | + +## Outputs + +No outputs. + + + + +## License + +Distributed under the MIT License. See `LICENSE.txt` for more information. + +

(back to top)

+ + + +## Contact + +Zachary Hill - [![LinkedIn][linkedin-shield]][linkedin-url] - zhill@zacharyhill.co + +Project Link: [https://github.com/zachreborn/terraform-modules](https://github.com/zachreborn/terraform-modules) + +

(back to top)

+ + + +## Acknowledgments + +- [Zachary Hill](https://zacharyhill.co) +- [Jake Jones](https://github.com/jakeasarus) + +

(back to top)

+ + + + +[contributors-shield]: https://img.shields.io/github/contributors/zachreborn/terraform-modules.svg?style=for-the-badge +[contributors-url]: https://github.com/zachreborn/terraform-modules/graphs/contributors +[forks-shield]: https://img.shields.io/github/forks/zachreborn/terraform-modules.svg?style=for-the-badge +[forks-url]: https://github.com/zachreborn/terraform-modules/network/members +[stars-shield]: https://img.shields.io/github/stars/zachreborn/terraform-modules.svg?style=for-the-badge +[stars-url]: https://github.com/zachreborn/terraform-modules/stargazers +[issues-shield]: https://img.shields.io/github/issues/zachreborn/terraform-modules.svg?style=for-the-badge +[issues-url]: https://github.com/zachreborn/terraform-modules/issues +[license-shield]: https://img.shields.io/github/license/zachreborn/terraform-modules.svg?style=for-the-badge +[license-url]: https://github.com/zachreborn/terraform-modules/blob/master/LICENSE.txt +[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555 +[linkedin-url]: https://www.linkedin.com/in/zachary-hill-5524257a/ +[product-screenshot]: /images/screenshot.webp +[Terraform.io]: https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform +[Terraform-url]: https://terraform.io diff --git a/modules/aws/amplify/main.tf b/modules/aws/amplify/main.tf new file mode 100755 index 000000000..7d27f3061 --- /dev/null +++ b/modules/aws/amplify/main.tf @@ -0,0 +1,137 @@ +########################### +# Provider Configuration +########################### +terraform { + required_version = ">= 1.0.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0.0" + } + } +} + +########################### +# Data Sources +########################### + + +########################### +# Locals +########################### + +########################### +# Module Configuration +########################### + +########################### +# Amplify App +########################### +resource "aws_amplify_app" "this" { + access_token = var.access_token + auto_branch_creation_patterns = var.auto_branch_creation_patterns + basic_auth_credentials = var.basic_auth_credentials != null ? base64encode(var.basic_auth_credentials) : null + build_spec = var.build_spec + custom_headers = var.custom_headers + description = var.description + enable_auto_branch_creation = var.enable_auto_branch_creation + enable_basic_auth = var.enable_basic_auth + enable_branch_auto_build = var.enable_branch_auto_build + enable_branch_auto_deletion = var.enable_branch_auto_deletion + environment_variables = var.environment_variables + name = var.name + iam_service_role_arn = var.iam_service_role_arn + oauth_token = var.oauth_token + platform = var.platform + repository = var.repository + tags = var.tags + + dynamic "auto_branch_creation_config" { + for_each = var.auto_branch_creation_config != null ? var.auto_branch_creation_config : {} + content { + basic_auth_credentials = auto_branch_creation_config.value.basic_auth_credentials != null ? base64encode(auto_branch_creation_config.value.basic_auth_credentials) : null + build_spec = auto_branch_creation_config.value.build_spec + enable_auto_build = auto_branch_creation_config.value.enable_auto_build + enable_basic_auth = auto_branch_creation_config.value.enable_basic_auth + enable_performance_mode = auto_branch_creation_config.value.enable_performance_mode + enable_pull_request_preview = auto_branch_creation_config.value.enable_pull_request_preview + environment_variables = auto_branch_creation_config.value.environment_variables + framework = auto_branch_creation_config.value.framework + pull_request_environment_name = auto_branch_creation_config.value.pull_request_environment_name + stage = auto_branch_creation_config.value.stage + } + } + + dynamic "cache_config" { + for_each = var.cache_config_type != null ? [true] : [] + content { + type = var.cache_config_type + } + } + dynamic "custom_rule" { + for_each = var.custom_rules != null ? var.custom_rules : [] + content { + condition = custom_rule.value.condition + source = custom_rule.value.source + status = custom_rule.value.status + target = custom_rule.value.target + } + } +} + +########################### +# Amplify App Branch +########################### +resource "aws_amplify_branch" "this" { + for_each = var.branches != null ? var.branches : {} + app_id = aws_amplify_app.this.id + basic_auth_credentials = each.value.basic_auth_credentials != null ? base64encode(each.value.basic_auth_credentials) : null + branch_name = each.key + description = each.value.description + display_name = each.value.display_name != null ? each.value.display_name : each.key + enable_auto_build = each.value.enable_auto_build + enable_basic_auth = each.value.enable_basic_auth + enable_notification = each.value.enable_notification + enable_performance_mode = each.value.enable_performance_mode + enable_pull_request_preview = each.value.enable_pull_request_preview + environment_variables = each.value.environment_variables + framework = each.value.framework + pull_request_environment_name = each.value.pull_request_environment_name + stage = each.value.stage + tags = var.tags + ttl = each.value.ttl +} + +########################### +# Amplify App Domain Association +########################### +resource "aws_amplify_domain_association" "this" { + for_each = var.branches + app_id = aws_amplify_app.this.id + domain_name = each.value.domain_name + enable_auto_sub_domain = each.value.enable_auto_sub_domain + wait_for_verification = each.value.wait_for_verification + dynamic "certificate_settings" { + for_each = each.value.enable_certificate ? [true] : [] + content { + custom_certificate_arn = each.value.custom_certificate_arn + type = each.value.certificate_type + } + } + + dynamic "sub_domain" { + for_each = var.branches + content { + branch_name = each.key + prefix = "" + } + } + + dynamic "sub_domain" { + for_each = each.value.sub_domains != null ? each.value.sub_domains : [] + content { + branch_name = each.key + prefix = sub_domain.key + } + } +} diff --git a/modules/aws/amplify/outputs.tf b/modules/aws/amplify/outputs.tf new file mode 100755 index 000000000..9a2435c60 --- /dev/null +++ b/modules/aws/amplify/outputs.tf @@ -0,0 +1,4 @@ +########################### +# Resource Outputs +########################### + diff --git a/modules/aws/amplify/variables.tf b/modules/aws/amplify/variables.tf new file mode 100755 index 000000000..7ae4f5576 --- /dev/null +++ b/modules/aws/amplify/variables.tf @@ -0,0 +1,222 @@ +########################### +# Resource Variables +########################### + +########################### +# Amplify App +########################### + +variable "access_token" { + description = "Access token for the Amplify App." + type = string + default = null +} + +variable "auto_branch_creation_config" { + description = "Auto branch creation config for the Amplify App." + type = map(object({ + basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password". + build_spec = optional(string) # Build spec for the branch. + enable_auto_build = optional(bool) # Enable auto build for the branch. + enable_basic_auth = optional(bool) # Enable basic auth for the branch. + enable_performance_mode = optional(bool) # Enable performance mode for the branch. + enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch. + environment_variables = optional(map(string)) # Map of environment variables for the branch. + framework = optional(string) # The framework for the branch. + pull_request_environment_name = optional(string) # The name of the pull request environment. + stage = optional(string) # Description of the stage. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST. + })) + default = null +} + +variable "auto_branch_creation_patterns" { + description = "Patterns for auto branch creation." + type = list(string) + default = null +} + +variable "basic_auth_credentials" { + description = "Basic auth credentials for the Amplify App. Must be input as 'username:password'." + type = string + sensitive = false + default = null +} + +variable "build_spec" { + description = "Build spec for the Amplify App." + type = string + default = null +} + +variable "cache_config_type" { + description = "Cache config type for the Amplify App. Valid values are AMPLIFY_MANAGED, AMPLIFY_MANAGED_NO_COOKIES, " + type = string + default = "AMPLIFY_MANAGED" + validation { + condition = var.cache_config_type == "AMPLIFY_MANAGED" || var.cache_config_type == "AMPLIFY_MANAGED_NO_COOKIES" + error_message = "Cache config type must be either AMPLIFY_MANAGED or AMPLIFY_MANAGED_NO_COOKIES." + } +} + +variable "custom_headers" { + description = "Custom headers string for the Amplify App." + type = string + default = null +} + +variable "custom_rules" { + description = "List of custom rules for the Amplify App." + type = list(object({ + condition = optional(string) # Condition for a URL redirect or rewrite. + source = string # Source pattern for URL redirect or rewrite. + status = optional(string) # Status code for URL redirect or rewrite. Valid values are 200, 301, 302, 404, 404-200. + target = string # Target pattern for URL redirect or rewrite. + })) + default = null + # Example: + # custom_rules = [ + # { + # source = "/<*>" + # status = "404-200" + # target = "/404" + # }, + # { + # source = "https://www.example.org" + # status = "301" + # target = "https://example.org" + # } + # ] +} + +variable "description" { + description = "Description of the Amplify App." + type = string + default = null +} + +variable "enable_auto_branch_creation" { + description = "Enable auto branch creation for the Amplify App." + type = bool + default = false +} + +variable "enable_basic_auth" { + description = "Enable basic auth for the Amplify App." + type = bool + default = false +} + +variable "enable_branch_auto_build" { + description = "Enable branch auto build for the Amplify App." + type = bool + default = false +} + +variable "enable_branch_auto_deletion" { + description = "Enable branch auto deletion for the Amplify App." + type = bool + default = false +} + +variable "environment_variables" { + description = "Environment variables in a map for the Amplify App." + type = map(string) + default = null +} + +variable "name" { + description = "Name of the Amplify App." + type = string +} + +variable "iam_service_role_arn" { + description = "IAM service role ARN for the Amplify App." + type = string + default = null +} + +variable "oauth_token" { + description = "OAuth token for the Amplify App." + type = string + default = null +} + +variable "platform" { + description = "Platform for the Amplify App. Options are WEB or WEB_COMPUTE." + type = string + default = "WEB" + validation { + condition = var.platform == "WEB" || var.platform == "WEB_COMPUTE" + error_message = "Platform must be either WEB or WEB_COMPUTE." + } +} + +variable "repository" { + description = "Repository for the Amplify App. This could be hosted in AWS Code Commit, Bitbucket, GitHub, GitLab, etc." + type = string + default = null +} + +########################### +# Amplify Branch +########################### + +variable "branches" { + description = "A map of branches for the Amplify App. The key becomes the branch name and the value is an object of branch attributes or settings." + type = map(object({ + basic_auth_credentials = optional(string) # Basic auth credentials for the branch. Must be input as "username:password". + certificate_type = optional(string, "AMPLIFY_MANAGED") # The certificate type for the domain association. Valid values are AMPLIFY_MANAGED or CUSTOM. + custom_certificate_arn = optional(string) # The ARN for the custom certificate. + description = optional(string) # The description of the branch. + display_name = optional(string) # The display name of the branch. This gets used as the default domain prefix. + domain_name = string # The domain name for the domain association. + enable_auto_build = optional(bool, true) # Enable auto build for the branch. + enable_auto_sub_domain = optional(bool, false) # Enable auto sub domain for the domain association. + enable_basic_auth = optional(bool) # Enable basic auth for the branch. + enable_certificate = optional(bool, true) # Enable certificate for the domain association. + enable_notification = optional(bool) # Enable notification for the branch. + enable_performance_mode = optional(bool) # Enable performance mode for the branch. + enable_pull_request_preview = optional(bool) # Enable pull request preview for the branch. + environment_variables = optional(map(string)) # Map of environment variables for the branch. + framework = optional(string) # The framework for the branch. + pull_request_environment_name = optional(string) # The name of the pull request environment. + stage = optional(string) # The stage for the branch. Valid values are PRODUCTION, BETA, DEVELOPMENT, EXPERIMENTAL, PULL_REQUEST. + sub_domains = optional(set(string)) # A list of sub domains to associate with the branch. + ttl = optional(number) # The TTL for the branch. + wait_for_verification = optional(bool, true) # Wait for verification for the domain association. + })) + # Example: + # branches = { + # main = { + # domain_name = "example.org" + # framework = "Astro" + # stage = "PRODUCTION" + # sub_domains = ["www"] + # }, + # staging = { + # basic_auth_credentials = var.example_basic_auth_credentials + # domain_name = "staging.example.org" + # enable_basic_auth = true + # framework = "Astro" + # }, + # dev = { + # basic_auth_credentials = var.example_basic_auth_credentials + # domain_name = "dev.example.org" + # enable_basic_auth = true + # framework = "Astro" + # } +} + +########################### +# General Variables +########################### + +variable "tags" { + description = "Tags for the Amplify App." + type = map(string) + default = { + created_by = "terraform" # Your name goes here + terraform = "true" + environment = "prod" + } +} From 16567aa8bcc458ea8bc998a413298c9fc91909d4 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 21:03:17 -0500 Subject: [PATCH 2/5] Deprecate tfsec (#113) * removed the tfsec scan * converting nighly scan from tfsec to checkov --- .github/workflows/scan.yml | 41 +++++++++++++++++++ .../scheduled_tfsec_security_scan.yml | 32 --------------- .github/workflows/test.yml | 14 ------- 3 files changed, 41 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/scan.yml delete mode 100644 .github/workflows/scheduled_tfsec_security_scan.yml diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml new file mode 100644 index 000000000..e4df70fe0 --- /dev/null +++ b/.github/workflows/scan.yml @@ -0,0 +1,41 @@ +--- +name: Checkov Scan + +on: + # Allows this workflow to be run manually from the Actions tab in GitHub. + workflow_dispatch: + + # Runs the workflow on a schedule, every 12 hours. + schedule: + - cron: "33 */12 * * *" + +jobs: + scan: + name: Checkov Scan + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Clone repo + uses: actions/checkout@v4 + + - name: Checkov Scan + uses: bridgecrewio/checkov-action@v12 + with: + # This will add both a CLI output to the console and create a results.sarif file + output_format: cli,sarif + output_file_path: console,results.sarif + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + # Results are generated only on a success or failure + # this is required since GitHub by default won't run the next step + # when the previous one has failed. Security checks that do not pass will 'fail'. + # An alternative is to add `continue-on-error: true` to the previous step + # Or 'soft_fail: true' to checkov. + if: success() || failure() + with: + sarif_file: results.sarif diff --git a/.github/workflows/scheduled_tfsec_security_scan.yml b/.github/workflows/scheduled_tfsec_security_scan.yml deleted file mode 100644 index 629dadd3f..000000000 --- a/.github/workflows/scheduled_tfsec_security_scan.yml +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: Nightly - tfsec Security Scan - -on: - workflow_dispatch: - schedule: - - cron: "33 */12 * * *" - -jobs: - tfsec: - name: Run tfsec Security Scan Report - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - steps: - - name: Clone repo - uses: actions/checkout@v4 - - - name: Run tfsec scan with SARIF output - uses: aquasecurity/tfsec-sarif-action@master - with: - sarif_file: tfsec.sarif - full_repo_scan: true - - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 - with: - # Path to SARIF file relative to the root of the repository - sarif_file: tfsec.sarif diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6a511dda2..c8ba81e56 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,20 +28,6 @@ jobs: id: fmt run: terraform fmt -check -diff -recursive - test_tfsec: - name: tfsec - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Run tfsec and write pull request comments - uses: aquasecurity/tfsec-pr-commenter-action@main - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - tfsec_args: --force-all-dirs - test_linter: name: Linter runs-on: ubuntu-latest From 213a55810646b65ae9af730edb89baa3c0725d17 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 21:12:14 -0500 Subject: [PATCH 3/5] updated scan with continue-on-error (#114) --- .github/workflows/scan.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index e4df70fe0..f8ab0747c 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -25,6 +25,8 @@ jobs: - name: Checkov Scan uses: bridgecrewio/checkov-action@v12 with: + # Ensures that the scan will continue even if there are errors + continue-on-error: true # This will add both a CLI output to the console and create a results.sarif file output_format: cli,sarif output_file_path: console,results.sarif From 55462889e4f62ed596ca853615a058a2a69f6d04 Mon Sep 17 00:00:00 2001 From: Zachary Hill Date: Thu, 9 Jan 2025 21:17:34 -0500 Subject: [PATCH 4/5] continue-on-error to soft_fail (#115) --- .github/workflows/scan.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index f8ab0747c..9f736ff12 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -25,12 +25,13 @@ jobs: - name: Checkov Scan uses: bridgecrewio/checkov-action@v12 with: - # Ensures that the scan will continue even if there are errors - continue-on-error: true # This will add both a CLI output to the console and create a results.sarif file output_format: cli,sarif output_file_path: console,results.sarif + # Ensures that the scan will continue even if there are errors + soft_fail: true + - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v3 # Results are generated only on a success or failure From 0e8f64b0423e324ff0ab30847d7bce5e99cbf5fe Mon Sep 17 00:00:00 2001 From: Jake Jones Date: Thu, 9 Jan 2025 21:48:22 -0500 Subject: [PATCH 5/5] VPC Module - Allow disabling of the internet gateway (#107) * updated igw args to allow false == 0 count * added new logic for igw * added two new examples for disabling the igw * fixed index of the pointers * corrected variable to enable_internet_gateway * added type to all vpc variables * chore: terraform fmt and terraform-docs --------- Co-authored-by: Jakeasaurus Co-authored-by: Zachary Hill --- modules/aws/vpc/README.md | 115 ++++++++++++++++++++++++++--------- modules/aws/vpc/main.tf | 19 ++++-- modules/aws/vpc/variables.tf | 94 +++++++++++++++++++--------- 3 files changed, 165 insertions(+), 63 deletions(-) diff --git a/modules/aws/vpc/README.md b/modules/aws/vpc/README.md index 34656c366..846578115 100755 --- a/modules/aws/vpc/README.md +++ b/modules/aws/vpc/README.md @@ -1,7 +1,7 @@ - + + [![Contributors][contributors-shield]][contributors-url] [![Forks][forks-shield]][forks-url] [![Stargazers][stars-shield]][stars-url] @@ -18,7 +19,6 @@ [![MIT License][license-shield]][license-url] [![LinkedIn][linkedin-shield]][linkedin-url] -
@@ -41,7 +41,6 @@

-
Table of Contents @@ -59,11 +58,14 @@
- + ## Usage + ### Simple Example + This example sends uses an internet gateway for the public subnets and NAT gateways for the internal subnets. It utilizes the 10.11.0.0/16 subnet space with /24 subnets for each segmented subnet per availability zone. + ``` module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -81,7 +83,9 @@ module "vpc" { ``` ### Firewall Example + This example sends all egress traffic out a EC2 instance acting as a firewall. It also changes the default VPC CIDR block and subnets. + ``` module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -101,7 +105,9 @@ module "vpc" { ``` ### Setting Subnet Example + This example sends uses an internet gateway for the public subnets and NAT gateways for the internal subnets. It utilizes a unique 10.100.0.0/16 subnet space with /24 subnets for each segmented subnet per availability zone. + ``` module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -125,7 +131,9 @@ module "vpc" { ``` ### Disabling Unneeded Subnets + This example disabled unused subnets and associated resources. In the example we leave only the public and private subnets enabled. + ```hcl module "vpc" { source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" @@ -148,6 +156,57 @@ module "vpc" { } ``` +### Disabling the Internet Gateway + +This example disables the internet gateway, making this VPC a private VPC. This is useful for VPCs which do not need to communicate with the internet, or do so via an egress inspection VPC, SDWAN, or other solution. + +```hcl +module "vpc" { + source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" + + name = "client_prod_vpc" + vpc_cidr = "10.11.0.0/16" + azs = ["us-east-1a", "us-east-1b", "us-east-1c"] + db_subnets_list = [] + dmz_subnets_list = [] + mgmt_subnets_list = [] + private_subnets_list = ["10.11.0.0/24", "10.11.1.0/24", "10.11.2.0/24"] + public_subnets_list = [] + workspaces_subnets_list = [] + tags = { + terraform = "true" + created_by = "Zachary Hill" + environment = "prod" + project = "core_infrastructure" + } +} +``` + +Alternatively, you can disable the internet gateway by setting the `enable_internet_gateway` variable to `false`. This is useful if you still want to have public subnets. + +```hcl +module "vpc" { + source = "github.com/zachreborn/terraform-modules//modules/aws/vpc" + + name = "client_prod_vpc" + vpc_cidr = "10.11.0.0/16" + azs = ["us-east-1a", "us-east-1b", "us-east-1c"] + db_subnets_list = [] + dmz_subnets_list = [] + mgmt_subnets_list = [] + private_subnets_list = ["10.11.0.0/24", "10.11.1.0/24", "10.11.2.0/24"] + public_subnets_list = ["10.11.200.0/24", "10.11.201.0/24", "10.11.202.0/24"] + workspaces_subnets_list = [] + enable_internet_gateway = false + tags = { + terraform = "true" + created_by = "Zachary Hill" + environment = "prod" + project = "core_infrastructure" + } +} +``` + _For more examples, please refer to the [Documentation](https://github.com/zachreborn/terraform-modules)_

(back to top)

@@ -227,17 +286,18 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [azs](#input\_azs) | A list of Availability zones in the region | `list` |
[
"us-east-2a",
"us-east-2b",
"us-east-2c"
]
| no | +| [azs](#input\_azs) | A list of Availability zones in the region | `list(string)` |
[
"us-east-2a",
"us-east-2b",
"us-east-2c"
]
| no | | [cloudwatch\_name\_prefix](#input\_cloudwatch\_name\_prefix) | (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. | `string` | `"flow_logs_"` | no | | [cloudwatch\_retention\_in\_days](#input\_cloudwatch\_retention\_in\_days) | (Optional) Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire. | `number` | `90` | no | -| [db\_propagating\_vgws](#input\_db\_propagating\_vgws) | A list of VGWs the db route table should propagate. | `list` | `[]` | no | -| [db\_subnets\_list](#input\_db\_subnets\_list) | A list of database subnets inside the VPC. | `list` |
[
"10.11.11.0/24",
"10.11.12.0/24",
"10.11.13.0/24"
]
| no | -| [dmz\_propagating\_vgws](#input\_dmz\_propagating\_vgws) | A list of VGWs the DMZ route table should propagate. | `list` | `[]` | no | -| [dmz\_subnets\_list](#input\_dmz\_subnets\_list) | A list of DMZ subnets inside the VPC. | `list` |
[
"10.11.101.0/24",
"10.11.102.0/24",
"10.11.103.0/24"
]
| no | +| [db\_propagating\_vgws](#input\_db\_propagating\_vgws) | A list of VGWs the db route table should propagate. | `list(string)` | `null` | no | +| [db\_subnets\_list](#input\_db\_subnets\_list) | A list of database subnets inside the VPC. | `list(string)` |
[
"10.11.11.0/24",
"10.11.12.0/24",
"10.11.13.0/24"
]
| no | +| [dmz\_propagating\_vgws](#input\_dmz\_propagating\_vgws) | A list of VGWs the DMZ route table should propagate. | `list(string)` | `null` | no | +| [dmz\_subnets\_list](#input\_dmz\_subnets\_list) | A list of DMZ subnets inside the VPC. | `list(string)` |
[
"10.11.101.0/24",
"10.11.102.0/24",
"10.11.103.0/24"
]
| no | | [enable\_dns\_hostnames](#input\_enable\_dns\_hostnames) | (Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false. | `bool` | `true` | no | | [enable\_dns\_support](#input\_enable\_dns\_support) | (Optional) A boolean flag to enable/disable DNS support in the VPC. Defaults true. | `bool` | `true` | no | | [enable\_firewall](#input\_enable\_firewall) | (Optional) A boolean flag to enable/disable the use of a firewall instance within the VPC. Defaults False. | `bool` | `false` | no | | [enable\_flow\_logs](#input\_enable\_flow\_logs) | (Optional) A boolean flag to enable/disable the use of flow logs with the resources. Defaults True. | `bool` | `true` | no | +| [enable\_internet\_gateway](#input\_enable\_internet\_gateway) | (Optional) A boolean flag to enable/disable the use of Internet gateways. Defaults True. | `bool` | `true` | no | | [enable\_nat\_gateway](#input\_enable\_nat\_gateway) | (Optional) A boolean flag to enable/disable the use of NAT gateways in the private subnets. Defaults True. | `bool` | `true` | no | | [enable\_s3\_endpoint](#input\_enable\_s3\_endpoint) | (Optional) A boolean flag to enable/disable the use of a S3 endpoint with the VPC. Defaults False | `bool` | `false` | no | | [enable\_ssm\_vpc\_endpoints](#input\_enable\_ssm\_vpc\_endpoints) | (Optional) A boolean flag to enable/disable SSM (Systems Manager) VPC endpoints. Defaults true. | `bool` | `false` | no | @@ -246,8 +306,8 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr | [flow\_log\_format](#input\_flow\_log\_format) | (Optional) The fields to include in the flow log record, in the order in which they should appear. For more information, see Flow Log Records. Default: fields are in the order that they are described in the Flow Log Records section. | `string` | `null` | no | | [flow\_max\_aggregation\_interval](#input\_flow\_max\_aggregation\_interval) | (Optional) The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: 60 seconds (1 minute) or 600 seconds (10 minutes). Default: 600. | `number` | `60` | no | | [flow\_traffic\_type](#input\_flow\_traffic\_type) | (Optional) The type of traffic to capture. Valid values: ACCEPT,REJECT, ALL. | `string` | `"ALL"` | no | -| [fw\_dmz\_network\_interface\_id](#input\_fw\_dmz\_network\_interface\_id) | Firewall DMZ eni id | `list(any)` | `[]` | no | -| [fw\_network\_interface\_id](#input\_fw\_network\_interface\_id) | Firewall network interface id | `list` | `[]` | no | +| [fw\_dmz\_network\_interface\_id](#input\_fw\_dmz\_network\_interface\_id) | Firewall DMZ eni id | `list(string)` | `null` | no | +| [fw\_network\_interface\_id](#input\_fw\_network\_interface\_id) | Firewall network interface id | `list(string)` | `null` | no | | [iam\_policy\_name\_prefix](#input\_iam\_policy\_name\_prefix) | (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with name. | `string` | `"flow_log_policy_"` | no | | [iam\_policy\_path](#input\_iam\_policy\_path) | (Optional, default '/') Path in which to create the policy. See IAM Identifiers for more information. | `string` | `"/"` | no | | [iam\_role\_description](#input\_iam\_role\_description) | (Optional) The description of the role. | `string` | `"Role utilized for VPC flow logs. This role allows creation of log streams and adding logs to the log streams in cloudwatch"` | no | @@ -255,18 +315,18 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr | [instance\_tenancy](#input\_instance\_tenancy) | A tenancy option for instances launched into the VPC | `string` | `"default"` | no | | [key\_name\_prefix](#input\_key\_name\_prefix) | (Optional) Creates an unique alias beginning with the specified prefix. The name must start with the word alias followed by a forward slash (alias/). | `string` | `"alias/flow_logs_key_"` | no | | [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | (Optional) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default is false. | `bool` | `true` | no | -| [mgmt\_propagating\_vgws](#input\_mgmt\_propagating\_vgws) | A list of VGWs the mgmt route table should propagate. | `list` | `[]` | no | -| [mgmt\_subnets\_list](#input\_mgmt\_subnets\_list) | A list of mgmt subnets inside the VPC. | `list` |
[
"10.11.61.0/24",
"10.11.62.0/24",
"10.11.63.0/24"
]
| no | +| [mgmt\_propagating\_vgws](#input\_mgmt\_propagating\_vgws) | A list of VGWs the mgmt route table should propagate. | `list(any)` | `null` | no | +| [mgmt\_subnets\_list](#input\_mgmt\_subnets\_list) | A list of mgmt subnets inside the VPC. | `list(string)` |
[
"10.11.61.0/24",
"10.11.62.0/24",
"10.11.63.0/24"
]
| no | | [name](#input\_name) | (Required) Name to be tagged on all of the resources as an identifier | `string` | n/a | yes | -| [private\_propagating\_vgws](#input\_private\_propagating\_vgws) | A list of VGWs the private route table should propagate. | `list` | `[]` | no | -| [private\_subnets\_list](#input\_private\_subnets\_list) | A list of private subnets inside the VPC. | `list` |
[
"10.11.1.0/24",
"10.11.2.0/24",
"10.11.3.0/24"
]
| no | -| [public\_propagating\_vgws](#input\_public\_propagating\_vgws) | A list of VGWs the public route table should propagate. | `list` | `[]` | no | -| [public\_subnets\_list](#input\_public\_subnets\_list) | A list of public subnets inside the VPC. | `list` |
[
"10.11.201.0/24",
"10.11.202.0/24",
"10.11.203.0/24"
]
| no | +| [private\_propagating\_vgws](#input\_private\_propagating\_vgws) | A list of VGWs the private route table should propagate. | `list(any)` | `null` | no | +| [private\_subnets\_list](#input\_private\_subnets\_list) | A list of private subnets inside the VPC. | `list(string)` |
[
"10.11.1.0/24",
"10.11.2.0/24",
"10.11.3.0/24"
]
| no | +| [public\_propagating\_vgws](#input\_public\_propagating\_vgws) | A list of VGWs the public route table should propagate. | `list(any)` | `null` | no | +| [public\_subnets\_list](#input\_public\_subnets\_list) | A list of public subnets inside the VPC. | `list(string)` |
[
"10.11.201.0/24",
"10.11.202.0/24",
"10.11.203.0/24"
]
| no | | [single\_nat\_gateway](#input\_single\_nat\_gateway) | (Optional) A boolean flag to enable/disable use of only a single shared NAT Gateway across all of your private networks. Defaults False. | `bool` | `false` | no | -| [tags](#input\_tags) | (Optional) A mapping of tags to assign to the object. | `map` |
{
"created_by": "",
"environment": "prod",
"priority": "high",
"terraform": "true"
}
| no | +| [tags](#input\_tags) | (Optional) A mapping of tags to assign to the object. | `map(string)` |
{
"created_by": "",
"environment": "prod",
"priority": "high",
"terraform": "true"
}
| no | | [vpc\_cidr](#input\_vpc\_cidr) | The CIDR block for the VPC | `string` | `"10.11.0.0/16"` | no | -| [workspaces\_propagating\_vgws](#input\_workspaces\_propagating\_vgws) | A list of VGWs the workspaces route table should propagate. | `list` | `[]` | no | -| [workspaces\_subnets\_list](#input\_workspaces\_subnets\_list) | A list of workspaces subnets inside the VPC. | `list` |
[
"10.11.21.0/24",
"10.11.22.0/24",
"10.11.23.0/24"
]
| no | +| [workspaces\_propagating\_vgws](#input\_workspaces\_propagating\_vgws) | A list of VGWs the workspaces route table should propagate. | `list(any)` | `null` | no | +| [workspaces\_subnets\_list](#input\_workspaces\_subnets\_list) | A list of workspaces subnets inside the VPC. | `list(string)` |
[
"10.11.21.0/24",
"10.11.22.0/24",
"10.11.23.0/24"
]
| no | ## Outputs @@ -298,15 +358,15 @@ _For more examples, please refer to the [Documentation](https://github.com/zachr + ## License Distributed under the MIT License. See `LICENSE.txt` for more information.

(back to top)

- - + ## Contact Zachary Hill - [![LinkedIn][linkedin-shield]][linkedin-url] - zhill@zacharyhill.co @@ -315,19 +375,18 @@ Project Link: [https://github.com/zachreborn/terraform-modules](https://github.c

(back to top)

- - + ## Acknowledgments -* [Zachary Hill](https://zacharyhill.co) -* [Jake Jones](https://github.com/jakeasarus) +- [Zachary Hill](https://zacharyhill.co) +- [Jake Jones](https://github.com/jakeasarus)

(back to top)

- + [contributors-shield]: https://img.shields.io/github/contributors/zachreborn/terraform-modules.svg?style=for-the-badge [contributors-url]: https://github.com/zachreborn/terraform-modules/graphs/contributors [forks-shield]: https://img.shields.io/github/forks/zachreborn/terraform-modules.svg?style=for-the-badge @@ -342,4 +401,4 @@ Project Link: [https://github.com/zachreborn/terraform-modules](https://github.c [linkedin-url]: https://www.linkedin.com/in/zachary-hill-5524257a/ [product-screenshot]: /images/screenshot.webp [Terraform.io]: https://img.shields.io/badge/Terraform-7B42BC?style=for-the-badge&logo=terraform -[Terraform-url]: https://terraform.io \ No newline at end of file +[Terraform-url]: https://terraform.io diff --git a/modules/aws/vpc/main.tf b/modules/aws/vpc/main.tf index f4f29e5eb..81788bdf4 100644 --- a/modules/aws/vpc/main.tf +++ b/modules/aws/vpc/main.tf @@ -14,7 +14,13 @@ terraform { data "aws_caller_identity" "current" {} data "aws_region" "current" {} +########################### +# Locals +########################### + locals { + # Disable the IGW if either enable_internet_gateway is false or public_subnets_list is empty + enable_igw = var.enable_internet_gateway ? ((length(var.public_subnets_list) != 0 || var.public_subnets_list != null) ? true : false) : false service_name = "com.amazonaws.${data.aws_region.current.name}.s3" } @@ -194,20 +200,23 @@ resource "aws_subnet" "workspaces_subnets" { ########################### resource "aws_internet_gateway" "igw" { + count = local.enable_igw ? 1 : 0 tags = merge(var.tags, ({ "Name" = format("%s-igw", var.name) })) vpc_id = aws_vpc.vpc.id } resource "aws_route_table" "public_route_table" { + count = length(var.public_subnets_list) != 0 ? 1 : 0 propagating_vgws = var.public_propagating_vgws tags = merge(var.tags, ({ "Name" = format("%s-rt-public", var.name) })) vpc_id = aws_vpc.vpc.id } resource "aws_route" "public_default_route" { + count = local.enable_igw ? 1 : 0 destination_cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.igw.id - route_table_id = aws_route_table.public_route_table.id + gateway_id = aws_internet_gateway.igw[0].id + route_table_id = aws_route_table.public_route_table[0].id } resource "aws_eip" "nateip" { @@ -218,8 +227,8 @@ resource "aws_eip" "nateip" { resource "aws_nat_gateway" "natgw" { depends_on = [aws_internet_gateway.igw] + count = var.enable_nat_gateway ? (local.enable_igw ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0) : 0 allocation_id = element(aws_eip.nateip[*].id, (var.single_nat_gateway ? 0 : count.index)) - count = var.enable_nat_gateway ? (var.single_nat_gateway ? 1 : length(var.azs)) : 0 subnet_id = element(aws_subnet.public_subnets[*].id, (var.single_nat_gateway ? 0 : count.index)) } @@ -347,7 +356,7 @@ resource "aws_vpc_endpoint_route_table_association" "private_s3" { resource "aws_vpc_endpoint_route_table_association" "public_s3" { count = var.enable_s3_endpoint ? length(var.public_subnets_list) : 0 vpc_endpoint_id = aws_vpc_endpoint.s3[count.index] - route_table_id = aws_route_table.public_route_table.id + route_table_id = aws_route_table.public_route_table[0].id } resource "aws_route_table_association" "private" { @@ -358,7 +367,7 @@ resource "aws_route_table_association" "private" { resource "aws_route_table_association" "public" { count = length(var.public_subnets_list) - route_table_id = aws_route_table.public_route_table.id + route_table_id = aws_route_table.public_route_table[0].id subnet_id = element(aws_subnet.public_subnets[*].id, count.index) } diff --git a/modules/aws/vpc/variables.tf b/modules/aws/vpc/variables.tf index 3224b0083..19c8a0a4f 100644 --- a/modules/aws/vpc/variables.tf +++ b/modules/aws/vpc/variables.tf @@ -1,28 +1,32 @@ ########################### # VPC ########################### - variable "vpc_cidr" { description = "The CIDR block for the VPC" - default = "10.11.0.0/16" type = string + default = "10.11.0.0/16" } variable "enable_dns_hostnames" { description = "(Optional) A boolean flag to enable/disable DNS hostnames in the VPC. Defaults false." - default = true type = bool + default = true } variable "enable_dns_support" { description = "(Optional) A boolean flag to enable/disable DNS support in the VPC. Defaults true." - default = true type = bool + default = true } variable "instance_tenancy" { description = "A tenancy option for instances launched into the VPC" + type = string default = "default" + validation { + condition = can(regex("^(default|dedicated)$", var.instance_tenancy)) + error_message = "instance_tenancy must be either default or dedicated" + } } ########################### @@ -30,8 +34,8 @@ variable "instance_tenancy" { ########################### variable "enable_ssm_vpc_endpoints" { - type = bool description = "(Optional) A boolean flag to enable/disable SSM (Systems Manager) VPC endpoints. Defaults true." + type = bool default = false } @@ -41,42 +45,49 @@ variable "enable_ssm_vpc_endpoints" { variable "azs" { description = "A list of Availability zones in the region" + type = list(string) default = ["us-east-2a", "us-east-2b", "us-east-2c"] } variable "db_subnets_list" { description = "A list of database subnets inside the VPC." + type = list(string) default = ["10.11.11.0/24", "10.11.12.0/24", "10.11.13.0/24"] } variable "dmz_subnets_list" { description = "A list of DMZ subnets inside the VPC." + type = list(string) default = ["10.11.101.0/24", "10.11.102.0/24", "10.11.103.0/24"] } variable "map_public_ip_on_launch" { description = "(Optional) Specify true to indicate that instances launched into the subnet should be assigned a public IP address. Default is false." - default = true type = bool + default = true } variable "mgmt_subnets_list" { description = "A list of mgmt subnets inside the VPC." + type = list(string) default = ["10.11.61.0/24", "10.11.62.0/24", "10.11.63.0/24"] } variable "private_subnets_list" { description = "A list of private subnets inside the VPC." + type = list(string) default = ["10.11.1.0/24", "10.11.2.0/24", "10.11.3.0/24"] } variable "public_subnets_list" { description = "A list of public subnets inside the VPC." + type = list(string) default = ["10.11.201.0/24", "10.11.202.0/24", "10.11.203.0/24"] } variable "workspaces_subnets_list" { description = "A list of workspaces subnets inside the VPC." + type = list(string) default = ["10.11.21.0/24", "10.11.22.0/24", "10.11.23.0/24"] } @@ -86,6 +97,7 @@ variable "workspaces_subnets_list" { variable "single_nat_gateway" { description = "(Optional) A boolean flag to enable/disable use of only a single shared NAT Gateway across all of your private networks. Defaults False." + type = bool default = false } @@ -95,43 +107,50 @@ variable "single_nat_gateway" { variable "db_propagating_vgws" { description = "A list of VGWs the db route table should propagate." - default = [] + type = list(string) + default = null } variable "dmz_propagating_vgws" { description = "A list of VGWs the DMZ route table should propagate." - default = [] + type = list(string) + default = null } variable "fw_dmz_network_interface_id" { - type = list(any) description = "Firewall DMZ eni id" - default = [] + type = list(string) + default = null } variable "fw_network_interface_id" { description = "Firewall network interface id" - default = [] + type = list(string) + default = null } variable "mgmt_propagating_vgws" { description = "A list of VGWs the mgmt route table should propagate." - default = [] + type = list(any) + default = null } variable "private_propagating_vgws" { description = "A list of VGWs the private route table should propagate." - default = [] + type = list(any) + default = null } variable "public_propagating_vgws" { description = "A list of VGWs the public route table should propagate." - default = [] + type = list(any) + default = null } variable "workspaces_propagating_vgws" { description = "A list of VGWs the workspaces route table should propagate." - default = [] + type = list(any) + default = null } ########################### @@ -139,74 +158,82 @@ variable "workspaces_propagating_vgws" { ########################### variable "cloudwatch_name_prefix" { description = "(Optional, Forces new resource) Creates a unique name beginning with the specified prefix." - default = "flow_logs_" type = string + default = "flow_logs_" } variable "cloudwatch_retention_in_days" { description = "(Optional) Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire." - default = 90 type = number + default = 90 + validation { + condition = can(index([1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, 0], var.cloudwatch_retention_in_days)) + error_message = "cloudwatch_retention_in_days must be one of: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, 0." + } } variable "iam_policy_name_prefix" { description = "(Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with name." - default = "flow_log_policy_" type = string + default = "flow_log_policy_" } variable "iam_policy_path" { - type = string description = "(Optional, default '/') Path in which to create the policy. See IAM Identifiers for more information." + type = string default = "/" } variable "iam_role_description" { - type = string description = "(Optional) The description of the role." + type = string default = "Role utilized for VPC flow logs. This role allows creation of log streams and adding logs to the log streams in cloudwatch" } variable "iam_role_name_prefix" { - type = string description = "(Required, Forces new resource) Creates a unique friendly name beginning with the specified prefix. Conflicts with name." + type = string default = "flow_logs_role_" } variable "key_name_prefix" { description = "(Optional) Creates an unique alias beginning with the specified prefix. The name must start with the word alias followed by a forward slash (alias/)." - default = "alias/flow_logs_key_" type = string + default = "alias/flow_logs_key_" } variable "flow_deliver_cross_account_role" { - type = string description = "(Optional) The ARN of the IAM role that posts logs to CloudWatch Logs in a different account." + type = string default = null } variable "flow_log_destination_type" { - type = string description = "(Optional) The type of the logging destination. Valid values: cloud-watch-logs, s3. Default: cloud-watch-logs." + type = string default = "cloud-watch-logs" } variable "flow_log_format" { - type = string description = "(Optional) The fields to include in the flow log record, in the order in which they should appear. For more information, see Flow Log Records. Default: fields are in the order that they are described in the Flow Log Records section." + type = string default = null } variable "flow_max_aggregation_interval" { - type = number description = "(Optional) The maximum interval of time during which a flow of packets is captured and aggregated into a flow log record. Valid Values: 60 seconds (1 minute) or 600 seconds (10 minutes). Default: 600." + type = number default = 60 } variable "flow_traffic_type" { - type = string description = "(Optional) The type of traffic to capture. Valid values: ACCEPT,REJECT, ALL." + type = string default = "ALL" + validation { + condition = can(index(["ACCEPT", "REJECT", "ALL"], var.flow_traffic_type)) + error_message = "flow_traffic_type must be one of: ACCEPT, REJECT, ALL." + } } ############################################################### @@ -215,26 +242,32 @@ variable "flow_traffic_type" { variable "enable_firewall" { description = "(Optional) A boolean flag to enable/disable the use of a firewall instance within the VPC. Defaults False." - default = false type = bool + default = false } variable "enable_nat_gateway" { description = "(Optional) A boolean flag to enable/disable the use of NAT gateways in the private subnets. Defaults True." + type = bool default = true +} + +variable "enable_internet_gateway" { + description = "(Optional) A boolean flag to enable/disable the use of Internet gateways. Defaults True." type = bool + default = true } variable "enable_s3_endpoint" { description = "(Optional) A boolean flag to enable/disable the use of a S3 endpoint with the VPC. Defaults False" - default = false type = bool + default = false } variable "enable_flow_logs" { description = "(Optional) A boolean flag to enable/disable the use of flow logs with the resources. Defaults True." - default = true type = bool + default = true } variable "name" { @@ -244,6 +277,7 @@ variable "name" { variable "tags" { description = "(Optional) A mapping of tags to assign to the object." + type = map(string) default = { terraform = "true" created_by = ""