diff --git a/.github/workflows/cicd-2-publish.yaml b/.github/workflows/cicd-2-publish.yaml index dad3923..51affce 100644 --- a/.github/workflows/cicd-2-publish.yaml +++ b/.github/workflows/cicd-2-publish.yaml @@ -61,4 +61,3 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} default_bump: patch tag_prefix: "v" - diff --git a/.tool-versions b/.tool-versions index 0d035de..acdecd3 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,8 +1,8 @@ # This file is for you! Please, updated to the versions agreed by your team. terraform 1.13.2 -terraform-docs 0.19.0 -pre-commit 3.6.0 +terraform-docs 0.23.0 +pre-commit 4.6.0 python 3.12 vale 3.6.0 diff --git a/.tool-versions.yaml b/.tool-versions.yaml index 72ca576..8e788f8 100644 --- a/.tool-versions.yaml +++ b/.tool-versions.yaml @@ -1,7 +1,7 @@ infrastructure: terraform: 1.13.2 - terraform-docs: 0.19.0 - pre-commit: 3.6.0 + terraform-docs: 0.23.0 + pre-commit: 4.6.0 vale: 3.6.0 python: 3.12.0 nodejs: 24.8.0 diff --git a/docs/developer-guides/Scripting_Docker.md b/docs/developer-guides/Scripting_Docker.md index 304920d..08b6a4f 100644 --- a/docs/developer-guides/Scripting_Docker.md +++ b/docs/developer-guides/Scripting_Docker.md @@ -228,7 +228,7 @@ Here is a step-by-step guide for an image which packages a third-party tool. It You can specify the version tags that the automated build process applies to your images with a `VERSION` file. This file must be located adjacent to the `Dockerfile` where each image is defined. -It may be a "_statically defined_" version, such as `1.2.3`, `20230601`, etc., or a "_dynamic pattern_" based on the current time and commit hash, e.g. `${yyyy}${mm}${dd}${HH}${MM}${SS}-${hash}`. This pattern will be substituted during the build process to create a `.version` file in the same directory, containing effective content like `20230601153000-123abcd`. See [this function](https://github.com/nhs-england-tools/repository-template/blob/main/scripts/docker/docker.lib.sh#L118) for what template substitutions are available. +It may be a "_statically defined_" version, such as `1.2.3`, `20230601`, etc., or a "_dynamic pattern_" based on the current time and commit hash, e.g. `${yyyy}${mm}${dd}${HH}${MM}${SS}-${hash}`. This pattern will be substituted during the build process to create a `.version` file in the same directory, containing effective content like `20230601153000-123abcd`. See [this function](https://github.com/nhs-england-tools/repository-template/blob/ec475e15f049b8ec1ac1b69088297e70ea5c1291/scripts/docker/docker.lib.sh#L118) for what template substitutions are available. This file is then used by functions defined in [docker.lib.sh](../../scripts/docker/docker.lib.sh) but is ignored by Git, and is not checked in with other files. diff --git a/docs/developer-guides/Scripting_Terraform.md b/docs/developer-guides/Scripting_Terraform.md index 837288f..a8508c2 100644 --- a/docs/developer-guides/Scripting_Terraform.md +++ b/docs/developer-guides/Scripting_Terraform.md @@ -56,7 +56,7 @@ Here are some key features built into this repository's Terraform module: - [`check-terraform-format.sh`](../../scripts/githooks/check-terraform-format.sh): Git hook - Usage example - Declarative infrastructure definition example [`terraform-state-aws-s3`](../../scripts/terraform/examples/terraform-state-aws-s3) to store Terraform state - - A set of [make targets](https://github.com/nhs-england-tools/repository-template/blob/main/scripts/terraform/terraform.mk#L44) to run the example + - A set of [make targets](https://github.com/nhs-england-tools/repository-template/blob/ec475e15f049b8ec1ac1b69088297e70ea5c1291/scripts/terraform/terraform.mk#L44) to run the example ## Usage diff --git a/infrastructure/modules/api-gateway/main.tf b/infrastructure/modules/api-gateway/main.tf index 9417850..1b5d1ae 100644 --- a/infrastructure/modules/api-gateway/main.tf +++ b/infrastructure/modules/api-gateway/main.tf @@ -250,5 +250,3 @@ resource "aws_api_gateway_base_path_mapping" "custom_domain_mapping" { depends_on = [aws_api_gateway_stage.stage] } - - diff --git a/infrastructure/modules/api-gateway/outputs.tf b/infrastructure/modules/api-gateway/outputs.tf index 51dc20b..8e68c1f 100644 --- a/infrastructure/modules/api-gateway/outputs.tf +++ b/infrastructure/modules/api-gateway/outputs.tf @@ -22,4 +22,3 @@ output "api_key_secret_arn" { description = "The ARN of the API key secret in Secrets Manager" value = aws_secretsmanager_secret.api_token.arn } - diff --git a/infrastructure/modules/api-gateway/readme.md b/infrastructure/modules/api-gateway/readme.md index e928a0c..5729566 100644 --- a/infrastructure/modules/api-gateway/readme.md +++ b/infrastructure/modules/api-gateway/readme.md @@ -9,9 +9,9 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [random](#provider_random) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [random](#provider\_random) | 3.8.1 | ## Modules @@ -20,7 +20,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_acm_certificate.cert](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate) | resource | | [aws_acm_certificate_validation.cert_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation) | resource | | [aws_api_gateway_account.account](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_account) | resource | @@ -48,31 +48,31 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [api_gateway_description](#input_api_gateway_description) | Description for the API Gateway | `string` | n/a | yes | -| [api_gateway_name](#input_api_gateway_name) | the name of the API Gateway | `any` | n/a | yes | -| [api_path_part](#input_api_path_part) | the url path for the API | `any` | n/a | yes | -| [aws_account_id](#input_aws_account_id) | n/a | `any` | n/a | yes | -| [aws_lambda_arn](#input_aws_lambda_arn) | n/a | `any` | n/a | yes | -| [aws_lambda_name](#input_aws_lambda_name) | n/a | `any` | n/a | yes | -| [aws_region](#input_aws_region) | The AWS region where the API Gateway is deployed | `string` | `"eu-west-2"` | no | -| [certificate_arn](#input_certificate_arn) | The ARN of the ACM certificate to use for the custom domain (optional, will create if not provided) | `string` | `null` | no | -| [domain_name_prefix](#input_domain_name_prefix) | Prefix for the custom domain name | `string` | n/a | yes | -| [hosted_zone_name](#input_hosted_zone_name) | The hosted zone name for the custom domain | `string` | n/a | yes | -| [http_method](#input_http_method) | The HTTP method to use for the API Gateway | `string` | n/a | yes | -| [name_prefix](#input_name_prefix) | Prefix for naming resources | `string` | n/a | yes | -| [route53_hosted_zone_id](#input_route53_hosted_zone_id) | The ID of the Route53 hosted zone | `string` | n/a | yes | -| [secret_replication_regions](#input_secret_replication_regions) | List of additional regions where created secrets should be replicated | `list(string)` | n/a | yes | -| [stage_name](#input_stage_name) | the API stage name | `any` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [api\_gateway\_description](#input\_api\_gateway\_description) | Description for the API Gateway | `string` | n/a | yes | +| [api\_gateway\_name](#input\_api\_gateway\_name) | the name of the API Gateway | `any` | n/a | yes | +| [api\_path\_part](#input\_api\_path\_part) | the url path for the API | `any` | n/a | yes | +| [aws\_account\_id](#input\_aws\_account\_id) | n/a | `any` | n/a | yes | +| [aws\_lambda\_arn](#input\_aws\_lambda\_arn) | n/a | `any` | n/a | yes | +| [aws\_lambda\_name](#input\_aws\_lambda\_name) | n/a | `any` | n/a | yes | +| [aws\_region](#input\_aws\_region) | The AWS region where the API Gateway is deployed | `string` | `"eu-west-2"` | no | +| [certificate\_arn](#input\_certificate\_arn) | The ARN of the ACM certificate to use for the custom domain (optional, will create if not provided) | `string` | `null` | no | +| [domain\_name\_prefix](#input\_domain\_name\_prefix) | Prefix for the custom domain name | `string` | n/a | yes | +| [hosted\_zone\_name](#input\_hosted\_zone\_name) | The hosted zone name for the custom domain | `string` | n/a | yes | +| [http\_method](#input\_http\_method) | The HTTP method to use for the API Gateway | `string` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | Prefix for naming resources | `string` | n/a | yes | +| [route53\_hosted\_zone\_id](#input\_route53\_hosted\_zone\_id) | The ID of the Route53 hosted zone | `string` | n/a | yes | +| [secret\_replication\_regions](#input\_secret\_replication\_regions) | List of additional regions where created secrets should be replicated | `list(string)` | n/a | yes | +| [stage\_name](#input\_stage\_name) | the API stage name | `any` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [api_gateway_id](#output_api_gateway_id) | The ID of the API Gateway | -| [api_gateway_invoke_url](#output_api_gateway_invoke_url) | The invoke URL of the API Gateway stage | -| [api_gateway_url](#output_api_gateway_url) | The URL of the API Gateway custom domain | -| [api_key_id](#output_api_key_id) | The ID of the API key | -| [api_key_secret_arn](#output_api_key_secret_arn) | The ARN of the API key secret in Secrets Manager | +| ---- | ----------- | +| [api\_gateway\_id](#output\_api\_gateway\_id) | The ID of the API Gateway | +| [api\_gateway\_invoke\_url](#output\_api\_gateway\_invoke\_url) | The invoke URL of the API Gateway stage | +| [api\_gateway\_url](#output\_api\_gateway\_url) | The URL of the API Gateway custom domain | +| [api\_key\_id](#output\_api\_key\_id) | The ID of the API key | +| [api\_key\_secret\_arn](#output\_api\_key\_secret\_arn) | The ARN of the API key secret in Secrets Manager | diff --git a/infrastructure/modules/aws-backup-destination/readme.md b/infrastructure/modules/aws-backup-destination/readme.md index fb5fb21..865c67f 100644 --- a/infrastructure/modules/aws-backup-destination/readme.md +++ b/infrastructure/modules/aws-backup-destination/readme.md @@ -34,16 +34,15 @@ module "test_backup_vault" { ``` - ## Requirements No requirements. ## Providers -| Name | Version | -| ------------------------------------------------ | ------- | -| [aws](#provider_aws) | n/a | +| Name | Version | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -51,41 +50,40 @@ No modules. ## Resources -| Name | Type | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| [aws_backup_vault.vault](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource | -| [aws_backup_vault_lock_configuration.vault_lock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_lock_configuration) | resource | -| [aws_backup_vault_policy.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_policy) | resource | -| [aws_iam_role.copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.copy_recovery_point_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_policy_document.copy_recovery_point_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| Name | Type | +| ---- | ---- | +| [aws_backup_vault.vault](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource | +| [aws_backup_vault_lock_configuration.vault_lock](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_lock_configuration) | resource | +| [aws_backup_vault_policy.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_policy) | resource | +| [aws_iam_role.copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.copy_recovery_point_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_policy_document.copy_recovery_point_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.copy_recovery_point_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | - -## Module Inputs - -| Name | Description | Type | Default | Required | -| ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------------- | :------: | -| [account_id](#input_account_id) | The id of the account that the vault will be in | `string` | n/a | yes | -| [changeable_for_days](#input_changeable_for_days) | How long you want the vault lock to be changeable for, only applies to compliance mode. This value is expressed in days no less than 3 and no greater than 36,500; otherwise, an error will return. | `number` | `14` | no | -| [enable_cross_account_vault_access](#input_enable_cross_account_vault_access) | Flag to enable cross account vault access for AWS Backup | `bool` | `false` | no | -| [enable_vault_protection](#input_enable_vault_protection) | Flag which controls if the vault lock is enabled | `bool` | `false` | no | -| [kms_key](#input_kms_key) | The KMS key used to secure the vault | `string` | n/a | yes | -| [name_prefix](#input_name_prefix) | Optional name prefix for vault resources | `string` | `null` | no | -| [region](#input_region) | The region we should be operating in | `string` | `"eu-west-2"` | no | -| [source_account_ids](#input_source_account_ids) | The ids of the accounts that backups will come from | `list(string)` | n/a | yes | -| [source_account_name](#input_source_account_name) | The name of the account that backups will come from | `string` | n/a | yes | -| [source_vault_arn](#input_source_vault_arn) | Source account vault arn, if set copies back are restricted to only this vault | `string` | `""` | no | -| [vault_lock_max_retention_days](#input_vault_lock_max_retention_days) | The maximum retention period required on recovery points when vault lock enabled | `number` | `365` | no | -| [vault_lock_min_retention_days](#input_vault_lock_min_retention_days) | The minimum retention period required on recovery points when vault lock enabled | `number` | `365` | no | -| [vault_lock_type](#input_vault_lock_type) | The type of lock that the vault should be, will default to governance | `string` | `"governance"` | no | +| [aws_iam_policy_document.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -## Outputs +## Inputs -| Name | Description | -| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -| [copy_recovery_point_role_arn](#output_copy_recovery_point_role_arn) | arn of role to assume from source account lambda (set ASSUME_ROLE_ARN to this). Only present if enabled. | -| [vault_arn](#output_vault_arn) | n/a | -| [vault_name](#output_vault_name) | The name of the backup vault. | +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [account\_id](#input\_account\_id) | The id of the account that the vault will be in | `string` | n/a | yes | +| [changeable\_for\_days](#input\_changeable\_for\_days) | How long you want the vault lock to be changeable for, only applies to compliance mode. This value is expressed in days no less than 3 and no greater than 36,500; otherwise, an error will return. | `number` | `14` | no | +| [enable\_cross\_account\_vault\_access](#input\_enable\_cross\_account\_vault\_access) | Flag to enable cross account vault access for AWS Backup | `bool` | `false` | no | +| [enable\_vault\_protection](#input\_enable\_vault\_protection) | Flag which controls if the vault lock is enabled | `bool` | `false` | no | +| [kms\_key](#input\_kms\_key) | The KMS key used to secure the vault | `string` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | Optional name prefix for vault resources | `string` | `null` | no | +| [region](#input\_region) | The region we should be operating in | `string` | `"eu-west-2"` | no | +| [source\_account\_ids](#input\_source\_account\_ids) | The ids of the accounts that backups will come from | `list(string)` | n/a | yes | +| [source\_account\_name](#input\_source\_account\_name) | The name of the account that backups will come from | `string` | n/a | yes | +| [source\_vault\_arn](#input\_source\_vault\_arn) | Source account vault arn, if set copies back are restricted to only this vault | `string` | `""` | no | +| [vault\_lock\_max\_retention\_days](#input\_vault\_lock\_max\_retention\_days) | The maximum retention period required on recovery points when vault lock enabled | `number` | `365` | no | +| [vault\_lock\_min\_retention\_days](#input\_vault\_lock\_min\_retention\_days) | The minimum retention period required on recovery points when vault lock enabled | `number` | `365` | no | +| [vault\_lock\_type](#input\_vault\_lock\_type) | The type of lock that the vault should be, will default to governance | `string` | `"governance"` | no | + +## Outputs +| Name | Description | +| ---- | ----------- | +| [copy\_recovery\_point\_role\_arn](#output\_copy\_recovery\_point\_role\_arn) | ARN of role to assume from source account lambda (set ASSUME\_ROLE\_ARN to this). Only present if enabled. | +| [vault\_arn](#output\_vault\_arn) | n/a | +| [vault\_name](#output\_vault\_name) | The name of the backup vault. | diff --git a/infrastructure/modules/aws-backup-source/outputs.tf b/infrastructure/modules/aws-backup-source/outputs.tf index 8856d0b..f8f4845 100644 --- a/infrastructure/modules/aws-backup-source/outputs.tf +++ b/infrastructure/modules/aws-backup-source/outputs.tf @@ -27,4 +27,3 @@ output "restore_validation_eventbridge_rule_name" { value = var.backup_plan_config_rds.enable && var.restore_validation_enable ? aws_cloudwatch_event_rule.restore_testing_complete[0].name : null description = "Name of the EventBridge rule that triggers restore validation" } - diff --git a/infrastructure/modules/aws-backup-source/readme.md b/infrastructure/modules/aws-backup-source/readme.md index 1c09931..393535c 100644 --- a/infrastructure/modules/aws-backup-source/readme.md +++ b/infrastructure/modules/aws-backup-source/readme.md @@ -17,145 +17,143 @@ module "test_aws_backup" { ``` - ## Requirements -| Name | Version | -| ------------------------------------------------------------------------ | -------- | -| [terraform](#requirement_terraform) | >= 1.9.5 | -| [archive](#requirement_archive) | ~> 2 | -| [aws](#requirement_aws) | > 6 | +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.9.5 | +| [archive](#requirement\_archive) | ~> 2 | +| [aws](#requirement\_aws) | > 6 | ## Providers -| Name | Version | -| ------------------------------------------------------------------ | ------- | -| [archive](#provider_archive) | ~> 2 | -| [aws](#provider_aws) | > 6 | -| [terraform](#provider_terraform) | n/a | +| Name | Version | +| ---- | ------- | +| [archive](#provider\_archive) | 2.7.1 | +| [aws](#provider\_aws) | 6.43.0 | +| [terraform](#provider\_terraform) | n/a | ## Modules -| Name | Source | Version | -| ----------------------------------------------------------------------- | ------------------------------------- | ------- | -| [eventbridge](#module_eventbridge) | terraform-aws-modules/eventbridge/aws | 4.3.0 | -| [lambda_layer](#module_lambda_layer) | ../../modules/lambda-layer | n/a | +| Name | Source | Version | +| ---- | ------ | ------- | +| [eventbridge](#module\_eventbridge) | terraform-aws-modules/eventbridge/aws | 4.3.0 | +| [lambda\_layer](#module\_lambda\_layer) | ../../modules/lambda-layer | n/a | ## Resources -| Name | Type | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| [aws_backup_framework.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_framework) | resource | -| [aws_backup_plan.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_plan) | resource | -| [aws_backup_report_plan.backup_jobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | -| [aws_backup_report_plan.backup_restore_testing_jobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | -| [aws_backup_report_plan.copy_jobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | -| [aws_backup_report_plan.resource_compliance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | -| [aws_backup_restore_testing_plan.backup_restore_testing_plan](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_restore_testing_plan) | resource | -| [aws_backup_restore_testing_selection.backup_restore_testing_selection_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_restore_testing_selection) | resource | -| [aws_backup_selection.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_selection) | resource | -| [aws_backup_vault.intermediary_vault](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource | -| [aws_backup_vault.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource | -| [aws_backup_vault_notifications.backup_notification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_notifications) | resource | -| [aws_backup_vault_policy.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_policy) | resource | -| [aws_cloudwatch_event_rule.restore_testing_complete](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | -| [aws_cloudwatch_event_target.restore_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | -| [aws_cloudwatch_log_group.restore_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_iam_policy.iam_policy_for_lambda_copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.restore_validation_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_role.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.iam_for_lambda_copy_job](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.iam_for_lambda_copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.restore_validation_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.cross_account_iam_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.lambda_copy_recovery_point_policy_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.lambda_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.restore](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.restore_validation_lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.restore_validation_lambda_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.s3_backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.s3_restore](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_kms_alias.backup_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.aws_backup_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_kms_key_policy.backup_key_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key_policy) | resource | -| [aws_lambda_function.lambda_copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [aws_lambda_function.restore_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [aws_lambda_function.start_cross_account_copy_job_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [aws_lambda_permission.allow_eventbridge](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | -| [aws_lambda_permission.eventbridge_invoke_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | -| [aws_security_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_sns_topic.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | -| [aws_sns_topic_subscription.aws_backup_notifications_email_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | -| [aws_vpc_security_group_egress_rule.lambda_egress_for_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | -| [aws_vpc_security_group_egress_rule.lambda_egress_https](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | -| [aws_vpc_security_group_ingress_rule.lambda_ingress_for_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | -| [archive_file.lambda_copy_recovery_point_zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | -| [archive_file.lambda_restore_validation_zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | -| [archive_file.start_cross_account_copy_job_lambda_zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | -| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_iam_policy_document.allow_backup_to_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.backup_key_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.lambda_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.lambda_copy_job_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_roles.roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_roles) | data source | -| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | -| [terraform_remote_state.rds_instance](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source | -| [terraform_remote_state.vpc](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source | +| Name | Type | +| ---- | ---- | +| [aws_backup_framework.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_framework) | resource | +| [aws_backup_plan.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_plan) | resource | +| [aws_backup_report_plan.backup_jobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | +| [aws_backup_report_plan.backup_restore_testing_jobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | +| [aws_backup_report_plan.copy_jobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | +| [aws_backup_report_plan.resource_compliance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_report_plan) | resource | +| [aws_backup_restore_testing_plan.backup_restore_testing_plan](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_restore_testing_plan) | resource | +| [aws_backup_restore_testing_selection.backup_restore_testing_selection_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_restore_testing_selection) | resource | +| [aws_backup_selection.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_selection) | resource | +| [aws_backup_vault.intermediary_vault](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource | +| [aws_backup_vault.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource | +| [aws_backup_vault_notifications.backup_notification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_notifications) | resource | +| [aws_backup_vault_policy.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_policy) | resource | +| [aws_cloudwatch_event_rule.restore_testing_complete](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_target.restore_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_log_group.restore_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_policy.iam_policy_for_lambda_copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.restore_validation_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.iam_for_lambda_copy_job](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.iam_for_lambda_copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.restore_validation_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.cross_account_iam_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.lambda_copy_recovery_point_policy_attach](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.lambda_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.restore](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.restore_validation_lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.restore_validation_lambda_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.s3_backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.s3_restore](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kms_alias.backup_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.aws_backup_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_kms_key_policy.backup_key_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key_policy) | resource | +| [aws_lambda_function.lambda_copy_recovery_point](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_function.restore_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_function.start_cross_account_copy_job_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_permission.allow_eventbridge](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_lambda_permission.eventbridge_invoke_validation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_security_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_sns_topic.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | +| [aws_sns_topic_subscription.aws_backup_notifications_email_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_vpc_security_group_egress_rule.lambda_egress_for_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_egress_rule.lambda_egress_https](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource | +| [aws_vpc_security_group_ingress_rule.lambda_ingress_for_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource | +| [archive_file.lambda_copy_recovery_point_zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | +| [archive_file.lambda_restore_validation_zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | +| [archive_file.start_cross_account_copy_job_lambda_zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.allow_backup_to_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.backup_key_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_copy_job_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_roles.roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_roles) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | +| [terraform_remote_state.rds_instance](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source | +| [terraform_remote_state.vpc](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source | ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------: | -| [api_endpoint](#input_api_endpoint) | API endpoint to send post build version notifications to | `string` | `""` | no | -| [api_token](#input_api_token) | API token to authenticate with the API endpoint | `string` | `""` | no | -| [backup_copy_vault_account_id](#input_backup_copy_vault_account_id) | The account id of the destination backup vault for allowing restores back into the source account. | `string` | `""` | no | -| [backup_copy_vault_arn](#input_backup_copy_vault_arn) | The arn of the destination backup vault for cross-account backup copies. | `string` | `""` | no | -| [backup_plan_config_rds](#input_backup_plan_config_rds) | Configuration for backup plans with RDS |
object({
enable = bool
selection_tag = string
selection_tag_value = optional(string)
selection_tags = optional(list(object({
key = optional(string)
value = optional(string)
})))
compliance_resource_types = list(string)
restore_testing_overrides = optional(map(string))
validation_window_hours = optional(number)
rules = optional(list(object({
name = string
schedule = string
completion_window = optional(number)
enable_continuous_backup = optional(bool)
lifecycle = object({
delete_after = number
cold_storage_after = optional(number)
})
copy_action = optional(object({
delete_after = optional(number)
}))
})))
})
|
{
"compliance_resource_types": [
"RDS"
],
"enable": true,
"rules": [
{
"completion_window": 24,
"copy_action": {
"delete_after": 365
},
"lifecycle": {
"delete_after": 35
},
"name": "rds_daily_kept_5_weeks",
"schedule": "cron(0 0 * * ? *)"
},
{
"completion_window": 48,
"copy_action": {
"delete_after": 365
},
"lifecycle": {
"delete_after": 90
},
"name": "rds_weekly_kept_3_months",
"schedule": "cron(0 1 ? * SUN *)"
},
{
"completion_window": 72,
"copy_action": {
"delete_after": 365
},
"lifecycle": {
"cold_storage_after": 30,
"delete_after": 2555
},
"name": "rds_monthly_kept_7_years",
"schedule": "cron(0 2 1 * ? *)"
}
],
"selection_tag": "BackupRDS",
"selection_tag_value": "True",
"selection_tags": [],
"validation_window_hours": 1
}
| no | -| [bootstrap_kms_key_arn](#input_bootstrap_kms_key_arn) | The arn of the bootstrap KMS key used for encryption at rest of the SNS topic. | `string` | n/a | yes | -| [deletion_allowed_principal_arns](#input_deletion_allowed_principal_arns) | List of ARNs of principals allowed to delete backups. | `list(string)` | `null` | no | -| [destination_vault_retention_period](#input_destination_vault_retention_period) | Retention period for recovery points made with the copy job lambda | `number` | `365` | no | -| [enable_notifications](#input_enable_notifications) | Flag to enable backup notifications. | `bool` | `false` | no | -| [environment_name](#input_environment_name) | The name of the environment where AWS Backup is configured. | `string` | n/a | yes | -| [iam_role_permissions_boundary](#input_iam_role_permissions_boundary) | Optional permissions boundary arn for backup role | `string` | `""` | no | -| [lambda_copy_recovery_point_assume_role_arn](#input_lambda_copy_recovery_point_assume_role_arn) | arn of role in destination account the lambda assumes to initiate the copy job (if required for cross-account). | `string` | `""` | no | -| [lambda_copy_recovery_point_destination_vault_arn](#input_lambda_copy_recovery_point_destination_vault_arn) | Destination vault arn containing the recovery point to be copied back (the air-gapped vault). | `string` | `""` | no | -| [lambda_copy_recovery_point_enable](#input_lambda_copy_recovery_point_enable) | Flag to enable the copy recovery point lambda (copy recovery point from destination vault back to source). | `bool` | `false` | no | -| [lambda_copy_recovery_point_max_wait_minutes](#input_lambda_copy_recovery_point_max_wait_minutes) | Maximum number of minutes to wait for a copy job to reach a terminal state before returning running status. | `number` | `10` | no | -| [lambda_copy_recovery_point_poll_interval_seconds](#input_lambda_copy_recovery_point_poll_interval_seconds) | Polling interval in seconds for copy job status checks. | `number` | `30` | no | -| [lambda_copy_recovery_point_source_vault_arn](#input_lambda_copy_recovery_point_source_vault_arn) | Source vault arn to which the recovery point will be copied back. | `string` | `""` | no | -| [name_prefix](#input_name_prefix) | Name prefix for vault resources | `string` | `null` | no | -| [nation](#input_nation) | The nation this environment is for (e.g. en, ni) | `string` | n/a | yes | -| [notifications_sns_topic_arn](#input_notifications_sns_topic_arn) | The arn of the SNS topic to use for backup notifications. | `string` | `""` | no | -| [notifications_target_email_address](#input_notifications_target_email_address) | The email address to which backup notifications will be sent via SNS. | `string` | `""` | no | -| [project_name](#input_project_name) | The name of the project this relates to. | `string` | n/a | yes | -| [python_version](#input_python_version) | The Python version to use for the Lambda function | `string` | `"3.12"` | no | -| [reports_bucket](#input_reports_bucket) | Bucket to drop backup reports into | `string` | n/a | yes | -| [restore_testing_db_name](#input_restore_testing_db_name) | Name of the database to use for restore validation | `string` | n/a | yes | -| [restore_testing_plan_algorithm](#input_restore_testing_plan_algorithm) | Algorithm of the Recovery Selection Point | `string` | `"LATEST_WITHIN_WINDOW"` | no | -| [restore_testing_plan_recovery_point_types](#input_restore_testing_plan_recovery_point_types) | Recovery Point Types | `list(string)` |
[
"SNAPSHOT"
]
| no | -| [restore_testing_plan_scheduled_expression](#input_restore_testing_plan_scheduled_expression) | Scheduled Expression of Recovery Selection Point | `string` | `"cron(0 1 ? * SUN *)"` | no | -| [restore_testing_plan_selection_window_days](#input_restore_testing_plan_selection_window_days) | Selection window days | `number` | `7` | no | -| [restore_testing_plan_start_window](#input_restore_testing_plan_start_window) | Start window from the scheduled time during which the test should start | `number` | `1` | no | -| [restore_validation_db_credentials_secret_name](#input_restore_validation_db_credentials_secret_name) | Name of the Secrets Manager secret containing database credentials for connectivity testing | `string` | n/a | yes | -| [restore_validation_enable](#input_restore_validation_enable) | Enable automated validation of restored RDS instances during backup restore testing | `bool` | `false` | no | -| [restore_validation_expected_subnet_pattern](#input_restore_validation_expected_subnet_pattern) | Expected pattern in the DB subnet group name for configuration validation | `string` | n/a | yes | -| [restore_validation_log_retention_days](#input_restore_validation_log_retention_days) | Number of days to retain restore validation Lambda logs | `number` | `30` | no | -| [restore_validation_timeout_seconds](#input_restore_validation_timeout_seconds) | Timeout for the restore validation Lambda function in seconds | `number` | `300` | no | -| [terraform_role_arn](#input_terraform_role_arn) | arn of Terraform role used to deploy to account (deprecated, please swap to terraform_role_arns) | `string` | `""` | no | -| [terraform_role_arns](#input_terraform_role_arns) | arn of Terraform roles used to deploy to account, defaults to caller arn if list is empty | `list(string)` | `[]` | no | +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [api\_endpoint](#input\_api\_endpoint) | API endpoint to send post build version notifications to | `string` | `""` | no | +| [api\_token](#input\_api\_token) | API token to authenticate with the API endpoint | `string` | `""` | no | +| [backup\_copy\_vault\_account\_id](#input\_backup\_copy\_vault\_account\_id) | The account id of the destination backup vault for allowing restores back into the source account. | `string` | `""` | no | +| [backup\_copy\_vault\_arn](#input\_backup\_copy\_vault\_arn) | The ARN of the destination backup vault for cross-account backup copies. | `string` | `""` | no | +| [backup\_plan\_config\_rds](#input\_backup\_plan\_config\_rds) | Configuration for backup plans with RDS |
object({
enable = bool
selection_tag = string
selection_tag_value = optional(string)
selection_tags = optional(list(object({
key = optional(string)
value = optional(string)
})))
compliance_resource_types = list(string)
restore_testing_overrides = optional(map(string))
validation_window_hours = optional(number)
rules = optional(list(object({
name = string
schedule = string
completion_window = optional(number)
enable_continuous_backup = optional(bool)
lifecycle = object({
delete_after = number
cold_storage_after = optional(number)
})
copy_action = optional(object({
delete_after = optional(number)
}))
})))
})
|
{
"compliance_resource_types": [
"RDS"
],
"enable": true,
"rules": [
{
"completion_window": 24,
"copy_action": {
"delete_after": 365
},
"lifecycle": {
"delete_after": 35
},
"name": "rds_daily_kept_5_weeks",
"schedule": "cron(0 0 * * ? *)"
},
{
"completion_window": 48,
"copy_action": {
"delete_after": 365
},
"lifecycle": {
"delete_after": 90
},
"name": "rds_weekly_kept_3_months",
"schedule": "cron(0 1 ? * SUN *)"
},
{
"completion_window": 72,
"copy_action": {
"delete_after": 365
},
"lifecycle": {
"cold_storage_after": 30,
"delete_after": 2555
},
"name": "rds_monthly_kept_7_years",
"schedule": "cron(0 2 1 * ? *)"
}
],
"selection_tag": "BackupRDS",
"selection_tag_value": "True",
"selection_tags": [],
"validation_window_hours": 1
}
| no | +| [bootstrap\_kms\_key\_arn](#input\_bootstrap\_kms\_key\_arn) | The ARN of the bootstrap KMS key used for encryption at rest of the SNS topic. | `string` | n/a | yes | +| [deletion\_allowed\_principal\_arns](#input\_deletion\_allowed\_principal\_arns) | List of ARNs of principals allowed to delete backups. | `list(string)` | `null` | no | +| [destination\_vault\_retention\_period](#input\_destination\_vault\_retention\_period) | Retention period for recovery points made with the copy job lambda | `number` | `365` | no | +| [enable\_notifications](#input\_enable\_notifications) | Flag to enable backup notifications. | `bool` | `false` | no | +| [environment\_name](#input\_environment\_name) | The name of the environment where AWS Backup is configured. | `string` | n/a | yes | +| [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | Optional permissions boundary ARN for backup role | `string` | `""` | no | +| [lambda\_copy\_recovery\_point\_assume\_role\_arn](#input\_lambda\_copy\_recovery\_point\_assume\_role\_arn) | ARN of role in destination account the lambda assumes to initiate the copy job (if required for cross-account). | `string` | `""` | no | +| [lambda\_copy\_recovery\_point\_destination\_vault\_arn](#input\_lambda\_copy\_recovery\_point\_destination\_vault\_arn) | Destination vault ARN containing the recovery point to be copied back (the air-gapped vault). | `string` | `""` | no | +| [lambda\_copy\_recovery\_point\_enable](#input\_lambda\_copy\_recovery\_point\_enable) | Flag to enable the copy recovery point lambda (copy recovery point from destination vault back to source). | `bool` | `false` | no | +| [lambda\_copy\_recovery\_point\_max\_wait\_minutes](#input\_lambda\_copy\_recovery\_point\_max\_wait\_minutes) | Maximum number of minutes to wait for a copy job to reach a terminal state before returning running status. | `number` | `10` | no | +| [lambda\_copy\_recovery\_point\_poll\_interval\_seconds](#input\_lambda\_copy\_recovery\_point\_poll\_interval\_seconds) | Polling interval in seconds for copy job status checks. | `number` | `30` | no | +| [lambda\_copy\_recovery\_point\_source\_vault\_arn](#input\_lambda\_copy\_recovery\_point\_source\_vault\_arn) | Source vault ARN to which the recovery point will be copied back. | `string` | `""` | no | +| [name\_prefix](#input\_name\_prefix) | Name prefix for vault resources | `string` | `null` | no | +| [nation](#input\_nation) | The nation this environment is for (e.g. en, ni) | `string` | n/a | yes | +| [notifications\_sns\_topic\_arn](#input\_notifications\_sns\_topic\_arn) | The ARN of the SNS topic to use for backup notifications. | `string` | `""` | no | +| [notifications\_target\_email\_address](#input\_notifications\_target\_email\_address) | The email address to which backup notifications will be sent via SNS. | `string` | `""` | no | +| [project\_name](#input\_project\_name) | The name of the project this relates to. | `string` | n/a | yes | +| [python\_version](#input\_python\_version) | The Python version to use for the Lambda function | `string` | `"3.12"` | no | +| [reports\_bucket](#input\_reports\_bucket) | Bucket to drop backup reports into | `string` | n/a | yes | +| [restore\_testing\_db\_name](#input\_restore\_testing\_db\_name) | Name of the database to use for restore validation | `string` | n/a | yes | +| [restore\_testing\_plan\_algorithm](#input\_restore\_testing\_plan\_algorithm) | Algorithm of the Recovery Selection Point | `string` | `"LATEST_WITHIN_WINDOW"` | no | +| [restore\_testing\_plan\_recovery\_point\_types](#input\_restore\_testing\_plan\_recovery\_point\_types) | Recovery Point Types | `list(string)` |
[
"SNAPSHOT"
]
| no | +| [restore\_testing\_plan\_scheduled\_expression](#input\_restore\_testing\_plan\_scheduled\_expression) | Scheduled Expression of Recovery Selection Point | `string` | `"cron(0 1 ? * SUN *)"` | no | +| [restore\_testing\_plan\_selection\_window\_days](#input\_restore\_testing\_plan\_selection\_window\_days) | Selection window days | `number` | `7` | no | +| [restore\_testing\_plan\_start\_window](#input\_restore\_testing\_plan\_start\_window) | Start window from the scheduled time during which the test should start | `number` | `1` | no | +| [restore\_validation\_db\_credentials\_secret\_name](#input\_restore\_validation\_db\_credentials\_secret\_name) | Name of the Secrets Manager secret containing database credentials for connectivity testing | `string` | n/a | yes | +| [restore\_validation\_enable](#input\_restore\_validation\_enable) | Enable automated validation of restored RDS instances during backup restore testing | `bool` | `false` | no | +| [restore\_validation\_expected\_subnet\_pattern](#input\_restore\_validation\_expected\_subnet\_pattern) | Expected pattern in the DB subnet group name for configuration validation | `string` | n/a | yes | +| [restore\_validation\_log\_retention\_days](#input\_restore\_validation\_log\_retention\_days) | Number of days to retain restore validation Lambda logs | `number` | `30` | no | +| [restore\_validation\_timeout\_seconds](#input\_restore\_validation\_timeout\_seconds) | Timeout for the restore validation Lambda function in seconds | `number` | `300` | no | +| [terraform\_role\_arn](#input\_terraform\_role\_arn) | ARN of Terraform role used to deploy to account (deprecated, please swap to terraform\_role\_arns) | `string` | `""` | no | +| [terraform\_role\_arns](#input\_terraform\_role\_arns) | ARN of Terraform roles used to deploy to account, defaults to caller arn if list is empty | `list(string)` | `[]` | no | ## Outputs -| Name | Description | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| [backup_role_arn](#output_backup_role_arn) | arn of the of the backup role | -| [backup_vault_arn](#output_backup_vault_arn) | arn of the of the vault | -| [backup_vault_name](#output_backup_vault_name) | Name of the of the vault | -| [restore_validation_eventbridge_rule_name](#output_restore_validation_eventbridge_rule_name) | Name of the EventBridge rule that triggers restore validation | -| [restore_validation_lambda_arn](#output_restore_validation_lambda_arn) | arn of the restore validation Lambda function | -| [restore_validation_lambda_name](#output_restore_validation_lambda_name) | Name of the restore validation Lambda function | - +| Name | Description | +| ---- | ----------- | +| [backup\_role\_arn](#output\_backup\_role\_arn) | ARN of the of the backup role | +| [backup\_vault\_arn](#output\_backup\_vault\_arn) | ARN of the of the vault | +| [backup\_vault\_name](#output\_backup\_vault\_name) | Name of the of the vault | +| [restore\_validation\_eventbridge\_rule\_name](#output\_restore\_validation\_eventbridge\_rule\_name) | Name of the EventBridge rule that triggers restore validation | +| [restore\_validation\_lambda\_arn](#output\_restore\_validation\_lambda\_arn) | ARN of the restore validation Lambda function | +| [restore\_validation\_lambda\_name](#output\_restore\_validation\_lambda\_name) | Name of the restore validation Lambda function | diff --git a/infrastructure/modules/aws-scheduler/readme.md b/infrastructure/modules/aws-scheduler/readme.md index 9befb21..0d4ac5b 100644 --- a/infrastructure/modules/aws-scheduler/readme.md +++ b/infrastructure/modules/aws-scheduler/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_iam_role.scheduler_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.scheduler_lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_scheduler_schedule.env_expiry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/scheduler_schedule) | resource | @@ -28,13 +28,13 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [function_name](#input_function_name) | Lambda function name | `string` | n/a | yes | -| [lambda_inputs](#input_lambda_inputs) | Map of key-value pairs to send to the Lambda as input | `map(string)` | `{}` | no | -| [name_prefix](#input_name_prefix) | Prefix for naming resources | `string` | n/a | yes | -| [resource_suffix](#input_resource_suffix) | Sanitized environment name for resource naming | `string` | n/a | yes | -| [schedule_expression](#input_schedule_expression) | Schedule expression for the AWS Scheduler (e.g. rate(3 days) or cron(...)) | `string` | `null` | no | -| [start_time](#input_start_time) | RFC3339 timestamp to use as the scheduler start time | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [function\_name](#input\_function\_name) | Lambda function name | `string` | n/a | yes | +| [lambda\_inputs](#input\_lambda\_inputs) | Map of key-value pairs to send to the Lambda as input | `map(string)` | `{}` | no | +| [name\_prefix](#input\_name\_prefix) | Prefix for naming resources | `string` | n/a | yes | +| [resource\_suffix](#input\_resource\_suffix) | Sanitized environment name for resource naming | `string` | n/a | yes | +| [schedule\_expression](#input\_schedule\_expression) | Schedule expression for the AWS Scheduler (e.g. rate(3 days) or cron(...)) | `string` | `null` | no | +| [start\_time](#input\_start\_time) | RFC3339 timestamp to use as the scheduler start time | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/cognito/main.tf b/infrastructure/modules/cognito/main.tf index 4da3ac1..c9fe18d 100644 --- a/infrastructure/modules/cognito/main.tf +++ b/infrastructure/modules/cognito/main.tf @@ -119,4 +119,3 @@ resource "aws_cognito_user" "cognito_user_creation" { uid = each.value.uuid } } - diff --git a/infrastructure/modules/cognito/readme.md b/infrastructure/modules/cognito/readme.md index 68dc11b..60d6e91 100644 --- a/infrastructure/modules/cognito/readme.md +++ b/infrastructure/modules/cognito/readme.md @@ -48,9 +48,9 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [random](#provider_random) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [random](#provider\_random) | 3.8.1 | ## Modules @@ -59,7 +59,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_cognito_user.cognito_user_creation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user) | resource | | [aws_cognito_user_pool.cognito_user_pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool) | resource | | [aws_cognito_user_pool_domain.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cognito_user_pool_domain) | resource | @@ -71,26 +71,26 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [acr](#input_acr) | n/a | `string` | `"AAL1_USERPASS"` | no | -| [amr](#input_amr) | n/a | `string` | `"USERPASS"` | no | -| [attribute_names](#input_attribute_names) | n/a | `list(string)` |
[
"acr",
"amr",
"email",
"idassurancelevel",
"nhsid_nrbac_roles",
"bss_username",
"sid",
"uid"
]
| no | -| [deletion_protection](#input_deletion_protection) | ################################################################################# COGNITO ################################################################################# | `string` | `"INACTIVE"` | no | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [message_action](#input_message_action) | n/a | `string` | `"SUPPRESS"` | no | -| [mfa_configuration](#input_mfa_configuration) | n/a | `string` | `"OFF"` | no | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [recovery_window](#input_recovery_window) | The number of days that credentials should be retained for | `number` | n/a | yes | -| [secret_replication_regions](#input_secret_replication_regions) | List of additional regions where created secrets should be replicated | `list(string)` | n/a | yes | -| [user_email](#input_user_email) | n/a | `string` | `"nhsdigital.axe@nhs.net"` | no | -| [user_password](#input_user_password) | n/a | `string` | `"changeme"` | no | +| ---- | ----------- | ---- | ------- | :------: | +| [acr](#input\_acr) | n/a | `string` | `"AAL1_USERPASS"` | no | +| [amr](#input\_amr) | n/a | `string` | `"USERPASS"` | no | +| [attribute\_names](#input\_attribute\_names) | n/a | `list(string)` |
[
"acr",
"amr",
"email",
"idassurancelevel",
"nhsid_nrbac_roles",
"bss_username",
"sid",
"uid"
]
| no | +| [deletion\_protection](#input\_deletion\_protection) | ################################################################################# COGNITO ################################################################################# | `string` | `"INACTIVE"` | no | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [message\_action](#input\_message\_action) | n/a | `string` | `"SUPPRESS"` | no | +| [mfa\_configuration](#input\_mfa\_configuration) | n/a | `string` | `"OFF"` | no | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [recovery\_window](#input\_recovery\_window) | The number of days that credentials should be retained for | `number` | n/a | yes | +| [secret\_replication\_regions](#input\_secret\_replication\_regions) | List of additional regions where created secrets should be replicated | `list(string)` | n/a | yes | +| [user\_email](#input\_user\_email) | n/a | `string` | `"nhsdigital.axe@nhs.net"` | no | +| [user\_password](#input\_user\_password) | n/a | `string` | `"changeme"` | no | ## Outputs | Name | Description | -|------|-------------| -| [secrets_manager_random_passsword_arn](#output_secrets_manager_random_passsword_arn) | n/a | -| [user_pool_domain_prefix](#output_user_pool_domain_prefix) | n/a | -| [user_pool_id](#output_user_pool_id) | n/a | +| ---- | ----------- | +| [secrets\_manager\_random\_passsword\_arn](#output\_secrets\_manager\_random\_passsword\_arn) | n/a | +| [user\_pool\_domain\_prefix](#output\_user\_pool\_domain\_prefix) | n/a | +| [user\_pool\_id](#output\_user\_pool\_id) | n/a | diff --git a/infrastructure/modules/cw-firehose-splunk/readme.md b/infrastructure/modules/cw-firehose-splunk/readme.md index 8f7426d..fbe75e0 100644 --- a/infrastructure/modules/cw-firehose-splunk/readme.md +++ b/infrastructure/modules/cw-firehose-splunk/readme.md @@ -2,18 +2,17 @@ - ## Requirements No requirements. ## Providers -| Name | Version | -| ------------------------------------------------------------ | ------- | -| [archive](#provider_archive) | n/a | -| [aws](#provider_aws) | n/a | -| [local](#provider_local) | n/a | +| Name | Version | +| ---- | ------- | +| [archive](#provider\_archive) | 2.7.1 | +| [aws](#provider\_aws) | 6.43.0 | +| [local](#provider\_local) | 2.8.0 | ## Modules @@ -21,48 +20,47 @@ No modules. ## Resources -| Name | Type | -| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| [aws_iam_policy.cloudwatch_to_firehose](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.cw_firehose_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_policy.cw_lambda_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | -| [aws_iam_role.cloudwatch_to_firehose_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.cw_firehose_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.cw_lambda_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.cloudwatch_to_firehose_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.cw_firehose_att](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.cw_lambda_att](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_kinesis_firehose_delivery_stream.cw_logs_splunk_stream](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_firehose_delivery_stream) | resource | -| [aws_lambda_function.preprocess-cw-logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [aws_s3_bucket.undelivered_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_public_access_block.block_public_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | -| [aws_s3_bucket_server_side_encryption_configuration.undelivered_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | -| [local_file.preprocess-cw-logs-py](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | -| [archive_file.preprocess-cw-logs-zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | -| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.cw_firehose_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.cw_firehose_doc_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.cw_lambda_doc_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| Name | Type | +| ---- | ---- | +| [aws_iam_policy.cloudwatch_to_firehose](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.cw_firehose_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.cw_lambda_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.cloudwatch_to_firehose_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.cw_firehose_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.cw_lambda_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.cloudwatch_to_firehose_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.cw_firehose_att](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.cw_lambda_att](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kinesis_firehose_delivery_stream.cw_logs_splunk_stream](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_firehose_delivery_stream) | resource | +| [aws_lambda_function.preprocess-cw-logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_s3_bucket.undelivered_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_public_access_block.block_public_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.undelivered_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [local_file.preprocess-cw-logs-py](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | +| [archive_file.preprocess-cw-logs-zip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | +| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cw_firehose_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cw_firehose_doc_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.cw_lambda_doc_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs -| Name | Description | Type | Default | Required | -| ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------ | :------: | -| [aws_account_id](#input_aws_account_id) | The AWS account ID | `string` | n/a | yes | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [exclude_extra_logging](#input_exclude_extra_logging) | Exclude extra logging information in the Lambda function that preprocesses the CW logs before sending to Splunk | `bool` | `false` | no | -| [firehose_splunk_url](#input_firehose_splunk_url) | URL for splunk | `string` | `"https://firehose.inputs.splunk.aws.digital.nhs.uk/services/collector"` | no | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [python_version](#input_python_version) | The Python version to use for the Lambda function | `string` | n/a | yes | -| [splunk_hec_token](#input_splunk_hec_token) | Splunk HEC token which points to a specific log index in Splunk | `any` | n/a | yes | -| [splunk_index](#input_splunk_index) | Name of the Splunk index to post logs to | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [aws\_account\_id](#input\_aws\_account\_id) | The AWS account ID | `string` | n/a | yes | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [exclude\_extra\_logging](#input\_exclude\_extra\_logging) | Exclude extra logging information in the Lambda function that preprocesses the CW logs before sending to Splunk | `bool` | `false` | no | +| [firehose\_splunk\_url](#input\_firehose\_splunk\_url) | URL for splunk | `string` | `"https://firehose.inputs.splunk.aws.digital.nhs.uk/services/collector"` | no | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [python\_version](#input\_python\_version) | The Python version to use for the Lambda function | `string` | n/a | yes | +| [splunk\_hec\_token](#input\_splunk\_hec\_token) | Splunk HEC token which points to a specific log index in Splunk | `any` | n/a | yes | +| [splunk\_index](#input\_splunk\_index) | Name of the Splunk index to post logs to | `string` | n/a | yes | ## Outputs -| Name | Description | -| ----------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| [cw_to_splunk_firehose_role_arn](#output_cw_to_splunk_firehose_role_arn) | n/a | -| [cw_to_splunk_firehose_stream_arn](#output_cw_to_splunk_firehose_stream_arn) | n/a | - +| Name | Description | +| ---- | ----------- | +| [cw\_to\_splunk\_firehose\_role\_arn](#output\_cw\_to\_splunk\_firehose\_role\_arn) | n/a | +| [cw\_to\_splunk\_firehose\_stream\_arn](#output\_cw\_to\_splunk\_firehose\_stream\_arn) | n/a | diff --git a/infrastructure/modules/ecr/readme.md b/infrastructure/modules/ecr/readme.md index aba5897..64ead31 100644 --- a/infrastructure/modules/ecr/readme.md +++ b/infrastructure/modules/ecr/readme.md @@ -8,8 +8,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -18,7 +18,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_ecr_lifecycle_policy.ecr](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource | | [aws_ecr_repository.image_repository](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | | [aws_ecr_repository_policy.ecr_repo_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy) | resource | @@ -31,11 +31,11 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [developer_sso_role](#input_developer_sso_role) | The SSO role for developers | `string` | n/a | yes | -| [lifecycle_rules](#input_lifecycle_rules) | List of lifecycle rules. Each rule must be an object:
{
priority = number
description = string
selection = {
tag_status = string
tag_prefix_list = optional(list(string))
tag_pattern_list = optional(list(string))
count_type = string
count_number = number
count_unit = optional(string)
}
} |
list(object({
priority = number
description = string
selection = object({
tag_status = string
tag_prefix_list = optional(list(string))
tag_pattern_list = optional(list(string))
count_type = string
count_number = number
count_unit = optional(string)
})
}))
| `[]` | no | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [repo_name](#input_repo_name) | The name of the ECR repository | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [developer\_sso\_role](#input\_developer\_sso\_role) | The SSO role for developers | `string` | n/a | yes | +| [lifecycle\_rules](#input\_lifecycle\_rules) | List of lifecycle rules. Each rule must be an object:
{
priority = number
description = string
selection = {
tag\_status = string
tag\_prefix\_list = optional(list(string))
tag\_pattern\_list = optional(list(string))
count\_type = string
count\_number = number
count\_unit = optional(string)
}
} |
list(object({
priority = number
description = string
selection = object({
tag_status = string
tag_prefix_list = optional(list(string))
tag_pattern_list = optional(list(string))
count_type = string
count_number = number
count_unit = optional(string)
})
}))
| `[]` | no | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [repo\_name](#input\_repo\_name) | The name of the ECR repository | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/ecr/variables.tf b/infrastructure/modules/ecr/variables.tf index 83e07aa..da03954 100644 --- a/infrastructure/modules/ecr/variables.tf +++ b/infrastructure/modules/ecr/variables.tf @@ -47,4 +47,3 @@ EOT })) default = [] } - diff --git a/infrastructure/modules/ecs-cluster/ecs.tf b/infrastructure/modules/ecs-cluster/ecs.tf index bde1eb9..184a883 100644 --- a/infrastructure/modules/ecs-cluster/ecs.tf +++ b/infrastructure/modules/ecs-cluster/ecs.tf @@ -99,6 +99,3 @@ resource "aws_cloudwatch_metric_alarm" "task_memory_utilization_alarm" { comparison_operator = "GreaterThanThreshold" treat_missing_data = "notBreaching" } - - - diff --git a/infrastructure/modules/ecs-cluster/readme.md b/infrastructure/modules/ecs-cluster/readme.md index 17dd1fb..eddd822 100644 --- a/infrastructure/modules/ecs-cluster/readme.md +++ b/infrastructure/modules/ecs-cluster/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_cloudwatch_metric_alarm.task_cpu_utilization_alarm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | | [aws_cloudwatch_metric_alarm.task_memory_utilization_alarm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | | [aws_ecs_cluster.ecs_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource | @@ -32,21 +32,21 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws_account_id](#input_aws_account_id) | The AWS account ID | `string` | n/a | yes | -| [container_port](#input_container_port) | n/a | `number` | `4000` | no | -| [create_ecs_service_role](#input_create_ecs_service_role) | The service role can only be created once per account, only enable it in one stack | `bool` | `true` | no | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [name](#input_name) | the unique name of the resource | `string` | `"ecs"` | no | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [vpc_id](#input_vpc_id) | id of the vpc | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [aws\_account\_id](#input\_aws\_account\_id) | The AWS account ID | `string` | n/a | yes | +| [container\_port](#input\_container\_port) | n/a | `number` | `4000` | no | +| [create\_ecs\_service\_role](#input\_create\_ecs\_service\_role) | The service role can only be created once per account, only enable it in one stack | `bool` | `true` | no | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [name](#input\_name) | the unique name of the resource | `string` | `"ecs"` | no | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | id of the vpc | `string` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [ecs_cluster_arn](#output_ecs_cluster_arn) | n/a | -| [ecs_cluster_name](#output_ecs_cluster_name) | n/a | -| [ecs_sg_id](#output_ecs_sg_id) | n/a | +| ---- | ----------- | +| [ecs\_cluster\_arn](#output\_ecs\_cluster\_arn) | n/a | +| [ecs\_cluster\_name](#output\_ecs\_cluster\_name) | n/a | +| [ecs\_sg\_id](#output\_ecs\_sg\_id) | n/a | diff --git a/infrastructure/modules/elasticache/main.tf b/infrastructure/modules/elasticache/main.tf index 3adc117..fc2c899 100644 --- a/infrastructure/modules/elasticache/main.tf +++ b/infrastructure/modules/elasticache/main.tf @@ -105,4 +105,3 @@ resource "aws_cloudwatch_log_group" "redis_slow_log" { #kms_key_id = data.aws_kms_key.kms_key.arn retention_in_days = 365 } - diff --git a/infrastructure/modules/elasticache/readme.md b/infrastructure/modules/elasticache/readme.md index ece474c..494b3f5 100644 --- a/infrastructure/modules/elasticache/readme.md +++ b/infrastructure/modules/elasticache/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_cloudwatch_log_group.redis_engine_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.redis_slow_log](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_elasticache_parameter_group.bss_param_group_redis7](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_parameter_group) | resource | @@ -33,33 +33,33 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [apply_immediately](#input_apply_immediately) | whether to apply changes immediately - false will apply in maintenance window | `bool` | `false` | no | -| [auto_failover_enabled](#input_auto_failover_enabled) | n/a | `any` | n/a | yes | -| [aws_account_id](#input_aws_account_id) | The AWS account ID | `string` | n/a | yes | -| [create_elasticache_service_role](#input_create_elasticache_service_role) | The service role can only be created once per account, only enable it in one stack | `bool` | `true` | no | -| [ecs_sg_id](#input_ecs_sg_id) | The id of the ECS security group to enable access for | `string` | n/a | yes | -| [elasticache_port](#input_elasticache_port) | Port on which Elasticache runs | `number` | `6379` | no | -| [engine_version](#input_engine_version) | The Elasticache engine version | `any` | n/a | yes | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [multi_az](#input_multi_az) | n/a | `any` | n/a | yes | -| [name](#input_name) | The name of the resource | `string` | `"elasticache"` | no | -| [name_prefix](#input_name_prefix) | the prefix for the name which containts the environment and business unit | `string` | n/a | yes | -| [node_type](#input_node_type) | n/a | `any` | n/a | yes | -| [notification_topic_arn](#input_notification_topic_arn) | Name of the SNS topic used for Elasticache alerts | `any` | n/a | yes | -| [number_of_shards](#input_number_of_shards) | n/a | `number` | `1` | no | -| [redis_auth_token](#input_redis_auth_token) | Auth token for Redis cache | `any` | n/a | yes | -| [replicas_per_node_group](#input_replicas_per_node_group) | n/a | `number` | `2` | no | -| [replication_group_description](#input_replication_group_description) | Description for replication group | `string` | `"Redis cache for BS-Select application"` | no | -| [subnet_ids](#input_subnet_ids) | The subnets that will be used for elasticache, usually private | `list(string)` | n/a | yes | -| [vpc_id](#input_vpc_id) | The ID for the VPC | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [apply\_immediately](#input\_apply\_immediately) | whether to apply changes immediately - false will apply in maintenance window | `bool` | `false` | no | +| [auto\_failover\_enabled](#input\_auto\_failover\_enabled) | n/a | `any` | n/a | yes | +| [aws\_account\_id](#input\_aws\_account\_id) | The AWS account ID | `string` | n/a | yes | +| [create\_elasticache\_service\_role](#input\_create\_elasticache\_service\_role) | The service role can only be created once per account, only enable it in one stack | `bool` | `true` | no | +| [ecs\_sg\_id](#input\_ecs\_sg\_id) | The id of the ECS security group to enable access for | `string` | n/a | yes | +| [elasticache\_port](#input\_elasticache\_port) | Port on which Elasticache runs | `number` | `6379` | no | +| [engine\_version](#input\_engine\_version) | The Elasticache engine version | `any` | n/a | yes | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [multi\_az](#input\_multi\_az) | n/a | `any` | n/a | yes | +| [name](#input\_name) | The name of the resource | `string` | `"elasticache"` | no | +| [name\_prefix](#input\_name\_prefix) | the prefix for the name which containts the environment and business unit | `string` | n/a | yes | +| [node\_type](#input\_node\_type) | n/a | `any` | n/a | yes | +| [notification\_topic\_arn](#input\_notification\_topic\_arn) | Name of the SNS topic used for Elasticache alerts | `any` | n/a | yes | +| [number\_of\_shards](#input\_number\_of\_shards) | n/a | `number` | `1` | no | +| [redis\_auth\_token](#input\_redis\_auth\_token) | Auth token for Redis cache | `any` | n/a | yes | +| [replicas\_per\_node\_group](#input\_replicas\_per\_node\_group) | n/a | `number` | `2` | no | +| [replication\_group\_description](#input\_replication\_group\_description) | Description for replication group | `string` | `"Redis cache for BS-Select application"` | no | +| [subnet\_ids](#input\_subnet\_ids) | The subnets that will be used for elasticache, usually private | `list(string)` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | The ID for the VPC | `string` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [redis_configuration_endpoint_address](#output_redis_configuration_endpoint_address) | n/a | -| [redis_configuration_endpoint_port](#output_redis_configuration_endpoint_port) | n/a | -| [redis_security_group_id](#output_redis_security_group_id) | n/a | +| ---- | ----------- | +| [redis\_configuration\_endpoint\_address](#output\_redis\_configuration\_endpoint\_address) | n/a | +| [redis\_configuration\_endpoint\_port](#output\_redis\_configuration\_endpoint\_port) | n/a | +| [redis\_security\_group\_id](#output\_redis\_security\_group\_id) | n/a | diff --git a/infrastructure/modules/github-config/readme.md b/infrastructure/modules/github-config/readme.md index 78cf516..aadac28 100644 --- a/infrastructure/modules/github-config/readme.md +++ b/infrastructure/modules/github-config/readme.md @@ -2,18 +2,17 @@ - ## Requirements -| Name | Version | -| --------------------------------------------------------------- | ------- | -| [github](#requirement_github) | ~> 6.0 | +| Name | Version | +| ---- | ------- | +| [github](#requirement\_github) | ~> 6.0 | ## Providers -| Name | Version | -| --------------------------------------------------------- | ------- | -| [github](#provider_github) | ~> 6.0 | +| Name | Version | +| ---- | ------- | +| [github](#provider\_github) | 6.12.1 | ## Modules @@ -21,24 +20,23 @@ No modules. ## Resources -| Name | Type | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| [github_actions_environment_secret.aws_account](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_environment_secret) | resource | -| [github_repository_environment.repo_environment](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_environment) | resource | -| [github_repository.repo](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/repository) | data source | +| Name | Type | +| ---- | ---- | +| [github_actions_environment_secret.aws_account](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_environment_secret) | resource | +| [github_repository_environment.repo_environment](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_environment) | resource | +| [github_repository.repo](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/repository) | data source | ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------- | ------- | :------: | -| [aws_account_id](#input_aws_account_id) | The AWS account ID | `string` | n/a | yes | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [github_app_token](#input_github_app_token) | The GitHub App token used to authenticate with the GitHub provider | `string` | n/a | yes | -| [github_repo_name](#input_github_repo_name) | the name for the github repo | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [aws\_account\_id](#input\_aws\_account\_id) | The AWS account ID | `string` | n/a | yes | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [github\_app\_token](#input\_github\_app\_token) | The GitHub App token used to authenticate with the GitHub provider | `string` | n/a | yes | +| [github\_repo\_name](#input\_github\_repo\_name) | the name for the github repo | `string` | n/a | yes | ## Outputs No outputs. - diff --git a/infrastructure/modules/kms/README.md b/infrastructure/modules/kms/README.md new file mode 100644 index 0000000..c9b4aa8 --- /dev/null +++ b/infrastructure/modules/kms/README.md @@ -0,0 +1,121 @@ + +# AWS KMS Terraform module +Terraform module to provision a [KMS](https://aws.amazon.com/kms/) key with alias. + + + + +## Usage + +```hcl + module "kms_key" { + source = "git::https://github.com/NHSDigital/screening-terraform-modules-aws.git//infrastructure/modules/kms" + + service = "bcss" + project = "bcss" + environment = "test" + stack = "bootstrap" + workspace = terraform.workspace + name = "terraform-state" + + label_order = ["service", "environment", "stack", "workspace", "name", "attributes"] + + description = "KMS key for Terraform state bucket encryption" + deletion_window_in_days = 10 + enable_key_rotation = true + } +``` + + + + + + + + + + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.5.7 | +| [aws](#requirement\_aws) | >= 6.28 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +| ---- | ------ | ------- | +| [kms\_key](#module\_kms\_key) | terraform-aws-modules/kms/aws | 4.2.0 | +| [this](#module\_this) | git::https://github.com/NHSDigital/screening-terraform-modules-aws.git//infrastructure/modules/tags | feature/BCSS-23189-add-new-modules-to-suppport-bcss | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | +| [aliases](#input\_aliases) | A list of aliases to create. Note - due to the use of `toset()`, values must be static strings and not computed values. The prefix `alias` followed by a forward slash will be automatically added and should not be included. If not specified, the alias name will be auto-generated. | `list(string)` | `[]` | no | +| [aliases\_use\_name\_prefix](#input\_aliases\_use\_name\_prefix) | Determines whether the alias name is used as a prefix | `bool` | `false` | no | +| [application\_role](#input\_application\_role) | The role the application is performing | `string` | `"General"` | no | +| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | +| [aws\_region](#input\_aws\_region) | The AWS region | `string` | `"eu-west-2"` | no | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"project": null,
"regex_replace_chars": null,
"region": null,
"service": null,
"stack": null,
"tags": {},
"workspace": null
}
| no | +| [customer\_master\_key\_spec](#input\_customer\_master\_key\_spec) | Specifies whether the key contains a symmetric key or an asymmetric key pair and the encryption algorithms or signing algorithms that the key supports. Valid values: `SYMMETRIC_DEFAULT`, `RSA_2048`, `RSA_3072`, `RSA_4096`, `ECC_NIST_P256`, `ECC_NIST_P384`, `ECC_NIST_P521`, or `ECC_SECG_P256K1`. | `string` | `"SYMMETRIC_DEFAULT"` | no | +| [data\_classification](#input\_data\_classification) | Used to identify the data classification of the resource, e.g 1-5 | `string` | `"n/a"` | no | +| [data\_type](#input\_data\_type) | The tag data\_type | `string` | `"None"` | no | +| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | Duration in days after which the key is deleted after destruction of the resource | `number` | `14` | no | +| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [description](#input\_description) | The description of the key as viewed in AWS console | `string` | `"Parameter Store KMS master key"` | no | +| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | +| [enable\_default\_policy](#input\_enable\_default\_policy) | Specifies whether to enable the default key policy. Defaults to `true` | `bool` | `true` | no | +| [enable\_key\_rotation](#input\_enable\_key\_rotation) | Whether to enable automatic key rotation for the KMS key. Note that this is only applicable for symmetric keys. | `bool` | `true` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | ID element. Usually used to indicate role, e.g. 'prd', 'dev', 'test', 'preprod', 'prod', 'uat' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [key\_administrators](#input\_key\_administrators) | A list of IAM ARNs for [key administrators](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators) | `list(string)` | `[]` | no | +| [key\_owners](#input\_key\_owners) | A list of IAM ARNs for those who will have full key permissions (`kms:*`) | `list(string)` | `[]` | no | +| [key\_service\_users](#input\_key\_service\_users) | A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration) | `list(string)` | `[]` | no | +| [key\_statements](#input\_key\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage |
list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
}))
| `null` | no | +| [key\_usage](#input\_key\_usage) | Specifies the intended use of the key. Valid values: `ENCRYPT_DECRYPT` or `SIGN_VERIFY`. | `string` | `"ENCRYPT_DECRYPT"` | no | +| [key\_users](#input\_key\_users) | A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users) | `list(string)` | `[]` | no | +| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | +| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no | +| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no | +| [on\_off\_pattern](#input\_on\_off\_pattern) | Used to turn resources on and off based on a time pattern | `string` | `"n/a"` | no | +| [owner](#input\_owner) | The name and or NHS.net email address of the service owner | `string` | `"None"` | no | +| [policy](#input\_policy) | A valid KMS policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy. | `string` | `""` | no | +| [project](#input\_project) | ID element. A project identifier, indicating the name or role of the project the resource is for, such as `website` or `api` | `string` | `null` | no | +| [public\_facing](#input\_public\_facing) | Whether this resource is public facing | `bool` | `false` | no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [region](#input\_region) | ID element \_(Rarely used, not included by default)\_. Usually an abbreviation of the selected AWS region e.g. 'uw2', 'ew2' or 'gbl' for resources like IAM roles that have no region | `string` | `null` | no | +| [service](#input\_service) | ID element. Usually an abbreviation of your service directorate name, e.g. 'bcss' or 'csms', to help ensure generated IDs are globally unique | `string` | `null` | no | +| [service\_category](#input\_service\_category) | The tag service\_category | `string` | `"n/a"` | no | +| [stack](#input\_stack) | ID element. The name of the stack/component, e.g. `database`, `web`, `waf`, `eks` | `string` | `null` | no | +| [tag\_version](#input\_tag\_version) | Used to identify the tagging version in use | `string` | `"1.0"` | no | +| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | +| [tool](#input\_tool) | The tool used to deploy the resource | `string` | `"Terraform"` | no | +| [workspace](#input\_workspace) | ID element. The Terraform workspace, to help ensure generated IDs are unique across workspaces | `string` | `null` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [aliases](#output\_aliases) | A map of aliases created and their attributes | +| [grants](#output\_grants) | A map of grants created and their attributes | +| [key\_arn](#output\_key\_arn) | The Amazon Resource Name (ARN) of the key | +| [key\_id](#output\_key\_id) | The globally unique identifier for the key | +| [key\_policy](#output\_key\_policy) | The IAM resource policy set on the key | +| [key\_region](#output\_key\_region) | The region for the key | + + diff --git a/infrastructure/modules/kms/context.tf b/infrastructure/modules/kms/context.tf new file mode 100644 index 0000000..da16545 --- /dev/null +++ b/infrastructure/modules/kms/context.tf @@ -0,0 +1,344 @@ +# +# ONLY EDIT THIS FILE IN github.com/NHSDigital/screening-terraform-modules-aws/infrastructure/modules/tags +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/NHSDigital/screening-terraform-modules-aws/blob/master/infrastructure/modules/tags/exports/context.tf +# and then place it in your Terraform module to automatically get +# tag module standard configuration inputs suitable for passing +# to other modules. +# +# curl -sL https://raw.githubusercontent.com/NHSDigital/screening-terraform-modules-aws/master/infrastructure/modules/tags/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/NHSDigital/screening-terraform-modules-aws.git//infrastructure/modules/tags?ref=feature/BCSS-23189-add-new-modules-to-suppport-bcss" +} + +# Copy contents of screening-terraform-modules-aws/tags/variables.tf here +# tflint-ignore: terraform_unused_declarations +variable "aws_region" { + type = string + description = "The AWS region" + default = "eu-west-2" + validation { + condition = contains(["eu-west-1", "eu-west-2", "us-east-1"], var.aws_region) + error_message = "AWS Region must be one of eu-west-1, eu-west-2, us-east-1" + } +} + +variable "context" { + type = any + default = { + enabled = true + service = null + project = null + region = null + environment = null + stack = null + workspace = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "service" { + type = string + default = null + description = "ID element. Usually an abbreviation of your service directorate name, e.g. 'bcss' or 'csms', to help ensure generated IDs are globally unique" +} + +variable "region" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. Usually an abbreviation of the selected AWS region e.g. 'uw2', 'ew2' or 'gbl' for resources like IAM roles that have no region" +} + +variable "project" { + type = string + default = null + description = "ID element. A project identifier, indicating the name or role of the project the resource is for, such as `website` or `api`" +} +variable "stack" { + type = string + default = null + description = "ID element. The name of the stack/component, e.g. `database`, `web`, `waf`, `eks`" +} +variable "workspace" { + type = string + default = null + description = "ID element. The Terraform workspace, to help ensure generated IDs are unique across workspaces" +} +variable "environment" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prd', 'dev', 'test', 'preprod', 'prod', 'uat'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +variable "owner" { + type = string + description = "The name and or NHS.net email address of the service owner" + default = "None" +} + +variable "tag_version" { + type = string + description = "Used to identify the tagging version in use" + default = "1.0" +} + +variable "data_classification" { + type = string + description = "Used to identify the data classification of the resource, e.g 1-5" + default = "n/a" + validation { + condition = contains(["n/a", "1", "2", "3", "4", "5"], var.data_classification) + error_message = "Data Classification must be \"n/a\" or between 1-5" + } +} + +variable "data_type" { + type = string + description = "The tag data_type" + default = "None" + validation { + condition = contains(["None", "PCD", "PID", "Anonymised", "UserAccount", "Audit"], var.data_type) + error_message = "Data Type must be one of None, PCD, PID, Anonymised, UserAccount, Audit" + } +} + + +variable "public_facing" { + type = bool + description = "Whether this resource is public facing" + default = false +} + +variable "service_category" { + type = string + description = "The tag service_category" + default = "n/a" + validation { + condition = contains(["n/a", "Bronze", "Silver", "Gold", "Platinum"], var.service_category) + error_message = "The Service Category must be one of n/a, Bronze, Silver, Gold, Platinum" + } +} +variable "on_off_pattern" { + type = string + description = "Used to turn resources on and off based on a time pattern" + default = "n/a" +} + +variable "application_role" { + type = string + description = "The role the application is performing" + default = "General" +} + +variable "tool" { + type = string + description = "The tool used to deploy the resource" + default = "Terraform" +} + +#### End of copy of screening-terraform-modules-aws/tags/variables.tf diff --git a/infrastructure/modules/kms/locals.tf b/infrastructure/modules/kms/locals.tf new file mode 100644 index 0000000..551a5a3 --- /dev/null +++ b/infrastructure/modules/kms/locals.tf @@ -0,0 +1,4 @@ +locals { + name = format("alias/%v", module.this.id) + aliases = length(var.aliases) > 0 ? var.aliases : [local.name] +} diff --git a/infrastructure/modules/kms/main.tf b/infrastructure/modules/kms/main.tf new file mode 100644 index 0000000..ff71952 --- /dev/null +++ b/infrastructure/modules/kms/main.tf @@ -0,0 +1,32 @@ +module "kms_key" { + source = "terraform-aws-modules/kms/aws" + version = "4.2.0" + + create = module.this.enabled + + # Desired hard-set parameters for the KMS key. + bypass_policy_lockout_safety_check = false + + + aliases_use_name_prefix = var.aliases_use_name_prefix + + deletion_window_in_days = var.deletion_window_in_days + enable_key_rotation = var.enable_key_rotation + description = var.description + aliases = local.aliases + policy = var.policy + key_usage = var.key_usage + customer_master_key_spec = var.customer_master_key_spec + + + enable_default_policy = var.enable_default_policy + key_owners = var.key_owners + key_administrators = var.key_administrators + key_users = var.key_users + key_service_users = var.key_service_users + key_statements = var.key_statements + + + tags = module.this.tags + +} diff --git a/infrastructure/modules/kms/outputs.tf b/infrastructure/modules/kms/outputs.tf new file mode 100644 index 0000000..8c9a315 --- /dev/null +++ b/infrastructure/modules/kms/outputs.tf @@ -0,0 +1,30 @@ +output "key_arn" { + description = "The Amazon Resource Name (ARN) of the key" + value = module.kms_key.key_arn +} + +output "key_id" { + description = "The globally unique identifier for the key" + value = module.kms_key.key_id +} + +output "key_policy" { + description = "The IAM resource policy set on the key" + value = module.kms_key.key_policy +} + +output "key_region" { + description = "The region for the key" + value = module.kms_key.key_region +} + +output "aliases" { + description = "A map of aliases created and their attributes" + value = module.kms_key.aliases +} + +output "grants" { + description = "A map of grants created and their attributes" + value = module.kms_key.grants + sensitive = true +} diff --git a/infrastructure/modules/kms/variables.tf b/infrastructure/modules/kms/variables.tf new file mode 100644 index 0000000..2d2d3c6 --- /dev/null +++ b/infrastructure/modules/kms/variables.tf @@ -0,0 +1,102 @@ +variable "deletion_window_in_days" { + type = number + default = 14 + description = "Duration in days after which the key is deleted after destruction of the resource" +} + +variable "description" { + type = string + default = "Parameter Store KMS master key" + description = "The description of the key as viewed in AWS console" +} + +variable "aliases" { + description = "A list of aliases to create. Note - due to the use of `toset()`, values must be static strings and not computed values. The prefix `alias` followed by a forward slash will be automatically added and should not be included. If not specified, the alias name will be auto-generated." + type = list(string) + default = [] +} +variable "aliases_use_name_prefix" { + description = "Determines whether the alias name is used as a prefix" + type = bool + default = false +} + +variable "enable_key_rotation" { + type = bool + default = true + description = "Whether to enable automatic key rotation for the KMS key. Note that this is only applicable for symmetric keys." +} +variable "policy" { + type = string + default = "" + description = "A valid KMS policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy." +} + +variable "key_usage" { + type = string + default = "ENCRYPT_DECRYPT" + description = "Specifies the intended use of the key. Valid values: `ENCRYPT_DECRYPT` or `SIGN_VERIFY`." +} + +variable "customer_master_key_spec" { + type = string + default = "SYMMETRIC_DEFAULT" + description = "Specifies whether the key contains a symmetric key or an asymmetric key pair and the encryption algorithms or signing algorithms that the key supports. Valid values: `SYMMETRIC_DEFAULT`, `RSA_2048`, `RSA_3072`, `RSA_4096`, `ECC_NIST_P256`, `ECC_NIST_P384`, `ECC_NIST_P521`, or `ECC_SECG_P256K1`." +} + + +variable "enable_default_policy" { + description = "Specifies whether to enable the default key policy. Defaults to `true`" + type = bool + default = true +} + +variable "key_owners" { + description = "A list of IAM ARNs for those who will have full key permissions (`kms:*`)" + type = list(string) + default = [] +} + +variable "key_administrators" { + description = "A list of IAM ARNs for [key administrators](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-administrators)" + type = list(string) + default = [] +} + +variable "key_users" { + description = "A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users)" + type = list(string) + default = [] +} + +variable "key_service_users" { + description = "A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration)" + type = list(string) + default = [] +} + +variable "key_statements" { + description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage" + type = list(object({ + sid = optional(string) + actions = optional(list(string)) + not_actions = optional(list(string)) + effect = optional(string) + resources = optional(list(string)) + not_resources = optional(list(string)) + principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + not_principals = optional(list(object({ + type = string + identifiers = list(string) + }))) + condition = optional(list(object({ + test = string + values = list(string) + variable = string + }))) + })) + default = null +} diff --git a/infrastructure/modules/kms/versions.tf b/infrastructure/modules/kms/versions.tf new file mode 100644 index 0000000..d2afd5f --- /dev/null +++ b/infrastructure/modules/kms/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.5.7" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 6.28" + } + } +} diff --git a/infrastructure/modules/lambda-layer/readme.md b/infrastructure/modules/lambda-layer/readme.md index 720ca28..d2a95f1 100644 --- a/infrastructure/modules/lambda-layer/readme.md +++ b/infrastructure/modules/lambda-layer/readme.md @@ -9,9 +9,9 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [null](#provider_null) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [null](#provider\_null) | 3.2.4 | ## Modules @@ -20,25 +20,25 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_lambda_layer_version.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_layer_version) | resource | | [null_resource.build_lambda_layer](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [compatible_runtimes](#input_compatible_runtimes) | Compatible Python runtimes for the Lambda layer | `list(string)` |
[
"python3.12"
]
| no | -| [description](#input_description) | The description for the Lambda layer | `string` | n/a | yes | -| [layer_name](#input_layer_name) | The name of the Lambda layer | `string` | n/a | yes | -| [name_prefix](#input_name_prefix) | the prefix standard | `string` | n/a | yes | -| [source_path](#input_source_path) | The path of the stored layer zip file | `string` | `"../../layers"` | no | +| ---- | ----------- | ---- | ------- | :------: | +| [compatible\_runtimes](#input\_compatible\_runtimes) | Compatible Python runtimes for the Lambda layer | `list(string)` |
[
"python3.12"
]
| no | +| [description](#input\_description) | The description for the Lambda layer | `string` | n/a | yes | +| [layer\_name](#input\_layer\_name) | The name of the Lambda layer | `string` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | the prefix standard | `string` | n/a | yes | +| [source\_path](#input\_source\_path) | The path of the stored layer zip file | `string` | `"../../layers"` | no | ## Outputs | Name | Description | -|------|-------------| -| [layer_arn](#output_layer_arn) | n/a | +| ---- | ----------- | +| [layer\_arn](#output\_layer\_arn) | n/a | diff --git a/infrastructure/modules/lambda/readme.md b/infrastructure/modules/lambda/readme.md index 132300d..273590c 100644 --- a/infrastructure/modules/lambda/readme.md +++ b/infrastructure/modules/lambda/readme.md @@ -8,19 +8,19 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules | Name | Source | Version | -|------|--------|---------| -| [lambda_function](#module_lambda_function) | terraform-aws-modules/lambda/aws | 8.7.0 | +| ---- | ------ | ------- | +| [lambda\_function](#module\_lambda\_function) | terraform-aws-modules/lambda/aws | 8.7.0 | ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_iam_role_policy_attachment.lambda_to_cw_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.push_to_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | @@ -29,25 +29,25 @@ No requirements. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [environment](#input_environment) | Values to set in the Lambda function environment | `map(string)` | `{}` | no | -| [function_description](#input_function_description) | The description for the Lambda function | `string` | n/a | yes | -| [function_name](#input_function_name) | The name of the Lambda function | `string` | `"uk-forwarder"` | no | -| [handler_prefix](#input_handler_prefix) | The prefix for the Lambda handler function | `string` | n/a | yes | -| [layers](#input_layers) | List of Lambda Layer ARNs to attach to the function | `list(string)` | `[]` | no | -| [name_prefix](#input_name_prefix) | the prefix standard | `string` | n/a | yes | -| [python_version](#input_python_version) | The Python version to use for the Lambda function | `string` | n/a | yes | -| [timeout](#input_timeout) | Timeout for the Lambda function in seconds | `number` | `120` | no | -| [vpc_security_group_ids](#input_vpc_security_group_ids) | List of VPC security group IDs for the Lambda function | `list(string)` | `[]` | no | -| [vpc_subnet_ids](#input_vpc_subnet_ids) | List of VPC subnet IDs for the Lambda function | `list(string)` | `[]` | no | +| ---- | ----------- | ---- | ------- | :------: | +| [environment](#input\_environment) | Values to set in the Lambda function environment | `map(string)` | `{}` | no | +| [function\_description](#input\_function\_description) | The description for the Lambda function | `string` | n/a | yes | +| [function\_name](#input\_function\_name) | The name of the Lambda function | `string` | `"uk-forwarder"` | no | +| [handler\_prefix](#input\_handler\_prefix) | The prefix for the Lambda handler function | `string` | n/a | yes | +| [layers](#input\_layers) | List of Lambda Layer ARNs to attach to the function | `list(string)` | `[]` | no | +| [name\_prefix](#input\_name\_prefix) | the prefix standard | `string` | n/a | yes | +| [python\_version](#input\_python\_version) | The Python version to use for the Lambda function | `string` | n/a | yes | +| [timeout](#input\_timeout) | Timeout for the Lambda function in seconds | `number` | `120` | no | +| [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | List of VPC security group IDs for the Lambda function | `list(string)` | `[]` | no | +| [vpc\_subnet\_ids](#input\_vpc\_subnet\_ids) | List of VPC subnet IDs for the Lambda function | `list(string)` | `[]` | no | ## Outputs | Name | Description | -|------|-------------| -| [arn](#output_arn) | n/a | -| [function_name](#output_function_name) | n/a | -| [lambda_arn](#output_lambda_arn) | n/a | -| [lambda_log_group_name](#output_lambda_log_group_name) | n/a | -| [role_name](#output_role_name) | n/a | +| ---- | ----------- | +| [arn](#output\_arn) | n/a | +| [function\_name](#output\_function\_name) | n/a | +| [lambda\_arn](#output\_lambda\_arn) | n/a | +| [lambda\_log\_group\_name](#output\_lambda\_log\_group\_name) | n/a | +| [role\_name](#output\_role\_name) | n/a | diff --git a/infrastructure/modules/parameter_store/readme.md b/infrastructure/modules/parameter_store/readme.md index 0b40a0f..2634801 100644 --- a/infrastructure/modules/parameter_store/readme.md +++ b/infrastructure/modules/parameter_store/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,18 +19,18 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_ssm_parameter.cognito_users](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | | [aws_ssm_parameter.ecs_cw_agent_config_parameter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [cloudwatch_agent_config_json](#input_cloudwatch_agent_config_json) | The CloudWatch Agent configuration JSON for ECS tasks | `string` | `""` | no | -| [enable_cloudwatch_agent](#input_enable_cloudwatch_agent) | Whether to create the CloudWatch Agent configuration parameter for ECS tasks | `bool` | `false` | no | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [cloudwatch\_agent\_config\_json](#input\_cloudwatch\_agent\_config\_json) | The CloudWatch Agent configuration JSON for ECS tasks | `string` | `""` | no | +| [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Whether to create the CloudWatch Agent configuration parameter for ECS tasks | `bool` | `false` | no | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/r53-healthcheck/outputs.tf b/infrastructure/modules/r53-healthcheck/outputs.tf index 8b13789..e69de29 100644 --- a/infrastructure/modules/r53-healthcheck/outputs.tf +++ b/infrastructure/modules/r53-healthcheck/outputs.tf @@ -1 +0,0 @@ - diff --git a/infrastructure/modules/r53-healthcheck/r53-healthcheck.tf b/infrastructure/modules/r53-healthcheck/r53-healthcheck.tf index c634499..7a90a95 100644 --- a/infrastructure/modules/r53-healthcheck/r53-healthcheck.tf +++ b/infrastructure/modules/r53-healthcheck/r53-healthcheck.tf @@ -131,5 +131,3 @@ resource "aws_cloudwatch_metric_alarm" "bs_select_health_check_web_app_healthy" insufficient_data_actions = [] treat_missing_data = "notBreaching" } - - diff --git a/infrastructure/modules/r53-healthcheck/readme.md b/infrastructure/modules/r53-healthcheck/readme.md index 360de83..9b561db 100644 --- a/infrastructure/modules/r53-healthcheck/readme.md +++ b/infrastructure/modules/r53-healthcheck/readme.md @@ -8,10 +8,10 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [archive](#provider_archive) | n/a | -| [aws](#provider_aws) | n/a | -| [aws.us_east_1](#provider_aws.us_east_1) | n/a | +| ---- | ------- | +| [archive](#provider\_archive) | 2.7.1 | +| [aws](#provider\_aws) | 6.43.0 | +| [aws.us\_east\_1](#provider\_aws.us\_east\_1) | 6.43.0 | ## Modules @@ -20,7 +20,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_cloudwatch_metric_alarm.bs_select_health_check_web_app_healthy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | | [aws_iam_role.lambda_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.sns_publish_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | @@ -35,10 +35,10 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [environment](#input_environment) | the environment the healthcheck is deployed into | `any` | n/a | yes | -| [name_prefix](#input_name_prefix) | the name prefix for the healthcheck | `any` | n/a | yes | -| [sns_topic](#input_sns_topic) | Existing SNS topic in eu-west-2 for notifications | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [environment](#input\_environment) | the environment the healthcheck is deployed into | `any` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | the name prefix for the healthcheck | `any` | n/a | yes | +| [sns\_topic](#input\_sns\_topic) | Existing SNS topic in eu-west-2 for notifications | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/rds-database/readme.md b/infrastructure/modules/rds-database/readme.md index 22eb3cf..f282e75 100644 --- a/infrastructure/modules/rds-database/readme.md +++ b/infrastructure/modules/rds-database/readme.md @@ -5,15 +5,15 @@ ## Requirements | Name | Version | -|------|---------| -| [postgresql](#requirement_postgresql) | >= 1.25.0 | +| ---- | ------- | +| [postgresql](#requirement\_postgresql) | >= 1.25.0 | ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [postgresql](#provider_postgresql) | >= 1.25.0 | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [postgresql](#provider\_postgresql) | 1.26.0 | ## Modules @@ -22,7 +22,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [postgresql_database.my_db](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest/docs/resources/database) | resource | | [aws_db_instance.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/db_instance) | data source | | [aws_secretsmanager_secret.release_manager_password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/secretsmanager_secret) | data source | @@ -31,11 +31,11 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [db_name](#input_db_name) | the name for the users database | `string` | n/a | yes | -| [environment](#input_environment) | the environment the resource is deployed into | `string` | n/a | yes | -| [name_prefix](#input_name_prefix) | The name prefix which includes environment and region details | `string` | n/a | yes | -| [rds_name](#input_rds_name) | the name of the service | `string` | `"postgres"` | no | +| ---- | ----------- | ---- | ------- | :------: | +| [db\_name](#input\_db\_name) | the name for the users database | `string` | n/a | yes | +| [environment](#input\_environment) | the environment the resource is deployed into | `string` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | The name prefix which includes environment and region details | `string` | n/a | yes | +| [rds\_name](#input\_rds\_name) | the name of the service | `string` | `"postgres"` | no | ## Outputs diff --git a/infrastructure/modules/rds-gateway-ecs-task/outputs.tf b/infrastructure/modules/rds-gateway-ecs-task/outputs.tf index 8b13789..e69de29 100644 --- a/infrastructure/modules/rds-gateway-ecs-task/outputs.tf +++ b/infrastructure/modules/rds-gateway-ecs-task/outputs.tf @@ -1 +0,0 @@ - diff --git a/infrastructure/modules/rds-gateway-ecs-task/readme.md b/infrastructure/modules/rds-gateway-ecs-task/readme.md index 54f2f8d..a6444d2 100644 --- a/infrastructure/modules/rds-gateway-ecs-task/readme.md +++ b/infrastructure/modules/rds-gateway-ecs-task/readme.md @@ -8,8 +8,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -18,7 +18,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_cloudwatch_log_group.log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_ecs_service.ecs_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service) | resource | | [aws_ecs_task_definition.task_definition](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) | resource | @@ -35,15 +35,15 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws_account_id](#input_aws_account_id) | The aws account id | `string` | n/a | yes | -| [ecs_cluster_name](#input_ecs_cluster_name) | The ECS cluster name | `string` | n/a | yes | -| [image_name](#input_image_name) | The image name for the ECS task | `string` | `"public.ecr.aws/docker/library/busybox:stable"` | no | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [private_subnet_ids](#input_private_subnet_ids) | List of private subnet IDs | `list(string)` | n/a | yes | -| [rds_sg_id](#input_rds_sg_id) | The security group ID of the RDS instance | `string` | n/a | yes | -| [replica_task_count](#input_replica_task_count) | The number of task replicas to run | `number` | `1` | no | -| [vpc_id](#input_vpc_id) | id of the vpc | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [aws\_account\_id](#input\_aws\_account\_id) | The aws account id | `string` | n/a | yes | +| [ecs\_cluster\_name](#input\_ecs\_cluster\_name) | The ECS cluster name | `string` | n/a | yes | +| [image\_name](#input\_image\_name) | The image name for the ECS task | `string` | `"public.ecr.aws/docker/library/busybox:stable"` | no | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [private\_subnet\_ids](#input\_private\_subnet\_ids) | List of private subnet IDs | `list(string)` | n/a | yes | +| [rds\_sg\_id](#input\_rds\_sg\_id) | The security group ID of the RDS instance | `string` | n/a | yes | +| [replica\_task\_count](#input\_replica\_task\_count) | The number of task replicas to run | `number` | `1` | no | +| [vpc\_id](#input\_vpc\_id) | id of the vpc | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/rds-instance/readme.md b/infrastructure/modules/rds-instance/readme.md index 068e8aa..e9b1a57 100644 --- a/infrastructure/modules/rds-instance/readme.md +++ b/infrastructure/modules/rds-instance/readme.md @@ -5,15 +5,15 @@ ## Requirements | Name | Version | -|------|---------| -| [postgresql](#requirement_postgresql) | >= 1.25.0 | +| ---- | ------- | +| [postgresql](#requirement\_postgresql) | >= 1.25.0 | ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [random](#provider_random) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [random](#provider\_random) | 3.8.1 | ## Modules @@ -22,7 +22,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_db_instance.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance) | resource | | [aws_db_parameter_group.parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | | [aws_db_subnet_group.private_bss](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | resource | @@ -40,61 +40,61 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [allocated_storage](#input_allocated_storage) | The amount of storage to allocate to the database in GB | `number` | `50` | no | -| [allow_major_version_upgrade](#input_allow_major_version_upgrade) | Whether to allow major version upgrades to the database | `bool` | `false` | no | -| [apply_immediately](#input_apply_immediately) | Whether to apply changes to the database immediately | `bool` | `true` | no | -| [auto_minor_version_upgrade](#input_auto_minor_version_upgrade) | Whether to automatically upgrade the database to the latest minor version | `bool` | `true` | no | -| [aws_account_id](#input_aws_account_id) | The AWS account ID | `string` | n/a | yes | -| [aws_secret_id](#input_aws_secret_id) | The name of the secret that holds the postgresql login details | `string` | n/a | yes | -| [backup_retention_period](#input_backup_retention_period) | The number of days to retain automated backups for | `number` | `4` | no | -| [backup_window](#input_backup_window) | The time window to perform automated backups in UTC (HH:MM-HH:MM) | `string` | `"01:00-02:00"` | no | -| [cloudwatch_log_retention_days](#input_cloudwatch_log_retention_days) | Number of days to retain CloudWatch logs | `number` | `7` | no | -| [copy_tags_to_snapshot](#input_copy_tags_to_snapshot) | Whether to copy tags to database snapshots | `bool` | `true` | no | -| [database_insights_mode](#input_database_insights_mode) | Whether to set database insights mode to standard or advanced | `string` | n/a | yes | -| [db_max_connections](#input_db_max_connections) | how many connections are allowed | `number` | `5000` | no | -| [db_storage_encryption](#input_db_storage_encryption) | Whether the database storage should be encrypted | `bool` | `true` | no | -| [deletion_protection](#input_deletion_protection) | Whether to enable deletion protection for the database | `bool` | `false` | no | -| [ecs_sg_id](#input_ecs_sg_id) | The security group ID for the ECS service | `string` | n/a | yes | -| [enable_backup](#input_enable_backup) | Whether to enable automated backups for the database | `bool` | `false` | no | -| [enabled_cloudwatch_logs_exports](#input_enabled_cloudwatch_logs_exports) | Which logs should be exported | `list(string)` |
[
"postgresql"
]
| no | -| [encryption](#input_encryption) | If encryption should be enabled | `bool` | `true` | no | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [iops](#input_iops) | specify the provisioned IOPS, cannot be used if gp3 storage allocation is below 400 | `number` | `3000` | no | -| [is_temporary_shutdown](#input_is_temporary_shutdown) | Whether the database is in a temporary shutdown state (not a standard AWS attribute) | `bool` | `false` | no | -| [maintenance_window](#input_maintenance_window) | The time window to perform maintenance on the database in UTC (Day:HH:MM-Day:HH:MM) | `string` | `"Tue:02:30-Tue:03:30"` | no | -| [monitoring_interval](#input_monitoring_interval) | The interval in seconds to monitor the database | `number` | `10` | no | -| [multi_az](#input_multi_az) | Whether to deploy the database in multiple Availability Zones | `bool` | `true` | no | -| [name](#input_name) | The name of the resource | `any` | n/a | yes | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [performance_insights_enabled](#input_performance_insights_enabled) | Whether to enable Performance Insights for the database | `bool` | `false` | no | -| [performance_insights_retention_period](#input_performance_insights_retention_period) | The number of days to retain Performance Insights data for | `number` | `7` | no | -| [port](#input_port) | The port the database will listen on | `number` | `5432` | no | -| [private_subnet_ids](#input_private_subnet_ids) | A list of private subnets to use | `list(string)` | n/a | yes | -| [publicly_accessible](#input_publicly_accessible) | Whether the database is publicly accessible | `bool` | `false` | no | -| [rds_engine](#input_rds_engine) | The engine for the RDS instance | `string` | `"postgres"` | no | -| [rds_engine_version](#input_rds_engine_version) | The engine version for the RDS instance | `string` | `"16"` | no | -| [rds_instance_class](#input_rds_instance_class) | The instance class for the RDS instance | `string` | n/a | yes | -| [recovery_window](#input_recovery_window) | The number of days that credentials should be retained for | `number` | n/a | yes | -| [secret_replication_regions](#input_secret_replication_regions) | List of additional regions where created secrets should be replicated | `list(string)` | n/a | yes | -| [skip_final_snapshot](#input_skip_final_snapshot) | Should there be a snapshot taken when instance destroyed | `bool` | `false` | no | -| [snapshot_identifier](#input_snapshot_identifier) | Optional snapshot identifier to restore from (e.g. if on performance environent) | `string` | `""` | no | -| [storage](#input_storage) | The storage size for the instance | `string` | `100` | no | -| [storage_type](#input_storage_type) | The type of storage used, options are 'standard', 'gp2', 'gp3', 'io1' or 'io2' | `string` | `"gp3"` | no | -| [tags](#input_tags) | A map of tags to assign to the RDS instance in addition to the default tags | `map(string)` | `{}` | no | -| [user](#input_user) | username for postgres instance to use | `string` | `"postgres"` | no | -| [vpc_id](#input_vpc_id) | The id for the vpc | `string` | n/a | yes | -| [vpc_name](#input_vpc_name) | vpc name | `string` | `""` | no | +| ---- | ----------- | ---- | ------- | :------: | +| [allocated\_storage](#input\_allocated\_storage) | The amount of storage to allocate to the database in GB | `number` | `50` | no | +| [allow\_major\_version\_upgrade](#input\_allow\_major\_version\_upgrade) | Whether to allow major version upgrades to the database | `bool` | `false` | no | +| [apply\_immediately](#input\_apply\_immediately) | Whether to apply changes to the database immediately | `bool` | `true` | no | +| [auto\_minor\_version\_upgrade](#input\_auto\_minor\_version\_upgrade) | Whether to automatically upgrade the database to the latest minor version | `bool` | `true` | no | +| [aws\_account\_id](#input\_aws\_account\_id) | The AWS account ID | `string` | n/a | yes | +| [aws\_secret\_id](#input\_aws\_secret\_id) | The name of the secret that holds the postgresql login details | `string` | n/a | yes | +| [backup\_retention\_period](#input\_backup\_retention\_period) | The number of days to retain automated backups for | `number` | `4` | no | +| [backup\_window](#input\_backup\_window) | The time window to perform automated backups in UTC (HH:MM-HH:MM) | `string` | `"01:00-02:00"` | no | +| [cloudwatch\_log\_retention\_days](#input\_cloudwatch\_log\_retention\_days) | Number of days to retain CloudWatch logs | `number` | `7` | no | +| [copy\_tags\_to\_snapshot](#input\_copy\_tags\_to\_snapshot) | Whether to copy tags to database snapshots | `bool` | `true` | no | +| [database\_insights\_mode](#input\_database\_insights\_mode) | Whether to set database insights mode to standard or advanced | `string` | n/a | yes | +| [db\_max\_connections](#input\_db\_max\_connections) | how many connections are allowed | `number` | `5000` | no | +| [db\_storage\_encryption](#input\_db\_storage\_encryption) | Whether the database storage should be encrypted | `bool` | `true` | no | +| [deletion\_protection](#input\_deletion\_protection) | Whether to enable deletion protection for the database | `bool` | `false` | no | +| [ecs\_sg\_id](#input\_ecs\_sg\_id) | The security group ID for the ECS service | `string` | n/a | yes | +| [enable\_backup](#input\_enable\_backup) | Whether to enable automated backups for the database | `bool` | `false` | no | +| [enabled\_cloudwatch\_logs\_exports](#input\_enabled\_cloudwatch\_logs\_exports) | Which logs should be exported | `list(string)` |
[
"postgresql"
]
| no | +| [encryption](#input\_encryption) | If encryption should be enabled | `bool` | `true` | no | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [iops](#input\_iops) | specify the provisioned IOPS, cannot be used if gp3 storage allocation is below 400 | `number` | `3000` | no | +| [is\_temporary\_shutdown](#input\_is\_temporary\_shutdown) | Whether the database is in a temporary shutdown state (not a standard AWS attribute) | `bool` | `false` | no | +| [maintenance\_window](#input\_maintenance\_window) | The time window to perform maintenance on the database in UTC (Day:HH:MM-Day:HH:MM) | `string` | `"Tue:02:30-Tue:03:30"` | no | +| [monitoring\_interval](#input\_monitoring\_interval) | The interval in seconds to monitor the database | `number` | `10` | no | +| [multi\_az](#input\_multi\_az) | Whether to deploy the database in multiple Availability Zones | `bool` | `true` | no | +| [name](#input\_name) | The name of the resource | `any` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [performance\_insights\_enabled](#input\_performance\_insights\_enabled) | Whether to enable Performance Insights for the database | `bool` | `false` | no | +| [performance\_insights\_retention\_period](#input\_performance\_insights\_retention\_period) | The number of days to retain Performance Insights data for | `number` | `7` | no | +| [port](#input\_port) | The port the database will listen on | `number` | `5432` | no | +| [private\_subnet\_ids](#input\_private\_subnet\_ids) | A list of private subnets to use | `list(string)` | n/a | yes | +| [publicly\_accessible](#input\_publicly\_accessible) | Whether the database is publicly accessible | `bool` | `false` | no | +| [rds\_engine](#input\_rds\_engine) | The engine for the RDS instance | `string` | `"postgres"` | no | +| [rds\_engine\_version](#input\_rds\_engine\_version) | The engine version for the RDS instance | `string` | `"16"` | no | +| [rds\_instance\_class](#input\_rds\_instance\_class) | The instance class for the RDS instance | `string` | n/a | yes | +| [recovery\_window](#input\_recovery\_window) | The number of days that credentials should be retained for | `number` | n/a | yes | +| [secret\_replication\_regions](#input\_secret\_replication\_regions) | List of additional regions where created secrets should be replicated | `list(string)` | n/a | yes | +| [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | Should there be a snapshot taken when instance destroyed | `bool` | `false` | no | +| [snapshot\_identifier](#input\_snapshot\_identifier) | Optional snapshot identifier to restore from (e.g. if on performance environent) | `string` | `""` | no | +| [storage](#input\_storage) | The storage size for the instance | `string` | `100` | no | +| [storage\_type](#input\_storage\_type) | The type of storage used, options are 'standard', 'gp2', 'gp3', 'io1' or 'io2' | `string` | `"gp3"` | no | +| [tags](#input\_tags) | A map of tags to assign to the RDS instance in addition to the default tags | `map(string)` | `{}` | no | +| [user](#input\_user) | username for postgres instance to use | `string` | `"postgres"` | no | +| [vpc\_id](#input\_vpc\_id) | The id for the vpc | `string` | n/a | yes | +| [vpc\_name](#input\_vpc\_name) | vpc name | `string` | `""` | no | ## Outputs | Name | Description | -|------|-------------| -| [rds_instance_address](#output_rds_instance_address) | Endpoint of the instance excluding port | -| [rds_instance_arn](#output_rds_instance_arn) | The ARN of the RDS instance | -| [rds_instance_endpoint](#output_rds_instance_endpoint) | The endpoint of the RDS instance including port | -| [rds_instance_id](#output_rds_instance_id) | The ID of the RDS instance | -| [rds_name](#output_rds_name) | n/a | -| [rds_sg_id](#output_rds_sg_id) | The security group ID for the RDS instance | +| ---- | ----------- | +| [rds\_instance\_address](#output\_rds\_instance\_address) | Endpoint of the instance excluding port | +| [rds\_instance\_arn](#output\_rds\_instance\_arn) | The ARN of the RDS instance | +| [rds\_instance\_endpoint](#output\_rds\_instance\_endpoint) | The endpoint of the RDS instance including port | +| [rds\_instance\_id](#output\_rds\_instance\_id) | The ID of the RDS instance | +| [rds\_name](#output\_rds\_name) | n/a | +| [rds\_sg\_id](#output\_rds\_sg\_id) | The security group ID for the RDS instance | diff --git a/infrastructure/modules/rds-users/main.tf b/infrastructure/modules/rds-users/main.tf index ad69f61..0034b2d 100644 --- a/infrastructure/modules/rds-users/main.tf +++ b/infrastructure/modules/rds-users/main.tf @@ -103,4 +103,3 @@ resource "postgresql_role" "pi_4_user_role" { provider = postgresql search_path = ["pi_4"] } - diff --git a/infrastructure/modules/rds-users/readme.md b/infrastructure/modules/rds-users/readme.md index 92f43ba..b8193ed 100644 --- a/infrastructure/modules/rds-users/readme.md +++ b/infrastructure/modules/rds-users/readme.md @@ -5,16 +5,16 @@ ## Requirements | Name | Version | -|------|---------| -| [postgresql](#requirement_postgresql) | >= 1.25.0 | +| ---- | ------- | +| [postgresql](#requirement\_postgresql) | >= 1.25.0 | ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [postgresql](#provider_postgresql) | >= 1.25.0 | -| [random](#provider_random) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [postgresql](#provider\_postgresql) | 1.26.0 | +| [random](#provider\_random) | 3.8.1 | ## Modules @@ -23,7 +23,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_secretsmanager_secret.password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | | [aws_secretsmanager_secret_version.password](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | | [postgresql_role.audit_user_role](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest/docs/resources/role) | resource | @@ -37,19 +37,19 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [rds_endpoint](#input_rds_endpoint) | The endpoint to connect to the rds instance | `string` | n/a | yes | -| [rds_engine_version](#input_rds_engine_version) | The engine version for the RDS instance | `string` | `"12.5"` | no | -| [rds_password](#input_rds_password) | the password to login to rds with | `string` | n/a | yes | -| [recovery_window](#input_recovery_window) | The number of days that credentials should be retained for | `number` | n/a | yes | -| [secret_replication_regions](#input_secret_replication_regions) | List of additional regions where created secrets should be replicated | `list(string)` | `[]` | no | -| [users](#input_users) | List of usernames to generate passwords and secrets for | `list(string)` |
[
"pi_4_user",
"bss_user",
"bss_readwrite",
"bss_readonly",
"audit_user",
"release_manager"
]
| no | +| ---- | ----------- | ---- | ------- | :------: | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [rds\_endpoint](#input\_rds\_endpoint) | The endpoint to connect to the rds instance | `string` | n/a | yes | +| [rds\_engine\_version](#input\_rds\_engine\_version) | The engine version for the RDS instance | `string` | `"12.5"` | no | +| [rds\_password](#input\_rds\_password) | the password to login to rds with | `string` | n/a | yes | +| [recovery\_window](#input\_recovery\_window) | The number of days that credentials should be retained for | `number` | n/a | yes | +| [secret\_replication\_regions](#input\_secret\_replication\_regions) | List of additional regions where created secrets should be replicated | `list(string)` | `[]` | no | +| [users](#input\_users) | List of usernames to generate passwords and secrets for | `list(string)` |
[
"pi_4_user",
"bss_user",
"bss_readwrite",
"bss_readonly",
"audit_user",
"release_manager"
]
| no | ## Outputs | Name | Description | -|------|-------------| -| [bss_user_secret_arn](#output_bss_user_secret_arn) | n/a | +| ---- | ----------- | +| [bss\_user\_secret\_arn](#output\_bss\_user\_secret\_arn) | n/a | diff --git a/infrastructure/modules/s3/main.tf b/infrastructure/modules/s3/main.tf index 6b2f5ce..4632d9b 100644 --- a/infrastructure/modules/s3/main.tf +++ b/infrastructure/modules/s3/main.tf @@ -43,4 +43,3 @@ resource "aws_s3_bucket_policy" "access_policy" { bucket = aws_s3_bucket.bucket.id policy = var.bucket_policy } - diff --git a/infrastructure/modules/s3/readme.md b/infrastructure/modules/s3/readme.md index 92d2c07..0f8c51a 100644 --- a/infrastructure/modules/s3/readme.md +++ b/infrastructure/modules/s3/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_s3_bucket.bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_logging.bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_ownership_controls.ownership](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | @@ -31,13 +31,13 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [additional_kms_key_policy_statements](#input_additional_kms_key_policy_statements) | Additional statements to add to the kms key policy | `list(any)` | `[]` | no | -| [bucket_name](#input_bucket_name) | The name of the bucket | `string` | n/a | yes | -| [bucket_policy](#input_bucket_policy) | The access policy for the bucket | `string` | n/a | yes | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [logging_bucket](#input_logging_bucket) | The bucket where logs are stored for s3 events | `string` | `"logging"` | no | -| [name_prefix](#input_name_prefix) | provides the prefix to keep consistancy | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [additional\_kms\_key\_policy\_statements](#input\_additional\_kms\_key\_policy\_statements) | Additional statements to add to the kms key policy | `list(any)` | `[]` | no | +| [bucket\_name](#input\_bucket\_name) | The name of the bucket | `string` | n/a | yes | +| [bucket\_policy](#input\_bucket\_policy) | The access policy for the bucket | `string` | n/a | yes | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [logging\_bucket](#input\_logging\_bucket) | The bucket where logs are stored for s3 events | `string` | `"logging"` | no | +| [name\_prefix](#input\_name\_prefix) | provides the prefix to keep consistancy | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/sns/readme.md b/infrastructure/modules/sns/readme.md index e05a855..73f6a64 100644 --- a/infrastructure/modules/sns/readme.md +++ b/infrastructure/modules/sns/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_sns_topic.sns_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | | [aws_sns_topic_policy.sns_topic_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource | | [aws_iam_policy_document.sns_topic_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -27,16 +27,16 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws_account_id](#input_aws_account_id) | The AWS account ID | `string` | n/a | yes | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [aws\_account\_id](#input\_aws\_account\_id) | The AWS account ID | `string` | n/a | yes | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [sns_topic_arn](#output_sns_topic_arn) | n/a | -| [sns_topic_name](#output_sns_topic_name) | n/a | +| ---- | ----------- | +| [sns\_topic\_arn](#output\_sns\_topic\_arn) | n/a | +| [sns\_topic\_name](#output\_sns\_topic\_name) | n/a | diff --git a/infrastructure/modules/sns/variables.tf b/infrastructure/modules/sns/variables.tf index 4f8ba41..cca1020 100644 --- a/infrastructure/modules/sns/variables.tf +++ b/infrastructure/modules/sns/variables.tf @@ -13,4 +13,3 @@ variable "environment" { description = "The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD" type = string } - diff --git a/infrastructure/modules/sqs/readme.md b/infrastructure/modules/sqs/readme.md index cc08c01..e07ad48 100644 --- a/infrastructure/modules/sqs/readme.md +++ b/infrastructure/modules/sqs/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_sqs_queue.queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | | [aws_sqs_queue.sqs_queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | | [aws_sqs_queue_policy.allow_sns_publish](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | @@ -27,15 +27,15 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [name_prefix](#input_name_prefix) | The account, environment etc | `string` | n/a | yes | -| [stack_name](#input_stack_name) | Name of stack calling the module to use in resource naming | `string` | n/a | yes | -| [topic_arn](#input_topic_arn) | Source SNS topic arn | `any` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [name\_prefix](#input\_name\_prefix) | The account, environment etc | `string` | n/a | yes | +| [stack\_name](#input\_stack\_name) | Name of stack calling the module to use in resource naming | `string` | n/a | yes | +| [topic\_arn](#input\_topic\_arn) | Source SNS topic arn | `any` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [arn](#output_arn) | n/a | +| ---- | ----------- | +| [arn](#output\_arn) | n/a | diff --git a/infrastructure/modules/tags/README.md b/infrastructure/modules/tags/README.md new file mode 100644 index 0000000..0a617cf --- /dev/null +++ b/infrastructure/modules/tags/README.md @@ -0,0 +1,149 @@ +# AWS Tag Terraform module + +Terraform module designed to generate consistent names and tags for resources. Use `tags` to implement a strict naming and tagging convention. + +There are 8 inputs considered "labels" or "ID elements" (because the labels are used to construct the ID): +1. service +1. project +1. region +1. environment +1. workspace +1. stack +1. name +1. attributes + +This module generates IDs using the following convention by default: `{service}-{project}-{environment}-{stack}-{name}-{attributes}`. +However, it is highly configurable. The delimiter (e.g. `-`) is configurable. Each label item is optional (although you must provide at least one). +So if you prefer the term `workspace` to `environment` and do not need `stack`, you can exclude them +and the label `id` will look like `{service}-{project}-{workspace}-{name}-{attributes}`. +- The `attributes` input is actually a list of strings and `{attributes}` expands to the list elements joined by the delimiter. +- If `attributes` is excluded but `service`, `project`, and `workspace` are included, `id` will look like `{service}-{project}-{workspace}-{name}`. + Excluding `attributes` is discouraged, though, because attributes are the main way modules modify the ID to ensure uniqueness when provisioning the same resource types. +- If you want the label items in a different order, you can specify that, too, with the `label_order` list. +- You can set a maximum length for the `id`, and the module will create a (probably) unique name that fits within that length. + (The module uses a portion of the MD5 hash of the full `id` to represent the missing part, so there remains a slight chance of name collision.) +- You can control the letter case of the generated labels which make up the `id` using `var.label_value_case`. +- By default, all of the non-empty labels are also exported as tags, whether they appear in the `id` or not. +You can control which labels are exported as tags by setting `labels_as_tags` to the list of labels you want exported, +or the empty list `[]` if you want no labels exported as tags at all. Tags passed in via the `tags` variable are +always exported, and regardless of settings, empty labels are never exported as tags. +You can control the case of the tag names (keys) for the labels using `var.label_key_case`. +Unlike the tags generated from the label inputs, tags passed in via the `tags` input are not modified. + +There is an unfortunate collision over the use of the key `name`. We use `name` in this module +to represent the component, such as `eks` or `rds`. AWS uses a tag with the key `Name` to store the full human-friendly +identifier of the thing tagged, which this module outputs as `id`, not `name`. So when converting input labels +to tags, the value of the `Name` key is set to the module `id` output, and there is no tag corresponding to the +module `name` output. An empty `name` label will not prevent the `Name` tag from being exported. + +It's recommended to use one `tags` module for every unique resource of a given resource type. +For example, if you have 10 instances, there should be 10 different labels. +However, if you have multiple different kinds of resources (e.g. instances, security groups, file systems, and elastic ips), then they can all share the same label assuming they are logically related. + +For most purposes, the `id` output is sufficient to create an ID or label for a resource, and if you want a different +ID or a different format, you would instantiate another instance of `tags` and configure it accordingly. However, +to accommodate situations where you want all the same inputs to generate multiple descriptors, this module provides +the `descriptors` output, which is a map of strings generated according to the format specified by the +`descriptor_formats` input. This feature is intentionally simple and minimally configurable and will not be +enhanced to add more features that are already in `tags`. See [examples/complete/descriptors.tf](examples/complete/descriptors.tf) for examples. + + +The recommended convention is to use labels as follows: +- `service`: A short (3-4 letters) abbreviation of the service directorate to ensure globally unique IDs for things like S3 buckets i.e. bcss +- `project`: The name or role of the project the resource is for, such as `web` or `api` +- `region`: By default this will auto-populate the provider region, but can be overridden or set to `gbl` for resources like IAM roles that have no region +- `environment`: The name or role of the account the resource is for, such as `prod` or `dev` +- `workspace`: _(Rarely needed)_ Typically, the singular environment label suffices as there would only be a singular resource created per environment. On occasion, there may be multiple sub-environment, still of a singular environment/with shared environment resources i.e. sit1, sit2, nft1, nft2). `workspace` can be used to identify the specific sub-environment the resources relate to and by default is auto-populated to the `terraform.workspace` value. +- `name`: The name of the component that owns the resources, such as `eks` or `rds` + +## Usage + +## Examples + + +## Requirements + +| Name | Version | +| ---- | ------- | +| [terraform](#requirement\_terraform) | >= 1.13.0 | +| [aws](#requirement\_aws) | >= 6.14.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +| ---- | ---- | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_session_context.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_session_context) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | +| [application\_role](#input\_application\_role) | The role the application is performing | `string` | `"General"` | no | +| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | +| [aws\_region](#input\_aws\_region) | The AWS region | `string` | `"eu-west-2"` | no | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"project": null,
"regex_replace_chars": null,
"region": null,
"service": null,
"stack": null,
"tags": {},
"workspace": null
}
| no | +| [data\_classification](#input\_data\_classification) | Used to identify the data classification of the resource, e.g 1-5 | `string` | `"n/a"` | no | +| [data\_type](#input\_data\_type) | The tag data\_type | `string` | `"None"` | no | +| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | ID element. Usually used to indicate role, e.g. 'prd', 'dev', 'test', 'preprod', 'prod', 'uat' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["service", "project", "environment", "stack", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | +| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no | +| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no | +| [on\_off\_pattern](#input\_on\_off\_pattern) | Used to turn resources on and off based on a time pattern | `string` | `"n/a"` | no | +| [owner](#input\_owner) | The name and or NHS.net email address of the service owner | `string` | `"None"` | no | +| [project](#input\_project) | ID element. A project identifier, indicating the name or role of the project the resource is for, such as `website` or `api` | `string` | `null` | no | +| [public\_facing](#input\_public\_facing) | Whether this resource is public facing | `bool` | `false` | no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [region](#input\_region) | ID element \_(Rarely used, not included by default)\_. Usually an abbreviation of the selected AWS region e.g. 'uw2', 'ew2' or 'gbl' for resources like IAM roles that have no region | `string` | `null` | no | +| [service](#input\_service) | ID element. Usually an abbreviation of your service directorate name, e.g. 'bcss' or 'csms', to help ensure generated IDs are globally unique | `string` | `null` | no | +| [service\_category](#input\_service\_category) | The tag service\_category | `string` | `"n/a"` | no | +| [stack](#input\_stack) | ID element. The name of the stack/component, e.g. `database`, `web`, `waf`, `eks` | `string` | `null` | no | +| [tag\_version](#input\_tag\_version) | Used to identify the tagging version in use | `string` | `"1.0"` | no | +| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | +| [tool](#input\_tool) | The tool used to deploy the resource | `string` | `"Terraform"` | no | +| [workspace](#input\_workspace) | ID element. The Terraform workspace, to help ensure generated IDs are unique across workspaces | `string` | `null` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [additional\_tag\_map](#output\_additional\_tag\_map) | The merged additional\_tag\_map | +| [attributes](#output\_attributes) | List of attributes | +| [context](#output\_context) | Merged but otherwise unmodified input to this module, to be used as context input to other modules.
Note: this version will have null values as defaults, not the values actually used as defaults. | +| [delimiter](#output\_delimiter) | Delimiter between `namespace`, `tenant`, `environment`, `stage`, `name` and `attributes` | +| [descriptors](#output\_descriptors) | Map of descriptors as configured by `descriptor_formats` | +| [enabled](#output\_enabled) | True if module is enabled, false otherwise | +| [environment](#output\_environment) | Normalized environment | +| [id](#output\_id) | Disambiguated ID string restricted to `id_length_limit` characters in total | +| [id\_full](#output\_id\_full) | ID string not restricted in length | +| [id\_length\_limit](#output\_id\_length\_limit) | The id\_length\_limit actually used to create the ID, with `0` meaning unlimited | +| [label\_order](#output\_label\_order) | The naming order actually used to create the ID | +| [name](#output\_name) | Normalized name | +| [normalized\_context](#output\_normalized\_context) | Normalized context of this module | +| [project](#output\_project) | Normalized project | +| [regex\_replace\_chars](#output\_regex\_replace\_chars) | The regex\_replace\_chars actually used to create the ID | +| [region](#output\_region) | Normalized region short name | +| [service](#output\_service) | Normalized service | +| [stack](#output\_stack) | Normalized stack | +| [tags](#output\_tags) | Normalized Tag map | +| [tags\_as\_list\_of\_maps](#output\_tags\_as\_list\_of\_maps) | This is a list with one map for each `tag`. Each map contains the tag `key`,
`value`, and contents of `var.additional_tag_map`. Used in the rare cases
where resources need additional configuration information for each tag. | +| [workspace](#output\_workspace) | Normalized workspace | + diff --git a/infrastructure/modules/tags/data.tf b/infrastructure/modules/tags/data.tf new file mode 100644 index 0000000..b7fdb1d --- /dev/null +++ b/infrastructure/modules/tags/data.tf @@ -0,0 +1,9 @@ +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +data "aws_iam_session_context" "current" { + # This data source provides information on the source + # IAM role when an assumed role is utilized + arn = data.aws_caller_identity.current.arn +} diff --git a/infrastructure/modules/tags/descriptors.tf b/infrastructure/modules/tags/descriptors.tf new file mode 100644 index 0000000..800ee44 --- /dev/null +++ b/infrastructure/modules/tags/descriptors.tf @@ -0,0 +1,28 @@ +# It would be nice to have a fixed array of arguments passed into +# `format()` so all you need to provide is a format string, but +# unfortunately, that does not work easily +# due to https://github.com/hashicorp/terraform/issues/28558 +# which requires that the format string consume the last argument passed in. +# We could hack around it by adding then removing a trailing arg, like +# +# trimsuffix(format("${var.format_string}%[${length(local.labels)+1}]v", concat(local.labels, ["x"])...), "x") +# +# but that is kind of a hack, and overlooks the fact that local.labels +# drops empty label elements, so the index of an element is not guaranteed. +# +# +# So we require the user to specify the arguments as well as the format string. +# + +# There is a lot of room for enhancement, but since this is a new feature +# with only 2 use cases, we are going to keep it simple for now. + +locals { + descriptor_labels = { for k, v in local.descriptor_formats : k => [ + for label in v.labels : local.id_context[label] + ] } + descriptors = { for k, v in local.descriptor_formats : k => ( + format(v.format, local.descriptor_labels[k]...) + ) + } +} diff --git a/infrastructure/modules/tags/exports/README.md b/infrastructure/modules/tags/exports/README.md new file mode 100644 index 0000000..5824610 --- /dev/null +++ b/infrastructure/modules/tags/exports/README.md @@ -0,0 +1,60 @@ +# exports + + +## Requirements + +No requirements. + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +| ---- | ------ | ------- | +| [this](#module\_this) | git::https://github.com/NHSDigital/screening-terraform-modules-aws.git//infrastructure/modules/tags | feature/BCSS-23189-add-new-modules-to-suppport-bcss | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
This is for some rare cases where resources want additional configuration of tags
and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no | +| [application\_role](#input\_application\_role) | The role the application is performing | `string` | `"General"` | no | +| [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
in the order they appear in the list. New attributes are appended to the
end of the list. The elements of the list are joined by the `delimiter`
and treated as a single ID element. | `list(string)` | `[]` | no | +| [aws\_region](#input\_aws\_region) | The AWS region | `string` | `"eu-west-2"` | no | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"project": null,
"regex_replace_chars": null,
"region": null,
"service": null,
"stack": null,
"tags": {},
"workspace": null
}
| no | +| [data\_classification](#input\_data\_classification) | Used to identify the data classification of the resource, e.g 1-5 | `string` | `"n/a"` | no | +| [data\_type](#input\_data\_type) | The tag data\_type | `string` | `"None"` | no | +| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | ID element. Usually used to indicate role, e.g. 'prd', 'dev', 'test', 'preprod', 'prod', 'uat' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for keep the existing setting, which defaults to `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.
Does not affect keys of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,
set as tag values, and output by this module individually.
Does not affect values of tags passed in via the `tags` input.
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
Default value: `lower`. | `string` | `null` | no | +| [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.
Default is to include all labels.
Tags with empty values will not be included in the `tags` output.
Set to `[]` to suppress all generated tags.
**Notes:**
The value of the `name` tag, if included, will be the `id`, not the `name`.
Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` |
[
"default"
]
| no | +| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
This is the only ID element not also included as a `tag`.
The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no | +| [on\_off\_pattern](#input\_on\_off\_pattern) | Used to turn resources on and off based on a time pattern | `string` | `"n/a"` | no | +| [owner](#input\_owner) | The name and or NHS.net email address of the service owner | `string` | `"None"` | no | +| [project](#input\_project) | ID element. A project identifier, indicating the name or role of the project the resource is for, such as `website` or `api` | `string` | `null` | no | +| [public\_facing](#input\_public\_facing) | Whether this resource is public facing | `bool` | `false` | no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [region](#input\_region) | ID element \_(Rarely used, not included by default)\_. Usually an abbreviation of the selected AWS region e.g. 'uw2', 'ew2' or 'gbl' for resources like IAM roles that have no region | `string` | `null` | no | +| [service](#input\_service) | ID element. Usually an abbreviation of your service directorate name, e.g. 'bcss' or 'csms', to help ensure generated IDs are globally unique | `string` | `null` | no | +| [service\_category](#input\_service\_category) | The tag service\_category | `string` | `"n/a"` | no | +| [stack](#input\_stack) | ID element. The name of the stack/component, e.g. `database`, `web`, `waf`, `eks` | `string` | `null` | no | +| [tag\_version](#input\_tag\_version) | Used to identify the tagging version in use | `string` | `"1.0"` | no | +| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | +| [tool](#input\_tool) | The tool used to deploy the resource | `string` | `"Terraform"` | no | +| [workspace](#input\_workspace) | ID element. The Terraform workspace, to help ensure generated IDs are unique across workspaces | `string` | `null` | no | + +## Outputs + +No outputs. + diff --git a/infrastructure/modules/tags/exports/context.tf b/infrastructure/modules/tags/exports/context.tf new file mode 100644 index 0000000..c56d7f6 --- /dev/null +++ b/infrastructure/modules/tags/exports/context.tf @@ -0,0 +1,365 @@ +# +# ONLY EDIT THIS FILE IN github.com/NHSDigital/screening-terraform-modules-aws/infrastructure/modules/tags +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/NHSDigital/screening-terraform-modules-aws/blob/master/infrastructure/modules/tags/exports/context.tf +# and then place it in your Terraform module to automatically get +# tag module standard configuration inputs suitable for passing +# to other modules. +# +# curl -sL https://raw.githubusercontent.com/NHSDigital/screening-terraform-modules-aws/master/infrastructure/modules/tags/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "git::https://github.com/NHSDigital/screening-terraform-modules-aws.git//infrastructure/modules/tags?ref=feature/BCSS-23189-add-new-modules-to-suppport-bcss" + + service = var.service + project = var.project + region = var.region + environment = var.environment + stack = var.stack + workspace = var.workspace + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of screening-terraform-modules-aws/tags/variables.tf here +# tflint-ignore: terraform_unused_declarations +variable "aws_region" { + type = string + description = "The AWS region" + default = "eu-west-2" + validation { + condition = contains(["eu-west-1", "eu-west-2", "us-east-1"], var.aws_region) + error_message = "AWS Region must be one of eu-west-1, eu-west-2, us-east-1" + } +} + +variable "context" { + type = any + default = { + enabled = true + service = null + project = null + region = null + environment = null + stack = null + workspace = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "service" { + type = string + default = null + description = "ID element. Usually an abbreviation of your service directorate name, e.g. 'bcss' or 'csms', to help ensure generated IDs are globally unique" +} + +variable "region" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. Usually an abbreviation of the selected AWS region e.g. 'uw2', 'ew2' or 'gbl' for resources like IAM roles that have no region" +} + +variable "project" { + type = string + default = null + description = "ID element. A project identifier, indicating the name or role of the project the resource is for, such as `website` or `api`" +} +variable "stack" { + type = string + default = null + description = "ID element. The name of the stack/component, e.g. `database`, `web`, `waf`, `eks`" +} +variable "workspace" { + type = string + default = null + description = "ID element. The Terraform workspace, to help ensure generated IDs are unique across workspaces" +} +variable "environment" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prd', 'dev', 'test', 'preprod', 'prod', 'uat'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +variable "owner" { + type = string + description = "The name and or NHS.net email address of the service owner" + default = "None" +} + +variable "tag_version" { + type = string + description = "Used to identify the tagging version in use" + default = "1.0" +} + +variable "data_classification" { + type = string + description = "Used to identify the data classification of the resource, e.g 1-5" + default = "n/a" + validation { + condition = contains(["n/a", "1", "2", "3", "4", "5"], var.data_classification) + error_message = "Data Classification must be \"n/a\" or between 1-5" + } +} + +variable "data_type" { + type = string + description = "The tag data_type" + default = "None" + validation { + condition = contains(["None", "PCD", "PID", "Anonymised", "UserAccount", "Audit"], var.data_type) + error_message = "Data Type must be one of None, PCD, PID, Anonymised, UserAccount, Audit" + } +} + + +variable "public_facing" { + type = bool + description = "Whether this resource is public facing" + default = false +} + +variable "service_category" { + type = string + description = "The tag service_category" + default = "n/a" + validation { + condition = contains(["n/a", "Bronze", "Silver", "Gold", "Platinum"], var.service_category) + error_message = "The Service Category must be one of n/a, Bronze, Silver, Gold, Platinum" + } +} +variable "on_off_pattern" { + type = string + description = "Used to turn resources on and off based on a time pattern" + default = "n/a" +} + +variable "application_role" { + type = string + description = "The role the application is performing" + default = "General" +} + +variable "tool" { + type = string + description = "The tool used to deploy the resource" + default = "Terraform" +} + +#### End of copy of screening-terraform-modules-aws/tags/variables.tf diff --git a/infrastructure/modules/tags/main.tf b/infrastructure/modules/tags/main.tf new file mode 100644 index 0000000..96940bb --- /dev/null +++ b/infrastructure/modules/tags/main.tf @@ -0,0 +1,192 @@ +locals { + + defaults = { + label_order = ["service", "project", "environment", "stack", "name", "attributes"] + regex_replace_chars = "/[^-a-zA-Z0-9]/" + delimiter = "-" + replacement = "" + id_length_limit = 0 + id_hash_length = 5 + label_key_case = "title" + label_value_case = "lower" + } + + default_labels_as_tags = keys(local.tags_context) + + context_labels_as_tags_is_unset = try(contains(var.context.labels_as_tags, "unset"), true) + + # Do not to allow overriding replacement or id_hash_length + replacement = local.defaults.replacement + id_hash_length = local.defaults.id_hash_length + + + # The values provided by variables supersede the values inherited from the context object, + # except for tags and attributes which are merged. + input = { + # It would be nice to use coalesce here, but we cannot, because it + # is an error for all the arguments to coalesce to be empty. + enabled = var.enabled == null ? var.context.enabled : var.enabled + service = var.service == null ? var.context.service : var.service + project = var.project == null ? var.context.project : var.project + region = var.region == null ? lookup(local.to_short, data.aws_region.current.region, null) : var.region + environment = var.environment == null ? var.context.environment : var.environment + stack = var.stack == null ? var.context.stack : var.stack + name = var.name == null ? var.context.name : var.name + workspace = var.workspace == null ? terraform.workspace : var.workspace + delimiter = var.delimiter == null ? var.context.delimiter : var.delimiter + # modules tack on attributes (passed by var) to the end of the list (passed by context) + attributes = compact(distinct(concat(coalesce(var.context.attributes, []), coalesce(var.attributes, [])))) + tags = merge(var.context.tags, var.tags) + + additional_tag_map = merge(var.context.additional_tag_map, var.additional_tag_map) + label_order = var.label_order == null ? var.context.label_order : var.label_order + regex_replace_chars = var.regex_replace_chars == null ? var.context.regex_replace_chars : var.regex_replace_chars + id_length_limit = var.id_length_limit == null ? var.context.id_length_limit : var.id_length_limit + label_key_case = var.label_key_case == null ? lookup(var.context, "label_key_case", null) : var.label_key_case + label_value_case = var.label_value_case == null ? lookup(var.context, "label_value_case", null) : var.label_value_case + + descriptor_formats = merge(lookup(var.context, "descriptor_formats", {}), var.descriptor_formats) + labels_as_tags = local.context_labels_as_tags_is_unset ? var.labels_as_tags : var.context.labels_as_tags + } + + enabled = local.input.enabled + regex_replace_chars = coalesce(local.input.regex_replace_chars, local.defaults.regex_replace_chars) + + # string_label_names are names of inputs that are strings (not list of strings) used as labels + string_label_names = ["service", "project", "environment", "stack", "name", "workspace", "region"] + normalized_labels = { for k in local.string_label_names : k => + local.input[k] == null ? "" : replace(local.input[k], local.regex_replace_chars, local.replacement) + } + normalized_attributes = compact(distinct([for v in local.input.attributes : replace(v, local.regex_replace_chars, local.replacement)])) + + formatted_labels = { for k in local.string_label_names : k => local.label_value_case == "none" ? local.normalized_labels[k] : + local.label_value_case == "title" ? title(lower(local.normalized_labels[k])) : + local.label_value_case == "upper" ? upper(local.normalized_labels[k]) : lower(local.normalized_labels[k]) + } + + attributes = compact(distinct([ + for v in local.normalized_attributes : (local.label_value_case == "none" ? v : + local.label_value_case == "title" ? title(lower(v)) : + local.label_value_case == "upper" ? upper(v) : lower(v)) + ])) + + service = local.formatted_labels["service"] + project = local.formatted_labels["project"] + + region = local.formatted_labels["region"] + environment = local.formatted_labels["environment"] + stack = local.formatted_labels["stack"] + name = local.formatted_labels["name"] + workspace = local.formatted_labels["workspace"] + + delimiter = local.input.delimiter == null ? local.defaults.delimiter : local.input.delimiter + label_order = local.input.label_order == null ? local.defaults.label_order : coalescelist(local.input.label_order, local.defaults.label_order) + id_length_limit = local.input.id_length_limit == null ? local.defaults.id_length_limit : local.input.id_length_limit + label_key_case = local.input.label_key_case == null ? local.defaults.label_key_case : local.input.label_key_case + label_value_case = local.input.label_value_case == null ? local.defaults.label_value_case : local.input.label_value_case + + # labels_as_tags is an exception to the rule that input vars override context values (see above) + labels_as_tags = contains(local.input.labels_as_tags, "default") ? local.default_labels_as_tags : local.input.labels_as_tags + + # Just for standardization and completeness + descriptor_formats = local.input.descriptor_formats + + additional_tag_map = merge(var.context.additional_tag_map, var.additional_tag_map) + + tags = merge(local.generated_tags, local.input.tags) + + tags_as_list_of_maps = flatten([ + for key in keys(local.tags) : merge( + { + key = key + value = local.tags[key] + }, local.additional_tag_map) + ]) + + tags_context = { + service = local.service + project = local.project + region = local.region + environment = local.environment + stack = local.stack + workspace = local.workspace + # For AWS we need `Name` to be disambiguated since it has a special meaning + name = local.id + attributes = local.id_context.attributes + # Additional NHS specific tags which may be useful for filtering and auditing, but are not part of the ID and not included in the hash + # so they do not affect the ID length and do not cause the ID to change when they change. They are included in the tags output and can be used as tags on resources. + owner = var.owner + tag_version = var.tag_version + data_classification = var.data_classification + data_type = var.data_type + public_facing = tostring(var.public_facing) + service_category = var.service_category + on_off_pattern = var.on_off_pattern + application_role = var.application_role + terraform_source = path.module + deployed_by = data.aws_iam_session_context.current.arn + deployed_by_source = data.aws_iam_session_context.current.issuer_arn + tool = var.tool + } + + generated_tags = { + for l in setintersection(keys(local.tags_context), local.labels_as_tags) : + local.label_key_case == "upper" ? upper(l) : ( + local.label_key_case == "lower" ? lower(l) : title(lower(l)) + ) => local.tags_context[l] if length(local.tags_context[l]) > 0 + } + + id_context = { + service = local.service + project = local.project + region = local.region + environment = local.environment + stack = local.stack + workspace = local.workspace + name = local.name + attributes = join(local.delimiter, local.attributes) + } + + labels = [for l in local.label_order : local.id_context[l] if length(local.id_context[l]) > 0] + + id_full = join(local.delimiter, local.labels) + # Create a truncated ID if needed + delimiter_length = length(local.delimiter) + # Calculate length of normal part of ID, leaving room for delimiter and hash + id_truncated_length_limit = local.id_length_limit - (local.id_hash_length + local.delimiter_length) + # Truncate the ID and ensure a single (not double) trailing delimiter + id_truncated = local.id_truncated_length_limit <= 0 ? "" : "${trimsuffix(substr(local.id_full, 0, local.id_truncated_length_limit), local.delimiter)}${local.delimiter}" + # Support usages that disallow numeric characters. Would prefer tr 0-9 q-z but Terraform does not support it. + # Probably would have been better to take the hash of only the characters being removed, + # so identical removed strings would produce identical hashes, but it is not worth breaking existing IDs for. + id_hash_plus = "${md5(local.id_full)}qrstuvwxyz" + id_hash_case = local.label_value_case == "title" ? title(local.id_hash_plus) : local.label_value_case == "upper" ? upper(local.id_hash_plus) : local.label_value_case == "lower" ? lower(local.id_hash_plus) : local.id_hash_plus + id_hash = replace(local.id_hash_case, local.regex_replace_chars, local.replacement) + # Create the short ID by adding a hash to the end of the truncated ID + id_short = substr("${local.id_truncated}${local.id_hash}", 0, local.id_length_limit) + id = local.id_length_limit != 0 && length(local.id_full) > local.id_length_limit ? local.id_short : local.id_full + + + # Context of this label to pass to other label modules + output_context = { + enabled = local.enabled + service = local.service + project = local.project + region = local.region + environment = local.environment + stack = local.stack + name = local.name + delimiter = local.delimiter + attributes = local.attributes + tags = local.tags + additional_tag_map = local.additional_tag_map + label_order = local.label_order + regex_replace_chars = local.regex_replace_chars + id_length_limit = local.id_length_limit + label_key_case = local.label_key_case + label_value_case = local.label_value_case + labels_as_tags = local.labels_as_tags + descriptor_formats = local.descriptor_formats + } + +} diff --git a/infrastructure/modules/tags/outputs.tf b/infrastructure/modules/tags/outputs.tf new file mode 100644 index 0000000..612890b --- /dev/null +++ b/infrastructure/modules/tags/outputs.tf @@ -0,0 +1,111 @@ +output "id" { + value = local.enabled ? local.id : "" + description = "Disambiguated ID string restricted to `id_length_limit` characters in total" +} + +output "id_full" { + value = local.enabled ? local.id_full : "" + description = "ID string not restricted in length" +} + +output "enabled" { + value = local.enabled + description = "True if module is enabled, false otherwise" +} + +output "service" { + value = local.enabled ? local.service : "" + description = "Normalized service" +} + +output "project" { + value = local.enabled ? local.project : "" + description = "Normalized project" +} + +output "region" { + value = local.enabled ? local.region : "" + description = "Normalized region short name" +} + +output "environment" { + value = local.enabled ? local.environment : "" + description = "Normalized environment" +} + +output "workspace" { + value = local.enabled ? local.workspace : "" + description = "Normalized workspace" +} + +output "stack" { + value = local.enabled ? local.stack : "" + description = "Normalized stack" +} + +output "name" { + value = local.enabled ? local.name : "" + description = "Normalized name" +} + +output "delimiter" { + value = local.enabled ? local.delimiter : "" + description = "Delimiter between `namespace`, `tenant`, `environment`, `stage`, `name` and `attributes`" +} + +output "attributes" { + value = local.enabled ? local.attributes : [] + description = "List of attributes" +} + +output "tags" { + value = local.enabled ? local.tags : {} + description = "Normalized Tag map" +} + +output "additional_tag_map" { + value = local.additional_tag_map + description = "The merged additional_tag_map" +} + +output "label_order" { + value = local.label_order + description = "The naming order actually used to create the ID" +} + +output "regex_replace_chars" { + value = local.regex_replace_chars + description = "The regex_replace_chars actually used to create the ID" +} + +output "id_length_limit" { + value = local.id_length_limit + description = "The id_length_limit actually used to create the ID, with `0` meaning unlimited" +} + +output "tags_as_list_of_maps" { + value = local.tags_as_list_of_maps + description = <<-EOT + This is a list with one map for each `tag`. Each map contains the tag `key`, + `value`, and contents of `var.additional_tag_map`. Used in the rare cases + where resources need additional configuration information for each tag. + EOT +} + +output "descriptors" { + value = local.descriptors + description = "Map of descriptors as configured by `descriptor_formats`" +} + +output "normalized_context" { + value = local.output_context + description = "Normalized context of this module" +} + +output "context" { + value = local.input + description = <<-EOT + Merged but otherwise unmodified input to this module, to be used as context input to other modules. + Note: this version will have null values as defaults, not the values actually used as defaults. +EOT +} diff --git a/infrastructure/modules/tags/region.tf b/infrastructure/modules/tags/region.tf new file mode 100644 index 0000000..6907c4c --- /dev/null +++ b/infrastructure/modules/tags/region.tf @@ -0,0 +1,799 @@ +locals { + # Key can be a region, availability zone, or local zone. + # Key CANNOT be an Availability Zone ID or Wavelength Zone. + # Local zone keys may be incomplete. + # WARNING: If a current local zone mapping conflicts with a future region mapping, + # we may change the local zone mapping in order to keep the region mappings consistent. + # This is particularly likely to happen with the "fixed" mappings, so we recommend using + # the "short" mappings if you plan to use local zones. + # For some degree of future proofing, we provide mappings for some AZs that do not yet exist. + # INCLUSION IN THE MAP does NOT necessarily mean the region or AZ exists. + + # See https://github.com/jsonmaur/aws-regions for complete list of regions + + # to_display_name maps full region names to geographic display names + # using https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/resources/com/amazonaws/partitions/endpoints.json + # as a reference source, since there is appears to be no API available. + # Note that https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html + # claims you can get display names from `aws lightsail`, but Lightsail is not available in + # all regions, so its list is incomplete. + # + # The map contents can be regenerated (will need to be reformatted with `terraform fmt`) with: + # curl -sSL https://raw.githubusercontent.com/aws/aws-sdk-java/master/aws-java-sdk-core/src/main/resources/com/amazonaws/partitions/endpoints.json \ + # | jq -r '.partitions[] |select( .partition | test("aws(-cn|-us-gov)?$") ) | .regions | to_entries |.[] | "\"\(.key)\" = \"\(.value.description)\""' + + # tflint-ignore: terraform_unused_declarations + to_display_name = { + "af-south-1" = "Africa (Cape Town)" + "ap-east-1" = "Asia Pacific (Hong Kong)" + "ap-northeast-1" = "Asia Pacific (Tokyo)" + "ap-northeast-2" = "Asia Pacific (Seoul)" + "ap-northeast-3" = "Asia Pacific (Osaka)" + "ap-south-1" = "Asia Pacific (Mumbai)" + "ap-south-2" = "Asia Pacific (Hyderabad)" + "ap-southeast-1" = "Asia Pacific (Singapore)" + "ap-southeast-2" = "Asia Pacific (Sydney)" + "ap-southeast-3" = "Asia Pacific (Jakarta)" + "ap-southeast-4" = "Asia Pacific (Melbourne)" + "ca-central-1" = "Canada (Central)" + "ca-west-1" = "Canada West (Calgary)" + "eu-central-1" = "Europe (Frankfurt)" + "eu-central-2" = "Europe (Zurich)" + "eu-north-1" = "Europe (Stockholm)" + "eu-south-1" = "Europe (Milan)" + "eu-south-2" = "Europe (Milan)" + "eu-west-1" = "Europe (Ireland)" + "eu-west-2" = "Europe (London)" + "eu-west-3" = "Europe (Paris)" + "il-central-1" = "Israel (Tel Aviv)" + "me-central-1" = "Middle East (UAE)" + "me-south-1" = "Middle East (Bahrain)" + "sa-east-1" = "South America (Sao Paulo)" + "us-east-1" = "US East (N. Virginia)" + "us-east-2" = "US East (Ohio)" + "us-west-1" = "US West (N. California)" + "us-west-2" = "US West (Oregon)" + "cn-north-1" = "China (Beijing)" + "cn-northwest-1" = "China (Ningxia)" + "us-gov-east-1" = "AWS GovCloud (US-East)" + "us-gov-west-1" = "AWS GovCloud (US-West)" + } + + # tflint-ignore: terraform_unused_declarations + to_fixed = { + "ap-east-1" = "ae1" + "ap-east-1a" = "ae1a" + "ap-east-1b" = "ae1b" + "ap-east-1c" = "ae1c" + "ap-east-1d" = "ae1d" + "ap-east-1e" = "ae1e" + "ap-east-1f" = "ae1f" + "ap-east-1g" = "ae1g" + "ap-east-1h" = "ae1h" + + "ap-northeast-1" = "an1" + "ap-northeast-1a" = "an1a" + "ap-northeast-1b" = "an1b" + "ap-northeast-1c" = "an1c" + "ap-northeast-1d" = "an1d" + "ap-northeast-1e" = "an1e" + "ap-northeast-1f" = "an1f" + "ap-northeast-1g" = "an1g" + "ap-northeast-1h" = "an1h" + + "ap-northeast-2" = "an2" + "ap-northeast-2a" = "an2a" + "ap-northeast-2b" = "an2b" + "ap-northeast-2c" = "an2c" + "ap-northeast-2d" = "an2d" + "ap-northeast-2e" = "an2e" + "ap-northeast-2f" = "an2f" + "ap-northeast-2g" = "an2g" + "ap-northeast-2h" = "an2h" + + "ap-northeast-3" = "an3" + "ap-northeast-3a" = "an3a" + "ap-northeast-3b" = "an3b" + "ap-northeast-3c" = "an3c" + "ap-northeast-3d" = "an3d" + "ap-northeast-3e" = "an3e" + "ap-northeast-3f" = "an3f" + "ap-northeast-3g" = "an3g" + "ap-northeast-3h" = "an3h" + + # Abbreviation for ap-south-1 would be "as1" but that is already used for ap-southeast-1 + # So we use "as0" for ap-south-1 + "ap-south-1" = "as0" + "ap-south-1a" = "as0a" + "ap-south-1b" = "as0b" + "ap-south-1c" = "as0c" + "ap-south-1d" = "as0d" + "ap-south-1e" = "as0e" + "ap-south-1f" = "as0f" + "ap-south-1g" = "as0g" + "ap-south-1h" = "as0h" + + # Abbreviation for ap-south-2 would be "as2" but that is already used for ap-southeast-2 + # Using a different number as we did for ap-south-1 in not as extensible as using a different letter, + # which allows us to leaves the region number consistent. + # So we use "ar2" (r is letter before s) for ap-south-2 + "ap-south-2" = "ar2" + "ap-south-2a" = "ar2a" + "ap-south-2b" = "ar2b" + "ap-south-2c" = "ar2c" + "ap-south-2d" = "ar2d" + "ap-south-2e" = "ar2e" + "ap-south-2f" = "ar2f" + "ap-south-2g" = "ar2g" + "ap-south-2h" = "ar2h" + + "ap-southeast-1" = "as1" + "ap-southeast-1a" = "as1a" + "ap-southeast-1b" = "as1b" + "ap-southeast-1c" = "as1c" + "ap-southeast-1d" = "as1d" + "ap-southeast-1e" = "as1e" + "ap-southeast-1f" = "as1f" + "ap-southeast-1g" = "as1g" + "ap-southeast-1h" = "as1h" + + "ap-southeast-2" = "as2" + "ap-southeast-2a" = "as2a" + "ap-southeast-2b" = "as2b" + "ap-southeast-2c" = "as2c" + "ap-southeast-2d" = "as2d" + "ap-southeast-2e" = "as2e" + "ap-southeast-2f" = "as2f" + "ap-southeast-2g" = "as2g" + "ap-southeast-2h" = "as2h" + + "ap-southeast-3" = "as3" + "ap-southeast-3a" = "as3a" + "ap-southeast-3b" = "as3b" + "ap-southeast-3c" = "as3c" + "ap-southeast-3d" = "as3d" + "ap-southeast-3e" = "as3e" + "ap-southeast-3f" = "as3f" + "ap-southeast-3g" = "as3g" + "ap-southeast-3h" = "as3h" + + "ap-southeast-4" = "as4" + "ap-southeast-4a" = "as4a" + "ap-southeast-4b" = "as4b" + "ap-southeast-4c" = "as4c" + "ap-southeast-4d" = "as4d" + "ap-southeast-4e" = "as4e" + "ap-southeast-4f" = "as4f" + "ap-southeast-4g" = "as4g" + "ap-southeast-4h" = "as4h" + + "ca-central-1" = "cc1" + "ca-central-1a" = "cc1a" + "ca-central-1b" = "cc1b" + "ca-central-1c" = "cc1c" + "ca-central-1d" = "cc1d" + "ca-central-1e" = "cc1e" + "ca-central-1f" = "cc1f" + "ca-central-1g" = "cc1g" + "ca-central-1h" = "cc1h" + + "ca-west-1" = "cw1" + "ca-west-1a" = "cw1a" + "ca-west-1b" = "cw1b" + "ca-west-1c" = "cw1c" + + "eu-central-1" = "ec1" + "eu-central-1a" = "ec1a" + "eu-central-1b" = "ec1b" + "eu-central-1c" = "ec1c" + "eu-central-1d" = "ec1d" + "eu-central-1e" = "ec1e" + "eu-central-1f" = "ec1f" + "eu-central-1g" = "ec1g" + "eu-central-1h" = "ec1h" + + "eu-central-2" = "ec2" + "eu-central-2a" = "ec2a" + "eu-central-2b" = "ec2b" + "eu-central-2c" = "ec2c" + "eu-central-2d" = "ec2d" + "eu-central-2e" = "ec2e" + "eu-central-2f" = "ec2f" + "eu-central-2g" = "ec2g" + "eu-central-2h" = "ec2h" + + "eu-north-1" = "en1" + "eu-north-1a" = "en1a" + "eu-north-1b" = "en1b" + "eu-north-1c" = "en1c" + "eu-north-1d" = "en1d" + "eu-north-1e" = "en1e" + "eu-north-1f" = "en1f" + "eu-north-1g" = "en1g" + "eu-north-1h" = "en1h" + + "eu-south-1" = "es1" + "eu-south-1a" = "es1a" + "eu-south-1b" = "es1b" + "eu-south-1c" = "es1c" + "eu-south-1d" = "es1d" + "eu-south-1e" = "es1e" + "eu-south-1f" = "es1f" + "eu-south-1g" = "es1g" + "eu-south-1h" = "es1h" + + "eu-south-2" = "es2" + "eu-south-2a" = "es2a" + "eu-south-2b" = "es2b" + "eu-south-2c" = "es2c" + "eu-south-2d" = "es2d" + "eu-south-2e" = "es2e" + "eu-south-2f" = "es2f" + "eu-south-2g" = "es2g" + "eu-south-2h" = "es2h" + + "eu-west-1" = "ew1" + "eu-west-1a" = "ew1a" + "eu-west-1b" = "ew1b" + "eu-west-1c" = "ew1c" + "eu-west-1d" = "ew1d" + "eu-west-1e" = "ew1e" + "eu-west-1f" = "ew1f" + "eu-west-1g" = "ew1g" + "eu-west-1h" = "ew1h" + + "eu-west-2" = "ew2" + "eu-west-2a" = "ew2a" + "eu-west-2b" = "ew2b" + "eu-west-2c" = "ew2c" + "eu-west-2d" = "ew2d" + "eu-west-2e" = "ew2e" + "eu-west-2f" = "ew2f" + "eu-west-2g" = "ew2g" + "eu-west-2h" = "ew2h" + + "eu-west-3" = "ew3" + "eu-west-3a" = "ew3a" + "eu-west-3b" = "ew3b" + "eu-west-3c" = "ew3c" + "eu-west-3d" = "ew3d" + "eu-west-3e" = "ew3e" + "eu-west-3f" = "ew3f" + "eu-west-3g" = "ew3g" + "eu-west-3h" = "ew3h" + + "af-south-1" = "fs1" + "af-south-1a" = "fs1a" + "af-south-1b" = "fs1b" + "af-south-1c" = "fs1c" + "af-south-1d" = "fs1d" + "af-south-1e" = "fs1e" + "af-south-1f" = "fs1f" + "af-south-1g" = "fs1g" + "af-south-1h" = "fs1h" + + "us-gov-east-1" = "ge1" + "us-gov-east-1a" = "ge1a" + "us-gov-east-1b" = "ge1b" + "us-gov-east-1c" = "ge1c" + "us-gov-east-1d" = "ge1d" + "us-gov-east-1e" = "ge1e" + "us-gov-east-1f" = "ge1f" + "us-gov-east-1g" = "ge1g" + "us-gov-east-1h" = "ge1h" + + "us-gov-west-1" = "gw1" + "us-gov-west-1a" = "gw1a" + "us-gov-west-1b" = "gw1b" + "us-gov-west-1c" = "gw1c" + "us-gov-west-1d" = "gw1d" + "us-gov-west-1e" = "gw1e" + "us-gov-west-1f" = "gw1f" + "us-gov-west-1g" = "gw1g" + "us-gov-west-1h" = "gw1h" + + "il-central-1" = "ic1" + "il-central-1a" = "ic1a" + "il-central-1b" = "ic1b" + "il-central-1c" = "ic1c" + + "me-central-1" = "mc1" + "me-central-1a" = "mc1a" + "me-central-1b" = "mc1b" + "me-central-1c" = "mc1c" + "me-central-1d" = "mc1d" + "me-central-1e" = "mc1e" + "me-central-1f" = "mc1f" + "me-central-1g" = "mc1g" + "me-central-1h" = "mc1h" + + "me-south-1" = "ms1" + "me-south-1a" = "ms1a" + "me-south-1b" = "ms1b" + "me-south-1c" = "ms1c" + "me-south-1d" = "ms1d" + "me-south-1e" = "ms1e" + "me-south-1f" = "ms1f" + "me-south-1g" = "ms1g" + "me-south-1h" = "ms1h" + + "cn-north-1" = "nn0" + "cn-north-1a" = "nn0a" + "cn-north-1b" = "nn0b" + "cn-north-1c" = "nn0c" + "cn-north-1d" = "nn0d" + "cn-north-1e" = "nn0e" + "cn-north-1f" = "nn0f" + "cn-north-1g" = "nn0g" + "cn-north-1h" = "nn0h" + + "cn-northwest-1" = "nn1" + "cn-northwest-1a" = "nn1a" + "cn-northwest-1b" = "nn1b" + "cn-northwest-1c" = "nn1c" + "cn-northwest-1d" = "nn1d" + "cn-northwest-1e" = "nn1e" + "cn-northwest-1f" = "nn1f" + "cn-northwest-1g" = "nn1g" + "cn-northwest-1h" = "nn1h" + + "sa-east-1" = "se1" + "sa-east-1a" = "se1a" + "sa-east-1b" = "se1b" + "sa-east-1c" = "se1c" + "sa-east-1d" = "se1d" + "sa-east-1e" = "se1e" + "sa-east-1f" = "se1f" + "sa-east-1g" = "se1g" + "sa-east-1h" = "se1h" + + "us-east-1" = "ue1" + "us-east-1a" = "ue1a" + "us-east-1b" = "ue1b" + "us-east-1c" = "ue1c" + "us-east-1d" = "ue1d" + "us-east-1e" = "ue1e" + "us-east-1f" = "ue1f" + "us-east-1g" = "ue1g" + "us-east-1h" = "ue1h" + + "us-east-1-atl-1" = "at1" + "us-east-1-atl-1a" = "at1a" + "us-east-1-bos-1" = "bo1" + "us-east-1-bos-1a" = "bo1a" + "us-east-1-chi-1" = "ch1" + "us-east-1-chi-1a" = "ch1a" + "us-east-1-dfw-1" = "df1" + "us-east-1-dfw-1a" = "df1a" + "us-east-1-iah-1" = "ia1" + "us-east-1-iah-1a" = "ia1a" + # Cannot use mc for mci, taken by me-central + # Want to avoid second letter "c" as it may be a future "central" + "us-east-1-mci-1" = "ks1" + "us-east-1-mci-1a" = "ks1a" + "us-east-1-mia-1" = "mi1" + "us-east-1-mia-1a" = "mi1a" + # Want to avoid second letter "s" as it may be a future "south" + "us-east-1-msp-1" = "mn1" + "us-east-1-msp-1a" = "mn1a" + "us-east-1-nyc-1" = "ny1" + "us-east-1-nyc-1a" = "ny1a" + # Use pl for phl to avoid clash with phx + "us-east-1-phl-1" = "pl1" + "us-east-1-phl-1a" = "pl1a" + + "us-east-2" = "ue2" + "us-east-2a" = "ue2a" + "us-east-2b" = "ue2b" + "us-east-2c" = "ue2c" + "us-east-2d" = "ue2d" + "us-east-2e" = "ue2e" + "us-east-2f" = "ue2f" + "us-east-2g" = "ue2g" + "us-east-2h" = "ue2h" + + "us-west-1" = "uw1" + "us-west-1a" = "uw1a" + "us-west-1b" = "uw1b" + "us-west-1c" = "uw1c" + "us-west-1d" = "uw1d" + "us-west-1e" = "uw1e" + "us-west-1f" = "uw1f" + "us-west-1g" = "uw1g" + "us-west-1h" = "uw1h" + + "us-west-2" = "uw2" + "us-west-2a" = "uw2a" + "us-west-2b" = "uw2b" + "us-west-2c" = "uw2c" + "us-west-2d" = "uw2d" + "us-west-2e" = "uw2e" + "us-west-2f" = "uw2f" + "us-west-2g" = "uw2g" + "us-west-2h" = "uw2h" + + # Want to avoid second letter "e" or "n" in case of future "east" or "north" + "us-west-2-den-1" = "dv1" + "us-west-2-den-1a" = "dv1a" + # use lv for Las Vegas and lx for Los Angeles (LAX) to reduce confusion + "us-west-2-las-1" = "lv1" + "us-west-2-las-1a" = "lv1a" + "us-west-2-lax-1" = "lx1" + "us-west-2-lax-1a" = "lx1a" + "us-west-2-lax-1b" = "lx1b" + "us-west-2-pdx-1" = "pd1" + "us-west-2-pdx-1a" = "pd1a" + # Use px for phl to avoid clash with phl + "us-west-2-phx-1" = "px1" + "us-west-2-phx-1a" = "px1a" + # Cannot use se for sea, taken by sa-east + "us-west-2-sea-1" = "st1" + "us-west-2-sea-1a" = "st1a" + } + + to_short = { + "ap-east-1" = "ape1" + "ap-east-1a" = "ape1a" + "ap-east-1b" = "ape1b" + "ap-east-1c" = "ape1c" + "ap-east-1d" = "ape1d" + "ap-east-1e" = "ape1e" + "ap-east-1f" = "ape1f" + "ap-east-1g" = "ape1g" + "ap-east-1h" = "ape1h" + + "ap-northeast-1" = "apne1" + "ap-northeast-1a" = "apne1a" + "ap-northeast-1b" = "apne1b" + "ap-northeast-1c" = "apne1c" + "ap-northeast-1d" = "apne1d" + "ap-northeast-1e" = "apne1e" + "ap-northeast-1f" = "apne1f" + "ap-northeast-1g" = "apne1g" + "ap-northeast-1h" = "apne1h" + + "ap-northeast-2" = "apne2" + "ap-northeast-2a" = "apne2a" + "ap-northeast-2b" = "apne2b" + "ap-northeast-2c" = "apne2c" + "ap-northeast-2d" = "apne2d" + "ap-northeast-2e" = "apne2e" + "ap-northeast-2f" = "apne2f" + "ap-northeast-2g" = "apne2g" + "ap-northeast-2h" = "apne2h" + + "ap-northeast-3" = "apne3" + "ap-northeast-3a" = "apne3a" + "ap-northeast-3b" = "apne3b" + "ap-northeast-3c" = "apne3c" + "ap-northeast-3d" = "apne3d" + "ap-northeast-3e" = "apne3e" + "ap-northeast-3f" = "apne3f" + "ap-northeast-3g" = "apne3g" + "ap-northeast-3h" = "apne3h" + + "ap-south-1" = "aps1" + "ap-south-1a" = "aps1a" + "ap-south-1b" = "aps1b" + "ap-south-1c" = "aps1c" + "ap-south-1d" = "aps1d" + "ap-south-1e" = "aps1e" + "ap-south-1f" = "aps1f" + "ap-south-1g" = "aps1g" + "ap-south-1h" = "aps1h" + + "ap-south-2" = "aps2" + "ap-south-2a" = "aps2a" + "ap-south-2b" = "aps2b" + "ap-south-2c" = "aps2c" + "ap-south-2d" = "aps2d" + "ap-south-2e" = "aps2e" + "ap-south-2f" = "aps2f" + "ap-south-2g" = "aps2g" + "ap-south-2h" = "aps2h" + + "ap-southeast-1" = "apse1" + "ap-southeast-1a" = "apse1a" + "ap-southeast-1b" = "apse1b" + "ap-southeast-1c" = "apse1c" + "ap-southeast-1d" = "apse1d" + "ap-southeast-1e" = "apse1e" + "ap-southeast-1f" = "apse1f" + "ap-southeast-1g" = "apse1g" + "ap-southeast-1h" = "apse1h" + + "ap-southeast-2" = "apse2" + "ap-southeast-2a" = "apse2a" + "ap-southeast-2b" = "apse2b" + "ap-southeast-2c" = "apse2c" + "ap-southeast-2d" = "apse2d" + "ap-southeast-2e" = "apse2e" + "ap-southeast-2f" = "apse2f" + "ap-southeast-2g" = "apse2g" + "ap-southeast-2h" = "apse2h" + + "ap-southeast-3" = "apse3" + "ap-southeast-3a" = "apse3a" + "ap-southeast-3b" = "apse3b" + "ap-southeast-3c" = "apse3c" + "ap-southeast-3d" = "apse3d" + "ap-southeast-3e" = "apse3e" + "ap-southeast-3f" = "apse3f" + "ap-southeast-3g" = "apse3g" + "ap-southeast-3h" = "apse3h" + + "ap-southeast-4" = "apse4" + "ap-southeast-4a" = "apse4a" + "ap-southeast-4b" = "apse4b" + "ap-southeast-4c" = "apse4c" + "ap-southeast-4d" = "apse4d" + "ap-southeast-4e" = "apse4e" + "ap-southeast-4f" = "apse4f" + "ap-southeast-4g" = "apse4g" + "ap-southeast-4h" = "apse4h" + + "ca-central-1" = "cac1" + "ca-central-1a" = "cac1a" + "ca-central-1b" = "cac1b" + "ca-central-1c" = "cac1c" + "ca-central-1d" = "cac1d" + "ca-central-1e" = "cac1e" + "ca-central-1f" = "cac1f" + "ca-central-1g" = "cac1g" + "ca-central-1h" = "cac1h" + + "ca-west-1" = "caw1" + "ca-west-1a" = "caw1a" + "ca-west-1b" = "caw1b" + "ca-west-1c" = "caw1c" + + "eu-central-1" = "euc1" + "eu-central-1a" = "euc1a" + "eu-central-1b" = "euc1b" + "eu-central-1c" = "euc1c" + "eu-central-1d" = "euc1d" + "eu-central-1e" = "euc1e" + "eu-central-1f" = "euc1f" + "eu-central-1g" = "euc1g" + "eu-central-1h" = "euc1h" + + "eu-central-2" = "euc2" + "eu-central-2a" = "euc2a" + "eu-central-2b" = "euc2b" + "eu-central-2c" = "euc2c" + "eu-central-2d" = "euc2d" + "eu-central-2e" = "euc2e" + "eu-central-2f" = "euc2f" + "eu-central-2g" = "euc2g" + "eu-central-2h" = "euc2h" + + "eu-north-1" = "eun1" + "eu-north-1a" = "eun1a" + "eu-north-1b" = "eun1b" + "eu-north-1c" = "eun1c" + "eu-north-1d" = "eun1d" + "eu-north-1e" = "eun1e" + "eu-north-1f" = "eun1f" + "eu-north-1g" = "eun1g" + "eu-north-1h" = "eun1h" + + "eu-south-1" = "eus1" + "eu-south-1a" = "eus1a" + "eu-south-1b" = "eus1b" + "eu-south-1c" = "eus1c" + "eu-south-1d" = "eus1d" + "eu-south-1e" = "eus1e" + "eu-south-1f" = "eus1f" + "eu-south-1g" = "eus1g" + "eu-south-1h" = "eus1h" + + "eu-south-2" = "eus2" + "eu-south-2a" = "eus2a" + "eu-south-2b" = "eus2b" + "eu-south-2c" = "eus2c" + "eu-south-2d" = "eus2d" + "eu-south-2e" = "eus2e" + "eu-south-2f" = "eus2f" + "eu-south-2g" = "eus2g" + "eu-south-2h" = "eus2h" + + "eu-west-1" = "euw1" + "eu-west-1a" = "euw1a" + "eu-west-1b" = "euw1b" + "eu-west-1c" = "euw1c" + "eu-west-1d" = "euw1d" + "eu-west-1e" = "euw1e" + "eu-west-1f" = "euw1f" + "eu-west-1g" = "euw1g" + "eu-west-1h" = "euw1h" + + "eu-west-2" = "euw2" + "eu-west-2a" = "euw2a" + "eu-west-2b" = "euw2b" + "eu-west-2c" = "euw2c" + "eu-west-2d" = "euw2d" + "eu-west-2e" = "euw2e" + "eu-west-2f" = "euw2f" + "eu-west-2g" = "euw2g" + "eu-west-2h" = "euw2h" + + "eu-west-3" = "euw3" + "eu-west-3a" = "euw3a" + "eu-west-3b" = "euw3b" + "eu-west-3c" = "euw3c" + "eu-west-3d" = "euw3d" + "eu-west-3e" = "euw3e" + "eu-west-3f" = "euw3f" + "eu-west-3g" = "euw3g" + "eu-west-3h" = "euw3h" + + "af-south-1" = "afs1" + "af-south-1a" = "afs1a" + "af-south-1b" = "afs1b" + "af-south-1c" = "afs1c" + "af-south-1d" = "afs1d" + "af-south-1e" = "afs1e" + "af-south-1f" = "afs1f" + "af-south-1g" = "afs1g" + "af-south-1h" = "afs1h" + + "us-gov-east-1" = "usge1" + "us-gov-east-1a" = "usge1a" + "us-gov-east-1b" = "usge1b" + "us-gov-east-1c" = "usge1c" + "us-gov-east-1d" = "usge1d" + "us-gov-east-1e" = "usge1e" + "us-gov-east-1f" = "usge1f" + "us-gov-east-1g" = "usge1g" + "us-gov-east-1h" = "usge1h" + + "us-gov-west-1" = "usgw1" + "us-gov-west-1a" = "usgw1a" + "us-gov-west-1b" = "usgw1b" + "us-gov-west-1c" = "usgw1c" + "us-gov-west-1d" = "usgw1d" + "us-gov-west-1e" = "usgw1e" + "us-gov-west-1f" = "usgw1f" + "us-gov-west-1g" = "usgw1g" + "us-gov-west-1h" = "usgw1h" + + "il-central-1" = "ilc1" + "il-central-1a" = "ilc1a" + "il-central-1b" = "ilc1b" + "il-central-1c" = "ilc1c" + + "me-central-1" = "mec1" + "me-central-1a" = "mec1a" + "me-central-1b" = "mec1b" + "me-central-1c" = "mec1c" + "me-central-1d" = "mec1d" + "me-central-1e" = "mec1e" + "me-central-1f" = "mec1f" + "me-central-1g" = "mec1g" + "me-central-1h" = "mec1h" + + "me-south-1" = "mes1" + "me-south-1a" = "mes1a" + "me-south-1b" = "mes1b" + "me-south-1c" = "mes1c" + "me-south-1d" = "mes1d" + "me-south-1e" = "mes1e" + "me-south-1f" = "mes1f" + "me-south-1g" = "mes1g" + "me-south-1h" = "mes1h" + + "cn-north-1" = "cnn1" + "cn-north-1a" = "cnn1a" + "cn-north-1b" = "cnn1b" + "cn-north-1c" = "cnn1c" + "cn-north-1d" = "cnn1d" + "cn-north-1e" = "cnn1e" + "cn-north-1f" = "cnn1f" + "cn-north-1g" = "cnn1g" + "cn-north-1h" = "cnn1h" + + "cn-northwest-1" = "cnnw1" + "cn-northwest-1a" = "cnnw1a" + "cn-northwest-1b" = "cnnw1b" + "cn-northwest-1c" = "cnnw1c" + "cn-northwest-1d" = "cnnw1d" + "cn-northwest-1e" = "cnnw1e" + "cn-northwest-1f" = "cnnw1f" + "cn-northwest-1g" = "cnnw1g" + "cn-northwest-1h" = "cnnw1h" + + "sa-east-1" = "sae1" + "sa-east-1a" = "sae1a" + "sa-east-1b" = "sae1b" + "sa-east-1c" = "sae1c" + "sa-east-1d" = "sae1d" + "sa-east-1e" = "sae1e" + "sa-east-1f" = "sae1f" + "sa-east-1g" = "sae1g" + "sa-east-1h" = "sae1h" + + "us-east-1" = "use1" + "us-east-1a" = "use1a" + "us-east-1b" = "use1b" + "us-east-1c" = "use1c" + "us-east-1d" = "use1d" + "us-east-1e" = "use1e" + "us-east-1f" = "use1f" + "us-east-1g" = "use1g" + "us-east-1h" = "use1h" + + "us-east-1-atl-1" = "atl1" + "us-east-1-atl-1a" = "atl1a" + "us-east-1-bos-1" = "bos1" + "us-east-1-bos-1a" = "bos1a" + "us-east-1-chi-1" = "chi1" + "us-east-1-chi-1a" = "chi1a" + "us-east-1-dfw-1" = "dfw1" + "us-east-1-dfw-1a" = "dfw1a" + "us-east-1-iah-1" = "iah1" + "us-east-1-iah-1a" = "iah1a" + "us-east-1-mci-1" = "mci1" + "us-east-1-mci-1a" = "mci1a" + "us-east-1-mia-1" = "mia1" + "us-east-1-mia-1a" = "mia1a" + "us-east-1-msp-1" = "msp1" + "us-east-1-msp-1a" = "msp1a" + "us-east-1-nyc-1" = "nyc1" + "us-east-1-nyc-1a" = "nyc1a" + "us-east-1-phl-1" = "phi1" + "us-east-1-phl-1a" = "phi1a" + + "us-east-2" = "use2" + "us-east-2a" = "use2a" + "us-east-2b" = "use2b" + "us-east-2c" = "use2c" + "us-east-2d" = "use2d" + "us-east-2e" = "use2e" + "us-east-2f" = "use2f" + "us-east-2g" = "use2g" + "us-east-2h" = "use2h" + + "us-west-1" = "usw1" + "us-west-1a" = "usw1a" + "us-west-1b" = "usw1b" + "us-west-1c" = "usw1c" + "us-west-1d" = "usw1d" + "us-west-1e" = "usw1e" + "us-west-1f" = "usw1f" + "us-west-1g" = "usw1g" + "us-west-1h" = "usw1h" + + "us-west-2" = "usw2" + "us-west-2a" = "usw2a" + "us-west-2b" = "usw2b" + "us-west-2c" = "usw2c" + "us-west-2d" = "usw2d" + "us-west-2e" = "usw2e" + "us-west-2f" = "usw2f" + "us-west-2g" = "usw2g" + "us-west-2h" = "usw2h" + + "us-west-2-den-1" = "den1" + "us-west-2-den-1a" = "den1a" + "us-west-2-las-1" = "las1" + "us-west-2-las-1a" = "las1a" + "us-west-2-lax-1" = "lax1" + "us-west-2-lax-1a" = "lax1a" + "us-west-2-lax-1b" = "lax1b" + "us-west-2-pdx-1" = "pdx1" + "us-west-2-pdx-1a" = "pdx1a" + "us-west-2-phx-1" = "phx1" + "us-west-2-phx-1a" = "phx1a" + "us-west-2-sea-1" = "sea1" + "us-west-2-sea-1a" = "sea1a" + } + + # tflint-ignore: terraform_unused_declarations + from_fixed = zipmap(values(local.to_fixed), keys(local.to_fixed)) + # tflint-ignore: terraform_unused_declarations + from_short = zipmap(values(local.to_short), keys(local.to_short)) + + # tflint-ignore: terraform_unused_declarations + identity = { for k, v in local.to_short : k => k } + +} diff --git a/infrastructure/modules/tags/variables.tf b/infrastructure/modules/tags/variables.tf new file mode 100644 index 0000000..d27e436 --- /dev/null +++ b/infrastructure/modules/tags/variables.tf @@ -0,0 +1,315 @@ +# tflint-ignore: terraform_unused_declarations +variable "aws_region" { + type = string + description = "The AWS region" + default = "eu-west-2" + validation { + condition = contains(["eu-west-1", "eu-west-2", "us-east-1"], var.aws_region) + error_message = "AWS Region must be one of eu-west-1, eu-west-2, us-east-1" + } +} + +variable "context" { + type = any + default = { + enabled = true + service = null + project = null + region = null + environment = null + stack = null + workspace = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "service" { + type = string + default = null + description = "ID element. Usually an abbreviation of your service directorate name, e.g. 'bcss' or 'csms', to help ensure generated IDs are globally unique" +} + +variable "region" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. Usually an abbreviation of the selected AWS region e.g. 'uw2', 'ew2' or 'gbl' for resources like IAM roles that have no region" +} + +variable "project" { + type = string + default = null + description = "ID element. A project identifier, indicating the name or role of the project the resource is for, such as `website` or `api`" +} +variable "stack" { + type = string + default = null + description = "ID element. The name of the stack/component, e.g. `database`, `web`, `waf`, `eks`" +} +variable "workspace" { + type = string + default = null + description = "ID element. The Terraform workspace, to help ensure generated IDs are unique across workspaces" +} +variable "environment" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prd', 'dev', 'test', 'preprod', 'prod', 'uat'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["service", "project", "environment", "stack", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +variable "owner" { + type = string + description = "The name and or NHS.net email address of the service owner" + default = "None" +} + +variable "tag_version" { + type = string + description = "Used to identify the tagging version in use" + default = "1.0" +} + +variable "data_classification" { + type = string + description = "Used to identify the data classification of the resource, e.g 1-5" + default = "n/a" + validation { + condition = contains(["n/a", "1", "2", "3", "4", "5"], var.data_classification) + error_message = "Data Classification must be \"n/a\" or between 1-5" + } +} + +variable "data_type" { + type = string + description = "The tag data_type" + default = "None" + validation { + condition = contains(["None", "PCD", "PID", "Anonymised", "UserAccount", "Audit"], var.data_type) + error_message = "Data Type must be one of None, PCD, PID, Anonymised, UserAccount, Audit" + } +} + + +variable "public_facing" { + type = bool + description = "Whether this resource is public facing" + default = false +} + +variable "service_category" { + type = string + description = "The tag service_category" + default = "n/a" + validation { + condition = contains(["n/a", "Bronze", "Silver", "Gold", "Platinum"], var.service_category) + error_message = "The Service Category must be one of n/a, Bronze, Silver, Gold, Platinum" + } +} +variable "on_off_pattern" { + type = string + description = "Used to turn resources on and off based on a time pattern" + default = "n/a" +} + +variable "application_role" { + type = string + description = "The role the application is performing" + default = "General" +} + +variable "tool" { + type = string + description = "The tool used to deploy the resource" + default = "Terraform" +} diff --git a/infrastructure/modules/tags/versions.tf b/infrastructure/modules/tags/versions.tf new file mode 100644 index 0000000..a9561ef --- /dev/null +++ b/infrastructure/modules/tags/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.13.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 6.14.0" + } + } +} diff --git a/infrastructure/modules/vpc/readme.md b/infrastructure/modules/vpc/readme.md index e1482bb..ada1499 100644 --- a/infrastructure/modules/vpc/readme.md +++ b/infrastructure/modules/vpc/readme.md @@ -67,8 +67,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -77,7 +77,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_eip.eip_a](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | | [aws_eip.eip_b](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | | [aws_eip.eip_c](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | @@ -106,19 +106,19 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `any` | n/a | yes | -| [name](#input_name) | The name of the resource | `string` | `""` | no | -| [name_prefix](#input_name_prefix) | the environment and project | `any` | n/a | yes | -| [vpc_cidr_prefix](#input_vpc_cidr_prefix) | The CIDR block prefix for the VPC | `any` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `any` | n/a | yes | +| [name](#input\_name) | The name of the resource | `string` | `""` | no | +| [name\_prefix](#input\_name\_prefix) | the environment and project | `any` | n/a | yes | +| [vpc\_cidr\_prefix](#input\_vpc\_cidr\_prefix) | The CIDR block prefix for the VPC | `any` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [private_subnet_ids](#output_private_subnet_ids) | IDs of the public subnets | -| [public_subnet_ids](#output_public_subnet_ids) | IDs of the public subnets | -| [vpc_cidr_block](#output_vpc_cidr_block) | CIDR range of the VPC | -| [vpc_id](#output_vpc_id) | ID of the VPC | +| ---- | ----------- | +| [private\_subnet\_ids](#output\_private\_subnet\_ids) | IDs of the public subnets | +| [public\_subnet\_ids](#output\_public\_subnet\_ids) | IDs of the public subnets | +| [vpc\_cidr\_block](#output\_vpc\_cidr\_block) | CIDR range of the VPC | +| [vpc\_id](#output\_vpc\_id) | ID of the VPC | diff --git a/infrastructure/modules/vpc/variables.tf b/infrastructure/modules/vpc/variables.tf index cca0dbf..462e540 100644 --- a/infrastructure/modules/vpc/variables.tf +++ b/infrastructure/modules/vpc/variables.tf @@ -14,4 +14,3 @@ variable "name_prefix" { variable "vpc_cidr_prefix" { description = "The CIDR block prefix for the VPC" } - diff --git a/infrastructure/modules/vpce/main.tf b/infrastructure/modules/vpce/main.tf index 6c51f58..86bac67 100644 --- a/infrastructure/modules/vpce/main.tf +++ b/infrastructure/modules/vpce/main.tf @@ -75,4 +75,3 @@ resource "aws_route53_record" "vpc_endpoint" { zone_id = aws_vpc_endpoint.endpoint.dns_entry[0]["hosted_zone_id"] } } - diff --git a/infrastructure/modules/vpce/readme.md b/infrastructure/modules/vpce/readme.md index e2fdac4..0873709 100644 --- a/infrastructure/modules/vpce/readme.md +++ b/infrastructure/modules/vpce/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_route53_record.vpc_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | | [aws_security_group.vpce](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_security_group_rule.vpce_egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | @@ -30,26 +30,26 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [hosted_zone_id](#input_hosted_zone_id) | Set the hosted zone id if you would like a R53 alias record set up for this VPCE | `any` | n/a | yes | -| [hosted_zone_name](#input_hosted_zone_name) | Set the hosted zone name if you would like a R53 alias record set up for this VPCE | `any` | n/a | yes | -| [inbound_port](#input_inbound_port) | TCP port for which ingress will be allowed to VPCE | `any` | n/a | yes | -| [ingress_cidr_range](#input_ingress_cidr_range) | Optional CIDR range that will be allowed to send traffic to VPCE e.g. the VPC cidr range | `string` | `""` | no | -| [name_prefix](#input_name_prefix) | the environment and project | `any` | n/a | yes | -| [outbound_port](#input_outbound_port) | TCP port for which egress will be allowed to VPCE | `any` | n/a | yes | -| [service_name](#input_service_name) | VPC endpoint service name to connect to | `any` | n/a | yes | -| [source_sg_id](#input_source_sg_id) | Optional id of source SG that will be allowed to send traffic to VPCE e.g. RDS SG | `string` | `""` | no | -| [subnet_azs](#input_subnet_azs) | AZs of subnets to associate - this must match the subnets of the remote VPC endpoint service e.g. euw2-az2, euw2-az3 | `list(string)` | `[]` | no | -| [subnet_ids](#input_subnet_ids) | Subnet ids | `any` | n/a | yes | -| [vpc_id](#input_vpc_id) | VPC id | `any` | n/a | yes | -| [vpce_name](#input_vpce_name) | The name of the VPCE | `any` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [hosted\_zone\_id](#input\_hosted\_zone\_id) | Set the hosted zone id if you would like a R53 alias record set up for this VPCE | `any` | n/a | yes | +| [hosted\_zone\_name](#input\_hosted\_zone\_name) | Set the hosted zone name if you would like a R53 alias record set up for this VPCE | `any` | n/a | yes | +| [inbound\_port](#input\_inbound\_port) | TCP port for which ingress will be allowed to VPCE | `any` | n/a | yes | +| [ingress\_cidr\_range](#input\_ingress\_cidr\_range) | Optional CIDR range that will be allowed to send traffic to VPCE e.g. the VPC cidr range | `string` | `""` | no | +| [name\_prefix](#input\_name\_prefix) | the environment and project | `any` | n/a | yes | +| [outbound\_port](#input\_outbound\_port) | TCP port for which egress will be allowed to VPCE | `any` | n/a | yes | +| [service\_name](#input\_service\_name) | VPC endpoint service name to connect to | `any` | n/a | yes | +| [source\_sg\_id](#input\_source\_sg\_id) | Optional id of source SG that will be allowed to send traffic to VPCE e.g. RDS SG | `string` | `""` | no | +| [subnet\_azs](#input\_subnet\_azs) | AZs of subnets to associate - this must match the subnets of the remote VPC endpoint service e.g. euw2-az2, euw2-az3 | `list(string)` | `[]` | no | +| [subnet\_ids](#input\_subnet\_ids) | Subnet ids | `any` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC id | `any` | n/a | yes | +| [vpce\_name](#input\_vpce\_name) | The name of the VPCE | `any` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [vpce_arn](#output_vpce_arn) | n/a | -| [vpce_dns_name](#output_vpce_dns_name) | n/a | -| [vpce_hosted_zone_id](#output_vpce_hosted_zone_id) | n/a | +| ---- | ----------- | +| [vpce\_arn](#output\_vpce\_arn) | n/a | +| [vpce\_dns\_name](#output\_vpce\_dns\_name) | n/a | +| [vpce\_hosted\_zone\_id](#output\_vpce\_hosted\_zone\_id) | n/a | diff --git a/infrastructure/modules/vpces/outputs.tf b/infrastructure/modules/vpces/outputs.tf index 8b13789..e69de29 100644 --- a/infrastructure/modules/vpces/outputs.tf +++ b/infrastructure/modules/vpces/outputs.tf @@ -1 +0,0 @@ - diff --git a/infrastructure/modules/vpces/readme.md b/infrastructure/modules/vpces/readme.md index dd2b191..b42708b 100644 --- a/infrastructure/modules/vpces/readme.md +++ b/infrastructure/modules/vpces/readme.md @@ -9,8 +9,8 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | ## Modules @@ -19,7 +19,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_lb.nlb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb) | resource | | [aws_lb_listener.listener](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener) | resource | | [aws_lb_target_group.nlb_tg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group) | resource | @@ -38,22 +38,22 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [access_logs_bucket](#input_access_logs_bucket) | The S3 bucket to store access logs | `string` | n/a | yes | -| [access_logs_prefix](#input_access_logs_prefix) | The S3 prefix for access logs | `string` | n/a | yes | -| [alb_arn](#input_alb_arn) | The ARN of the ALB to target | `string` | n/a | yes | -| [alb_listener](#input_alb_listener) | The ARN of the ALB listener to target | `string` | n/a | yes | -| [allowed_principal_secret_name](#input_allowed_principal_secret_name) | The name of the Secrets Manager secret containing the AWS account ID allowed to use this VPCE service | `string` | n/a | yes | -| [environment](#input_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | -| [nation](#input_nation) | en for england or ni for northern ireland | `string` | `"en"` | no | -| [nlb_name](#input_nlb_name) | The name of the Network Load Balancer | `string` | n/a | yes | -| [prefix](#input_prefix) | The prefix to use for naming resources | `string` | n/a | yes | -| [ssm_parameter_name](#input_ssm_parameter_name) | The name of the SSM parameter to store the allowed IPs | `string` | n/a | yes | -| [subnet_ids](#input_subnet_ids) | The Subnet IDs where the Network Load Balancer will be created | `list(string)` | n/a | yes | -| [target_alb_sg_id](#input_target_alb_sg_id) | The security group ID of the target ALB to allow inbound from the NLB | `string` | n/a | yes | -| [tg_name](#input_tg_name) | The name of the Target Group | `string` | n/a | yes | -| [vpc_id](#input_vpc_id) | The VPC ID where the VPC Endpoint Service will be created | `string` | n/a | yes | -| [vpces_name](#input_vpces_name) | The name of the VPC Endpoint Service | `string` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [access\_logs\_bucket](#input\_access\_logs\_bucket) | The S3 bucket to store access logs | `string` | n/a | yes | +| [access\_logs\_prefix](#input\_access\_logs\_prefix) | The S3 prefix for access logs | `string` | n/a | yes | +| [alb\_arn](#input\_alb\_arn) | The ARN of the ALB to target | `string` | n/a | yes | +| [alb\_listener](#input\_alb\_listener) | The ARN of the ALB listener to target | `string` | n/a | yes | +| [allowed\_principal\_secret\_name](#input\_allowed\_principal\_secret\_name) | The name of the Secrets Manager secret containing the AWS account ID allowed to use this VPCE service | `string` | n/a | yes | +| [environment](#input\_environment) | The name of the Environment this is deployed into, for example CICD, NFT, UAT or PROD | `string` | n/a | yes | +| [nation](#input\_nation) | en for england or ni for northern ireland | `string` | `"en"` | no | +| [nlb\_name](#input\_nlb\_name) | The name of the Network Load Balancer | `string` | n/a | yes | +| [prefix](#input\_prefix) | The prefix to use for naming resources | `string` | n/a | yes | +| [ssm\_parameter\_name](#input\_ssm\_parameter\_name) | The name of the SSM parameter to store the allowed IPs | `string` | n/a | yes | +| [subnet\_ids](#input\_subnet\_ids) | The Subnet IDs where the Network Load Balancer will be created | `list(string)` | n/a | yes | +| [target\_alb\_sg\_id](#input\_target\_alb\_sg\_id) | The security group ID of the target ALB to allow inbound from the NLB | `string` | n/a | yes | +| [tg\_name](#input\_tg\_name) | The name of the Target Group | `string` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | The VPC ID where the VPC Endpoint Service will be created | `string` | n/a | yes | +| [vpces\_name](#input\_vpces\_name) | The name of the VPC Endpoint Service | `string` | n/a | yes | ## Outputs diff --git a/infrastructure/modules/waf/outputs.tf b/infrastructure/modules/waf/outputs.tf index 3d5cc37..148239a 100644 --- a/infrastructure/modules/waf/outputs.tf +++ b/infrastructure/modules/waf/outputs.tf @@ -1,4 +1,3 @@ output "web_acl_arn" { value = aws_wafv2_web_acl.bss-waf-acl.arn } - diff --git a/infrastructure/modules/waf/readme.md b/infrastructure/modules/waf/readme.md index b1b1051..3f90949 100644 --- a/infrastructure/modules/waf/readme.md +++ b/infrastructure/modules/waf/readme.md @@ -9,9 +9,9 @@ No requirements. ## Providers | Name | Version | -|------|---------| -| [aws](#provider_aws) | n/a | -| [time](#provider_time) | n/a | +| ---- | ------- | +| [aws](#provider\_aws) | 6.43.0 | +| [time](#provider\_time) | 0.13.1 | ## Modules @@ -20,7 +20,7 @@ No modules. ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [aws_cloudwatch_event_rule.shield_ddos_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_target.shield_ddos_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_log_group.waf_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | @@ -48,21 +48,21 @@ No modules. ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [aws_account_id](#input_aws_account_id) | n/a | `any` | n/a | yes | -| [aws_region](#input_aws_region) | n/a | `any` | n/a | yes | -| [environment](#input_environment) | Environment i.e prod, nonprod | `any` | n/a | yes | -| [exclude_ip_set_name](#input_exclude_ip_set_name) | Service | `any` | n/a | yes | -| [name_prefix](#input_name_prefix) | n/a | `any` | n/a | yes | -| [waf_log_group_name](#input_waf_log_group_name) | waf log group | `any` | n/a | yes | -| [waf_name](#input_waf_name) | waf name | `any` | n/a | yes | -| [web_services_ip_set_name](#input_web_services_ip_set_name) | n/a | `any` | n/a | yes | -| [webservices_ip_set_addresses](#input_webservices_ip_set_addresses) | List of IP addresses for web services | `list(string)` | n/a | yes | +| ---- | ----------- | ---- | ------- | :------: | +| [aws\_account\_id](#input\_aws\_account\_id) | n/a | `any` | n/a | yes | +| [aws\_region](#input\_aws\_region) | n/a | `any` | n/a | yes | +| [environment](#input\_environment) | Environment i.e prod, nonprod | `any` | n/a | yes | +| [exclude\_ip\_set\_name](#input\_exclude\_ip\_set\_name) | Service | `any` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | n/a | `any` | n/a | yes | +| [waf\_log\_group\_name](#input\_waf\_log\_group\_name) | waf log group | `any` | n/a | yes | +| [waf\_name](#input\_waf\_name) | waf name | `any` | n/a | yes | +| [web\_services\_ip\_set\_name](#input\_web\_services\_ip\_set\_name) | n/a | `any` | n/a | yes | +| [webservices\_ip\_set\_addresses](#input\_webservices\_ip\_set\_addresses) | List of IP addresses for web services | `list(string)` | n/a | yes | ## Outputs | Name | Description | -|------|-------------| -| [web_acl_arn](#output_web_acl_arn) | n/a | +| ---- | ----------- | +| [web\_acl\_arn](#output\_web\_acl\_arn) | n/a | diff --git a/infrastructure/modules/waf/variables.tf b/infrastructure/modules/waf/variables.tf index f06e2dc..3b3befa 100644 --- a/infrastructure/modules/waf/variables.tf +++ b/infrastructure/modules/waf/variables.tf @@ -33,4 +33,3 @@ variable "webservices_ip_set_addresses" { variable "environment" { description = "Environment i.e prod, nonprod" } -