feat!: Increase Terraform and AWS provider minimum supported versions; update auth configuration schema (#17)

Co-authored-by: Orest Kapko <orest.kapko@welltech.com>
Co-authored-by: Amitai Getzler <amitai.getzler@explorium.ai>
Co-authored-by: Orest Kapko <kapko2311@gmail.com>
Co-authored-by: Bryant Biggs <bryantbiggs@gmail.com>
Co-authored-by: Anton Babenko <anton@antonbabenko.com>
This commit is contained in:
jatalocks 2023-06-09 14:30:52 +03:00 committed by GitHub
parent 5d1c5e67ea
commit cc39e9d029
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 626 additions and 750 deletions

View file

@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform - repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.76.0 rev: v1.80.0
hooks: hooks:
- id: terraform_fmt - id: terraform_fmt
- id: terraform_validate - id: terraform_validate
@ -23,7 +23,7 @@ repos:
- '--args=--only=terraform_standard_module_structure' - '--args=--only=terraform_standard_module_structure'
- '--args=--only=terraform_workspace_remote' - '--args=--only=terraform_workspace_remote'
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0 rev: v4.4.0
hooks: hooks:
- id: check-merge-conflict - id: check-merge-conflict
- id: end-of-file-fixer - id: end-of-file-fixer

View file

@ -15,7 +15,7 @@ module "rds_proxy" {
vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"] vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"]
vpc_security_group_ids = ["sg-f1d03a88"] vpc_security_group_ids = ["sg-f1d03a88"]
db_proxy_endpoints = { endpoints = {
read_write = { read_write = {
name = "read-write-endpoint" name = "read-write-endpoint"
vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"] vpc_subnet_ids = ["subnet-30ef7b3c", "subnet-1ecda77b", "subnet-ca09ddbc"]
@ -29,18 +29,17 @@ module "rds_proxy" {
} }
} }
secrets = { auth = {
"superuser" = { "superuser" = {
description = "Aurora PostgreSQL superuser password" description = "Aurora PostgreSQL superuser password"
arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:superuser-6gsjLD" secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:superuser-6gsjLD"
kms_key_id = "6ca29066-552a-46c5-a7d7-7bf9a15fc255"
} }
} }
# Target Aurora cluster # Target Aurora cluster
engine_family = "POSTGRESQL" engine_family = "POSTGRESQL"
target_db_cluster = true target_db_cluster = true
db_cluster_identifier = "myendpoint" db_cluster_identifier = "my-endpoint"
tags = { tags = {
Terraform = "true" Terraform = "true"
@ -63,14 +62,14 @@ Examples codified under the [`examples`](https://github.com/terraform-aws-module
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 | | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.38 | | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
## Providers ## Providers
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.38 | | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
## Modules ## Modules
@ -90,23 +89,23 @@ No modules.
| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
## Inputs ## Inputs
| Name | Description | Type | Default | Required | | Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:| |------|-------------|------|---------|:--------:|
| <a name="input_auth_scheme"></a> [auth\_scheme](#input\_auth\_scheme) | The type of authentication that the proxy uses for connections from the proxy to the underlying database. One of `SECRETS` | `string` | `"SECRETS"` | no | | <a name="input_auth"></a> [auth](#input\_auth) | Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters | `any` | `{}` | no |
| <a name="input_connection_borrow_timeout"></a> [connection\_borrow\_timeout](#input\_connection\_borrow\_timeout) | The number of seconds for a proxy to wait for a connection to become available in the connection pool | `number` | `null` | no | | <a name="input_connection_borrow_timeout"></a> [connection\_borrow\_timeout](#input\_connection\_borrow\_timeout) | The number of seconds for a proxy to wait for a connection to become available in the connection pool | `number` | `null` | no |
| <a name="input_create"></a> [create](#input\_create) | Whether cluster should be created (affects nearly all resources) | `bool` | `true` | no |
| <a name="input_create_iam_policy"></a> [create\_iam\_policy](#input\_create\_iam\_policy) | Determines whether an IAM policy is created | `bool` | `true` | no | | <a name="input_create_iam_policy"></a> [create\_iam\_policy](#input\_create\_iam\_policy) | Determines whether an IAM policy is created | `bool` | `true` | no |
| <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created | `bool` | `true` | no | | <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created | `bool` | `true` | no |
| <a name="input_create_proxy"></a> [create\_proxy](#input\_create\_proxy) | Determines whether a proxy and its resources will be created | `bool` | `true` | no |
| <a name="input_db_cluster_identifier"></a> [db\_cluster\_identifier](#input\_db\_cluster\_identifier) | DB cluster identifier | `string` | `""` | no | | <a name="input_db_cluster_identifier"></a> [db\_cluster\_identifier](#input\_db\_cluster\_identifier) | DB cluster identifier | `string` | `""` | no |
| <a name="input_db_instance_identifier"></a> [db\_instance\_identifier](#input\_db\_instance\_identifier) | DB instance identifier | `string` | `""` | no | | <a name="input_db_instance_identifier"></a> [db\_instance\_identifier](#input\_db\_instance\_identifier) | DB instance identifier | `string` | `""` | no |
| <a name="input_db_proxy_endpoints"></a> [db\_proxy\_endpoints](#input\_db\_proxy\_endpoints) | Map of DB proxy endpoints to create and their attributes (see `aws_db_proxy_endpoint`) | `any` | `{}` | no |
| <a name="input_debug_logging"></a> [debug\_logging](#input\_debug\_logging) | Whether the proxy includes detailed information about SQL statements in its logs | `bool` | `false` | no | | <a name="input_debug_logging"></a> [debug\_logging](#input\_debug\_logging) | Whether the proxy includes detailed information about SQL statements in its logs | `bool` | `false` | no |
| <a name="input_endpoints"></a> [endpoints](#input\_endpoints) | Map of DB proxy endpoints to create and their attributes (see `aws_db_proxy_endpoint`) | `any` | `{}` | no |
| <a name="input_engine_family"></a> [engine\_family](#input\_engine\_family) | The kind of database engine that the proxy will connect to. Valid values are `MYSQL` or `POSTGRESQL` | `string` | `""` | no | | <a name="input_engine_family"></a> [engine\_family](#input\_engine\_family) | The kind of database engine that the proxy will connect to. Valid values are `MYSQL` or `POSTGRESQL` | `string` | `""` | no |
| <a name="input_iam_auth"></a> [iam\_auth](#input\_iam\_auth) | Whether to require or disallow AWS Identity and Access Management (IAM) authentication for connections to the proxy. One of `DISABLED`, `REQUIRED` | `string` | `"REQUIRED"` | no |
| <a name="input_iam_policy_name"></a> [iam\_policy\_name](#input\_iam\_policy\_name) | The name of the role policy. If omitted, Terraform will assign a random, unique name | `string` | `""` | no | | <a name="input_iam_policy_name"></a> [iam\_policy\_name](#input\_iam\_policy\_name) | The name of the role policy. If omitted, Terraform will assign a random, unique name | `string` | `""` | no |
| <a name="input_iam_role_description"></a> [iam\_role\_description](#input\_iam\_role\_description) | The description of the role | `string` | `""` | no | | <a name="input_iam_role_description"></a> [iam\_role\_description](#input\_iam\_role\_description) | The description of the role | `string` | `""` | no |
| <a name="input_iam_role_force_detach_policies"></a> [iam\_role\_force\_detach\_policies](#input\_iam\_role\_force\_detach\_policies) | Specifies to force detaching any policies the role has before destroying it | `bool` | `true` | no | | <a name="input_iam_role_force_detach_policies"></a> [iam\_role\_force\_detach\_policies](#input\_iam\_role\_force\_detach\_policies) | Specifies to force detaching any policies the role has before destroying it | `bool` | `true` | no |
@ -117,6 +116,7 @@ No modules.
| <a name="input_iam_role_tags"></a> [iam\_role\_tags](#input\_iam\_role\_tags) | A map of tags to apply to the IAM role | `map(string)` | `{}` | no | | <a name="input_iam_role_tags"></a> [iam\_role\_tags](#input\_iam\_role\_tags) | A map of tags to apply to the IAM role | `map(string)` | `{}` | no |
| <a name="input_idle_client_timeout"></a> [idle\_client\_timeout](#input\_idle\_client\_timeout) | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | | <a name="input_idle_client_timeout"></a> [idle\_client\_timeout](#input\_idle\_client\_timeout) | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no |
| <a name="input_init_query"></a> [init\_query](#input\_init\_query) | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `""` | no | | <a name="input_init_query"></a> [init\_query](#input\_init\_query) | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `""` | no |
| <a name="input_kms_key_arns"></a> [kms\_key\_arns](#input\_kms\_key\_arns) | List of KMS Key ARNs to allow access to decrypt SecretsManager secrets | `list(string)` | `[]` | no |
| <a name="input_log_group_kms_key_id"></a> [log\_group\_kms\_key\_id](#input\_log\_group\_kms\_key\_id) | The ARN of the KMS Key to use when encrypting log data | `string` | `null` | no | | <a name="input_log_group_kms_key_id"></a> [log\_group\_kms\_key\_id](#input\_log\_group\_kms\_key\_id) | The ARN of the KMS Key to use when encrypting log data | `string` | `null` | no |
| <a name="input_log_group_retention_in_days"></a> [log\_group\_retention\_in\_days](#input\_log\_group\_retention\_in\_days) | Specifies the number of days you want to retain log events in the log group | `number` | `30` | no | | <a name="input_log_group_retention_in_days"></a> [log\_group\_retention\_in\_days](#input\_log\_group\_retention\_in\_days) | Specifies the number of days you want to retain log events in the log group | `number` | `30` | no |
| <a name="input_log_group_tags"></a> [log\_group\_tags](#input\_log\_group\_tags) | A map of tags to apply to the CloudWatch log group | `map(string)` | `{}` | no | | <a name="input_log_group_tags"></a> [log\_group\_tags](#input\_log\_group\_tags) | A map of tags to apply to the CloudWatch log group | `map(string)` | `{}` | no |
@ -127,11 +127,10 @@ No modules.
| <a name="input_proxy_tags"></a> [proxy\_tags](#input\_proxy\_tags) | A map of tags to apply to the RDS Proxy | `map(string)` | `{}` | no | | <a name="input_proxy_tags"></a> [proxy\_tags](#input\_proxy\_tags) | A map of tags to apply to the RDS Proxy | `map(string)` | `{}` | no |
| <a name="input_require_tls"></a> [require\_tls](#input\_require\_tls) | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy | `bool` | `true` | no | | <a name="input_require_tls"></a> [require\_tls](#input\_require\_tls) | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy | `bool` | `true` | no |
| <a name="input_role_arn"></a> [role\_arn](#input\_role\_arn) | The Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | `""` | no | | <a name="input_role_arn"></a> [role\_arn](#input\_role\_arn) | The Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | `""` | no |
| <a name="input_secrets"></a> [secrets](#input\_secrets) | Map of secerets to be used by RDS Proxy for authentication to the database | `map(object({ arn = string, description = string, kms_key_id = string }))` | `{}` | no |
| <a name="input_session_pinning_filters"></a> [session\_pinning\_filters](#input\_session\_pinning\_filters) | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `[]` | no | | <a name="input_session_pinning_filters"></a> [session\_pinning\_filters](#input\_session\_pinning\_filters) | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `[]` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to use on all resources | `map(string)` | `{}` | no | | <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
| <a name="input_target_db_cluster"></a> [target\_db\_cluster](#input\_target\_db\_cluster) | Determines whether DB cluster is targetted by proxy | `bool` | `false` | no | | <a name="input_target_db_cluster"></a> [target\_db\_cluster](#input\_target\_db\_cluster) | Determines whether DB cluster is targeted by proxy | `bool` | `false` | no |
| <a name="input_target_db_instance"></a> [target\_db\_instance](#input\_target\_db\_instance) | Determines whether DB instance is targetted by proxy | `bool` | `false` | no | | <a name="input_target_db_instance"></a> [target\_db\_instance](#input\_target\_db\_instance) | Determines whether DB instance is targeted by proxy | `bool` | `false` | no |
| <a name="input_use_policy_name_prefix"></a> [use\_policy\_name\_prefix](#input\_use\_policy\_name\_prefix) | Whether to use unique name beginning with the specified `iam_policy_name` | `bool` | `false` | no | | <a name="input_use_policy_name_prefix"></a> [use\_policy\_name\_prefix](#input\_use\_policy\_name\_prefix) | Whether to use unique name beginning with the specified `iam_policy_name` | `bool` | `false` | no |
| <a name="input_use_role_name_prefix"></a> [use\_role\_name\_prefix](#input\_use\_role\_name\_prefix) | Whether to use unique name beginning with the specified `iam_role_name` | `bool` | `false` | no | | <a name="input_use_role_name_prefix"></a> [use\_role\_name\_prefix](#input\_use\_role\_name\_prefix) | Whether to use unique name beginning with the specified `iam_role_name` | `bool` | `false` | no |
| <a name="input_vpc_security_group_ids"></a> [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | One or more VPC security group IDs to associate with the new proxy | `list(string)` | `[]` | no | | <a name="input_vpc_security_group_ids"></a> [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | One or more VPC security group IDs to associate with the new proxy | `list(string)` | `[]` | no |

79
UPGRADE-3.0.md Normal file
View file

@ -0,0 +1,79 @@
# Upgrade from v2.x to v3.x
If you have any questions regarding this upgrade process, please consult the `examples` directory.
If you find a bug, please open an issue with supporting configuration to reproduce.
## List of backwards incompatible changes
- Minimum supported Terraform version is now 1.0
- Minimum supported AWS provider version is now 5.0
- The manner in which authentication is configured has changed - previously auth settings were provided under `secrets` in conjunction with `auth_scheme` and `iam_auth` variables. Now, auth settings are provided under the `auth` variable for multiple auth entries.
### Variable and output changes
1. Removed variables:
- `auth_scheme` is now set under the `auth` variable for a given auth entry
- `iam_auth` is now set under the `auth` variable for a given auth entry
2. Renamed variables:
- `create_proxy` -> `create`
- `secrets` -> `auth`
- `db_proxy_endpoints` -> `endpoints`
3. Added variables:
- `kms_key_arns` - list of KMS key ARNs to use allowing permission to decrypt SecretsManager secrets
4. Removed outputs:
- None
5. Renamed outputs:
- None
6. Added outputs:
- None
## Diff of Before (v2.x) vs After (v3.x)
```diff
module "rds_proxy" {
source = "terraform-aws-modules/rds-proxy/aws"
- version = "~> 2.0"
+ version = "~> 3.0"
# Only the affected attributes are shown
- create_proxy = true
+ create = true
- db_proxy_endpoints = {
- ...
- }
+ endpoints = {
+ ...
+ }
- secrets = {
- "superuser" = {
- description = "Aurora PostgreSQL superuser password"
- arn = "arn:aws:secretsmanager:eu-west-1:123456789012:secret:superuser-6gsjLD"
- kms_key_id = "6ca29066-552a-46c5-a7d7-7bf9a15fc255"
- }
- }
+ auth = {
+ "superuser" = {
+ description = "Aurora PostgreSQL superuser password"
+ secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:superuser-6gsjLD"
+ }
+ }
+ kms_key_arns = ["arn:aws:kms:eu-west-1:123456789012:key/6ca29066-552a-46c5-a7d7-7bf9a15fc255"]
}
```
### State Changes
- None

View file

@ -30,37 +30,29 @@ An EC2 instance configuration has been provided for use in validating the exampl
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 | | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.38 | | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
## Providers ## Providers
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.38 | | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
## Modules ## Modules
| Name | Source | Version | | Name | Source | Version |
|------|--------|---------| |------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds-aurora/aws | ~> 6.0 | | <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds-aurora/aws | ~> 8.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a | | <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 4.0 | | <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | | <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
## Resources ## Resources
| Name | Type | | Name | Type |
|------|------| |------|------|
| [aws_db_parameter_group.aurora_db_mysql57_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_rds_cluster_parameter_group.aurora_cluster_mysql57_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource |
| [aws_secretsmanager_secret.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource |
| [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source |
## Inputs ## Inputs

View file

@ -0,0 +1,144 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
locals {
name = "ex-${basename(path.cwd)}"
region = "eu-west-1"
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
auth = {
"root" = {
description = "Cluster generated master user password"
secret_arn = module.rds.cluster_master_user_secret[0].secret_arn
}
}
engine_family = "MYSQL"
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.cluster_id
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "~> 8.0"
name = local.name
engine = "aurora-mysql"
engine_version = "8.0"
master_username = "root"
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
instance_class = "db.r6g.large"
instances = {
1 = {}
2 = {}
}
vpc_id = module.vpc.vpc_id
db_subnet_group_name = module.vpc.database_subnet_group_name
security_group_rules = {
vpc_ingress = {
cidr_blocks = module.vpc.private_subnets_cidr_blocks
}
}
apply_immediately = true
skip_final_snapshot = true
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "${local.name}-proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}

View file

@ -66,7 +66,7 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endponts # DB proxy endpoints
output "db_proxy_endpoints" { output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created" description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints value = module.rds_proxy.db_proxy_endpoints

View file

@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}

View file

@ -30,26 +30,26 @@ An EC2 instance configuration has been provided for use in validating the exampl
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 | | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.38 | | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 | | <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
## Providers ## Providers
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.38 | | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 | | <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
## Modules ## Modules
| Name | Source | Version | | Name | Source | Version |
|------|--------|---------| |------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds/aws | ~> 3.0 | | <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds/aws | ~> 5.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a | | <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 4.0 | | <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_rds_sg"></a> [rds\_sg](#module\_rds\_sg) | terraform-aws-modules/security-group/aws | ~> 4.0 | | <a name="module_rds_sg"></a> [rds\_sg](#module\_rds\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | | <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
## Resources ## Resources
@ -59,6 +59,7 @@ An EC2 instance configuration has been provided for use in validating the exampl
| [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | | [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | | [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | | [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | | [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source |
## Inputs ## Inputs

View file

@ -2,17 +2,22 @@ provider "aws" {
region = local.region region = local.region
} }
data "aws_availability_zones" "available" {}
locals { locals {
region = "us-east-1" name = "ex-${basename(path.cwd)}"
name = "rds-proxy-ex-${replace(basename(path.cwd), "_", "-")}" region = "eu-west-1"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result db_password = random_password.password.result
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = { tags = {
Name = local.name
Example = local.name Example = local.name
Repository = "https://github.com/terraform-aws-modules/terraform-aws-rds-proxy" GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
} }
} }
@ -23,14 +28,12 @@ locals {
module "rds_proxy" { module "rds_proxy" {
source = "../../" source = "../../"
create_proxy = true
name = local.name name = local.name
iam_role_name = local.name iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id] vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
db_proxy_endpoints = { endpoints = {
read_write = { read_write = {
name = "read-write-endpoint" name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets vpc_subnet_ids = module.vpc.private_subnets
@ -46,11 +49,10 @@ module "rds_proxy" {
} }
} }
secrets = { auth = {
(local.db_username) = { (local.db_username) = {
description = aws_secretsmanager_secret.superuser.description description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn secret_arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
} }
} }
@ -80,38 +82,52 @@ resource "random_password" "password" {
module "vpc" { module "vpc" {
source = "terraform-aws-modules/vpc/aws" source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0" version = "~> 5.0"
name = local.name name = local.name
cidr = "10.0.0.0/18" cidr = local.vpc_cidr
azs = ["${local.region}a", "${local.region}b", "${local.region}c"] azs = local.azs
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"] private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"] database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
create_database_subnet_group = true tags = local.tags
enable_nat_gateway = true }
single_nat_gateway = true
map_public_ip_on_launch = false
manage_default_security_group = true module "rds" {
default_security_group_ingress = [] source = "terraform-aws-modules/rds/aws"
default_security_group_egress = [] version = "~> 5.0"
enable_flow_log = true username = local.db_username
flow_log_destination_type = "cloud-watch-logs" password = local.db_password
create_flow_log_cloudwatch_log_group = true
create_flow_log_cloudwatch_iam_role = true # When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
flow_log_max_aggregation_interval = 60 iam_database_authentication_enabled = false
flow_log_log_format = "$${version} $${account-id} $${interface-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${start} $${end} $${action} $${log-status} $${vpc-id} $${subnet-id} $${instance-id} $${tcp-flags} $${type} $${pkt-srcaddr} $${pkt-dstaddr} $${region} $${az-id} $${sublocation-type} $${sublocation-id}"
identifier = local.name
engine = "mysql"
engine_version = "8.0"
family = "mysql8.0" # DB parameter group
major_engine_version = "8.0" # DB option group
instance_class = "db.t4g.large"
allocated_storage = 20
port = 3306
apply_immediately = true
db_subnet_group_name = module.vpc.database_subnet_group
vpc_security_group_ids = [module.rds_sg.security_group_id]
multi_az = true
backup_retention_period = 0
deletion_protection = false
tags = local.tags tags = local.tags
} }
module "rds_sg" { module "rds_sg" {
source = "terraform-aws-modules/security-group/aws" source = "terraform-aws-modules/security-group/aws"
version = "~> 4.0" version = "~> 5.0"
name = "rds" name = "rds"
description = "MySQL RDS example security group" description = "MySQL RDS example security group"
@ -130,57 +146,19 @@ module "rds_sg" {
tags = local.tags tags = local.tags
} }
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "~> 3.0"
name = "example"
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
identifier = local.name
engine = "mysql"
engine_version = "5.7.31"
family = "mysql5.7"
major_engine_version = "5.7"
port = 3306
instance_class = "db.t3.micro"
allocated_storage = 5
storage_encrypted = true
apply_immediately = true
enabled_cloudwatch_logs_exports = ["general", "error", "slowquery"]
monitoring_interval = 60
create_monitoring_role = true
vpc_security_group_ids = [module.rds_sg.security_group_id]
subnet_ids = module.vpc.database_subnets
multi_az = true
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
backup_retention_period = 0
deletion_protection = false
tags = local.tags
}
module "rds_proxy_sg" { module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws" source = "terraform-aws-modules/security-group/aws"
version = "~> 4.0" version = "~> 5.0"
name = "rds_proxy" name = "${local.name}-proxy"
description = "MySQL RDS Proxy example security group" description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true revoke_rules_on_delete = true
ingress_with_cidr_blocks = [ ingress_with_cidr_blocks = [
{ {
description = "Private subnet PostgreSQL access" description = "Private subnet MySQL access"
rule = "mysql-tcp" rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks) cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
} }
@ -207,7 +185,7 @@ data "aws_kms_alias" "secretsmanager" {
resource "aws_secretsmanager_secret" "superuser" { resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values" description = "Database superuser, ${local.db_username}, database connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags tags = local.tags

View file

@ -66,7 +66,7 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endponts # DB proxy endpoints
output "db_proxy_endpoints" { output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created" description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints value = module.rds_proxy.db_proxy_endpoints

View file

@ -1,10 +1,10 @@
terraform { terraform {
required_version = ">= 0.13.1" required_version = ">= 1.0"
required_providers { required_providers {
aws = { aws = {
source = "hashicorp/aws" source = "hashicorp/aws"
version = ">= 3.38" version = ">= 5.0"
} }
random = { random = {
source = "hashicorp/random" source = "hashicorp/random"

View file

@ -1,217 +0,0 @@
provider "aws" {
region = local.region
}
locals {
region = "us-east-1"
name = "rds-proxy-ex-${replace(basename(path.cwd), "_", "-")}"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
tags = {
Name = local.name
Example = local.name
Repository = "https://github.com/terraform-aws-modules/terraform-aws-rds-proxy"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
create_proxy = true
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
db_proxy_endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
secrets = {
(local.db_username) = {
description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
}
}
engine_family = "MYSQL"
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.cluster_id
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0"
name = local.name
cidr = "10.0.0.0/18"
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
create_database_subnet_group = true
enable_nat_gateway = true
single_nat_gateway = true
map_public_ip_on_launch = false
manage_default_security_group = true
default_security_group_ingress = []
default_security_group_egress = []
enable_flow_log = true
flow_log_destination_type = "cloud-watch-logs"
create_flow_log_cloudwatch_log_group = true
create_flow_log_cloudwatch_iam_role = true
flow_log_max_aggregation_interval = 60
flow_log_log_format = "$${version} $${account-id} $${interface-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${start} $${end} $${action} $${log-status} $${vpc-id} $${subnet-id} $${instance-id} $${tcp-flags} $${type} $${pkt-srcaddr} $${pkt-dstaddr} $${region} $${az-id} $${sublocation-type} $${sublocation-id}"
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "~> 6.0"
name = local.name
database_name = "example"
master_username = local.db_username
master_password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
engine = "aurora-mysql"
engine_version = "5.7.12"
instance_class = "db.r6g.large"
instances = { 1 = {}, 2 = {} }
storage_encrypted = true
apply_immediately = true
skip_final_snapshot = true
enabled_cloudwatch_logs_exports = ["general", "error", "slowquery"]
monitoring_interval = 60
create_monitoring_role = true
vpc_id = module.vpc.vpc_id
subnets = module.vpc.database_subnets
create_security_group = false
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
db_subnet_group_name = local.name # Created by VPC module
create_db_subnet_group = false
db_parameter_group_name = aws_db_parameter_group.aurora_db_mysql57_parameter_group.id
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_mysql57_parameter_group.id
tags = local.tags
}
resource "aws_db_parameter_group" "aurora_db_mysql57_parameter_group" {
name = "example-aurora-db-57-parameter-group"
family = "aurora-mysql5.7"
description = "example-aurora-db-57-parameter-group"
tags = local.tags
}
resource "aws_rds_cluster_parameter_group" "aurora_cluster_mysql57_parameter_group" {
name = "example-aurora-57-cluster-parameter-group"
family = "aurora-mysql5.7"
description = "example-aurora-57-cluster-parameter-group"
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 4.0"
name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet MySQL access"
rule = "mysql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}

View file

@ -1,14 +0,0 @@
terraform {
required_version = ">= 0.13.1"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.38"
}
random = {
source = "hashicorp/random"
version = ">= 2.0"
}
}
}

View file

@ -30,37 +30,29 @@ An EC2 instance configuration has been provided for use in validating the exampl
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 | | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.38 | | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
## Providers ## Providers
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.38 | | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
## Modules ## Modules
| Name | Source | Version | | Name | Source | Version |
|------|--------|---------| |------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds-aurora/aws | ~> 6.0 | | <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds-aurora/aws | ~> 8.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a | | <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 4.0 | | <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | | <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
## Resources ## Resources
| Name | Type | | Name | Type |
|------|------| |------|------|
| [aws_db_parameter_group.aurora_db_postgres11_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_rds_cluster_parameter_group.aurora_cluster_postgres11_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource |
| [aws_secretsmanager_secret.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource |
| [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source |
## Inputs ## Inputs

View file

@ -0,0 +1,144 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
locals {
name = "ex-${basename(path.cwd)}"
region = "eu-west-1"
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Example = local.name
GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
auth = {
"root" = {
description = "Cluster generated master user password"
secret_arn = module.rds.cluster_master_user_secret[0].secret_arn
}
}
engine_family = "POSTGRESQL"
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.cluster_id
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "~> 8.0"
name = local.name
engine = "aurora-postgresql"
engine_version = "14.7"
master_username = "root"
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
instance_class = "db.r6g.large"
instances = {
1 = {}
2 = {}
}
vpc_id = module.vpc.vpc_id
db_subnet_group_name = module.vpc.database_subnet_group_name
security_group_rules = {
vpc_ingress = {
cidr_blocks = module.vpc.private_subnets_cidr_blocks
}
}
apply_immediately = true
skip_final_snapshot = true
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.0"
name = "${local.name}-proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}

View file

@ -66,7 +66,7 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endponts # DB proxy endpoints
output "db_proxy_endpoints" { output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created" description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints value = module.rds_proxy.db_proxy_endpoints

View file

@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}

View file

@ -30,26 +30,26 @@ An EC2 instance configuration has been provided for use in validating the exampl
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 | | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.38 | | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 | | <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |
## Providers ## Providers
| Name | Version | | Name | Version |
|------|---------| |------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.38 | | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 | | <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
## Modules ## Modules
| Name | Source | Version | | Name | Source | Version |
|------|--------|---------| |------|--------|---------|
| <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds/aws | ~> 3.0 | | <a name="module_rds"></a> [rds](#module\_rds) | terraform-aws-modules/rds/aws | ~> 5.0 |
| <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a | | <a name="module_rds_proxy"></a> [rds\_proxy](#module\_rds\_proxy) | ../../ | n/a |
| <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 4.0 | | <a name="module_rds_proxy_sg"></a> [rds\_proxy\_sg](#module\_rds\_proxy\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_rds_sg"></a> [rds\_sg](#module\_rds\_sg) | terraform-aws-modules/security-group/aws | ~> 4.0 | | <a name="module_rds_sg"></a> [rds\_sg](#module\_rds\_sg) | terraform-aws-modules/security-group/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | | <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
## Resources ## Resources
@ -59,6 +59,7 @@ An EC2 instance configuration has been provided for use in validating the exampl
| [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | | [aws_secretsmanager_secret_version.superuser](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | | [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | | [random_pet.users](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | | [aws_kms_alias.secretsmanager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source |
## Inputs ## Inputs

View file

@ -2,17 +2,22 @@ provider "aws" {
region = local.region region = local.region
} }
data "aws_availability_zones" "available" {}
locals { locals {
region = "us-east-1" name = "ex-${basename(path.cwd)}"
name = "rds-proxy-ex-${replace(basename(path.cwd), "_", "-")}" region = "eu-west-1"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result db_password = random_password.password.result
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = { tags = {
Name = local.name
Example = local.name Example = local.name
Repository = "https://github.com/terraform-aws-modules/terraform-aws-rds-proxy" GithubRepo = "terraform-aws-rds-proxy"
GithubOrg = "terraform-aws-modules"
} }
} }
@ -23,14 +28,12 @@ locals {
module "rds_proxy" { module "rds_proxy" {
source = "../../" source = "../../"
create_proxy = true
name = local.name name = local.name
iam_role_name = local.name iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id] vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
db_proxy_endpoints = { endpoints = {
read_write = { read_write = {
name = "read-write-endpoint" name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets vpc_subnet_ids = module.vpc.private_subnets
@ -46,11 +49,10 @@ module "rds_proxy" {
} }
} }
secrets = { auth = {
(local.db_username) = { (local.db_username) = {
description = aws_secretsmanager_secret.superuser.description description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn secret_arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
} }
} }
@ -80,38 +82,52 @@ resource "random_password" "password" {
module "vpc" { module "vpc" {
source = "terraform-aws-modules/vpc/aws" source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0" version = "~> 5.0"
name = local.name name = local.name
cidr = "10.0.0.0/18" cidr = local.vpc_cidr
azs = ["${local.region}a", "${local.region}b", "${local.region}c"] azs = local.azs
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"] private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"] database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]
create_database_subnet_group = true tags = local.tags
enable_nat_gateway = true }
single_nat_gateway = true
map_public_ip_on_launch = false
manage_default_security_group = true module "rds" {
default_security_group_ingress = [] source = "terraform-aws-modules/rds/aws"
default_security_group_egress = [] version = "~> 5.0"
enable_flow_log = true username = local.db_username
flow_log_destination_type = "cloud-watch-logs" password = local.db_password
create_flow_log_cloudwatch_log_group = true
create_flow_log_cloudwatch_iam_role = true # When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
flow_log_max_aggregation_interval = 60 iam_database_authentication_enabled = false
flow_log_log_format = "$${version} $${account-id} $${interface-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${start} $${end} $${action} $${log-status} $${vpc-id} $${subnet-id} $${instance-id} $${tcp-flags} $${type} $${pkt-srcaddr} $${pkt-dstaddr} $${region} $${az-id} $${sublocation-type} $${sublocation-id}"
identifier = local.name
engine = "postgres"
engine_version = "14"
family = "postgres14" # DB parameter group
major_engine_version = "14" # DB option group
instance_class = "db.t4g.large"
allocated_storage = 20
port = 5432
apply_immediately = true
db_subnet_group_name = module.vpc.database_subnet_group
vpc_security_group_ids = [module.rds_sg.security_group_id]
multi_az = true
backup_retention_period = 0
deletion_protection = false
tags = local.tags tags = local.tags
} }
module "rds_sg" { module "rds_sg" {
source = "terraform-aws-modules/security-group/aws" source = "terraform-aws-modules/security-group/aws"
version = "~> 4.0" version = "~> 5.0"
name = "rds" name = "rds"
description = "PostgreSQL RDS example security group" description = "PostgreSQL RDS example security group"
@ -130,47 +146,9 @@ module "rds_sg" {
tags = local.tags tags = local.tags
} }
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "~> 3.0"
name = "example"
username = local.db_username
password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
identifier = local.name
engine = "postgres"
engine_version = "11.12"
family = "postgres11"
major_engine_version = "11"
port = 5432
instance_class = "db.t3.micro"
allocated_storage = 5
storage_encrypted = true
apply_immediately = true
enabled_cloudwatch_logs_exports = ["postgresql"]
monitoring_interval = 60
create_monitoring_role = true
vpc_security_group_ids = [module.rds_sg.security_group_id]
subnet_ids = module.vpc.database_subnets
multi_az = true
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
backup_retention_period = 0
deletion_protection = false
tags = local.tags
}
module "rds_proxy_sg" { module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws" source = "terraform-aws-modules/security-group/aws"
version = "~> 4.0" version = "~> 5.0"
name = "rds_proxy" name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group" description = "PostgreSQL RDS Proxy example security group"
@ -207,7 +185,7 @@ data "aws_kms_alias" "secretsmanager" {
resource "aws_secretsmanager_secret" "superuser" { resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values" description = "Database superuser, ${local.db_username}, database connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags tags = local.tags

View file

@ -66,7 +66,7 @@ output "proxy_target_type" {
value = module.rds_proxy.proxy_target_type value = module.rds_proxy.proxy_target_type
} }
# DB proxy endponts # DB proxy endpoints
output "db_proxy_endpoints" { output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created" description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = module.rds_proxy.db_proxy_endpoints value = module.rds_proxy.db_proxy_endpoints

View file

@ -1,10 +1,10 @@
terraform { terraform {
required_version = ">= 0.13.1" required_version = ">= 1.0"
required_providers { required_providers {
aws = { aws = {
source = "hashicorp/aws" source = "hashicorp/aws"
version = ">= 3.38" version = ">= 5.0"
} }
random = { random = {
source = "hashicorp/random" source = "hashicorp/random"

View file

@ -1,217 +0,0 @@
provider "aws" {
region = local.region
}
locals {
region = "us-east-1"
name = "rds-proxy-ex-${replace(basename(path.cwd), "_", "-")}"
db_username = random_pet.users.id # using random here due to secrets taking at least 7 days before fully deleting from account
db_password = random_password.password.result
tags = {
Name = local.name
Example = local.name
Repository = "https://github.com/terraform-aws-modules/terraform-aws-rds-proxy"
}
}
################################################################################
# RDS Proxy
################################################################################
module "rds_proxy" {
source = "../../"
create_proxy = true
name = local.name
iam_role_name = local.name
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
db_proxy_endpoints = {
read_write = {
name = "read-write-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
tags = local.tags
},
read_only = {
name = "read-only-endpoint"
vpc_subnet_ids = module.vpc.private_subnets
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
target_role = "READ_ONLY"
tags = local.tags
}
}
secrets = {
(local.db_username) = {
description = aws_secretsmanager_secret.superuser.description
arn = aws_secretsmanager_secret.superuser.arn
kms_key_id = aws_secretsmanager_secret.superuser.kms_key_id
}
}
engine_family = "POSTGRESQL"
debug_logging = true
# Target Aurora cluster
target_db_cluster = true
db_cluster_identifier = module.rds.cluster_id
tags = local.tags
}
################################################################################
# Supporting Resources
################################################################################
resource "random_pet" "users" {
length = 2
separator = "_"
}
resource "random_password" "password" {
length = 16
special = false
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0"
name = local.name
cidr = "10.0.0.0/18"
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24"]
database_subnets = ["10.0.7.0/24", "10.0.8.0/24", "10.0.9.0/24"]
create_database_subnet_group = true
enable_nat_gateway = true
single_nat_gateway = true
map_public_ip_on_launch = false
manage_default_security_group = true
default_security_group_ingress = []
default_security_group_egress = []
enable_flow_log = true
flow_log_destination_type = "cloud-watch-logs"
create_flow_log_cloudwatch_log_group = true
create_flow_log_cloudwatch_iam_role = true
flow_log_max_aggregation_interval = 60
flow_log_log_format = "$${version} $${account-id} $${interface-id} $${srcaddr} $${dstaddr} $${srcport} $${dstport} $${protocol} $${packets} $${bytes} $${start} $${end} $${action} $${log-status} $${vpc-id} $${subnet-id} $${instance-id} $${tcp-flags} $${type} $${pkt-srcaddr} $${pkt-dstaddr} $${region} $${az-id} $${sublocation-type} $${sublocation-id}"
tags = local.tags
}
module "rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "~> 6.0"
name = local.name
database_name = "example"
master_username = local.db_username
master_password = local.db_password
# When using RDS Proxy w/ IAM auth - Database must be username/password auth, not IAM
iam_database_authentication_enabled = false
engine = "aurora-postgresql"
engine_version = "11.12"
instance_class = "db.r6g.large"
instances = { 1 = {}, 2 = {} }
storage_encrypted = true
apply_immediately = true
skip_final_snapshot = true
enabled_cloudwatch_logs_exports = ["postgresql"]
monitoring_interval = 60
create_monitoring_role = true
vpc_id = module.vpc.vpc_id
subnets = module.vpc.database_subnets
create_security_group = false
vpc_security_group_ids = [module.rds_proxy_sg.security_group_id]
db_subnet_group_name = local.name # Created by VPC module
create_db_subnet_group = false
db_parameter_group_name = aws_db_parameter_group.aurora_db_postgres11_parameter_group.id
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_postgres11_parameter_group.id
tags = local.tags
}
resource "aws_db_parameter_group" "aurora_db_postgres11_parameter_group" {
name = "example-aurora-db-postgres11-parameter-group"
family = "aurora-postgresql11"
description = "test-aurora-db-postgres11-parameter-group"
tags = local.tags
}
resource "aws_rds_cluster_parameter_group" "aurora_cluster_postgres11_parameter_group" {
name = "example-aurora-postgres11-cluster-parameter-group"
family = "aurora-postgresql11"
description = "example-aurora-postgres11-cluster-parameter-group"
tags = local.tags
}
module "rds_proxy_sg" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 4.0"
name = "rds_proxy"
description = "PostgreSQL RDS Proxy example security group"
vpc_id = module.vpc.vpc_id
revoke_rules_on_delete = true
ingress_with_cidr_blocks = [
{
description = "Private subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.private_subnets_cidr_blocks)
}
]
egress_with_cidr_blocks = [
{
description = "Database subnet PostgreSQL access"
rule = "postgresql-tcp"
cidr_blocks = join(",", module.vpc.database_subnets_cidr_blocks)
},
]
tags = local.tags
}
################################################################################
# Secrets - DB user passwords
################################################################################
data "aws_kms_alias" "secretsmanager" {
name = "alias/aws/secretsmanager"
}
resource "aws_secretsmanager_secret" "superuser" {
name = local.db_username
description = "Database superuser, ${local.db_username}, databse connection values"
kms_key_id = data.aws_kms_alias.secretsmanager.id
tags = local.tags
}
resource "aws_secretsmanager_secret_version" "superuser" {
secret_id = aws_secretsmanager_secret.superuser.id
secret_string = jsonencode({
username = local.db_username
password = local.db_password
})
}

View file

@ -1,14 +0,0 @@
terraform {
required_version = ">= 0.13.1"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.38"
}
random = {
source = "hashicorp/random"
version = ">= 2.0"
}
}
}

67
main.tf
View file

@ -1,44 +1,48 @@
locals { locals {
role_arn = var.create_proxy && var.create_iam_role ? aws_iam_role.this[0].arn : var.role_arn role_arn = var.create && var.create_iam_role ? aws_iam_role.this[0].arn : var.role_arn
role_name = coalesce(var.iam_role_name, var.name) role_name = coalesce(var.iam_role_name, var.name)
policy_name = coalesce(var.iam_policy_name, var.name) policy_name = coalesce(var.iam_policy_name, var.name)
} }
data "aws_region" "current" {} data "aws_region" "current" {}
data "aws_partition" "current" {}
################################################################################ ################################################################################
# RDS Proxy # RDS Proxy
################################################################################ ################################################################################
resource "aws_db_proxy" "this" { resource "aws_db_proxy" "this" {
count = var.create_proxy ? 1 : 0 count = var.create ? 1 : 0
dynamic "auth" {
for_each = var.auth
content {
auth_scheme = try(auth.value.auth_scheme, "SECRETS")
client_password_auth_type = try(auth.value.client_password_auth_type, null)
description = try(auth.value.description, null)
iam_auth = try(auth.value.iam_auth, null)
secret_arn = try(auth.value.secret_arn, null)
username = try(auth.value.username, null)
}
}
name = var.name
debug_logging = var.debug_logging debug_logging = var.debug_logging
engine_family = var.engine_family engine_family = var.engine_family
idle_client_timeout = var.idle_client_timeout idle_client_timeout = var.idle_client_timeout
name = var.name
require_tls = var.require_tls require_tls = var.require_tls
role_arn = local.role_arn role_arn = local.role_arn
vpc_security_group_ids = var.vpc_security_group_ids vpc_security_group_ids = var.vpc_security_group_ids
vpc_subnet_ids = var.vpc_subnet_ids vpc_subnet_ids = var.vpc_subnet_ids
dynamic "auth" {
for_each = var.secrets
content {
auth_scheme = var.auth_scheme
description = auth.value.description
iam_auth = var.iam_auth
secret_arn = auth.value.arn
}
}
tags = merge(var.tags, var.proxy_tags) tags = merge(var.tags, var.proxy_tags)
depends_on = [aws_cloudwatch_log_group.this] depends_on = [aws_cloudwatch_log_group.this]
} }
resource "aws_db_proxy_default_target_group" "this" { resource "aws_db_proxy_default_target_group" "this" {
count = var.create_proxy ? 1 : 0 count = var.create ? 1 : 0
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
@ -52,7 +56,7 @@ resource "aws_db_proxy_default_target_group" "this" {
} }
resource "aws_db_proxy_target" "db_instance" { resource "aws_db_proxy_target" "db_instance" {
count = var.create_proxy && var.target_db_instance ? 1 : 0 count = var.create && var.target_db_instance ? 1 : 0
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
target_group_name = aws_db_proxy_default_target_group.this[0].name target_group_name = aws_db_proxy_default_target_group.this[0].name
@ -60,7 +64,7 @@ resource "aws_db_proxy_target" "db_instance" {
} }
resource "aws_db_proxy_target" "db_cluster" { resource "aws_db_proxy_target" "db_cluster" {
count = var.create_proxy && var.target_db_cluster ? 1 : 0 count = var.create && var.target_db_cluster ? 1 : 0
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
target_group_name = aws_db_proxy_default_target_group.this[0].name target_group_name = aws_db_proxy_default_target_group.this[0].name
@ -68,7 +72,7 @@ resource "aws_db_proxy_target" "db_cluster" {
} }
resource "aws_db_proxy_endpoint" "this" { resource "aws_db_proxy_endpoint" "this" {
for_each = { for k, v in var.db_proxy_endpoints : k => v if var.create_proxy } for_each = { for k, v in var.endpoints : k => v if var.create }
db_proxy_name = aws_db_proxy.this[0].name db_proxy_name = aws_db_proxy.this[0].name
db_proxy_endpoint_name = each.value.name db_proxy_endpoint_name = each.value.name
@ -84,7 +88,7 @@ resource "aws_db_proxy_endpoint" "this" {
################################################################################ ################################################################################
resource "aws_cloudwatch_log_group" "this" { resource "aws_cloudwatch_log_group" "this" {
count = var.create_proxy && var.manage_log_group ? 1 : 0 count = var.create && var.manage_log_group ? 1 : 0
name = "/aws/rds/proxy/${var.name}" name = "/aws/rds/proxy/${var.name}"
retention_in_days = var.log_group_retention_in_days retention_in_days = var.log_group_retention_in_days
@ -98,7 +102,7 @@ resource "aws_cloudwatch_log_group" "this" {
################################################################################ ################################################################################
data "aws_iam_policy_document" "assume_role" { data "aws_iam_policy_document" "assume_role" {
count = var.create_proxy && var.create_iam_role ? 1 : 0 count = var.create && var.create_iam_role ? 1 : 0
statement { statement {
sid = "RDSAssume" sid = "RDSAssume"
@ -107,13 +111,13 @@ data "aws_iam_policy_document" "assume_role" {
principals { principals {
type = "Service" type = "Service"
identifiers = ["rds.amazonaws.com"] identifiers = ["rds.${data.aws_partition.current.dns_suffix}"]
} }
} }
} }
resource "aws_iam_role" "this" { resource "aws_iam_role" "this" {
count = var.create_proxy && var.create_iam_role ? 1 : 0 count = var.create && var.create_iam_role ? 1 : 0
name = var.use_role_name_prefix ? null : local.role_name name = var.use_role_name_prefix ? null : local.role_name
name_prefix = var.use_role_name_prefix ? "${local.role_name}-" : null name_prefix = var.use_role_name_prefix ? "${local.role_name}-" : null
@ -129,19 +133,22 @@ resource "aws_iam_role" "this" {
} }
data "aws_iam_policy_document" "this" { data "aws_iam_policy_document" "this" {
count = var.create_proxy && var.create_iam_role ? 1 : 0 count = var.create && var.create_iam_role && var.create_iam_policy ? 1 : 0
statement { statement {
sid = "DecryptSecrets" sid = "DecryptSecrets"
effect = "Allow" effect = "Allow"
actions = ["kms:Decrypt"] actions = ["kms:Decrypt"]
resources = distinct([for secret in var.secrets : secret.kms_key_id]) resources = coalescelist(
var.kms_key_arns,
["arn:${data.aws_partition.current.partition}:kms:*:*:key/*"]
)
condition { condition {
test = "StringEquals" test = "StringEquals"
variable = "kms:ViaService" variable = "kms:ViaService"
values = [ values = [
"secretsmanager.${data.aws_region.current.name}.amazonaws.com" "secretsmanager.${data.aws_region.current.name}.${data.aws_partition.current.dns_suffix}"
] ]
} }
} }
@ -166,12 +173,12 @@ data "aws_iam_policy_document" "this" {
"secretsmanager:ListSecretVersionIds", "secretsmanager:ListSecretVersionIds",
] ]
resources = distinct([for secret in var.secrets : secret.arn]) resources = distinct([for auth in var.auth : auth.secret_arn])
} }
} }
resource "aws_iam_role_policy" "this" { resource "aws_iam_role_policy" "this" {
count = var.create_proxy && var.create_iam_role && var.create_iam_policy ? 1 : 0 count = var.create && var.create_iam_role && var.create_iam_policy ? 1 : 0
name = var.use_policy_name_prefix ? null : local.policy_name name = var.use_policy_name_prefix ? null : local.policy_name
name_prefix = var.use_policy_name_prefix ? "${local.policy_name}-" : null name_prefix = var.use_policy_name_prefix ? "${local.policy_name}-" : null

View file

@ -1,72 +1,72 @@
# RDS Proxy # RDS Proxy
output "proxy_id" { output "proxy_id" {
description = "The ID for the proxy" description = "The ID for the proxy"
value = try(aws_db_proxy.this[0].id, "") value = try(aws_db_proxy.this[0].id, null)
} }
output "proxy_arn" { output "proxy_arn" {
description = "The Amazon Resource Name (ARN) for the proxy" description = "The Amazon Resource Name (ARN) for the proxy"
value = try(aws_db_proxy.this[0].arn, "") value = try(aws_db_proxy.this[0].arn, null)
} }
output "proxy_endpoint" { output "proxy_endpoint" {
description = "The endpoint that you can use to connect to the proxy" description = "The endpoint that you can use to connect to the proxy"
value = try(aws_db_proxy.this[0].endpoint, "") value = try(aws_db_proxy.this[0].endpoint, null)
} }
# Proxy Default Target Group # Proxy Default Target Group
output "proxy_default_target_group_id" { output "proxy_default_target_group_id" {
description = "The ID for the default target group" description = "The ID for the default target group"
value = try(aws_db_proxy_default_target_group.this[0].id, "") value = try(aws_db_proxy_default_target_group.this[0].id, null)
} }
output "proxy_default_target_group_arn" { output "proxy_default_target_group_arn" {
description = "The Amazon Resource Name (ARN) for the default target group" description = "The Amazon Resource Name (ARN) for the default target group"
value = try(aws_db_proxy_default_target_group.this[0].arn, "") value = try(aws_db_proxy_default_target_group.this[0].arn, null)
} }
output "proxy_default_target_group_name" { output "proxy_default_target_group_name" {
description = "The name of the default target group" description = "The name of the default target group"
value = try(aws_db_proxy_default_target_group.this[0].name, "") value = try(aws_db_proxy_default_target_group.this[0].name, null)
} }
# Proxy Target # Proxy Target
output "proxy_target_endpoint" { output "proxy_target_endpoint" {
description = "Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type" description = "Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type"
value = try(aws_db_proxy_target.db_instance[0].endpoint, aws_db_proxy_target.db_cluster[0].endpoint, "") value = try(aws_db_proxy_target.db_instance[0].endpoint, aws_db_proxy_target.db_cluster[0].endpoint, null)
} }
output "proxy_target_id" { output "proxy_target_id" {
description = "Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/)" description = "Identifier of `db_proxy_name`, `target_group_name`, target type (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (/)"
value = try(aws_db_proxy_target.db_instance[0].id, aws_db_proxy_target.db_cluster[0].id, "") value = try(aws_db_proxy_target.db_instance[0].id, aws_db_proxy_target.db_cluster[0].id, null)
} }
output "proxy_target_port" { output "proxy_target_port" {
description = "Port for the target RDS DB Instance or Aurora DB Cluster" description = "Port for the target RDS DB Instance or Aurora DB Cluster"
value = try(aws_db_proxy_target.db_instance[0].port, aws_db_proxy_target.db_cluster[0].port, "") value = try(aws_db_proxy_target.db_instance[0].port, aws_db_proxy_target.db_cluster[0].port, null)
} }
output "proxy_target_rds_resource_id" { output "proxy_target_rds_resource_id" {
description = "Identifier representing the DB Instance or DB Cluster target" description = "Identifier representing the DB Instance or DB Cluster target"
value = try(aws_db_proxy_target.db_instance[0].rds_resource_id, aws_db_proxy_target.db_cluster[0].rds_resource_id, "") value = try(aws_db_proxy_target.db_instance[0].rds_resource_id, aws_db_proxy_target.db_cluster[0].rds_resource_id, null)
} }
output "proxy_target_target_arn" { output "proxy_target_target_arn" {
description = "Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API" description = "Amazon Resource Name (ARN) for the DB instance or DB cluster. Currently not returned by the RDS API"
value = try(aws_db_proxy_target.db_instance[0].target_arn, aws_db_proxy_target.db_cluster[0].target_arn, "") value = try(aws_db_proxy_target.db_instance[0].target_arn, aws_db_proxy_target.db_cluster[0].target_arn, null)
} }
output "proxy_target_tracked_cluster_id" { output "proxy_target_tracked_cluster_id" {
description = "DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS_INSTANCE target that is part of a DB Cluster" description = "DB Cluster identifier for the DB Instance target. Not returned unless manually importing an RDS_INSTANCE target that is part of a DB Cluster"
value = try(aws_db_proxy_target.db_cluster[0].tracked_cluster_id, "") value = try(aws_db_proxy_target.db_cluster[0].tracked_cluster_id, null)
} }
output "proxy_target_type" { output "proxy_target_type" {
description = "Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`" description = "Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`"
value = try(aws_db_proxy_target.db_instance[0].type, aws_db_proxy_target.db_cluster[0].type, "") value = try(aws_db_proxy_target.db_instance[0].type, aws_db_proxy_target.db_cluster[0].type, null)
} }
# DB proxy endponts # DB proxy endpoints
output "db_proxy_endpoints" { output "db_proxy_endpoints" {
description = "Array containing the full resource object and attributes for all DB proxy endpoints created" description = "Array containing the full resource object and attributes for all DB proxy endpoints created"
value = aws_db_proxy_endpoint.this value = aws_db_proxy_endpoint.this
@ -75,5 +75,5 @@ output "db_proxy_endpoints" {
# CloudWatch logs # CloudWatch logs
output "log_group_arn" { output "log_group_arn" {
description = "The Amazon Resource Name (ARN) of the CloudWatch log group" description = "The Amazon Resource Name (ARN) of the CloudWatch log group"
value = try(aws_cloudwatch_log_group.this[0].arn, "") value = try(aws_cloudwatch_log_group.this[0].arn, null)
} }

View file

@ -1,15 +1,18 @@
variable "create" {
description = "Whether cluster should be created (affects nearly all resources)"
type = bool
default = true
}
variable "tags" { variable "tags" {
description = "A map of tags to use on all resources" description = "A map of tags to add to all resources"
type = map(string) type = map(string)
default = {} default = {}
} }
################################################################################
# RDS Proxy # RDS Proxy
variable "create_proxy" { ################################################################################
description = "Determines whether a proxy and its resources will be created"
type = bool
default = true
}
variable "name" { variable "name" {
description = "The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens" description = "The identifier for the proxy. This name must be unique for all proxies owned by your AWS account in the specified AWS Region. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens; it can't end with a hyphen or contain two consecutive hyphens"
@ -17,6 +20,12 @@ variable "name" {
default = "" default = ""
} }
variable "auth" {
description = "Configuration block(s) with authorization mechanisms to connect to the associated instances or clusters"
type = any
default = {}
}
variable "debug_logging" { variable "debug_logging" {
description = "Whether the proxy includes detailed information about SQL statements in its logs" description = "Whether the proxy includes detailed information about SQL statements in its logs"
type = bool type = bool
@ -59,30 +68,12 @@ variable "vpc_subnet_ids" {
default = [] default = []
} }
variable "auth_scheme" {
description = "The type of authentication that the proxy uses for connections from the proxy to the underlying database. One of `SECRETS`"
type = string
default = "SECRETS"
}
variable "iam_auth" {
description = "Whether to require or disallow AWS Identity and Access Management (IAM) authentication for connections to the proxy. One of `DISABLED`, `REQUIRED`"
type = string
default = "REQUIRED"
}
variable "proxy_tags" { variable "proxy_tags" {
description = "A map of tags to apply to the RDS Proxy" description = "A map of tags to apply to the RDS Proxy"
type = map(string) type = map(string)
default = {} default = {}
} }
variable "secrets" {
description = "Map of secerets to be used by RDS Proxy for authentication to the database"
type = map(object({ arn = string, description = string, kms_key_id = string }))
default = {}
}
# Proxy Default Target Group # Proxy Default Target Group
variable "connection_borrow_timeout" { variable "connection_borrow_timeout" {
description = "The number of seconds for a proxy to wait for a connection to become available in the connection pool" description = "The number of seconds for a proxy to wait for a connection to become available in the connection pool"
@ -116,7 +107,7 @@ variable "session_pinning_filters" {
# Proxy Target # Proxy Target
variable "target_db_instance" { variable "target_db_instance" {
description = "Determines whether DB instance is targetted by proxy" description = "Determines whether DB instance is targeted by proxy"
type = bool type = bool
default = false default = false
} }
@ -128,7 +119,7 @@ variable "db_instance_identifier" {
} }
variable "target_db_cluster" { variable "target_db_cluster" {
description = "Determines whether DB cluster is targetted by proxy" description = "Determines whether DB cluster is targeted by proxy"
type = bool type = bool
default = false default = false
} }
@ -140,13 +131,16 @@ variable "db_cluster_identifier" {
} }
# Proxy endpoints # Proxy endpoints
variable "db_proxy_endpoints" { variable "endpoints" {
description = "Map of DB proxy endpoints to create and their attributes (see `aws_db_proxy_endpoint`)" description = "Map of DB proxy endpoints to create and their attributes (see `aws_db_proxy_endpoint`)"
type = any type = any
default = {} default = {}
} }
################################################################################
# CloudWatch Logs # CloudWatch Logs
################################################################################
variable "manage_log_group" { variable "manage_log_group" {
description = "Determines whether Terraform will create/manage the CloudWatch log group or not. Note - this will fail if set to true after the log group has been created as the resource will already exist" description = "Determines whether Terraform will create/manage the CloudWatch log group or not. Note - this will fail if set to true after the log group has been created as the resource will already exist"
type = bool type = bool
@ -171,7 +165,10 @@ variable "log_group_tags" {
default = {} default = {}
} }
################################################################################
# IAM Role # IAM Role
################################################################################
variable "create_iam_role" { variable "create_iam_role" {
description = "Determines whether an IAM role is created" description = "Determines whether an IAM role is created"
type = bool type = bool
@ -244,3 +241,9 @@ variable "use_policy_name_prefix" {
type = bool type = bool
default = false default = false
} }
variable "kms_key_arns" {
description = "List of KMS Key ARNs to allow access to decrypt SecretsManager secrets"
type = list(string)
default = []
}

View file

@ -1,10 +1,10 @@
terraform { terraform {
required_version = ">= 0.13.1" required_version = ">= 1.0"
required_providers { required_providers {
aws = { aws = {
source = "hashicorp/aws" source = "hashicorp/aws"
version = ">= 3.38" version = ">= 5.0"
} }
} }
} }