diff --git a/.snyk b/.snyk new file mode 100644 index 0000000..7bcce15 --- /dev/null +++ b/.snyk @@ -0,0 +1,16 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-CC-AWS-710: + - aurora-cluster.tf > resource > aws_rds_cluster[this] > iam_database_authentication_enabled: + reason: IAM authentication is set by variable + expires: 2027-04-01T00:00:00.000Z + created: 2022-11-14T18:20:39.256Z + SNYK-CC-AWS-414: + - main.tf > resource > aws_db_instance[this] > iam_database_authentication_enabled: + reason: IAM authentication is set by variable + expires: 2027-04-01T00:00:00.000Z + created: 2022-11-14T18:20:39.256Z + +patch: {} diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index f3a780a..c56a9f6 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -2,84 +2,64 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.59.0" - constraints = ">= 2.0.0, >= 3.0.0, >= 4.0.0, >= 4.9.0, >= 4.23.0, >= 5.0.0, < 6.0.0" + version = "5.73.0" + constraints = ">= 4.0.0, ~> 5.0, < 6.0.0" hashes = [ - "h1:RTI7BbGzkYrknXFSa/Fmh6oNLP0FqgjNb+xyFNJeyKo=", - "zh:077f41a15057d01d833d7438322adf9b507d17ac0c8e1287430a305b6e609775", - "zh:130b112c85b67413bc65e95e5927188d8e41b45abd75350690b93d95771a587c", - "zh:16e97f1af67a5d4c6bf4f2df824a6a332b446be4516dd85a2e097317c959a174", - "zh:1cd7b0946eaf0fb11090710e9c774d22d90de0ca4516485253be96e332ebaf73", - "zh:2591d8a269014fb59111793cb8a175aafa12e370cd856fe2522577efbb72e5be", - "zh:3db5387ecc7da4e6a55a34877ea426ae87d10238bdbdf284a52e16b4be83302c", - "zh:78169400a85912d7f05fe99d4f3ba9a56871411442bdc133083dd657b18fae4e", + "h1:hyOg38/ifG8Jf/b4GC6ydR8ClyRRdsAF3SmMHL6qbes=", + "zh:0d24edc51ab6600f56d759831658a9d7a8f69b53900546b75038fc8e3f312406", + "zh:1f8b8414f710a8c5a8777cb1ef1cad1cb4293bc035deb804734a8ec698b0850d", + "zh:2cf76b03564051ee86ef5fbdaea1949e3af549f8836e56371fe94335cf795e1c", + "zh:2ffe05c62b4ae6292dda66cd3a3cbe3e290a1a04369f3e6f74812e885cf3f2f0", + "zh:3564069d9bc918e5bded252d65b6a8758d08b309e1ac54bf7c8e5947a94cdadc", + "zh:4eb5395d52cfcb3c78e86c4ca3759bf9736e0e8dfa6955b0e1a59d9a7f41d805", + "zh:6cd14cbabbcf8b1c15fa73f9ebba4d4df41215ef92bf8d14a3780a7cb571e5c4", + "zh:6f7dc212dee1be2edb4620d352d9b0ea759744b5be08b84012a7621efa262052", + "zh:7468a490d6df04a401f49422c86b46ef91eba00878cc9a5ec3ee4a12fe9447d0", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:ad93fedbf1d2694faab6d793c6697ff5732449cdebacaa49acf6452c0c8e2ea0", - "zh:b8a2884858dde9d204dc6855903e3078a1c402485ae85b41c28e667f99a2a777", - "zh:bd3d4bd51172d08c0df277673a25fb3f0818ef47ef9f491b0c41e880b1dedce3", - "zh:d8e132bcafee2e69e21173fac409e4b99d8c81d60a7d25c58c379c67067dbf36", - "zh:eee5113ff29a42c5a75c83e9853e99a9b5c0ed066e36d6fe251083b19d38c7eb", - "zh:f0d8bcdb01d0fa0c9ed2ca8c198d4f11aabfd9d42fa239286b65ddcc6f606dfd", - "zh:f8ae46d14ec54c275e20f71d052f1b6af0cf948819b0667016045a6244edf292", + "zh:b440ff1be9fc62235b2dcb522dd922cefe751065ba4a601415130462e79fb68e", + "zh:d53dfd7311d8f130f0ce3184ed50461c34086d3490913a0d80d63574dac104a6", + "zh:de9a130dd684aed5b89edc7ce44aef37fa38eca06549035cf387cde9d3937432", + "zh:e0922d81fbed02062a74ea126d3cc6830fa0c8eac92108825d1120a262980831", + "zh:fdd6cdabcf5e9bedb3a419ac18bd12b5b02d8371ba0fb2a6123420937354c8e1", ] } provider "registry.terraform.io/hashicorp/null" { - version = "3.2.2" - constraints = ">= 2.0.0, >= 3.1.1" + version = "3.2.3" + constraints = ">= 3.1.0" hashes = [ - "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", - "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", - "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", - "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", - "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", - "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", - "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", - "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "h1:I0Um8UkrMUb81Fxq/dxbr3HLP2cecTH2WMJiwKSrwQY=", + "zh:22d062e5278d872fe7aed834f5577ba0a5afe34a3bdac2b81f828d8d3e6706d2", + "zh:23dead00493ad863729495dc212fd6c29b8293e707b055ce5ba21ee453ce552d", + "zh:28299accf21763ca1ca144d8f660688d7c2ad0b105b7202554ca60b02a3856d3", + "zh:55c9e8a9ac25a7652df8c51a8a9a422bd67d784061b1de2dc9fe6c3cb4e77f2f", + "zh:756586535d11698a216291c06b9ed8a5cc6a4ec43eee1ee09ecd5c6a9e297ac1", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", - "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", - "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", - "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", + "zh:9d5eea62fdb587eeb96a8c4d782459f4e6b73baeece4d04b4a40e44faaee9301", + "zh:a6355f596a3fb8fc85c2fb054ab14e722991533f87f928e7169a486462c74670", + "zh:b5a65a789cff4ada58a5baffc76cb9767dc26ec6b45c00d2ec8b1b027f6db4ed", + "zh:db5ab669cf11d0e9f81dc380a6fdfcac437aea3d69109c7aef1a5426639d2d65", + "zh:de655d251c470197bcbb5ac45d289595295acb8f829f6c781d4a75c8c8b7c7dd", + "zh:f5c68199f2e6076bce92a12230434782bf768103a427e9bb9abee99b116af7b5", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.6.2" + version = "3.6.3" constraints = ">= 3.4.0" hashes = [ - "h1:VavG5unYCa3SYISMKF9pzc3718M0bhPlcbUZZGl7wuo=", - "zh:0ef01a4f81147b32c1bea3429974d4d104bbc4be2ba3cfa667031a8183ef88ec", - "zh:1bcd2d8161e89e39886119965ef0f37fcce2da9c1aca34263dd3002ba05fcb53", - "zh:37c75d15e9514556a5f4ed02e1548aaa95c0ecd6ff9af1119ac905144c70c114", - "zh:4210550a767226976bc7e57d988b9ce48f4411fa8a60cd74a6b246baf7589dad", - "zh:562007382520cd4baa7320f35e1370ffe84e46ed4e2071fdc7e4b1a9b1f8ae9b", - "zh:5efb9da90f665e43f22c2e13e0ce48e86cae2d960aaf1abf721b497f32025916", - "zh:6f71257a6b1218d02a573fc9bff0657410404fb2ef23bc66ae8cd968f98d5ff6", + "h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=", + "zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451", + "zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8", + "zh:4b4c11ccfba7319e901df2dac836b1ae8f12185e37249e8d870ee10bb87a13fe", + "zh:4fa45c44c0de582c2edb8a2e054f55124520c16a39b2dfc0355929063b6395b1", + "zh:588508280501a06259e023b0695f6a18149a3816d259655c424d068982cbdd36", + "zh:737c4d99a87d2a4d1ac0a54a73d2cb62974ccb2edbd234f333abd079a32ebc9e", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9647e18f221380a85f2f0ab387c68fdafd58af6193a932417299cdcae4710150", - "zh:bb6297ce412c3c2fa9fec726114e5e0508dd2638cad6a0cb433194930c97a544", - "zh:f83e925ed73ff8a5ef6e3608ad9225baa5376446349572c2449c0c0b3cf184b7", - "zh:fbef0781cb64de76b1df1ca11078aecba7800d82fd4a956302734999cfd9a4af", - ] -} - -provider "registry.terraform.io/hashicorp/time" { - version = "0.12.0" - constraints = ">= 0.7.0" - hashes = [ - "h1:Os2Ok7txtlUJHh6Hg7o+74Ql85SnRb/fGmah22yXpLw=", - "zh:019a4c09af254ef80b72cf0d843dfe72d99483e227138cf5b514a1b9977ab4c3", - "zh:0ae310ec740ebc6f275529507d60bb747d0bf39e72fc5a2fa90d74486006132c", - "zh:13d6aec117f05237fbf8c7d91d6ebb19797b00aa87e7a812642d3ea4738a394e", - "zh:2e87abbc261f9317d0c2ef26e01d5fabf77679da7d2cac6f47df7d198f720989", - "zh:4a6d471176ce0264455aa7d5457b8702f78400010c201c1719708958a1b7b647", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8978d5474a6da30bc0ad21c17db188d6918cacf3df3f6506b72ef3a268d53e2e", - "zh:b109efe138dfcb45dc04a9cc6809d185ab8b0ebc12040847c2dac430fda5af68", - "zh:b58e039b9106ac0a8de3c07f53b5279d7f0215fb35f2d23df642dfce0875382f", - "zh:ba2cbb2e515922d13efe3a46647be84f5426fcfcaa0f1520b3efeab8db847ed3", - "zh:c6c1ef1f26f25bca3abb5e07fa33dca37ed39cc26d0ff877964f2ffe5edd618c", - "zh:f8e171f923b7d2e789abd034072465dec3e6133c3a7644b7a7a965a74d52224e", + "zh:a357ab512e5ebc6d1fda1382503109766e21bbfdfaa9ccda43d313c122069b30", + "zh:c51bfb15e7d52cc1a2eaec2a903ac2aff15d162c172b1b4c17675190e8147615", + "zh:e0951ee6fa9df90433728b96381fb867e3db98f66f735e0c3e24f8f16903f0ad", + "zh:e3cdcb4e73740621dabd82ee6a37d6cfce7fee2a03d8074df65086760f5cf556", + "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", ] } diff --git a/README.md b/README.md index 5a301a4..96ec053 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Overview -The SourceFuse AWS Reference Architecture (ARC) Terraform module offers a comprehensive solution for efficiently managing Aurora and RDS (Relational Database Service) instances within the Amazon Web Services (AWS) environment. This Terraform module is designed to streamline the provisioning, configuration, and management of these database instances, leveraging best practices. +The SourceFuse AWS Reference Architecture (ARC) Terraform module offers a comprehensive solution for efficiently managing Aurora, RDS cluster, RDS proxy and RDS (Relational Database Service) instances within the Amazon Web Services (AWS) environment. This Terraform module is designed to streamline the provisioning, configuration, and management of these database instances, leveraging best practices. For more information about this repository and its usage, please see [Terraform AWS ARC DB Usage Guide](https://github.com/sourcefuse/terraform-aws-arc-db/blob/main/docs/module-usage-guide/README.md). @@ -31,172 +31,120 @@ To see a full example, check out the [main.tf](https://github.com/sourcefuse/ter | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.59.0 | -| [random](#provider\_random) | 3.6.2 | +| [aws](#provider\_aws) | 5.73.0 | +| [random](#provider\_random) | 3.6.3 | ## Modules | Name | Source | Version | |------|--------|---------| -| [aurora\_cluster](#module\_aurora\_cluster) | git::https://github.com/cloudposse/terraform-aws-rds-cluster.git | 1.11.0 | -| [db\_management](#module\_db\_management) | git::https://github.com/cloudposse/terraform-aws-s3-bucket | 4.5.0 | -| [rds\_instance](#module\_rds\_instance) | git::https://github.com/cloudposse/terraform-aws-rds | 1.1.2 | -| [this](#module\_this) | cloudposse/label/null | 0.25.0 | +| [proxy\_security\_group](#module\_proxy\_security\_group) | ./modules/security-group | n/a | +| [security\_group](#module\_security\_group) | ./modules/security-group | n/a | ## Resources | Name | Type | |------|------| -| [aws_db_instance_role_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance_role_association) | resource | +| [aws_db_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance) | resource | | [aws_db_option_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_option_group) | resource | -| [aws_iam_policy.option_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_db_parameter_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | +| [aws_db_proxy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy) | resource | +| [aws_db_proxy_default_target_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group) | resource | +| [aws_db_proxy_target.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | resource | +| [aws_db_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | resource | +| [aws_iam_policy.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.read_secrets](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.option_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.attach_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.option_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_kms_alias.aurora_cluster_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_alias.rds_db_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.aurora_cluster_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_kms_key.rds_db_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_security_group_rule.additional_ingress_rules_aurora](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | -| [aws_security_group_rule.additional_ingress_rules_rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | -| [aws_ssm_parameter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | -| [random_password.aurora_db_admin_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [random_password.rds_db_admin_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [aws_iam_policy_document.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_iam_role_policy_attachment.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kms_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.secret](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_rds_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | resource | +| [aws_rds_cluster_instance.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | resource | +| [aws_secretsmanager_secret.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret_version.db_secret_version](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_ssm_parameter.database_creds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [random_password.master](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) | data source | +| [aws_kms_alias.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | 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 | |------|-------------|------|---------|:--------:| -| [account\_id](#input\_account\_id) | Account ID where the resources will be deployed to. This is required if `enable_custom_option_group` is set to `true`. | `string` | `""` | no | -| [additional\_ingress\_rules\_aurora](#input\_additional\_ingress\_rules\_aurora) | Additional ingress rules for Aurora |
list(object({| `[]` | no | -| [additional\_ingress\_rules\_rds](#input\_additional\_ingress\_rules\_rds) | Additional ingress rules for RDS |
name = string
description = string
type = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
list(object({| `[]` | no | -| [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`.
name = string
description = string
type = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
list(object({| `[]` | no | -| [aurora\_security\_groups](#input\_aurora\_security\_groups) | List of security group IDs to be allowed to connect to the DB instance | `list(string)` | `[]` | no | -| [aurora\_serverlessv2\_scaling\_configuration](#input\_aurora\_serverlessv2\_scaling\_configuration) | serverlessv2 scaling properties |
auto_pause = bool
max_capacity = number
min_capacity = number
seconds_until_auto_pause = number
timeout_action = string
}))
object({| `null` | no | -| [aurora\_storage\_type](#input\_aurora\_storage\_type) | One of 'standard' (magnetic), 'gp2' / 'gp3' (general purpose SSD), or 'io1' (provisioned IOPS SSD) or aurora-iopt1 | `string` | `null` | no | -| [aurora\_subnets](#input\_aurora\_subnets) | Subnets for the cluster to run in. | `list(string)` | `[]` | no | -| [context](#input\_context) | Single object for setting entire context at once.
min_capacity = number
max_capacity = number
})
{| no | -| [deletion\_protection](#input\_deletion\_protection) | Protect the instance from being deleted | `bool` | `false` | no | -| [deletion\_window\_in\_days](#input\_deletion\_window\_in\_days) | n/a | `number` | `10` | no | -| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
"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"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
object({| n/a | yes | +| [delete\_automated\_backups](#input\_delete\_automated\_backups) | (optional) Specifies whether to remove automated backups immediately after the DB cluster is deleted. Default is true. | `string` | `true` | no | +| [deletion\_protection](#input\_deletion\_protection) | Whether to enable deletion protection for the DB cluster. | `bool` | `false` | no | +| [enable\_multi\_az](#input\_enable\_multi\_az) | Whether to enable Multi-AZ deployment for the RDS instance. | `bool` | `false` | no | +| [enabled\_cloudwatch\_logs\_exports](#input\_enabled\_cloudwatch\_logs\_exports) | List of log types to export to CloudWatch Logs. Valid values: audit, error, general, slowquery. | `list(string)` | `[]` | no | +| [engine](#input\_engine) | The database engine to use for the RDS cluster (e.g., aurora, aurora-mysql, aurora-postgresql). | `string` | n/a | yes | +| [engine\_lifecycle\_support](#input\_engine\_lifecycle\_support) | (optional) The life cycle type for this DB instance. This setting is valid for cluster types Aurora DB clusters and Multi-AZ DB clusters. Valid values are open-source-rds-extended-support, open-source-rds-extended-support-disabled. Default value is open-source-rds-extended-support | `string` | `"open-source-rds-extended-support"` | no | +| [engine\_mode](#input\_engine\_mode) | (optional) Database engine mode. Valid values: global (only valid for Aurora MySQL 1.21 and earlier), parallelquery, provisioned, serverless. Defaults to: provisioned
name = string
create = optional(bool, false)
description = optional(string, null)
subnet_ids = optional(list(string), [])
})
[| no | -| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
"default"
]
list(object({| `[]` | no | -| [rds\_instance\_db\_parameter](#input\_rds\_instance\_db\_parameter) | A list of DB parameters to apply. Note that parameters may differ from a DB family to another |
db_security_group_memberships = list(string)
option_name = string
port = number
version = string
vpc_security_group_memberships = list(string)
option_settings = list(object({
name = string
value = string
}))
}))
list(object({| `[]` | no | -| [rds\_instance\_db\_parameter\_group](#input\_rds\_instance\_db\_parameter\_group) | The DB parameter group family name. The value depends on DB engine used. See [DBParameterGroupFamily](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBParameterGroup.html#API_CreateDBParameterGroup_RequestParameters) for instructions on how to retrieve applicable value | `string` | `"postgres16"` | no | -| [rds\_instance\_db\_parameter\_group\_name](#input\_rds\_instance\_db\_parameter\_group\_name) | Name of the DB parameter group to associate. | `string` | `""` | no | -| [rds\_instance\_dns\_zone\_id](#input\_rds\_instance\_dns\_zone\_id) | The ID of the DNS Zone in Route53 where a new DNS record will be created for the DB host name | `string` | `""` | no | -| [rds\_instance\_enabled](#input\_rds\_instance\_enabled) | Enable creation of an RDS instance | `bool` | `false` | no | -| [rds\_instance\_engine](#input\_rds\_instance\_engine) | Database engine type. Required unless a snapshot\_identifier or replicate\_source\_db is provided. For supported values, see the Engine parameter in API action CreateDBInstance. | `string` | `"sqlserver-*"` | no | -| [rds\_instance\_engine\_version](#input\_rds\_instance\_engine\_version) | Database engine version, depends on engine type. Required unless a snapshot\_identifier or replicate\_source\_db is provided. | `string` | `"16.2"` | no | -| [rds\_instance\_host\_name](#input\_rds\_instance\_host\_name) | The DB host name created in Route53 | `string` | `"db"` | no | -| [rds\_instance\_instance\_class](#input\_rds\_instance\_instance\_class) | Class of RDS instance | `string` | `"db.t3.medium"` | no | -| [rds\_instance\_iops](#input\_rds\_instance\_iops) | RDS instance IOPS | `number` | `0` | no | -| [rds\_instance\_license\_model](#input\_rds\_instance\_license\_model) | License model for this DB. Optional, but required for some DB Engines. Valid values: license-included \| bring-your-own-license \| general-public-license | `string` | `""` | no | -| [rds\_instance\_maintenance\_window](#input\_rds\_instance\_maintenance\_window) | The window to perform maintenance in. Syntax: 'ddd:hh24:mi-ddd:hh24:mi' UTC | `string` | `"Mon:03:00-Mon:04:00"` | no | -| [rds\_instance\_major\_engine\_version](#input\_rds\_instance\_major\_engine\_version) | major\_engine\_version Database MAJOR engine version, depends on engine type | `string` | `"16"` | no | -| [rds\_instance\_multi\_az](#input\_rds\_instance\_multi\_az) | Set to true if multi AZ deployment must be supported | `bool` | `false` | no | -| [rds\_instance\_name](#input\_rds\_instance\_name) | RDS Instance name | `string` | `""` | no | -| [rds\_instance\_name\_override](#input\_rds\_instance\_name\_override) | If `true`, this will set a the RDS Instance name to what is defined in var.rds\_instance\_name.
apply_method = string
name = string
value = string
}))
object({|
create = string
update = string
delete = string
})
{| no | -| [vpc\_id](#input\_vpc\_id) | vpc\_id for the VPC to run the cluster. | `string` | n/a | yes | -| [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | Additional security group IDs to apply to the cluster, in addition to the provisioned default security group with ingress traffic from existing CIDR blocks and existing security groups | `list(string)` | `[]` | no | +| [final\_snapshot\_identifier](#input\_final\_snapshot\_identifier) | (optional) Name of your final DB snapshot when this DB cluster is deleted. If omitted, no final snapshot will be made. | `string` | `null` | no | +| [iam\_database\_authentication\_enabled](#input\_iam\_database\_authentication\_enabled) | Enable IAM database authentication for the RDS cluster. | `bool` | `false` | no | +| [iops](#input\_iops) | The amount of provisioned IOPS. Required if using io1 storage type. | `number` | `0` | no | +| [kms\_data](#input\_kms\_data) | Configuration for KMS key settings for RDS encryption and performance insights:
"create": "40m",
"delete": "60m",
"update": "80m"
}
object({|
create = optional(bool, true)
kms_key_id = optional(string, null)
performance_insights_kms_key_id = optional(string, null)
name = optional(string, null)
description = optional(string, null)
policy = optional(string, null)
deletion_window_in_days = optional(number, 7)
enable_key_rotation = optional(bool, true)
})
{| no | +| [license\_model](#input\_license\_model) | The license model for the DB instance (e.g., license-included, bring-your-own-license, general-public-license). | `string` | n/a | yes | +| [manage\_user\_password](#input\_manage\_user\_password) | (optional) Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if master\_password is provided."
"create": false
}
object({|
create = optional(bool, false)
name = optional(string, null)
engine_name = optional(string)
major_engine_version = optional(string)
description = optional(string, "Managed by Terraform")
options = map(object({
option_name = string
port = number
version = string
option_settings = map(object({
name = string
value = string
}))
}))
})
{| no | +| [parameter\_group\_config](#input\_parameter\_group\_config) | Configuration for RDS parameter group, with options to create or specify a group name, family, and a map of database parameters including settings and apply methods. |
"name": null,
"options": {}
}
object({|
create = optional(bool, false)
name = optional(string, null)
family = optional(string)
description = optional(string, "Managed by Terraform")
parameters = map(object({
name = string
value = string
apply_method = optional(string, "immediate") # Options: "immediate" or "pending-reboot"
}))
})
{| no | +| [password](#input\_password) | The password for the database. | `string` | `null` | no | +| [performance\_insights\_enabled](#input\_performance\_insights\_enabled) | (optional) Valid only for Non-Aurora Multi-AZ DB Clusters. Enables Performance Insights for the RDS Cluster | `bool` | `false` | no | +| [performance\_insights\_retention\_period](#input\_performance\_insights\_retention\_period) | The retention period (in days) for Performance Insights data. Valid values are 7, 731, or any value between 8 and 730. | `number` | `7` | no | +| [port](#input\_port) | Port on which the DB accepts connections | `number` | n/a | yes | +| [preferred\_backup\_window](#input\_preferred\_backup\_window) | The daily time range during which backups are taken. | `string` | `"07:00-09:00"` | no | +| [preferred\_maintenance\_window](#input\_preferred\_maintenance\_window) | The weekly time range during which maintenance can occur. | `string` | `"sun:06:00-sun:07:00"` | no | +| [proxy\_config](#input\_proxy\_config) | Configuration object for setting up an AWS RDS Proxy. It includes options for creating the proxy, connection pooling, authentication, and other proxy-specific settings.
"name": null,
"parameters": {}
}
object({|
create = optional(bool, false)
name = optional(string, null)
engine_family = string
vpc_subnet_ids = list(string)
require_tls = optional(bool, false)
debug_logging = optional(bool, false)
idle_client_timeout_secs = optional(number, 30 * 60) // in seconds The minimum is 1 minute and the maximum is 8 hours.
role_arn = optional(string, null) // null value will create new role
auth = object({
auth_scheme = string
description = optional(string, null)
iam_auth = optional(string, "DISABLED")
client_password_auth_type = string
})
additional_auth_list = optional(list(object({
auth_scheme = string
secret_arn = optional(string, null)
description = optional(string, null)
iam_auth = optional(string, "DISABLED")
client_password_auth_type = string
})), [])
connection_pool_config = object({
connection_borrow_timeout = optional(number, 5)
init_query = optional(string, null)
max_connections_percent = optional(number, 100)
max_idle_connections_percent = optional(number, 50)
session_pinning_filters = optional(list(string), [])
})
security_group_data = optional(object({
security_group_ids_to_attach = optional(list(string), [])
create = optional(bool, true)
description = optional(string, null)
ingress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
source_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
self = optional(bool, false)
})), [])
egress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
destination_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
})), [])
}))
})
{| no | +| [publicly\_accessible](#input\_publicly\_accessible) | Whether the RDS instance should be publicly accessible. | `bool` | `false` | no | +| [rds\_cluster\_instances](#input\_rds\_cluster\_instances) | "(optional) A list of objects defining configurations for RDS Cluster instances. Each object represents a single RDS instance configuration within the cluster, including options for instance class, monitoring, performance insights, maintenance windows, and other instance-specific settings."
"auth": null,
"connection_pool_config": null,
"create": false,
"engine_family": "POSTGRESQL",
"security_group_data": {
"create": false
},
"vpc_subnet_ids": []
}
list(object({| `[]` | no | +| [security\_group\_data](#input\_security\_group\_data) | (optional) Security Group data |
name = optional(string, null)
instance_class = string
availability_zone = optional(string, null)
publicly_accessible = optional(bool, false)
db_parameter_group_name = optional(string, null)
promotion_tier = optional(number, 0)
copy_tags_to_snapshot = optional(bool, true)
}))
object({|
security_group_ids_to_attach = optional(list(string), [])
create = optional(bool, true)
description = optional(string, null)
ingress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
source_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
})), [])
egress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
destination_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
})), [])
})
{| no | +| [serverlessv2\_scaling\_config](#input\_serverlessv2\_scaling\_config) | Configuration for Serverless V2 scaling:
"create": false
}
object({|
max_capacity = number
min_capacity = number
})
{| no | +| [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | (optional) Determines whether a final DB snapshot is created before the DB cluster is deleted. If true is specified, no DB snapshot is created. If false is specified, a DB snapshot is created before the DB cluster is deleted, using the value from final\_snapshot\_identifier. Default is false. | `string` | `true` | no | +| [storage\_encrypted](#input\_storage\_encrypted) | Whether to enable storage encryption. | `bool` | `true` | no | +| [storage\_type](#input\_storage\_type) | (optional) Required for Multi-AZ DB cluster) (Forces new for Multi-AZ DB clusters) Specifies the storage type to be associated with the DB cluster. For Aurora DB clusters, storage\_type modifications can be done in-place. For Multi-AZ DB Clusters, the iops argument must also be set. Valid values are: "", aurora-iopt1 (Aurora DB Clusters); io1, io2 (Multi-AZ DB Clusters). Default: "" (Aurora DB Clusters); io1 (Multi-AZ DB Clusters). | `string` | `""` | no | +| [tags](#input\_tags) | A map of tags to assign to the DB Cluster. | `map(string)` | `{}` | no | +| [username](#input\_username) | The username for the database. | `string` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC Id for creating security group | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| [aurora\_arn](#output\_aurora\_arn) | Amazon Resource Name (ARN) of cluster | -| [aurora\_cluster\_identifier](#output\_aurora\_cluster\_identifier) | Cluster Identifier | -| [aurora\_endpoint](#output\_aurora\_endpoint) | The DNS address of the RDS instance | -| [aurora\_master\_host](#output\_aurora\_master\_host) | DB Master hostname | -| [aurora\_master\_username](#output\_aurora\_master\_username) | Username for the master DB user | -| [aurora\_name](#output\_aurora\_name) | Database name | -| [aurora\_reader\_endpoint](#output\_aurora\_reader\_endpoint) | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas | -| [aurora\_replicas\_host](#output\_aurora\_replicas\_host) | Replicas hostname | -| [rds\_instance\_arn](#output\_rds\_instance\_arn) | The RDS Instance AWS ARN. | -| [rds\_instance\_endpoint](#output\_rds\_instance\_endpoint) | The DNS address to the RDS Instance. | -| [rds\_instance\_hostname](#output\_rds\_instance\_hostname) | Hostname of the RDS Instance. | -| [rds\_instance\_id](#output\_rds\_instance\_id) | The RDS Instance AWS ID. | -| [rds\_instance\_kms\_arn](#output\_rds\_instance\_kms\_arn) | RDS KMS Key ARN | -| [rds\_instance\_kms\_id](#output\_rds\_instance\_kms\_id) | Output RDS KMS Key ID if the var.rds\_kms\_key\_arn\_override is "" | -| [rds\_instance\_resource\_id](#output\_rds\_instance\_resource\_id) | The RDS Instance AWS resource ID. | +| [arn](#output\_arn) | Instance or Cluster ARN | +| [database](#output\_database) | database name | +| [endpoint](#output\_endpoint) | Instance or Cluster Endpoint | +| [id](#output\_id) | Instance or Cluster ID | +| [identifier](#output\_identifier) | Instance or Cluster Identifier | +| [kms\_key\_id](#output\_kms\_key\_id) | Instance or Cluster KM Key ID | +| [monitoring\_role\_arn](#output\_monitoring\_role\_arn) | Instance or Cluster Monitoring role arn | +| [performance\_insights\_kms\_key\_id](#output\_performance\_insights\_kms\_key\_id) | Instance or Cluster Performance insight KM Key ID | +| [port](#output\_port) | Dtabase server port | +| [username](#output\_username) | Username for the Database | ## Development diff --git a/aurora-cluster.tf b/aurora-cluster.tf new file mode 100644 index 0000000..7f598f8 --- /dev/null +++ b/aurora-cluster.tf @@ -0,0 +1,101 @@ +resource "random_password" "master" { + count = var.password == null && var.manage_user_password == null ? 1 : 0 + + length = 41 + special = true + override_special = "!#*^" + + lifecycle { + ignore_changes = [ + length, + lower, + min_lower, + min_numeric, + min_special, + min_upper, + override_special, + special, + upper + ] + } +} + +resource "aws_rds_cluster" "this" { + count = var.engine_type == "cluster" ? 1 : 0 + + cluster_identifier = var.name + engine = var.engine + engine_version = var.engine_version + engine_mode = var.engine_mode == "serverless" ? "provisioned" : var.engine_mode + port = var.port + master_username = var.username + master_password = var.password == null && var.manage_user_password == null ? random_password.master[0].result : var.password + manage_master_user_password = var.manage_user_password + database_name = var.database_name + db_cluster_instance_class = strcontains(var.engine, "aurora") ? null : var.db_server_class + vpc_security_group_ids = local.security_group_ids_to_attach + db_subnet_group_name = var.db_subnet_group_data.name + db_cluster_parameter_group_name = var.db_cluster_parameter_group_name + db_instance_parameter_group_name = var.db_instance_parameter_group_name + allocated_storage = strcontains(var.engine, "aurora") ? null : var.allocated_storage + backup_retention_period = var.backup_retention_period + preferred_backup_window = var.preferred_backup_window + preferred_maintenance_window = var.preferred_maintenance_window + storage_encrypted = var.storage_encrypted + iam_database_authentication_enabled = var.iam_database_authentication_enabled + storage_type = var.storage_type + ca_certificate_identifier = var.ca_certificate_identifier + kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.kms_key_id) + performance_insights_enabled = var.performance_insights_enabled + performance_insights_kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.performance_insights_kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.performance_insights_kms_key_id) + deletion_protection = var.deletion_protection + delete_automated_backups = var.delete_automated_backups + skip_final_snapshot = var.skip_final_snapshot + final_snapshot_identifier = var.final_snapshot_identifier + copy_tags_to_snapshot = var.copy_tags_to_snapshot + engine_lifecycle_support = var.engine_lifecycle_support + network_type = var.network_type + + + dynamic "serverlessv2_scaling_configuration" { + for_each = var.engine_mode == "serverless" ? [var.serverlessv2_scaling_config] : [] // Note :- For Serverless V2 , engine_mode should be "provisioned" but for simplecity "serverless" is expected + // Refer : serverless + + content { + max_capacity = serverlessv2_scaling_configuration.value.max_capacity + min_capacity = serverlessv2_scaling_configuration.value.max_capacity + } + + } + + tags = var.tags + depends_on = [aws_db_subnet_group.this, module.security_group] +} + +resource "aws_rds_cluster_instance" "this" { + for_each = { for idx, instance in var.rds_cluster_instances : idx => instance } + + cluster_identifier = aws_rds_cluster.this[0].id + identifier = each.value.name != null ? each.value.name : "${aws_rds_cluster.this[0].id}-${each.key + 1}" + instance_class = each.value.instance_class + + engine = aws_rds_cluster.this[0].engine + engine_version = aws_rds_cluster.this[0].engine_version + db_subnet_group_name = aws_rds_cluster.this[0].db_subnet_group_name + availability_zone = each.value.availability_zone + publicly_accessible = each.value.publicly_accessible + db_parameter_group_name = each.value.db_parameter_group_name + apply_immediately = var.apply_immediately + preferred_maintenance_window = var.preferred_maintenance_window + auto_minor_version_upgrade = var.auto_minor_version_upgrade + ca_cert_identifier = var.ca_cert_identifier + monitoring_interval = var.monitoring_interval + monitoring_role_arn = var.monitoring_interval > 0 ? (var.monitoring_role_arn == null ? aws_iam_role.enhanced_monitoring[0].arn : var.monitoring_role_arn) : null + performance_insights_enabled = var.performance_insights_enabled + performance_insights_kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.performance_insights_kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.performance_insights_kms_key_id) + performance_insights_retention_period = var.performance_insights_retention_period + promotion_tier = each.value.promotion_tier + copy_tags_to_snapshot = each.value.copy_tags_to_snapshot + + tags = var.tags +} diff --git a/common.tf b/common.tf new file mode 100644 index 0000000..d0db22f --- /dev/null +++ b/common.tf @@ -0,0 +1,177 @@ + + +resource "aws_db_subnet_group" "this" { + count = var.db_subnet_group_data.create ? 1 : 0 + + name = var.db_subnet_group_data.name + description = var.db_subnet_group_data.description + subnet_ids = var.db_subnet_group_data.subnet_ids + + tags = var.tags +} + +resource "aws_db_option_group" "this" { + count = var.option_group_config.create ? 1 : 0 + + name = var.option_group_config.name + engine_name = var.option_group_config.engine_name + major_engine_version = var.option_group_config.major_engine_version + option_group_description = var.option_group_config.description + + dynamic "option" { + for_each = var.option_group_config.options + content { + option_name = option.value.option_name + port = option.value.port + version = option.value.version + + dynamic "option_settings" { + for_each = option.value.option_settings + content { + name = option_settings.value.name + value = option_settings.value.value + } + } + } + } + + tags = var.tags +} + +resource "aws_db_parameter_group" "this" { + count = var.parameter_group_config.create ? 1 : 0 + + name = var.parameter_group_config.name + family = var.parameter_group_config.family + description = var.parameter_group_config.description + + dynamic "parameter" { + for_each = var.parameter_group_config.parameters + content { + name = parameter.value.name + value = parameter.value.value + apply_method = parameter.value.apply_method + } + } + + tags = var.tags +} + +################################################################################ +## KMS +################################################################################ + +resource "aws_kms_key" "this" { + count = var.kms_data.create ? 1 : 0 + + description = var.kms_data.description == null ? "RDS KMS key" : var.kms_data.description + deletion_window_in_days = var.kms_data.deletion_window_in_days + enable_key_rotation = var.kms_data.enable_key_rotation + + tags = merge(var.tags, { + Name = var.kms_data.name == null ? "${local.prefix}-${var.name}-kms-key" : var.kms_data.name + }) +} + +resource "aws_kms_alias" "this" { + count = var.kms_data.create ? 1 : 0 + + name = var.kms_data.name == null ? "alias/${local.prefix}-${var.name}-kms-key" : "alias/${var.kms_data.name}" + target_key_id = aws_kms_key.this[0].id +} + +################################################################################ +## IAM - create IAM role for monitoring +################################################################################ +resource "aws_iam_role" "enhanced_monitoring" { + count = var.monitoring_interval > 0 && var.monitoring_role_arn == null ? 1 : 0 + name = "${local.prefix}-${var.name}-enhanced-monitoring-role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "" + Principal = { + Service = "monitoring.rds.amazonaws.com" + } + }, + ] + }) + + tags = var.tags +} + +resource "aws_iam_policy" "logs" { + count = var.monitoring_interval > 0 && var.monitoring_role_arn == null ? 1 : 0 + + name = "${local.prefix}-${var.name}-policy" + description = "Policy for RDS Enhanced Monitoring" + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:CreateLogGroup", + ], + Resource = [ + "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/rds/instance/*:log-stream:*", + "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/rds/cluster/*:log-stream:*" + ] + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "attach_policy" { + count = var.monitoring_interval > 0 && var.monitoring_role_arn == null ? 1 : 0 + + role = aws_iam_role.enhanced_monitoring[0].name + policy_arn = aws_iam_policy.logs[0].arn +} + +data "aws_iam_policy" "enhanced_monitoring" { + count = var.monitoring_interval > 0 && var.monitoring_role_arn == null ? 1 : 0 + arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" +} + +resource "aws_iam_role_policy_attachment" "enhanced_monitoring" { + count = var.monitoring_interval > 0 && var.monitoring_role_arn == null ? 1 : 0 + + role = aws_iam_role.enhanced_monitoring[0].name + policy_arn = data.aws_iam_policy.enhanced_monitoring[0].arn +} + + +resource "aws_ssm_parameter" "database_creds" { + name = "/${var.namespace}/${var.environment}/${var.engine_type}/${var.name}/database-credentials" + description = "Database credentials" + type = "SecureString" + value = jsonencode({ + "username" : local.username + "password" : local.password + "database" : local.database + "endpoint" : local.endpoint + "port" : local.port + }) + + tags = var.tags +} + +module "security_group" { + source = "./modules/security-group" + + count = var.security_group_data.create ? 1 : 0 + + name = "${var.name}-security-group" + description = var.security_group_data.description == null ? "Allow inbound traffic and outbound traffic" : var.security_group_data.description + vpc_id = var.vpc_id + egress_rules = var.security_group_data.egress_rules + ingress_rules = local.db_ingress_rules + tags = var.tags +} diff --git a/context.tf b/context.tf deleted file mode 100644 index 841d622..0000000 --- a/context.tf +++ /dev/null @@ -1,277 +0,0 @@ -# -# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label -# All other instances of this file should be a copy of that one -# -# -# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf -# and then place it in your Terraform module to automatically get -# Cloud Posse's standard configuration inputs suitable for passing -# to Cloud Posse modules. -# -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/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 = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 - - enabled = var.enabled - namespace = var.namespace - tenant = var.tenant - environment = var.environment - stage = var.stage - 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 cloudposse/terraform-null-label/variables.tf here - -variable "context" { - type = any - default = { - enabled = true - namespace = null - tenant = null - environment = null - stage = null - name = 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 "namespace" { - type = string - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = "" - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" -} - -variable "environment" { - type = string - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "stage" { - type = string - default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" -} - -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 -} - -#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/data.tf b/data.tf new file mode 100644 index 0000000..a189edd --- /dev/null +++ b/data.tf @@ -0,0 +1,7 @@ +data "aws_kms_alias" "rds" { + name = "alias/aws/rds" +} + +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} diff --git a/docs/example/README.md b/docs/example/README.md deleted file mode 100644 index 49701be..0000000 --- a/docs/example/README.md +++ /dev/null @@ -1,83 +0,0 @@ - -## Requirements - -| Name | Version | -|------|---------| -| [null](#requirement\_null) | 3.1.0 | - -## Providers - -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | 3.59.0 | -| [random](#provider\_random) | 3.1.0 | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [rds\_cluster\_aurora\_postgres](#module\_rds\_cluster\_aurora\_postgres) | git::https://github.com/cloudposse/terraform-aws-rds-cluster.git | 0.46.2 | -| [this](#module\_this) | cloudposse/label/null | 0.25.0 | - -## Resources - -| Name | Type | -|------|------| -| [aws_iam_role.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_kms_alias.aurora_cluster_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | -| [aws_kms_key.aurora_cluster_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | -| [aws_ssm_parameter.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | -| [random_password.db_admin_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [aws_iam_policy_document.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | 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`.
"max_capacity": 1,
"min_capacity": 0.5
}
{| no | -| [db\_admin\_username](#input\_db\_admin\_username) | Name of the default DB admin user role | `string` | n/a | yes | -| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
"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"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
}
[| no | -| [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
"default"
]
list(object({| `[]` | no | -| [additional\_ingress\_rules\_rds](#input\_additional\_ingress\_rules\_rds) | Additional ingress rules for RDS |
name = string
description = string
type = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
list(object({| `[]` | no | -| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `"poc"` | no | -| [kms\_alias\_name](#input\_kms\_alias\_name) | Name of the KMS alias | `string` | `"alias/arc-poc-aurora-cluster-kms-key"` | no | -| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `"arc"` | no | -| [region](#input\_region) | AWS region | `string` | `"us-east-1"` | no | - -## Outputs - -No outputs. - diff --git a/example/main.tf b/example/main.tf deleted file mode 100644 index 7671db7..0000000 --- a/example/main.tf +++ /dev/null @@ -1,125 +0,0 @@ -################################################################################ -## defaults -################################################################################ -terraform { - required_version = "~> 1.3, < 2.0.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 4.0, < 6.0" - } - } -} - -provider "aws" { - region = var.region -} - -################################################################################ -## lookups -################################################################################ -data "aws_caller_identity" "this" {} - -################################################################################ -## db -################################################################################ -## aurora cluster -module "aurora" { - source = "../" - - environment = var.environment - namespace = var.namespace - region = var.region - vpc_id = data.aws_vpc.vpc.id - - aurora_cluster_enabled = true - aurora_cluster_name = "aurora-example" - enhanced_monitoring_name = "aurora-example-enhanced-monitoring" - aurora_db_admin_username = "example_db_admin" - aurora_db_name = "example" - aurora_allow_major_version_upgrade = true - aurora_auto_minor_version_upgrade = true - aurora_cluster_size = 1 - aurora_instance_type = "db.t3.medium" - aurora_subnets = data.aws_subnets.private.ids - aurora_security_groups = data.aws_security_groups.db_sg.ids - aurora_allowed_cidr_blocks = [data.aws_vpc.vpc.cidr_block] - performance_insights_enabled = true - performance_insights_retention_period = 7 - performance_insights_kms_key_id = data.aws_kms_alias.aurora_cluster_kms_arn.target_key_arn - kms_key_arn = data.aws_kms_alias.aurora_cluster_kms_arn.target_key_arn - iam_database_authentication_enabled = true - additional_ingress_rules_aurora = var.additional_ingress_rules_aurora -} - -## sql server rds instance -module "rds_sql_server" { - source = "../" - - environment = var.environment - namespace = var.namespace - region = var.region - vpc_id = data.aws_vpc.vpc.id - - account_id = data.aws_caller_identity.this.id - rds_instance_enabled = true - rds_instance_name = "sql-server-example" - enhanced_monitoring_name = "sql-server-example-enhanced-monitoring" - rds_instance_dns_zone_id = "" - rds_instance_host_name = "" - rds_instance_database_name = null // sql server database name must be null - rds_instance_database_user = "example_db_admin" - rds_instance_database_port = 1433 - rds_instance_engine = "sqlserver-ex" // express edition. - rds_instance_engine_version = "16.00.4105.2.v1" - rds_instance_major_engine_version = "16.00" - rds_instance_db_parameter_group = "sqlserver-ex-16.0" - rds_instance_db_parameter = [] - rds_instance_db_options = [] - rds_enable_custom_option_group = true - rds_instance_ca_cert_identifier = "rds-ca-2019" - rds_instance_publicly_accessible = false - rds_instance_multi_az = false - rds_instance_storage_type = "gp3" - rds_instance_instance_class = "db.t3.small" - rds_instance_allocated_storage = 400 - rds_instance_storage_encrypted = false // sql server express doesn't support encryption at rest - rds_instance_snapshot_identifier = null - rds_instance_auto_minor_version_upgrade = true - rds_instance_allow_major_version_upgrade = true - rds_instance_apply_immediately = true - rds_instance_maintenance_window = "Mon:00:00-Mon:02:00" - rds_instance_skip_final_snapshot = true - rds_instance_copy_tags_to_snapshot = true - rds_instance_backup_retention_period = 3 - rds_instance_backup_window = "22:00-23:59" - rds_instance_security_group_ids = data.aws_security_groups.db_sg.ids - rds_instance_allowed_cidr_blocks = [data.aws_vpc.vpc.cidr_block] - rds_instance_subnet_ids = data.aws_subnets.private.ids - additional_ingress_rules_rds = var.additional_ingress_rules_rds -} - -## postgresql rds instance -module "rds_postgresql" { - source = "../" - - environment = var.environment - namespace = var.namespace - region = var.region - vpc_id = data.aws_vpc.vpc.id - - account_id = data.aws_caller_identity.this.id - rds_instance_enabled = true - rds_instance_name = "postgresql-example" - performance_insights_enabled = true - enhanced_monitoring_name = "postgresql-example-enhanced-monitoring" - enhanced_monitoring_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" - rds_instance_database_name = "arc" - rds_instance_database_user = "example_db_admin" - - rds_instance_security_group_ids = data.aws_security_groups.db_sg.ids - rds_instance_allowed_cidr_blocks = [data.aws_vpc.vpc.cidr_block] - rds_instance_subnet_ids = data.aws_subnets.private.ids - additional_ingress_rules_rds = var.additional_ingress_rules_rds -} diff --git a/example/variables.tf b/example/variables.tf deleted file mode 100644 index a76895f..0000000 --- a/example/variables.tf +++ /dev/null @@ -1,54 +0,0 @@ -################################################################################ -## shared -################################################################################ -variable "region" { - type = string - default = "us-east-1" - description = "AWS region" -} - -variable "environment" { - type = string - default = "poc" - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "namespace" { - type = string - default = "arc" - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "kms_alias_name" { - type = string - description = "Name of the KMS alias" - default = "alias/arc-poc-aurora-cluster-kms-key" -} - -variable "additional_ingress_rules_aurora" { - description = "Additional ingress rules for Aurora" - type = list(object({ - name = string - description = string - type = string - from_port = number - to_port = number - protocol = string - cidr_blocks = list(string) - })) - default = [] -} - -variable "additional_ingress_rules_rds" { - description = "Additional ingress rules for RDS" - type = list(object({ - name = string - description = string - type = string - from_port = number - to_port = number - protocol = string - cidr_blocks = list(string) - })) - default = [] -} diff --git a/example/.terraform-version b/examples/aurora-serverless/.terraform-version similarity index 100% rename from example/.terraform-version rename to examples/aurora-serverless/.terraform-version diff --git a/examples/aurora-serverless/.terraform.lock.hcl b/examples/aurora-serverless/.terraform.lock.hcl new file mode 100644 index 0000000..30c9869 --- /dev/null +++ b/examples/aurora-serverless/.terraform.lock.hcl @@ -0,0 +1,65 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.74.0" + constraints = ">= 4.0.0, ~> 5.0, < 6.0.0" + hashes = [ + "h1:0Iq3x8RSdWedvATBO1RZbCQqRCHPNsdhkYVrRs9crEE=", + "zh:1e2d65add4d63af5b396ae33d55c48303eca6c86bd1be0f6fae13267a9b47bc4", + "zh:20ddec3dac3d06a188f12e58b6428854949b1295e937c5d4dca4866dc1c937af", + "zh:35b72de4e6a3e3d69efc07184fb413406262fe447b2d82d57eaf8c787a068a06", + "zh:44eada24a50cd869aadc4b29f9e791fdf262d7f426921e9ac2893bbb86013176", + "zh:455e666e3a9a2312b3b9f434b87a404b6515d64a8853751e20566a6548f9df9e", + "zh:58b3ae74abfca7b9b61f42f0c8b10d97f9b01aff18bd1d4ab091129c9d203707", + "zh:840a8a32d5923f9e7422f9c80d165c3f89bb6ea370b8283095081e39050a8ea8", + "zh:87cb6dbbdbc1b73bdde4b8b5d6d780914a3e8f1df0385da4ea7323dc1a68468f", + "zh:8b8953e39b0e6e6156c5570d1ca653450bfa0d9b280e2475f01ee5c51a6554db", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9bd750262e2fb0187a8420a561e55b0a1da738f690f53f5c7df170cb1f380459", + "zh:9d2474c1432dfa5e1db197e2dd6cd61a6a15452e0bc7acd09ca86b3cdb228871", + "zh:b763ecaf471c7737a5c6e4cf257b5318e922a6610fd83b36ed8eb68582a8642e", + "zh:c1344cd8fe03ff7433a19b14b14a1898c2ca5ba22a468fb8e1687f0a7f564d52", + "zh:dc0e0abf3be7402d0d022ced82816884356115ed27646df9c7222609e96840e6", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.3" + constraints = ">= 3.1.0" + hashes = [ + "h1:I0Um8UkrMUb81Fxq/dxbr3HLP2cecTH2WMJiwKSrwQY=", + "zh:22d062e5278d872fe7aed834f5577ba0a5afe34a3bdac2b81f828d8d3e6706d2", + "zh:23dead00493ad863729495dc212fd6c29b8293e707b055ce5ba21ee453ce552d", + "zh:28299accf21763ca1ca144d8f660688d7c2ad0b105b7202554ca60b02a3856d3", + "zh:55c9e8a9ac25a7652df8c51a8a9a422bd67d784061b1de2dc9fe6c3cb4e77f2f", + "zh:756586535d11698a216291c06b9ed8a5cc6a4ec43eee1ee09ecd5c6a9e297ac1", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9d5eea62fdb587eeb96a8c4d782459f4e6b73baeece4d04b4a40e44faaee9301", + "zh:a6355f596a3fb8fc85c2fb054ab14e722991533f87f928e7169a486462c74670", + "zh:b5a65a789cff4ada58a5baffc76cb9767dc26ec6b45c00d2ec8b1b027f6db4ed", + "zh:db5ab669cf11d0e9f81dc380a6fdfcac437aea3d69109c7aef1a5426639d2d65", + "zh:de655d251c470197bcbb5ac45d289595295acb8f829f6c781d4a75c8c8b7c7dd", + "zh:f5c68199f2e6076bce92a12230434782bf768103a427e9bb9abee99b116af7b5", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.3" + constraints = ">= 3.4.0" + hashes = [ + "h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=", + "zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451", + "zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8", + "zh:4b4c11ccfba7319e901df2dac836b1ae8f12185e37249e8d870ee10bb87a13fe", + "zh:4fa45c44c0de582c2edb8a2e054f55124520c16a39b2dfc0355929063b6395b1", + "zh:588508280501a06259e023b0695f6a18149a3816d259655c424d068982cbdd36", + "zh:737c4d99a87d2a4d1ac0a54a73d2cb62974ccb2edbd234f333abd079a32ebc9e", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:a357ab512e5ebc6d1fda1382503109766e21bbfdfaa9ccda43d313c122069b30", + "zh:c51bfb15e7d52cc1a2eaec2a903ac2aff15d162c172b1b4c17675190e8147615", + "zh:e0951ee6fa9df90433728b96381fb867e3db98f66f735e0c3e24f8f16903f0ad", + "zh:e3cdcb4e73740621dabd82ee6a37d6cfce7fee2a03d8074df65086760f5cf556", + "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", + ] +} diff --git a/examples/aurora-serverless/README.md b/examples/aurora-serverless/README.md new file mode 100644 index 0000000..67f97d8 --- /dev/null +++ b/examples/aurora-serverless/README.md @@ -0,0 +1,50 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.3, < 2.0.0 | +| [aws](#requirement\_aws) | >= 4.0, < 6.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.74.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [aurora](#module\_aurora) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_subnets.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | +| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `"poc"` | no | +| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `"arc"` | no | +| [region](#input\_region) | AWS region | `string` | `"us-east-1"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | Instance or Cluster ARN | +| [database](#output\_database) | Database name | +| [endpoint](#output\_endpoint) | Instance or Cluster Endpoint | +| [id](#output\_id) | Instance or Cluster ID | +| [identifier](#output\_identifier) | Instance or Cluster Identifier | +| [kms\_key\_id](#output\_kms\_key\_id) | Instance or Cluster KMS Key ID | +| [monitoring\_role\_arn](#output\_monitoring\_role\_arn) | Instance or Cluster Monitoring Role ARN | +| [performance\_insights\_kms\_key\_id](#output\_performance\_insights\_kms\_key\_id) | Instance or Cluster Performance Insights KMS Key ID | +| [port](#output\_port) | Database server port | +| [username](#output\_username) | Username for the Database | + diff --git a/example/data.tf b/examples/aurora-serverless/data.tf similarity index 51% rename from example/data.tf rename to examples/aurora-serverless/data.tf index 7e5ae7c..4fca06e 100644 --- a/example/data.tf +++ b/examples/aurora-serverless/data.tf @@ -11,28 +11,14 @@ data "aws_vpc" "vpc" { ## network data "aws_subnets" "private" { + filter { + name = "vpc-id" + values = [data.aws_vpc.vpc.id] + } filter { name = "tag:Name" values = [ - "${var.namespace}-${var.environment}-private-subnet-private-${var.region}a", - "${var.namespace}-${var.environment}-private-subnet-private-${var.region}b" + "*private*" ] } } - -## security -data "aws_security_groups" "db_sg" { - filter { - name = "group-name" - values = ["example-${var.environment}-db-sg"] - } - - filter { - name = "vpc-id" - values = [data.aws_vpc.vpc.id] - } -} - -data "aws_kms_alias" "aurora_cluster_kms_arn" { - name = var.kms_alias_name -} diff --git a/examples/aurora-serverless/main.tf b/examples/aurora-serverless/main.tf new file mode 100644 index 0000000..b6f17db --- /dev/null +++ b/examples/aurora-serverless/main.tf @@ -0,0 +1,93 @@ +################################################################################ +## defaults +################################################################################ +terraform { + required_version = "~> 1.3, < 2.0.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0, < 6.0" + } + } +} + +provider "aws" { + region = var.region +} + +locals { + rds_security_group_data = { + create = true + description = "Security Group for RDS Cluster" + + ingress_rules = [ + { + description = "Allow traffic from local network" + cidr_block = data.aws_vpc.vpc.cidr_block + from_port = 5432 + ip_protocol = "tcp" + to_port = 5432 + } + ] + + egress_rules = [ + { + description = "Allow all outbound traffic" + cidr_block = "0.0.0.0/0" + from_port = -1 + ip_protocol = "-1" + to_port = -1 + } + ] + } + +} + +module "aurora" { + source = "../../" + + environment = var.environment + namespace = var.namespace + vpc_id = data.aws_vpc.vpc.id + + name = "${var.namespace}-${var.environment}-aurora-serverless" + engine_type = "cluster" + port = 5432 + username = "postgres" + engine = "aurora-postgresql" + engine_version = "16.2" + engine_mode = "serverless" + + license_model = "postgresql-license" + rds_cluster_instances = [ + { + instance_class = "db.serverless" + db_parameter_group_name = "default.aurora-postgresql16" + apply_immediately = true + promotion_tier = 1 + } + ] + + serverlessv2_scaling_config = { + max_capacity = 1.0 + min_capacity = 0.5 + } + + db_subnet_group_data = { + name = "${var.namespace}-${var.environment}-subnet-group" + create = true + description = "Subnet group for rds instance" + subnet_ids = data.aws_subnets.private.ids + } + + performance_insights_enabled = true + + kms_data = { + create = true + description = "KMS for Performance insight and storage" + deletion_window_in_days = 7 + enable_key_rotation = true + } + security_group_data = local.rds_security_group_data +} diff --git a/examples/aurora-serverless/output.tf b/examples/aurora-serverless/output.tf new file mode 100644 index 0000000..3e50a17 --- /dev/null +++ b/examples/aurora-serverless/output.tf @@ -0,0 +1,49 @@ +output "id" { + value = module.aurora.id + description = "Instance or Cluster ID" +} + +output "identifier" { + value = module.aurora.identifier + description = "Instance or Cluster Identifier" +} + +output "arn" { + value = module.aurora.arn + description = "Instance or Cluster ARN" +} + +output "username" { + value = module.aurora.username + description = "Username for the Database" +} + +output "database" { + value = module.aurora.database + description = "Database name" +} + +output "port" { + value = module.aurora.port + description = "Database server port" +} + +output "endpoint" { + value = module.aurora.endpoint + description = "Instance or Cluster Endpoint" +} + +output "kms_key_id" { + value = module.aurora.kms_key_id + description = "Instance or Cluster KMS Key ID" +} + +output "performance_insights_kms_key_id" { + value = module.aurora.performance_insights_kms_key_id + description = "Instance or Cluster Performance Insights KMS Key ID" +} + +output "monitoring_role_arn" { + value = module.aurora.monitoring_role_arn + description = "Instance or Cluster Monitoring Role ARN" +} diff --git a/examples/aurora-serverless/variables.tf b/examples/aurora-serverless/variables.tf new file mode 100644 index 0000000..8e65782 --- /dev/null +++ b/examples/aurora-serverless/variables.tf @@ -0,0 +1,20 @@ +################################################################################ +## shared +################################################################################ +variable "region" { + type = string + default = "us-east-1" + description = "AWS region" +} + +variable "environment" { + type = string + default = "poc" + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "namespace" { + type = string + default = "arc" + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} diff --git a/examples/aurora/.terraform-version b/examples/aurora/.terraform-version new file mode 100644 index 0000000..7324740 --- /dev/null +++ b/examples/aurora/.terraform-version @@ -0,0 +1 @@ +latest:^1.7 diff --git a/examples/aurora/.terraform.lock.hcl b/examples/aurora/.terraform.lock.hcl new file mode 100644 index 0000000..30c9869 --- /dev/null +++ b/examples/aurora/.terraform.lock.hcl @@ -0,0 +1,65 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.74.0" + constraints = ">= 4.0.0, ~> 5.0, < 6.0.0" + hashes = [ + "h1:0Iq3x8RSdWedvATBO1RZbCQqRCHPNsdhkYVrRs9crEE=", + "zh:1e2d65add4d63af5b396ae33d55c48303eca6c86bd1be0f6fae13267a9b47bc4", + "zh:20ddec3dac3d06a188f12e58b6428854949b1295e937c5d4dca4866dc1c937af", + "zh:35b72de4e6a3e3d69efc07184fb413406262fe447b2d82d57eaf8c787a068a06", + "zh:44eada24a50cd869aadc4b29f9e791fdf262d7f426921e9ac2893bbb86013176", + "zh:455e666e3a9a2312b3b9f434b87a404b6515d64a8853751e20566a6548f9df9e", + "zh:58b3ae74abfca7b9b61f42f0c8b10d97f9b01aff18bd1d4ab091129c9d203707", + "zh:840a8a32d5923f9e7422f9c80d165c3f89bb6ea370b8283095081e39050a8ea8", + "zh:87cb6dbbdbc1b73bdde4b8b5d6d780914a3e8f1df0385da4ea7323dc1a68468f", + "zh:8b8953e39b0e6e6156c5570d1ca653450bfa0d9b280e2475f01ee5c51a6554db", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9bd750262e2fb0187a8420a561e55b0a1da738f690f53f5c7df170cb1f380459", + "zh:9d2474c1432dfa5e1db197e2dd6cd61a6a15452e0bc7acd09ca86b3cdb228871", + "zh:b763ecaf471c7737a5c6e4cf257b5318e922a6610fd83b36ed8eb68582a8642e", + "zh:c1344cd8fe03ff7433a19b14b14a1898c2ca5ba22a468fb8e1687f0a7f564d52", + "zh:dc0e0abf3be7402d0d022ced82816884356115ed27646df9c7222609e96840e6", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.3" + constraints = ">= 3.1.0" + hashes = [ + "h1:I0Um8UkrMUb81Fxq/dxbr3HLP2cecTH2WMJiwKSrwQY=", + "zh:22d062e5278d872fe7aed834f5577ba0a5afe34a3bdac2b81f828d8d3e6706d2", + "zh:23dead00493ad863729495dc212fd6c29b8293e707b055ce5ba21ee453ce552d", + "zh:28299accf21763ca1ca144d8f660688d7c2ad0b105b7202554ca60b02a3856d3", + "zh:55c9e8a9ac25a7652df8c51a8a9a422bd67d784061b1de2dc9fe6c3cb4e77f2f", + "zh:756586535d11698a216291c06b9ed8a5cc6a4ec43eee1ee09ecd5c6a9e297ac1", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9d5eea62fdb587eeb96a8c4d782459f4e6b73baeece4d04b4a40e44faaee9301", + "zh:a6355f596a3fb8fc85c2fb054ab14e722991533f87f928e7169a486462c74670", + "zh:b5a65a789cff4ada58a5baffc76cb9767dc26ec6b45c00d2ec8b1b027f6db4ed", + "zh:db5ab669cf11d0e9f81dc380a6fdfcac437aea3d69109c7aef1a5426639d2d65", + "zh:de655d251c470197bcbb5ac45d289595295acb8f829f6c781d4a75c8c8b7c7dd", + "zh:f5c68199f2e6076bce92a12230434782bf768103a427e9bb9abee99b116af7b5", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.3" + constraints = ">= 3.4.0" + hashes = [ + "h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=", + "zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451", + "zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8", + "zh:4b4c11ccfba7319e901df2dac836b1ae8f12185e37249e8d870ee10bb87a13fe", + "zh:4fa45c44c0de582c2edb8a2e054f55124520c16a39b2dfc0355929063b6395b1", + "zh:588508280501a06259e023b0695f6a18149a3816d259655c424d068982cbdd36", + "zh:737c4d99a87d2a4d1ac0a54a73d2cb62974ccb2edbd234f333abd079a32ebc9e", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:a357ab512e5ebc6d1fda1382503109766e21bbfdfaa9ccda43d313c122069b30", + "zh:c51bfb15e7d52cc1a2eaec2a903ac2aff15d162c172b1b4c17675190e8147615", + "zh:e0951ee6fa9df90433728b96381fb867e3db98f66f735e0c3e24f8f16903f0ad", + "zh:e3cdcb4e73740621dabd82ee6a37d6cfce7fee2a03d8074df65086760f5cf556", + "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", + ] +} diff --git a/examples/aurora/README.md b/examples/aurora/README.md new file mode 100644 index 0000000..67f97d8 --- /dev/null +++ b/examples/aurora/README.md @@ -0,0 +1,50 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.3, < 2.0.0 | +| [aws](#requirement\_aws) | >= 4.0, < 6.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.74.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [aurora](#module\_aurora) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_subnets.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | +| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `"poc"` | no | +| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `"arc"` | no | +| [region](#input\_region) | AWS region | `string` | `"us-east-1"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | Instance or Cluster ARN | +| [database](#output\_database) | Database name | +| [endpoint](#output\_endpoint) | Instance or Cluster Endpoint | +| [id](#output\_id) | Instance or Cluster ID | +| [identifier](#output\_identifier) | Instance or Cluster Identifier | +| [kms\_key\_id](#output\_kms\_key\_id) | Instance or Cluster KMS Key ID | +| [monitoring\_role\_arn](#output\_monitoring\_role\_arn) | Instance or Cluster Monitoring Role ARN | +| [performance\_insights\_kms\_key\_id](#output\_performance\_insights\_kms\_key\_id) | Instance or Cluster Performance Insights KMS Key ID | +| [port](#output\_port) | Database server port | +| [username](#output\_username) | Username for the Database | + diff --git a/examples/aurora/data.tf b/examples/aurora/data.tf new file mode 100644 index 0000000..4fca06e --- /dev/null +++ b/examples/aurora/data.tf @@ -0,0 +1,24 @@ +################################################ +## imports +################################################ +## vpc +data "aws_vpc" "vpc" { + filter { + name = "tag:Name" + values = ["${var.namespace}-${var.environment}-vpc"] + } +} + +## network +data "aws_subnets" "private" { + filter { + name = "vpc-id" + values = [data.aws_vpc.vpc.id] + } + filter { + name = "tag:Name" + values = [ + "*private*" + ] + } +} diff --git a/examples/aurora/main.tf b/examples/aurora/main.tf new file mode 100644 index 0000000..d8cabfc --- /dev/null +++ b/examples/aurora/main.tf @@ -0,0 +1,58 @@ +################################################################################ +## defaults +################################################################################ +terraform { + required_version = "~> 1.3, < 2.0.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0, < 6.0" + } + } +} + +provider "aws" { + region = var.region +} + +module "aurora" { + source = "../../" + + environment = var.environment + namespace = var.namespace + vpc_id = data.aws_vpc.vpc.id + + name = "${var.namespace}-${var.environment}-test" + engine_type = "cluster" + port = 5432 + username = "postgres" + engine = "aurora-postgresql" + engine_version = "16.2" + + license_model = "postgresql-license" + rds_cluster_instances = [ + { + instance_class = "db.t3.medium" + db_parameter_group_name = "default.aurora-postgresql16" + apply_immediately = true + promotion_tier = 1 + } + ] + + db_subnet_group_data = { + name = "${var.namespace}-${var.environment}-subnet-group" + create = true + description = "Subnet group for rds instance" + subnet_ids = data.aws_subnets.private.ids + } + + performance_insights_enabled = true + + kms_data = { + create = true + description = "KMS for Performance insight and storage" + deletion_window_in_days = 7 + enable_key_rotation = true + } +} diff --git a/examples/aurora/output.tf b/examples/aurora/output.tf new file mode 100644 index 0000000..3e50a17 --- /dev/null +++ b/examples/aurora/output.tf @@ -0,0 +1,49 @@ +output "id" { + value = module.aurora.id + description = "Instance or Cluster ID" +} + +output "identifier" { + value = module.aurora.identifier + description = "Instance or Cluster Identifier" +} + +output "arn" { + value = module.aurora.arn + description = "Instance or Cluster ARN" +} + +output "username" { + value = module.aurora.username + description = "Username for the Database" +} + +output "database" { + value = module.aurora.database + description = "Database name" +} + +output "port" { + value = module.aurora.port + description = "Database server port" +} + +output "endpoint" { + value = module.aurora.endpoint + description = "Instance or Cluster Endpoint" +} + +output "kms_key_id" { + value = module.aurora.kms_key_id + description = "Instance or Cluster KMS Key ID" +} + +output "performance_insights_kms_key_id" { + value = module.aurora.performance_insights_kms_key_id + description = "Instance or Cluster Performance Insights KMS Key ID" +} + +output "monitoring_role_arn" { + value = module.aurora.monitoring_role_arn + description = "Instance or Cluster Monitoring Role ARN" +} diff --git a/examples/aurora/variables.tf b/examples/aurora/variables.tf new file mode 100644 index 0000000..8e65782 --- /dev/null +++ b/examples/aurora/variables.tf @@ -0,0 +1,20 @@ +################################################################################ +## shared +################################################################################ +variable "region" { + type = string + default = "us-east-1" + description = "AWS region" +} + +variable "environment" { + type = string + default = "poc" + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "namespace" { + type = string + default = "arc" + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} diff --git a/examples/rds-proxy/.terraform-version b/examples/rds-proxy/.terraform-version new file mode 100644 index 0000000..7324740 --- /dev/null +++ b/examples/rds-proxy/.terraform-version @@ -0,0 +1 @@ +latest:^1.7 diff --git a/examples/rds-proxy/.terraform.lock.hcl b/examples/rds-proxy/.terraform.lock.hcl new file mode 100644 index 0000000..30c9869 --- /dev/null +++ b/examples/rds-proxy/.terraform.lock.hcl @@ -0,0 +1,65 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.74.0" + constraints = ">= 4.0.0, ~> 5.0, < 6.0.0" + hashes = [ + "h1:0Iq3x8RSdWedvATBO1RZbCQqRCHPNsdhkYVrRs9crEE=", + "zh:1e2d65add4d63af5b396ae33d55c48303eca6c86bd1be0f6fae13267a9b47bc4", + "zh:20ddec3dac3d06a188f12e58b6428854949b1295e937c5d4dca4866dc1c937af", + "zh:35b72de4e6a3e3d69efc07184fb413406262fe447b2d82d57eaf8c787a068a06", + "zh:44eada24a50cd869aadc4b29f9e791fdf262d7f426921e9ac2893bbb86013176", + "zh:455e666e3a9a2312b3b9f434b87a404b6515d64a8853751e20566a6548f9df9e", + "zh:58b3ae74abfca7b9b61f42f0c8b10d97f9b01aff18bd1d4ab091129c9d203707", + "zh:840a8a32d5923f9e7422f9c80d165c3f89bb6ea370b8283095081e39050a8ea8", + "zh:87cb6dbbdbc1b73bdde4b8b5d6d780914a3e8f1df0385da4ea7323dc1a68468f", + "zh:8b8953e39b0e6e6156c5570d1ca653450bfa0d9b280e2475f01ee5c51a6554db", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9bd750262e2fb0187a8420a561e55b0a1da738f690f53f5c7df170cb1f380459", + "zh:9d2474c1432dfa5e1db197e2dd6cd61a6a15452e0bc7acd09ca86b3cdb228871", + "zh:b763ecaf471c7737a5c6e4cf257b5318e922a6610fd83b36ed8eb68582a8642e", + "zh:c1344cd8fe03ff7433a19b14b14a1898c2ca5ba22a468fb8e1687f0a7f564d52", + "zh:dc0e0abf3be7402d0d022ced82816884356115ed27646df9c7222609e96840e6", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.3" + constraints = ">= 3.1.0" + hashes = [ + "h1:I0Um8UkrMUb81Fxq/dxbr3HLP2cecTH2WMJiwKSrwQY=", + "zh:22d062e5278d872fe7aed834f5577ba0a5afe34a3bdac2b81f828d8d3e6706d2", + "zh:23dead00493ad863729495dc212fd6c29b8293e707b055ce5ba21ee453ce552d", + "zh:28299accf21763ca1ca144d8f660688d7c2ad0b105b7202554ca60b02a3856d3", + "zh:55c9e8a9ac25a7652df8c51a8a9a422bd67d784061b1de2dc9fe6c3cb4e77f2f", + "zh:756586535d11698a216291c06b9ed8a5cc6a4ec43eee1ee09ecd5c6a9e297ac1", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9d5eea62fdb587eeb96a8c4d782459f4e6b73baeece4d04b4a40e44faaee9301", + "zh:a6355f596a3fb8fc85c2fb054ab14e722991533f87f928e7169a486462c74670", + "zh:b5a65a789cff4ada58a5baffc76cb9767dc26ec6b45c00d2ec8b1b027f6db4ed", + "zh:db5ab669cf11d0e9f81dc380a6fdfcac437aea3d69109c7aef1a5426639d2d65", + "zh:de655d251c470197bcbb5ac45d289595295acb8f829f6c781d4a75c8c8b7c7dd", + "zh:f5c68199f2e6076bce92a12230434782bf768103a427e9bb9abee99b116af7b5", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.3" + constraints = ">= 3.4.0" + hashes = [ + "h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=", + "zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451", + "zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8", + "zh:4b4c11ccfba7319e901df2dac836b1ae8f12185e37249e8d870ee10bb87a13fe", + "zh:4fa45c44c0de582c2edb8a2e054f55124520c16a39b2dfc0355929063b6395b1", + "zh:588508280501a06259e023b0695f6a18149a3816d259655c424d068982cbdd36", + "zh:737c4d99a87d2a4d1ac0a54a73d2cb62974ccb2edbd234f333abd079a32ebc9e", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:a357ab512e5ebc6d1fda1382503109766e21bbfdfaa9ccda43d313c122069b30", + "zh:c51bfb15e7d52cc1a2eaec2a903ac2aff15d162c172b1b4c17675190e8147615", + "zh:e0951ee6fa9df90433728b96381fb867e3db98f66f735e0c3e24f8f16903f0ad", + "zh:e3cdcb4e73740621dabd82ee6a37d6cfce7fee2a03d8074df65086760f5cf556", + "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", + ] +} diff --git a/examples/rds-proxy/README.md b/examples/rds-proxy/README.md new file mode 100644 index 0000000..6cf2958 --- /dev/null +++ b/examples/rds-proxy/README.md @@ -0,0 +1,50 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.3, < 2.0.0 | +| [aws](#requirement\_aws) | >= 4.0, < 6.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.74.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [rds](#module\_rds) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_subnets.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | +| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `"poc"` | no | +| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `"arc"` | no | +| [region](#input\_region) | AWS region | `string` | `"us-east-1"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | Instance or Cluster ARN | +| [database](#output\_database) | Database name | +| [endpoint](#output\_endpoint) | Instance or Cluster Endpoint | +| [id](#output\_id) | Instance or Cluster ID | +| [identifier](#output\_identifier) | Instance or Cluster Identifier | +| [kms\_key\_id](#output\_kms\_key\_id) | Instance or Cluster KMS Key ID | +| [monitoring\_role\_arn](#output\_monitoring\_role\_arn) | Instance or Cluster Monitoring Role ARN | +| [performance\_insights\_kms\_key\_id](#output\_performance\_insights\_kms\_key\_id) | Instance or Cluster Performance Insights KMS Key ID | +| [port](#output\_port) | Database server port | +| [username](#output\_username) | Username for the Database | + diff --git a/examples/rds-proxy/data.tf b/examples/rds-proxy/data.tf new file mode 100644 index 0000000..4fca06e --- /dev/null +++ b/examples/rds-proxy/data.tf @@ -0,0 +1,24 @@ +################################################ +## imports +################################################ +## vpc +data "aws_vpc" "vpc" { + filter { + name = "tag:Name" + values = ["${var.namespace}-${var.environment}-vpc"] + } +} + +## network +data "aws_subnets" "private" { + filter { + name = "vpc-id" + values = [data.aws_vpc.vpc.id] + } + filter { + name = "tag:Name" + values = [ + "*private*" + ] + } +} diff --git a/examples/rds-proxy/main.tf b/examples/rds-proxy/main.tf new file mode 100644 index 0000000..3d1b6e7 --- /dev/null +++ b/examples/rds-proxy/main.tf @@ -0,0 +1,142 @@ +################################################################################ +## defaults +################################################################################ +terraform { + required_version = "~> 1.3, < 2.0.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0, < 6.0" + } + } +} + +provider "aws" { + region = var.region +} + +locals { + rds_security_group_data = { + create = true + description = "Security Group for RDS instance" + + ingress_rules = [ + { + description = "Allow traffic from local network" + cidr_block = data.aws_vpc.vpc.cidr_block + from_port = 5432 + ip_protocol = "tcp" + to_port = 5432 + } + ] + + egress_rules = [ + { + description = "Allow all outbound traffic" + cidr_block = "0.0.0.0/0" + from_port = -1 + ip_protocol = "-1" + to_port = -1 + } + ] + } + + proxy_security_group_data = { + create = true + description = "Security Group for RDS Proxy" + + ingress_rules = [ + { + description = "Allow traffic from local network" + cidr_block = data.aws_vpc.vpc.cidr_block + from_port = 5432 + ip_protocol = "tcp" + to_port = 5432 + } + ] + + egress_rules = [ + { + description = "Allow all outbound traffic" + cidr_block = "0.0.0.0/0" + from_port = -1 + ip_protocol = "-1" + to_port = -1 + } + ] + } + + + parameter_group_config = { + create = true + family = "postgres16" + parameters = { + "paramter-1" = { + name = "log_connections" + value = "1" + } } + } + +} + +module "rds" { + source = "../../" + + environment = var.environment + namespace = var.namespace + vpc_id = data.aws_vpc.vpc.id + + name = "${var.namespace}-${var.environment}-test-proxy-2" + engine_type = "rds" + db_server_class = "db.t3.small" + port = 5432 + username = "postgres" + engine = "postgres" + engine_version = "16.3" + + monitoring_interval = 60 + license_model = "postgresql-license" + db_subnet_group_data = { + name = "${var.namespace}-${var.environment}-subnet-group-proxy" + create = true + description = "Subnet group for rds instance" + subnet_ids = data.aws_subnets.private.ids + } + + performance_insights_enabled = true + + kms_data = { + create = true + description = "KMS for Performance insight and storage" + deletion_window_in_days = 7 + enable_key_rotation = true + } + + parameter_group_config = local.parameter_group_config + security_group_data = local.rds_security_group_data + + proxy_config = { + create = true + engine_family = "POSTGRESQL" + vpc_subnet_ids = data.aws_subnets.private.ids + security_group_data = local.proxy_security_group_data + require_tls = true + debug_logging = true + idle_client_timeout_secs = 3600 # 1 hour + + auth = { + auth_scheme = "SECRETS" + description = "Authentication for RDS Proxy" + iam_auth = "DISABLED" // REQUIRED + client_password_auth_type = "POSTGRES_SCRAM_SHA_256" + } + + additional_auth_list = [] + + connection_pool_config = { + max_connections_percent = 100 + max_idle_connections_percent = 50 + } + } +} diff --git a/examples/rds-proxy/output.tf b/examples/rds-proxy/output.tf new file mode 100644 index 0000000..3b64723 --- /dev/null +++ b/examples/rds-proxy/output.tf @@ -0,0 +1,49 @@ +output "id" { + value = module.rds.id + description = "Instance or Cluster ID" +} + +output "identifier" { + value = module.rds.identifier + description = "Instance or Cluster Identifier" +} + +output "arn" { + value = module.rds.arn + description = "Instance or Cluster ARN" +} + +output "username" { + value = module.rds.username + description = "Username for the Database" +} + +output "database" { + value = module.rds.database + description = "Database name" +} + +output "port" { + value = module.rds.port + description = "Database server port" +} + +output "endpoint" { + value = module.rds.endpoint + description = "Instance or Cluster Endpoint" +} + +output "kms_key_id" { + value = module.rds.kms_key_id + description = "Instance or Cluster KMS Key ID" +} + +output "performance_insights_kms_key_id" { + value = module.rds.performance_insights_kms_key_id + description = "Instance or Cluster Performance Insights KMS Key ID" +} + +output "monitoring_role_arn" { + value = module.rds.monitoring_role_arn + description = "Instance or Cluster Monitoring Role ARN" +} diff --git a/examples/rds-proxy/variables.tf b/examples/rds-proxy/variables.tf new file mode 100644 index 0000000..8e65782 --- /dev/null +++ b/examples/rds-proxy/variables.tf @@ -0,0 +1,20 @@ +################################################################################ +## shared +################################################################################ +variable "region" { + type = string + default = "us-east-1" + description = "AWS region" +} + +variable "environment" { + type = string + default = "poc" + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "namespace" { + type = string + default = "arc" + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} diff --git a/examples/rds/.terraform-version b/examples/rds/.terraform-version new file mode 100644 index 0000000..7324740 --- /dev/null +++ b/examples/rds/.terraform-version @@ -0,0 +1 @@ +latest:^1.7 diff --git a/examples/rds/.terraform.lock.hcl b/examples/rds/.terraform.lock.hcl new file mode 100644 index 0000000..30c9869 --- /dev/null +++ b/examples/rds/.terraform.lock.hcl @@ -0,0 +1,65 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.74.0" + constraints = ">= 4.0.0, ~> 5.0, < 6.0.0" + hashes = [ + "h1:0Iq3x8RSdWedvATBO1RZbCQqRCHPNsdhkYVrRs9crEE=", + "zh:1e2d65add4d63af5b396ae33d55c48303eca6c86bd1be0f6fae13267a9b47bc4", + "zh:20ddec3dac3d06a188f12e58b6428854949b1295e937c5d4dca4866dc1c937af", + "zh:35b72de4e6a3e3d69efc07184fb413406262fe447b2d82d57eaf8c787a068a06", + "zh:44eada24a50cd869aadc4b29f9e791fdf262d7f426921e9ac2893bbb86013176", + "zh:455e666e3a9a2312b3b9f434b87a404b6515d64a8853751e20566a6548f9df9e", + "zh:58b3ae74abfca7b9b61f42f0c8b10d97f9b01aff18bd1d4ab091129c9d203707", + "zh:840a8a32d5923f9e7422f9c80d165c3f89bb6ea370b8283095081e39050a8ea8", + "zh:87cb6dbbdbc1b73bdde4b8b5d6d780914a3e8f1df0385da4ea7323dc1a68468f", + "zh:8b8953e39b0e6e6156c5570d1ca653450bfa0d9b280e2475f01ee5c51a6554db", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9bd750262e2fb0187a8420a561e55b0a1da738f690f53f5c7df170cb1f380459", + "zh:9d2474c1432dfa5e1db197e2dd6cd61a6a15452e0bc7acd09ca86b3cdb228871", + "zh:b763ecaf471c7737a5c6e4cf257b5318e922a6610fd83b36ed8eb68582a8642e", + "zh:c1344cd8fe03ff7433a19b14b14a1898c2ca5ba22a468fb8e1687f0a7f564d52", + "zh:dc0e0abf3be7402d0d022ced82816884356115ed27646df9c7222609e96840e6", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.3" + constraints = ">= 3.1.0" + hashes = [ + "h1:I0Um8UkrMUb81Fxq/dxbr3HLP2cecTH2WMJiwKSrwQY=", + "zh:22d062e5278d872fe7aed834f5577ba0a5afe34a3bdac2b81f828d8d3e6706d2", + "zh:23dead00493ad863729495dc212fd6c29b8293e707b055ce5ba21ee453ce552d", + "zh:28299accf21763ca1ca144d8f660688d7c2ad0b105b7202554ca60b02a3856d3", + "zh:55c9e8a9ac25a7652df8c51a8a9a422bd67d784061b1de2dc9fe6c3cb4e77f2f", + "zh:756586535d11698a216291c06b9ed8a5cc6a4ec43eee1ee09ecd5c6a9e297ac1", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:9d5eea62fdb587eeb96a8c4d782459f4e6b73baeece4d04b4a40e44faaee9301", + "zh:a6355f596a3fb8fc85c2fb054ab14e722991533f87f928e7169a486462c74670", + "zh:b5a65a789cff4ada58a5baffc76cb9767dc26ec6b45c00d2ec8b1b027f6db4ed", + "zh:db5ab669cf11d0e9f81dc380a6fdfcac437aea3d69109c7aef1a5426639d2d65", + "zh:de655d251c470197bcbb5ac45d289595295acb8f829f6c781d4a75c8c8b7c7dd", + "zh:f5c68199f2e6076bce92a12230434782bf768103a427e9bb9abee99b116af7b5", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.3" + constraints = ">= 3.4.0" + hashes = [ + "h1:zG9uFP8l9u+yGZZvi5Te7PV62j50azpgwPunq2vTm1E=", + "zh:04ceb65210251339f07cd4611885d242cd4d0c7306e86dda9785396807c00451", + "zh:448f56199f3e99ff75d5c0afacae867ee795e4dfda6cb5f8e3b2a72ec3583dd8", + "zh:4b4c11ccfba7319e901df2dac836b1ae8f12185e37249e8d870ee10bb87a13fe", + "zh:4fa45c44c0de582c2edb8a2e054f55124520c16a39b2dfc0355929063b6395b1", + "zh:588508280501a06259e023b0695f6a18149a3816d259655c424d068982cbdd36", + "zh:737c4d99a87d2a4d1ac0a54a73d2cb62974ccb2edbd234f333abd079a32ebc9e", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:a357ab512e5ebc6d1fda1382503109766e21bbfdfaa9ccda43d313c122069b30", + "zh:c51bfb15e7d52cc1a2eaec2a903ac2aff15d162c172b1b4c17675190e8147615", + "zh:e0951ee6fa9df90433728b96381fb867e3db98f66f735e0c3e24f8f16903f0ad", + "zh:e3cdcb4e73740621dabd82ee6a37d6cfce7fee2a03d8074df65086760f5cf556", + "zh:eff58323099f1bd9a0bec7cb04f717e7f1b2774c7d612bf7581797e1622613a0", + ] +} diff --git a/examples/rds/README.md b/examples/rds/README.md new file mode 100644 index 0000000..6cf2958 --- /dev/null +++ b/examples/rds/README.md @@ -0,0 +1,50 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | ~> 1.3, < 2.0.0 | +| [aws](#requirement\_aws) | >= 4.0, < 6.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.74.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [rds](#module\_rds) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_subnets.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | +| [aws_vpc.vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `"poc"` | no | +| [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `"arc"` | no | +| [region](#input\_region) | AWS region | `string` | `"us-east-1"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | Instance or Cluster ARN | +| [database](#output\_database) | Database name | +| [endpoint](#output\_endpoint) | Instance or Cluster Endpoint | +| [id](#output\_id) | Instance or Cluster ID | +| [identifier](#output\_identifier) | Instance or Cluster Identifier | +| [kms\_key\_id](#output\_kms\_key\_id) | Instance or Cluster KMS Key ID | +| [monitoring\_role\_arn](#output\_monitoring\_role\_arn) | Instance or Cluster Monitoring Role ARN | +| [performance\_insights\_kms\_key\_id](#output\_performance\_insights\_kms\_key\_id) | Instance or Cluster Performance Insights KMS Key ID | +| [port](#output\_port) | Database server port | +| [username](#output\_username) | Username for the Database | + diff --git a/examples/rds/data.tf b/examples/rds/data.tf new file mode 100644 index 0000000..c24a28d --- /dev/null +++ b/examples/rds/data.tf @@ -0,0 +1,20 @@ +################################################ +## imports +################################################ +## vpc +data "aws_vpc" "vpc" { + filter { + name = "tag:Name" + values = ["${var.namespace}-${var.environment}-vpc"] + } +} + +## network +data "aws_subnets" "private" { + filter { + name = "tag:Name" + values = [ + "*private*" + ] + } +} diff --git a/examples/rds/main.tf b/examples/rds/main.tf new file mode 100644 index 0000000..b51baba --- /dev/null +++ b/examples/rds/main.tf @@ -0,0 +1,80 @@ +################################################################################ +## defaults +################################################################################ +terraform { + required_version = "~> 1.3, < 2.0.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0, < 6.0" + } + } +} + +provider "aws" { + region = var.region +} + +locals { + rds_security_group_data = { + create = true + description = "Security Group for RDS instance" + + ingress_rules = [ + { + description = "Allow traffic from local network" + cidr_block = data.aws_vpc.vpc.cidr_block + from_port = 5432 + ip_protocol = "tcp" + to_port = 5432 + } + ] + + egress_rules = [ + { + description = "Allow all outbound traffic" + cidr_block = "0.0.0.0/0" + from_port = -1 + ip_protocol = "-1" + to_port = -1 + } + ] + } +} + +module "rds" { + source = "../../" + + environment = var.environment + namespace = var.namespace + vpc_id = data.aws_vpc.vpc.id + + name = "${var.namespace}-${var.environment}-test" + engine_type = "rds" + db_server_class = "db.t3.small" + port = 5432 + username = "postgres" + manage_user_password = true + engine = "postgres" + engine_version = "16.3" + + license_model = "postgresql-license" + db_subnet_group_data = { + name = "${var.namespace}-${var.environment}-subnet-group" + create = true + description = "Subnet group for rds instance" + subnet_ids = data.aws_subnets.private.ids + } + + security_group_data = local.rds_security_group_data + performance_insights_enabled = true + monitoring_interval = 5 + + kms_data = { + create = true + description = "KMS for Performance insight and storage" + deletion_window_in_days = 7 + enable_key_rotation = true + } +} diff --git a/examples/rds/output.tf b/examples/rds/output.tf new file mode 100644 index 0000000..3b64723 --- /dev/null +++ b/examples/rds/output.tf @@ -0,0 +1,49 @@ +output "id" { + value = module.rds.id + description = "Instance or Cluster ID" +} + +output "identifier" { + value = module.rds.identifier + description = "Instance or Cluster Identifier" +} + +output "arn" { + value = module.rds.arn + description = "Instance or Cluster ARN" +} + +output "username" { + value = module.rds.username + description = "Username for the Database" +} + +output "database" { + value = module.rds.database + description = "Database name" +} + +output "port" { + value = module.rds.port + description = "Database server port" +} + +output "endpoint" { + value = module.rds.endpoint + description = "Instance or Cluster Endpoint" +} + +output "kms_key_id" { + value = module.rds.kms_key_id + description = "Instance or Cluster KMS Key ID" +} + +output "performance_insights_kms_key_id" { + value = module.rds.performance_insights_kms_key_id + description = "Instance or Cluster Performance Insights KMS Key ID" +} + +output "monitoring_role_arn" { + value = module.rds.monitoring_role_arn + description = "Instance or Cluster Monitoring Role ARN" +} diff --git a/examples/rds/variables.tf b/examples/rds/variables.tf new file mode 100644 index 0000000..8e65782 --- /dev/null +++ b/examples/rds/variables.tf @@ -0,0 +1,20 @@ +################################################################################ +## shared +################################################################################ +variable "region" { + type = string + default = "us-east-1" + description = "AWS region" +} + +variable "environment" { + type = string + default = "poc" + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "namespace" { + type = string + default = "arc" + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} diff --git a/locals.tf b/locals.tf index a64bb39..43ba6b0 100644 --- a/locals.tf +++ b/locals.tf @@ -1,65 +1,34 @@ locals { - ## option group - instance_kms_id = "arn:aws:kms:${var.region}:${var.account_id}:key/${try(aws_kms_key.aurora_cluster_kms_key[0].key_id, aws_kms_key.rds_db_kms_key[0].key_id)}" - s3_kms_alias = try(var.s3_kms_alias_override ? var.s3_kms_alias_override != "" : var.s3_kms_alias_override, "arn:aws:kms:${var.region}:${var.account_id}:alias/aws/s3") - rds_instance_option_group_name = length(aws_db_option_group.this) > 0 ? aws_db_option_group.this[0].name : var.rds_instance_option_group_name + prefix = "${var.namespace}-${var.environment}" + security_group_ids_to_attach = var.security_group_data.create ? concat(var.security_group_data.security_group_ids_to_attach, [module.security_group[0].id]) : var.security_group_data.security_group_ids_to_attach + proxy_security_group_ids_to_attach = var.proxy_config.security_group_data.create ? concat(var.proxy_config.security_group_data.security_group_ids_to_attach, [module.proxy_security_group[0].id]) : var.proxy_config.security_group_data.security_group_ids_to_attach + secret_arn = var.manage_user_password == true ? (var.engine_type == "rds" ? aws_db_instance.this[0].master_user_secret[0].secret_arn : aws_rds_cluster.this[0].master_user_secret[0].secret_arn) : (var.proxy_config.create ? aws_secretsmanager_secret.this[0].arn : null) - ## aurora - aurora_cluster_name = var.aurora_cluster_name_override == true ? var.aurora_cluster_name : "${var.namespace}-${var.environment}-${var.aurora_cluster_name}" - aurora_ssm_params = var.aurora_cluster_enabled == true ? [ - { - name = "/${var.namespace}/${var.environment}/${var.aurora_cluster_name}/cluster_admin_db_password" - value = random_password.aurora_db_admin_password[0].result - type = "SecureString" - }, - { - name = "/${var.namespace}/${var.environment}/${var.aurora_cluster_name}/cluster_admin_db_username" - value = var.aurora_db_admin_username - type = "SecureString" - }, - { - name = "/${var.namespace}/${var.environment}/${var.aurora_cluster_name}/cluster_endpoint" - value = module.aurora_cluster[0].endpoint - type = "SecureString" - } - ] : [] + additional_secret_arn_list = [for auth in var.proxy_config.additional_auth_list : auth.secret_arn if auth.secret_arn != null] - aurora_ssm_tags = var.aurora_cluster_enabled == true ? { - AuroraName = "${var.namespace}-${var.environment}-db-cluster-ssm-param" - } : {} + secret_arn_list = concat([local.secret_arn], local.additional_secret_arn_list) - ## rds - rds_instance_name = var.rds_instance_name_override == true ? var.rds_instance_name : "${var.namespace}-${var.environment}-${var.rds_instance_name}" - rds_instance_ssm_params = var.rds_instance_enabled == true ? [ - { - name = "/${var.namespace}/${var.environment}/${var.rds_instance_name}/admin_db_password" - value = random_password.rds_db_admin_password[0].result - type = "SecureString" - }, - { - name = "/${var.namespace}/${var.environment}/${var.rds_instance_name}/admin_db_username" - value = var.rds_instance_database_user - type = "SecureString" - }, - { - name = "/${var.namespace}/${var.environment}/${var.rds_instance_name}/endpoint" - value = module.rds_instance[0].instance_endpoint - type = "SecureString" - } - ] : [] + // Adds inbound rule to RDS , so that proxy will be able to connect to RDS instance/cluster + db_ingress_rules = var.proxy_config.create ? concat(var.security_group_data.ingress_rules, + [ + { + description = "Allow traffic from RDS Proxy security group" + source_security_group_id = module.proxy_security_group[0].id + from_port = var.port + ip_protocol = "tcp" + to_port = var.port + } + ] + ) : var.security_group_data.ingress_rules - rds_instance_ssm_tags = var.rds_instance_enabled == true ? { - RDSName = "${var.namespace}-${var.environment}-rds-instance-ssm-param" - } : {} - ## concat locals - ssm_params = concat( - local.aurora_ssm_params, - local.rds_instance_ssm_params, - ) + username = var.engine_type == "rds" ? aws_db_instance.this[0].username : aws_rds_cluster.this[0].master_username + password = var.engine_type == "rds" ? aws_db_instance.this[0].password : aws_rds_cluster.this[0].master_password + database = var.engine_type == "rds" ? aws_db_instance.this[0].db_name : aws_rds_cluster.this[0].database_name + port = var.engine_type == "rds" ? aws_db_instance.this[0].port : aws_rds_cluster.this[0].port - ssm_tags = merge( - local.aurora_ssm_tags, - local.rds_instance_ssm_tags, - ) + kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.kms_key_id) + performance_insights_kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.performance_insights_kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.performance_insights_kms_key_id) + monitoring_role_arn = var.monitoring_interval > 0 ? (var.monitoring_role_arn == null ? aws_iam_role.enhanced_monitoring[0].arn : var.monitoring_role_arn) : null + endpoint = var.engine_type == "rds" ? aws_db_instance.this[0].endpoint : aws_rds_cluster.this[0].endpoint } diff --git a/main.tf b/main.tf index 994aff4..e85e6fc 100644 --- a/main.tf +++ b/main.tf @@ -1,454 +1,54 @@ ################################################################################ -## lookups -################################################################################ -data "aws_partition" "this" {} - -################################################################################ -## kms -################################################################################ -## aurora -// TODO: add alarms -resource "aws_kms_key" "aurora_cluster_kms_key" { - count = var.aurora_cluster_enabled == true ? 1 : 0 - - description = "Aurora cluster KMS key" - deletion_window_in_days = var.deletion_window_in_days - enable_key_rotation = var.enable_key_rotation - - tags = merge(var.tags, tomap({ - Name = "${var.namespace}-${var.environment}-aurora-cluster-kms-key" // TODO - add support for custom names - })) -} - -resource "aws_kms_alias" "aurora_cluster_kms_key" { - count = var.aurora_cluster_enabled == true ? 1 : 0 - - name = "alias/${var.namespace}-${var.environment}-aurora-cluster-kms-key" // TODO - add support for custom names - target_key_id = aws_kms_key.aurora_cluster_kms_key[0].id -} - -## rds -resource "aws_kms_key" "rds_db_kms_key" { - count = var.rds_instance_enabled == true ? 1 : 0 - - description = "RDS DB KMS key" - deletion_window_in_days = var.deletion_window_in_days - enable_key_rotation = var.enable_key_rotation - - tags = merge(var.tags, tomap({ - Name = "${var.namespace}-${var.environment}-${var.rds_instance_name}" - })) -} - -resource "aws_kms_alias" "rds_db_kms_key" { - count = var.rds_instance_enabled == true ? 1 : 0 - - name = "alias/${local.rds_instance_name}" - target_key_id = aws_kms_key.rds_db_kms_key[0].id -} - -################################################################################ -## iam -################################################################################ -# create IAM role for monitoring -resource "aws_iam_role" "enhanced_monitoring" { - name = "${var.enhanced_monitoring_name}-role" - assume_role_policy = data.aws_iam_policy_document.enhanced_monitoring.json - - tags = merge(var.tags, tomap({ - Name = "${var.enhanced_monitoring_name}-role" - })) -} - -# Attach Amazon's managed policy for RDS enhanced monitoring -resource "aws_iam_role_policy_attachment" "enhanced_monitoring" { - role = aws_iam_role.enhanced_monitoring.name - policy_arn = var.enhanced_monitoring_arn -} - -# allow rds to assume this role -data "aws_iam_policy_document" "enhanced_monitoring" { - statement { - actions = [ - "sts:AssumeRole", - ] - - effect = "Allow" - - principals { - type = "Service" - identifiers = ["monitoring.rds.amazonaws.com"] - } - } -} - -################################################################################ -## password generation -################################################################################ -## aurora -resource "random_password" "aurora_db_admin_password" { - count = var.aurora_cluster_enabled == true ? 1 : 0 - - length = 41 - special = true - override_special = "!#*^" - - lifecycle { - ignore_changes = [ - length, - lower, - min_lower, - min_numeric, - min_special, - min_upper, - override_special, - special, - upper - ] - } -} - -## rds -resource "random_password" "rds_db_admin_password" { - count = var.rds_instance_enabled == true ? 1 : 0 - - length = var.rds_random_admin_password_length - special = true - override_special = "!#*^" - - lifecycle { - ignore_changes = [ - length, - lower, - min_lower, - min_numeric, - min_special, - min_upper, - override_special, - special, - upper - ] - } -} - -################################################################################ -## aurora cluster -################################################################################ -module "aurora_cluster" { - source = "git::https://github.com/cloudposse/terraform-aws-rds-cluster.git?ref=1.11.0" - count = var.aurora_cluster_enabled == true ? 1 : 0 - - name = local.aurora_cluster_name - - engine = var.aurora_engine - engine_mode = var.aurora_engine_mode - allow_major_version_upgrade = var.aurora_allow_major_version_upgrade - auto_minor_version_upgrade = var.aurora_auto_minor_version_upgrade - engine_version = var.aurora_engine_version - cluster_family = var.aurora_cluster_family - cluster_size = var.aurora_cluster_size - - admin_user = var.aurora_db_admin_username - admin_password = var.aurora_db_admin_password != "" ? var.aurora_db_admin_password : random_password.aurora_db_admin_password[0].result - db_name = var.aurora_db_name - instance_type = var.aurora_instance_type - db_port = var.aurora_db_port - - vpc_id = var.vpc_id - security_groups = var.aurora_security_groups - allowed_cidr_blocks = var.aurora_allowed_cidr_blocks - subnets = var.aurora_subnets +## RDS instance +################################################################################ +resource "aws_db_instance" "this" { + count = var.engine_type == "rds" ? 1 : 0 + + identifier = var.name + db_name = var.database_name + allocated_storage = var.allocated_storage + engine = var.engine + engine_version = var.engine_version + engine_lifecycle_support = var.engine_lifecycle_support + port = var.port + instance_class = var.db_server_class + + + username = var.username + password = var.password == null && var.manage_user_password == null ? random_password.master[0].result : var.password + manage_master_user_password = var.manage_user_password + + iops = var.iops + db_subnet_group_name = var.db_subnet_group_data.create ? aws_db_subnet_group.this[0].name : null + vpc_security_group_ids = local.security_group_ids_to_attach + multi_az = var.enable_multi_az + publicly_accessible = var.publicly_accessible + storage_type = var.storage_type + auto_minor_version_upgrade = var.auto_minor_version_upgrade + allow_major_version_upgrade = var.allow_major_version_upgrade + backup_retention_period = var.backup_retention_period + backup_window = var.preferred_backup_window + maintenance_window = var.preferred_maintenance_window + delete_automated_backups = var.delete_automated_backups + skip_final_snapshot = var.skip_final_snapshot + final_snapshot_identifier = var.final_snapshot_identifier iam_database_authentication_enabled = var.iam_database_authentication_enabled deletion_protection = var.deletion_protection - enable_http_endpoint = var.enable_http_endpoint + ca_cert_identifier = var.ca_cert_identifier - storage_encrypted = true - storage_type = var.aurora_storage_type - iops = var.aurora_iops - copy_tags_to_snapshot = true + option_group_name = var.option_group_config.create ? aws_db_option_group.this[0].name : var.option_group_config.name + parameter_group_name = var.parameter_group_config.create ? aws_db_parameter_group.this[0].name : var.parameter_group_config.name - rds_monitoring_interval = var.rds_monitoring_interval + storage_encrypted = var.storage_encrypted + kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.kms_key_id) performance_insights_enabled = var.performance_insights_enabled - performance_insights_kms_key_id = var.performance_insights_enabled ? coalesce(var.performance_insights_kms_key_id, aws_kms_key.aurora_cluster_kms_key[0].arn) : "" + performance_insights_kms_key_id = var.kms_data.create ? aws_kms_alias.this[0].target_key_arn : (var.kms_data.performance_insights_kms_key_id == null ? data.aws_kms_alias.rds.target_key_arn : var.kms_data.performance_insights_kms_key_id) performance_insights_retention_period = var.performance_insights_retention_period - enabled_cloudwatch_logs_exports = var.aurora_enabled_cloudwatch_logs_exports - - backup_window = var.aurora_backup_window - retention_period = var.aurora_backup_retention_period - - vpc_security_group_ids = var.vpc_security_group_ids - kms_key_arn = var.kms_key_arn - ca_cert_identifier = var.aurora_ca_cert_identifier - - # reference iam role created above - rds_monitoring_role_arn = aws_iam_role.enhanced_monitoring.arn - - scaling_configuration = var.aurora_scaling_configuration - - serverlessv2_scaling_configuration = var.aurora_serverlessv2_scaling_configuration - - tags = merge(var.tags, tomap({ - Name = var.aurora_cluster_name - Namespace = var.namespace - Environment = var.environment - Stage = var.environment - })) -} - -resource "aws_security_group_rule" "additional_ingress_rules_aurora" { - for_each = { for rule in var.additional_ingress_rules_aurora : rule.name => rule } - - security_group_id = module.aurora_cluster[0].security_group_id - type = each.value.type - from_port = each.value.from_port - to_port = each.value.to_port - protocol = each.value.protocol - cidr_blocks = each.value.cidr_blocks -} - -################################################################################ -## s3 db management -################################################################################ -module "db_management" { - source = "git::https://github.com/cloudposse/terraform-aws-s3-bucket?ref=4.5.0" - count = var.rds_enable_custom_option_group == true ? 1 : 0 - - name = "${local.rds_instance_name}-db-management" - - acl = "private" - enabled = true - user_enabled = false - versioning_enabled = true - bucket_key_enabled = true - kms_master_key_arn = "arn:${data.aws_partition.this.partition}:kms:${var.region}:${var.account_id}:alias/aws/s3" - sse_algorithm = "aws:kms" - - tags = merge(var.tags, tomap({ - Namespace = var.namespace - Environment = var.environment - Stage = var.environment - })) -} - -################################################################################ -## option group -################################################################################ -resource "aws_iam_role" "option_group" { - count = var.rds_enable_custom_option_group == true ? 1 : 0 - - name_prefix = "${var.namespace}-${var.environment}-${var.rds_instance_name}-" - - assume_role_policy = jsonencode( - { - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow" - Action = "sts:AssumeRole", - Principal = { - Service = "rds.amazonaws.com" - }, - }, - ] - } - ) -} - -resource "aws_iam_policy" "option_group" { - count = var.rds_enable_custom_option_group == true ? 1 : 0 - - name_prefix = "${local.rds_instance_name}-" - - policy = jsonencode( - { - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Action = [ - "kms:DescribeKey", - "kms:GenerateDataKey", - "kms:Encrypt", - "kms:Decrypt" - ], - Resource = local.instance_kms_id - }, - { - Effect = "Allow", - Action = [ - "kms:DescribeKey", - "kms:GenerateDataKey", - "kms:Encrypt", - "kms:Decrypt" - ], - Resource = local.s3_kms_alias - }, - { - Effect = "Allow", - Action = [ - "s3:ListBucket", - "s3:GetBucketLocation" - ], - Resource = module.db_management[0].bucket_arn - }, - { - Effect = "Allow", - Action = [ - "s3:GetObjectAttributes", - "s3:GetObject", - "s3:PutObject", - "s3:PutObjectAcl", - "s3:ListMultipartUploadParts", - "s3:AbortMultipartUpload" - ], - Resource = "${module.db_management[0].bucket_arn}/*" - } - ] - } - ) -} - -resource "aws_iam_role_policy_attachment" "option_group" { - count = var.rds_enable_custom_option_group == true ? 1 : 0 - - role = aws_iam_role.option_group[0].name - policy_arn = aws_iam_policy.option_group[0].arn -} - -resource "aws_db_option_group" "this" { - count = var.rds_enable_custom_option_group == true ? 1 : 0 - - name = "${local.rds_instance_name}-option-group" - option_group_description = "${local.rds_instance_name} Custom Option Group" - engine_name = var.rds_instance_engine - major_engine_version = var.rds_instance_major_engine_version - - // TODO - add loop for more options - dynamic "option" { - for_each = var.rds_enable_custom_option_group == true && length(regexall("mariadb", var.rds_instance_engine)) == 0 ? [1] : [] // mariadb doesn't support this option - - content { - option_name = length(regexall("sqlserver", var.rds_instance_engine)) > 0 ? "SQLSERVER_BACKUP_RESTORE" : "S3_INTEGRATION" - db_security_group_memberships = [] // TODO - make variable - vpc_security_group_memberships = [] // TODO - make variable - port = 0 // TODO - make variable - # version = "1.0" // TODO - make variable - - // Only include the version attribute for S3_INTEGRATION - version = length(regexall("sqlserver", var.rds_instance_engine)) > 0 ? null : "1.0" - - dynamic "option_settings" { - for_each = length(regexall("sqlserver", var.rds_instance_engine)) > 0 ? [1] : [] - - content { - name = "IAM_ROLE_ARN" - value = try(aws_iam_role.option_group[0].arn, "") - } - } - } - } - - tags = merge(var.tags, tomap({ - Name = "${local.rds_instance_name}-option-group" - })) -} - -resource "aws_db_instance_role_association" "this" { - count = var.rds_enable_custom_option_group && length(regexall("oracle", var.rds_instance_engine)) > 0 ? 1 : 0 // mariadb doesn't support this option - - db_instance_identifier = module.rds_instance[0].instance_id - feature_name = "S3_INTEGRATION" - role_arn = aws_iam_role.option_group[0].arn -} - -################################################################################ -## rds -################################################################################ -module "rds_instance" { - count = var.rds_instance_enabled == true ? 1 : 0 - source = "git::https://github.com/cloudposse/terraform-aws-rds?ref=1.1.2" - - name = local.rds_instance_name - - dns_zone_id = var.rds_instance_dns_zone_id - host_name = var.rds_instance_host_name - vpc_id = var.vpc_id - multi_az = var.rds_instance_multi_az - storage_type = var.rds_instance_storage_type - instance_class = var.rds_instance_instance_class - allocated_storage = var.rds_instance_allocated_storage - storage_encrypted = var.rds_instance_storage_encrypted - security_group_ids = var.rds_instance_security_group_ids - allowed_cidr_blocks = var.rds_instance_allowed_cidr_blocks - subnet_ids = var.rds_instance_subnet_ids - license_model = var.rds_instance_license_model - deletion_protection = var.deletion_protection - iops = var.rds_instance_iops - - enabled_cloudwatch_logs_exports = var.rds_enabled_cloudwatch_logs_exports - monitoring_interval = var.rds_monitoring_interval - monitoring_role_arn = var.rds_monitoring_interval > 0 ? aws_iam_role.enhanced_monitoring.arn : null - performance_insights_enabled = var.performance_insights_enabled - performance_insights_kms_key_id = var.performance_insights_kms_key_id - performance_insights_retention_period = var.performance_insights_retention_period - - kms_key_arn = var.rds_instance_storage_encrypted == false ? "" : var.rds_kms_key_arn_override != "" ? var.rds_kms_key_arn_override : aws_kms_key.rds_db_kms_key[0].arn - database_name = var.rds_instance_database_name - database_user = var.rds_instance_database_user - database_password = var.rds_instance_database_password != "" ? var.rds_instance_database_password : random_password.rds_db_admin_password[0].result - database_port = var.rds_instance_database_port - engine = var.rds_instance_engine - engine_version = var.rds_instance_engine_version - major_engine_version = var.rds_instance_major_engine_version - parameter_group_name = var.rds_instance_db_parameter_group_name - db_parameter_group = var.rds_instance_db_parameter_group - db_parameter = var.rds_instance_db_parameter - db_options = var.rds_instance_db_options - option_group_name = local.rds_instance_option_group_name - ca_cert_identifier = var.rds_instance_ca_cert_identifier - publicly_accessible = var.rds_instance_publicly_accessible - snapshot_identifier = var.rds_instance_snapshot_identifier - auto_minor_version_upgrade = var.rds_instance_auto_minor_version_upgrade - allow_major_version_upgrade = var.rds_instance_allow_major_version_upgrade - apply_immediately = var.rds_instance_apply_immediately - maintenance_window = var.rds_instance_maintenance_window - skip_final_snapshot = var.rds_instance_skip_final_snapshot - copy_tags_to_snapshot = var.rds_instance_copy_tags_to_snapshot - backup_retention_period = var.rds_instance_backup_retention_period - backup_window = var.rds_instance_backup_window - iam_database_authentication_enabled = var.iam_database_authentication_enabled - timeouts = var.timeouts - - tags = merge(var.tags, tomap({ - Namespace = var.namespace - Environment = var.environment - Stage = var.environment - })) -} - - -resource "aws_security_group_rule" "additional_ingress_rules_rds" { - for_each = { for rule in var.additional_ingress_rules_rds : rule.name => rule } - - security_group_id = module.rds_instance[0].security_group_id - type = each.value.type - from_port = each.value.from_port - to_port = each.value.to_port - protocol = each.value.protocol - cidr_blocks = each.value.cidr_blocks -} - -################################################################################ -## ssm parameters -################################################################################ -resource "aws_ssm_parameter" "this" { - for_each = { for x in local.ssm_params : x.name => x } - - name = lookup(each.value, "name", null) - value = lookup(each.value, "value", null) - description = lookup(each.value, "description", "Managed by Terraform") - type = lookup(each.value, "type", null) - overwrite = lookup(each.value, "overwrite", true) + enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports + monitoring_interval = var.monitoring_interval + monitoring_role_arn = var.monitoring_interval > 0 ? (var.monitoring_role_arn == null ? aws_iam_role.enhanced_monitoring[0].arn : var.monitoring_role_arn) : null - tags = merge(var.tags, local.ssm_tags) + license_model = var.license_model + apply_immediately = var.apply_immediately + tags = var.tags } diff --git a/modules/security-group/.terraform.lock.hcl b/modules/security-group/.terraform.lock.hcl new file mode 100644 index 0000000..6e902b8 --- /dev/null +++ b/modules/security-group/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.68.0" + constraints = "~> 5.0" + hashes = [ + "h1:n1X7MVAm1J+cxX4nTWTQRBx+VFQ0ma2AMJ5Ll3URlLo=", + "zh:045f37b115a6c94a05c6a5f2aacfe4cecbaf4b40b56917ba852d988d487e94bf", + "zh:0c388f1a94e7941cf7e6abcd8d958a3e325e513cb60affa3cac82e75c7bbbb73", + "zh:15b1f2587c06bff35a15f2d1c22eab395d549908daf05582608d729cdf54ba40", + "zh:16a9c0c7fa7a33aa22313d4444aeecde20831bf51f9b481a0406e3cf583378fc", + "zh:3330c0d49fb329dff6de17913e1a774e75aa0913106c3197814c73c3a12a4c3f", + "zh:40920318f774ff397c7b6a01b5e89e46eb1a55d7dc9943a310669a9357b9b501", + "zh:838fbac358bb72f46c8d359a28a3effb6a9d7137cdd72b9e4d2f0fcf803dc462", + "zh:84e694c0720bf54b3b8521bf6e05700abe4a1b3e7dd2a104efd1eb55ae5866a0", + "zh:90606c399498027d7d07ab78a71b574a5d8b982c4372e6b67479f7e39e153e2f", + "zh:9162cf25d5c0fdf672c9bbc4c3c84dd87ab6a15b4971df1f32aea6b477c0e028", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9cd8ec40a88b25e9f0f7d7f51460a921f4529554a260ffbe5083ddeba2f41ae3", + "zh:adeffac1d01a35bc8d2497ccceb9978b4746872143016c2c631de6cb38b6aa8d", + "zh:c7b682c81f9ae850669deb6239a66d8aa960abed984aad25db2d3954c09c2616", + "zh:d10b9f40934e14d55cfc5731d728507e50d014561322e9e0c84b33ab255a4d51", + ] +} diff --git a/modules/security-group/main.tf b/modules/security-group/main.tf new file mode 100644 index 0000000..b8ba2cb --- /dev/null +++ b/modules/security-group/main.tf @@ -0,0 +1,43 @@ +resource "aws_security_group" "this" { + name = var.name + description = var.description == null ? "Allow inbound traffic and outbound traffic" : var.description + vpc_id = var.vpc_id + tags = merge( + var.tags, + { + Name = var.name + } + ) +} + +resource "aws_vpc_security_group_egress_rule" "this" { + for_each = { + for idx, rule in var.egress_rules : idx => rule + } + + security_group_id = aws_security_group.this.id + description = each.value.description + cidr_ipv4 = each.value.cidr_block + referenced_security_group_id = each.value.destination_security_group_id + from_port = each.value.from_port + ip_protocol = each.value.ip_protocol + to_port = each.value.to_port + + depends_on = [aws_security_group.this] +} + +resource "aws_vpc_security_group_ingress_rule" "this" { + for_each = { + for idx, rule in var.ingress_rules : idx => rule + } + + security_group_id = aws_security_group.this.id + description = each.value.description + cidr_ipv4 = each.value.cidr_block + referenced_security_group_id = each.value.self ? aws_security_group.this.id : each.value.source_security_group_id + from_port = each.value.from_port + ip_protocol = each.value.ip_protocol + to_port = each.value.to_port + + depends_on = [aws_security_group.this] +} diff --git a/modules/security-group/output.tf b/modules/security-group/output.tf new file mode 100644 index 0000000..e30e32d --- /dev/null +++ b/modules/security-group/output.tf @@ -0,0 +1,4 @@ +output "id" { + description = "Security Groupo ID" + value = aws_security_group.this.id +} diff --git a/modules/security-group/variables.tf b/modules/security-group/variables.tf new file mode 100644 index 0000000..ddaa754 --- /dev/null +++ b/modules/security-group/variables.tf @@ -0,0 +1,50 @@ +# Cluster identifier +variable "name" { + description = "The identifier for the RDS cluster." + type = string +} + +variable "vpc_id" { + type = string + description = "VPC Id for creating security group" +} + +variable "description" { + type = string + description = "(optional) Description of Security Group" + default = null +} + +variable "ingress_rules" { + description = "(optional) List of ingress rules for the security group." + type = list(object({ + description = optional(string, null) + cidr_block = optional(string, null) + source_security_group_id = optional(string, null) + from_port = number + ip_protocol = string + to_port = string + self = optional(bool, false) + })) + default = [] +} + +variable "egress_rules" { + description = "(optional) List of egress rules for the security group." + type = list(object({ + description = optional(string, null) + cidr_block = optional(string, null) + destination_security_group_id = optional(string, null) + from_port = number + ip_protocol = string + to_port = string + })) + default = [] +} + + +variable "tags" { + description = "A map of tags to assign to the DB Cluster." + type = map(string) + default = {} +} diff --git a/modules/security-group/version.tf b/modules/security-group/version.tf new file mode 100644 index 0000000..9121a5f --- /dev/null +++ b/modules/security-group/version.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/outputs.tf b/outputs.tf index d98f483..06ac2d1 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,80 +1,49 @@ -################################################################################ -## aurora -################################################################################ -output "aurora_name" { - value = try(module.aurora_cluster[0].database_name, null) - description = "Database name" +output "id" { + value = var.engine_type == "rds" ? aws_db_instance.this[0].id : aws_rds_cluster.this[0].id + description = "Instance or Cluster ID" } -output "aurora_master_username" { - value = try(module.aurora_cluster[0].master_username, null) - description = "Username for the master DB user" +output "identifier" { + value = var.engine_type == "rds" ? aws_db_instance.this[0].id : aws_rds_cluster.this[0].id + description = "Instance or Cluster Identifier " } -output "aurora_cluster_identifier" { - value = try(module.aurora_cluster[0].cluster_identifier, null) - description = "Cluster Identifier" +output "arn" { + value = var.engine_type == "rds" ? aws_db_instance.this[0].arn : aws_rds_cluster.this[0].arn + description = "Instance or Cluster ARN" } -output "aurora_arn" { - value = try(module.aurora_cluster[0].arn, null) - description = "Amazon Resource Name (ARN) of cluster" +output "username" { + value = local.username + description = "Username for the Database" } -output "aurora_endpoint" { - value = try(module.aurora_cluster[0].endpoint, null) - description = "The DNS address of the RDS instance" +output "database" { + value = local.database + description = "database name" } -output "aurora_reader_endpoint" { - value = try(module.aurora_cluster[0].reader_endpoint, null) - description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas" +output "port" { + value = local.port + description = "Dtabase server port" } -output "aurora_master_host" { - value = try(module.aurora_cluster[0].master_host, null) - description = "DB Master hostname" +output "endpoint" { + value = var.engine_type == "rds" ? aws_db_instance.this[0].endpoint : aws_rds_cluster.this[0].endpoint + description = "Instance or Cluster Endpoint" } -output "aurora_replicas_host" { - value = try(module.aurora_cluster[0].replicas_host, null) - description = "Replicas hostname" +output "kms_key_id" { + value = local.kms_key_id + description = "Instance or Cluster KM Key ID" } -################################################################################ -## rds -################################################################################ -output "rds_instance_arn" { - value = try(module.rds_instance[0].instance_arn, null) - description = "The RDS Instance AWS ARN." +output "performance_insights_kms_key_id" { + value = local.performance_insights_kms_key_id + description = "Instance or Cluster Performance insight KM Key ID" } -output "rds_instance_endpoint" { - value = try(module.rds_instance[0].instance_endpoint, null) - description = "The DNS address to the RDS Instance." -} - -output "rds_instance_hostname" { - value = try(module.rds_instance[0].hostname, null) - description = "Hostname of the RDS Instance." -} - -output "rds_instance_id" { - value = try(module.rds_instance[0].instance_id, null) - description = "The RDS Instance AWS ID." -} - -output "rds_instance_resource_id" { - value = try(module.rds_instance[0].resource_id, null) - description = "The RDS Instance AWS resource ID." -} - -output "rds_instance_kms_arn" { - value = var.rds_kms_key_arn_override != "" ? var.rds_kms_key_arn_override : try(aws_kms_key.rds_db_kms_key[0].arn, null) - description = "RDS KMS Key ARN" -} - -output "rds_instance_kms_id" { - value = var.rds_kms_key_id_override != "" ? var.rds_kms_key_id_override : try(aws_kms_key.rds_db_kms_key[0].key_id, null) - description = "Output RDS KMS Key ID if the var.rds_kms_key_arn_override is \"\"" +output "monitoring_role_arn" { + value = local.monitoring_role_arn + description = "Instance or Cluster Monitoring role arn" } diff --git a/proxy.tf b/proxy.tf new file mode 100644 index 0000000..0b827fe --- /dev/null +++ b/proxy.tf @@ -0,0 +1,178 @@ +resource "aws_kms_key" "secret" { + description = "KMS key for encrypting Secrets Manager secrets" + deletion_window_in_days = var.kms_data.deletion_window_in_days + enable_key_rotation = var.kms_data.enable_key_rotation + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "Enable IAM User Permissions", + Effect = "Allow", + Principal = { + AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + }, + Action = "kms:*", + Resource = "*" + }, + { + Sid = "Allow Secrets Manager to use the key", + Effect = "Allow", + Principal = { + Service = "secretsmanager.amazonaws.com" + }, + Action = [ + "kms:GenerateDataKey", + "kms:Decrypt" + ], + Resource = "*" + } + ] + }) + + tags = var.tags +} + +resource "aws_secretsmanager_secret" "this" { + count = var.manage_user_password == null && var.proxy_config.create ? 1 : 0 + + name = "${local.prefix}-${var.name}-secret" + description = "Credentials for RDS Proxy" + kms_key_id = var.kms_data.create ? aws_kms_key.secret.id : null + + tags = var.tags +} + +resource "aws_secretsmanager_secret_version" "db_secret_version" { + count = var.manage_user_password == null && var.proxy_config.create ? 1 : 0 + + secret_id = aws_secretsmanager_secret.this[0].id + secret_string = jsonencode({ + "username" = local.username + "password" = local.password + "database" = local.database + "endpoint" = local.endpoint + "port" = local.port + }) +} + + +resource "aws_db_proxy" "this" { + count = var.proxy_config.create ? 1 : 0 + + name = var.proxy_config.name == null ? var.name : var.proxy_config.name + engine_family = var.proxy_config.engine_family # Replace with your DB engine (MYSQL, POSTGRESQL, etc.) + role_arn = var.proxy_config.role_arn == null ? aws_iam_role.proxy[0].arn : var.proxy_config.role_arn + vpc_subnet_ids = var.proxy_config.vpc_subnet_ids + vpc_security_group_ids = local.proxy_security_group_ids_to_attach + require_tls = var.proxy_config.require_tls + debug_logging = var.proxy_config.debug_logging + idle_client_timeout = var.proxy_config.idle_client_timeout_secs + + auth { + auth_scheme = var.proxy_config.auth.auth_scheme + description = var.proxy_config.auth.description == null ? "Auth for RDS Proxy" : var.proxy_config.auth.description + iam_auth = var.proxy_config.auth.iam_auth + secret_arn = var.manage_user_password == true ? (var.engine_type == "rds" ? aws_db_instance.this[0].master_user_secret[0].secret_arn : aws_rds_cluster.this[0].master_user_secret[0].secret_arn) : aws_secretsmanager_secret.this[0].arn + username = var.proxy_config.auth.auth_scheme == "SECRETS" ? null : (var.engine_type == "rds" ? aws_db_instance.this[0].username : aws_rds_cluster.this[0].master_username) + client_password_auth_type = var.proxy_config.auth.client_password_auth_type + } + + dynamic "auth" { + for_each = var.proxy_config.additional_auth_list + content { + auth_scheme = auth.value.auth_scheme + description = auth.value.description == null ? "Auth for RDS Proxy" : auth.value.description + iam_auth = auth.value.iam_auth + secret_arn = auth.value.secret_arn + client_password_auth_type = auth.value.client_password_auth_type + } + } + + tags = var.tags +} + +resource "aws_db_proxy_default_target_group" "this" { + count = var.proxy_config.create ? 1 : 0 + + db_proxy_name = aws_db_proxy.this[0].name + + connection_pool_config { + connection_borrow_timeout = var.proxy_config.connection_pool_config.connection_borrow_timeout + init_query = var.proxy_config.connection_pool_config.init_query + max_connections_percent = var.proxy_config.connection_pool_config.max_connections_percent + max_idle_connections_percent = var.proxy_config.connection_pool_config.max_idle_connections_percent + session_pinning_filters = var.proxy_config.connection_pool_config.session_pinning_filters + } +} + +resource "aws_db_proxy_target" "this" { + count = var.proxy_config.create ? 1 : 0 + + db_proxy_name = aws_db_proxy.this[0].name + target_group_name = aws_db_proxy_default_target_group.this[0].name + db_cluster_identifier = var.engine_type == "cluster" ? aws_rds_cluster.this[0].cluster_identifier : null + db_instance_identifier = var.engine_type == "rds" ? aws_db_instance.this[0].identifier : null + depends_on = [aws_db_instance.this, aws_rds_cluster.this] +} + + +resource "aws_iam_role" "proxy" { + count = var.proxy_config.create && var.proxy_config.role_arn == null ? 1 : 0 + + name = "${local.prefix}-${var.name}-proxy" + assume_role_policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [{ + "Action" : "sts:AssumeRole", + "Effect" : "Allow", + "Principal" : { + "Service" : "rds.amazonaws.com" + } + }] + }) +} + +resource "aws_iam_policy" "read_secrets" { + count = var.proxy_config.create && var.proxy_config.role_arn == null ? 1 : 0 + + name = "${var.name}-read-secret-proxy" + description = "IAM policy to grant read access to secrets in AWS Secrets Manager" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "secretsmanager:GetSecretValue", + "secretsmanager:DescribeSecret", + "secretsmanager:ListSecretVersionIds" + ] + Resource = local.secret_arn_list + } + ] + }) + + depends_on = [aws_rds_cluster.this, aws_db_instance.this, aws_secretsmanager_secret.this] +} + + +resource "aws_iam_role_policy_attachment" "proxy" { + count = var.proxy_config.create && var.proxy_config.role_arn == null ? 1 : 0 + + role = aws_iam_role.proxy[0].name + policy_arn = aws_iam_policy.read_secrets[0].arn +} + +module "proxy_security_group" { + source = "./modules/security-group" + + count = var.proxy_config.security_group_data.create ? 1 : 0 + + name = "${var.name}-proxy-security-group" + description = var.proxy_config.security_group_data.description == null ? "Allow inbound traffic and outbound traffic" : var.proxy_config.security_group_data.description + vpc_id = var.vpc_id + egress_rules = var.proxy_config.security_group_data.egress_rules + ingress_rules = var.proxy_config.security_group_data.ingress_rules +} diff --git a/variables.tf b/variables.tf index 326b4c1..52797cc 100644 --- a/variables.tf +++ b/variables.tf @@ -1,598 +1,528 @@ -################################################################################ -## shared -################################################################################ -variable "vpc_id" { +variable "environment" { type = string - description = "vpc_id for the VPC to run the cluster." + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" } -variable "enhanced_monitoring_name" { +variable "namespace" { type = string - description = "Name to assign the enhanced monitoring resources." + description = "Namespace for the resources." } -variable "enhanced_monitoring_arn" { + +variable "name" { + description = "The identifier for the RDS instance or cluster." type = string - description = "ARN to the enhanced monitoring policy" - default = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" } -variable "deletion_protection" { - description = "Protect the instance from being deleted" - type = bool - default = false +variable "vpc_id" { + type = string + description = "VPC Id for creating security group" } - -variable "timeouts" { +variable "serverlessv2_scaling_config" { type = object({ - create = string - update = string - delete = string + max_capacity = number + min_capacity = number }) - description = "A list of DB timeouts to apply to the running code while creating, updating, or deleting the DB instance." default = { - create = "40m" - update = "80m" - delete = "60m" + max_capacity = 1.0 + min_capacity = 0.5 } + description = <
name = string
description = string
type = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))