Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional user and password #119

Closed
wants to merge 12 commits into from
131 changes: 74 additions & 57 deletions README.md

Large diffs are not rendered by default.

110 changes: 57 additions & 53 deletions README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,59 +41,61 @@ introduction: |-
usage: |-
```hcl
module "rds_instance" {
source = "cloudposse/rds/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "eg"
stage = "prod"
name = "app"
dns_zone_id = "Z89FN1IW975KPE"
host_name = "db"
security_group_ids = ["sg-xxxxxxxx"]
ca_cert_identifier = "rds-ca-2019"
allowed_cidr_blocks = ["XXX.XXX.XXX.XXX/32"]
database_name = "wordpress"
database_user = "admin"
database_password = "xxxxxxxxxxxx"
database_port = 3306
multi_az = true
storage_type = "gp2"
allocated_storage = 100
storage_encrypted = true
engine = "mysql"
engine_version = "5.7.17"
major_engine_version = "5.7"
instance_class = "db.t2.medium"
db_parameter_group = "mysql5.7"
option_group_name = "mysql-options"
publicly_accessible = false
subnet_ids = ["sb-xxxxxxxxx", "sb-xxxxxxxxx"]
vpc_id = "vpc-xxxxxxxx"
snapshot_identifier = "rds:production-2015-06-26-06-05"
auto_minor_version_upgrade = true
allow_major_version_upgrade = false
apply_immediately = false
maintenance_window = "Mon:03:00-Mon:04:00"
skip_final_snapshot = false
copy_tags_to_snapshot = true
backup_retention_period = 7
backup_window = "22:00-03:00"
source = "cloudposse/rds/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
namespace = "eg"
stage = "prod"
name = "app"
dns_zone_id = "Z89FN1IW975KPE"
host_name = "db"
security_group_ids = ["sg-xxxxxxxx"]
ca_cert_identifier = "rds-ca-2019"
allowed_cidr_blocks = ["XXX.XXX.XXX.XXX/32"]
database_name = "wordpress"
database_user = "admin"
database_password = "xxxxxxxxxxxx"
database_port = 3306
multi_az = true
storage_type = "gp2"
allocated_storage = 100
storage_encrypted = true
engine = "mysql"
engine_version = "5.7.17"
major_engine_version = "5.7"
instance_class = "db.t2.medium"
db_parameter_group = "mysql5.7"
option_group_name = "mysql-options"
publicly_accessible = false
subnet_ids = ["sb-xxxxxxxxx", "sb-xxxxxxxxx"]
vpc_id = "vpc-xxxxxxxx"
snapshot_identifier = "rds:production-2015-06-26-06-05"
auto_minor_version_upgrade = true
allow_major_version_upgrade = false
apply_immediately = false
maintenance_window = "Mon:03:00-Mon:04:00"
skip_final_snapshot = false
copy_tags_to_snapshot = true
backup_retention_period = 7
backup_window = "22:00-03:00"

db_parameter = [
{ name = "myisam_sort_buffer_size" value = "1048576" },
{ name = "sort_buffer_size" value = "2097152" }
]
db_parameter = [
{ name = "myisam_sort_buffer_size" value = "1048576" },
{ name = "sort_buffer_size" value = "2097152" }
]

db_options = [
{ option_name = "MARIADB_AUDIT_PLUGIN"
option_settings = [
{ name = "SERVER_AUDIT_EVENTS" value = "CONNECT" },
{ name = "SERVER_AUDIT_FILE_ROTATIONS" value = "37" }
]
}
]
db_options = [
{
option_name = "MARIADB_AUDIT_PLUGIN"
option_settings = [
{ name = "SERVER_AUDIT_EVENTS" value = "CONNECT" },
{ name = "SERVER_AUDIT_FILE_ROTATIONS" value = "37" }
]
}
]
}
```

### Character Sets

If you wish to create the database in a specific character set you can use one of the following options depending
Expand All @@ -103,9 +105,9 @@ usage: |-
to this module. For example, for Microsoft SQL, you could use:
```hcl
module "rds_instance" {
...
# ...
charset_name = "Korean_Wansung_CI_AS"
...
# ...
}
```

Expand All @@ -114,7 +116,7 @@ usage: |-

```hcl
module "rds_instance" {
...
# ...
db_parameter = [
{
name = "character_set_server"
Expand All @@ -127,7 +129,7 @@ usage: |-
apply_method = "immediate"
}
]
...
# ...
}
```
include:
Expand All @@ -150,3 +152,5 @@ contributors:
github: osulli
- name: Federico Márquez
github: fedemzcor
- name: RB
github: nitrocode
13 changes: 13 additions & 0 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.0 |
| <a name="requirement_null"></a> [null](#requirement\_null) | >= 2.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.0 |
| <a name="requirement_template"></a> [template](#requirement\_template) | >= 2.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 2.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 3.0 |

## Modules

Expand All @@ -34,6 +36,9 @@
| [aws_security_group_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.ingress_cidr_blocks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.ingress_security_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_ssm_parameter.rds_database](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource |
| [random_password.database_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
| [random_pet.database_user](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |

## Inputs

Expand Down Expand Up @@ -77,6 +82,7 @@
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br>Set to `0` for unlimited length.<br>Set to `null` for keep the existing setting, which defaults to `0`.<br>Does not affect `id_full`. | `number` | `null` | no |
| <a name="input_instance_class"></a> [instance\_class](#input\_instance\_class) | Class of RDS instance | `string` | n/a | yes |
| <a name="input_iops"></a> [iops](#input\_iops) | The amount of provisioned IOPS. Setting this implies a storage\_type of 'io1'. Default is 0 if rds storage type is not 'io1' | `number` | `0` | no |
| <a name="input_kms_alias_name_ssm"></a> [kms\_alias\_name\_ssm](#input\_kms\_alias\_name\_ssm) | KMS alias name for SSM | `string` | `"alias/aws/ssm"` | no |
| <a name="input_kms_key_arn"></a> [kms\_key\_arn](#input\_kms\_key\_arn) | The ARN of the existing KMS key to encrypt storage | `string` | `""` | no |
| <a name="input_label_key_case"></a> [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.<br>Does not affect keys of tags passed in via the `tags` input.<br>Possible values: `lower`, `title`, `upper`.<br>Default value: `title`. | `string` | `null` | no |
| <a name="input_label_order"></a> [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.<br>Defaults to ["namespace", "environment", "stage", "name", "attributes"].<br>You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no |
Expand All @@ -99,9 +105,14 @@
| <a name="input_publicly_accessible"></a> [publicly\_accessible](#input\_publicly\_accessible) | Determines if database can be publicly available (NOT recommended) | `bool` | `false` | no |
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br>Characters matching the regex will be removed from the ID elements.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| <a name="input_replicate_source_db"></a> [replicate\_source\_db](#input\_replicate\_source\_db) | Specifies that this resource is a Replicate database, and to use this value as the source database. This correlates to the `identifier` of another Amazon RDS Database to replicate (if replicating within a single region) or ARN of the Amazon RDS Database to replicate (if replicating cross-region). Note that if you are creating a cross-region replica of an encrypted database you will also need to specify a `kms_key_id`. See [DB Instance Replication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Replication.html) and [Working with PostgreSQL and MySQL Read Replicas](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html) for more information on using Replication. | `string` | `null` | no |
| <a name="input_save_parameter_ssm_map_default"></a> [save\_parameter\_ssm\_map\_default](#input\_save\_parameter\_ssm\_map\_default) | The map of ssm keys to the `aws_ssm_parameter` resource. The `description`, `type`, and `overwrite` are passed directly to that resource. The `suffix` is the last value in the `var.ssm_key_format`. If the `type = "SecureString"` then the `key_id = var.kms_alias_name_ssm`. | `any` | <pre>{<br> "hostname": {<br> "description": "RDS DB hostname",<br> "overwrite": true,<br> "suffix": "admin/db_hostname",<br> "type": "String"<br> },<br> "password": {<br> "description": "RDS DB password",<br> "overwrite": true,<br> "suffix": "admin/db_password",<br> "type": "SecureString"<br> },<br> "port": {<br> "description": "RDS DB port",<br> "overwrite": true,<br> "suffix": "admin/db_port",<br> "type": "String"<br> },<br> "user": {<br> "description": "RDS DB user",<br> "overwrite": true,<br> "suffix": "admin/db_user",<br> "type": "String"<br> }<br>}</pre> | no |
| <a name="input_save_parameter_ssm_map_merge"></a> [save\_parameter\_ssm\_map\_merge](#input\_save\_parameter\_ssm\_map\_merge) | This map will be merged with `var.save_parameter_ssm_map_default` so the defaults can be reused while only overwriting a handful of keys. | `any` | `{}` | no |
| <a name="input_security_group_ids"></a> [security\_group\_ids](#input\_security\_group\_ids) | The IDs of the security groups from which to allow `ingress` traffic to the DB instance | `list(string)` | `[]` | no |
| <a name="input_skip_final_snapshot"></a> [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | If true (default), no snapshot will be made before deleting DB | `bool` | `true` | no |
| <a name="input_snapshot_identifier"></a> [snapshot\_identifier](#input\_snapshot\_identifier) | Snapshot identifier e.g: rds:production-2019-06-26-06-05. If specified, the module create cluster from the snapshot | `string` | `null` | no |
| <a name="input_ssm_key_format"></a> [ssm\_key\_format](#input\_ssm\_key\_format) | SSM path format. The values will will be used in the following order: `var.ssm_key_prefix`, `module.this.name`, `var.ssm_key_*` | `string` | `"/%v/%v/%v"` | no |
| <a name="input_ssm_key_prefix"></a> [ssm\_key\_prefix](#input\_ssm\_key\_prefix) | SSM path prefix. Omit the leading forward slash `/`. | `string` | `"rds"` | no |
| <a name="input_ssm_parameters_enabled"></a> [ssm\_parameters\_enabled](#input\_ssm\_parameters\_enabled) | If `true` create SSM keys for the database information. | `bool` | `false` | no |
| <a name="input_stage"></a> [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
| <a name="input_storage_encrypted"></a> [storage\_encrypted](#input\_storage\_encrypted) | (Optional) Specifies whether the DB instance is encrypted. The default is false if not specified | `bool` | `true` | no |
| <a name="input_storage_type"></a> [storage\_type](#input\_storage\_type) | One of 'standard' (magnetic), 'gp2' (general purpose SSD), or 'io1' (provisioned IOPS SSD) | `string` | `"standard"` | no |
Expand All @@ -119,8 +130,10 @@
| <a name="output_instance_arn"></a> [instance\_arn](#output\_instance\_arn) | ARN of the instance |
| <a name="output_instance_endpoint"></a> [instance\_endpoint](#output\_instance\_endpoint) | DNS Endpoint of the instance |
| <a name="output_instance_id"></a> [instance\_id](#output\_instance\_id) | ID of the instance |
| <a name="output_instance_user"></a> [instance\_user](#output\_instance\_user) | RDS Username for the master DB user |
| <a name="output_option_group_id"></a> [option\_group\_id](#output\_option\_group\_id) | ID of the Option Group |
| <a name="output_parameter_group_id"></a> [parameter\_group\_id](#output\_parameter\_group\_id) | ID of the Parameter Group |
| <a name="output_rds_database_ssm_key_prefix"></a> [rds\_database\_ssm\_key\_prefix](#output\_rds\_database\_ssm\_key\_prefix) | SSM prefix |
| <a name="output_resource_id"></a> [resource\_id](#output\_resource\_id) | The RDS Resource ID of this instance. |
| <a name="output_security_group_id"></a> [security\_group\_id](#output\_security\_group\_id) | ID of the Security Group |
| <a name="output_subnet_group_id"></a> [subnet\_group\_id](#output\_subnet\_group\_id) | ID of the created Subnet Group |
Expand Down
4 changes: 2 additions & 2 deletions examples/complete/fixtures.us-east-2.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ deletion_protection = false

database_name = "test_db"

database_user = "admin"
database_user = "db_user"

database_password = "admin_password"
database_password = "db_password"

database_port = 3306

Expand Down
4 changes: 2 additions & 2 deletions examples/mssql/fixtures.us-east-2.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ deletion_protection = false

database_name = null

database_user = "admin"
database_user = "db_user"

database_password = "admin_password"
database_password = "db_password"

database_port = 1433

Expand Down
59 changes: 48 additions & 11 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module "final_snapshot_label" {
}

locals {
enabled = module.this.enabled

computed_major_engine_version = var.engine == "postgres" ? join(".", slice(split(".", var.engine_version), 0, 1)) : join(".", slice(split(".", var.engine_version), 0, 2))
major_engine_version = var.major_engine_version == "" ? local.computed_major_engine_version : var.major_engine_version

Expand All @@ -17,15 +19,50 @@ locals {
)

availability_zone = var.multi_az ? null : var.availability_zone

create_user = local.enabled && length(var.database_user) == 0
create_password = local.enabled && length(var.database_password) == 0

database_user = local.create_user ? substr(join("", random_pet.database_user.*.id), 0, 16) : var.database_user
database_password = local.create_password ? join("", random_password.database_password.*.result) : var.database_password
}

resource "random_pet" "database_user" {
count = local.create_user ? 1 : 0

# word length
length = 5

separator = ""

keepers = {
db_name = var.database_name
}
}

resource "random_password" "database_password" {
count = local.create_password ? 1 : 0

# character length
length = 33

# Leave special characters out to avoid quoting and other issues.
# Special characters have no additional security compared to increasing length.
special = false
override_special = "!#$%^&*()<>-_"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIU, you don't need override_specialif you includespecial = false`. No harm no foul, but just mentioning.


keepers = {
db_name = var.database_name
}
}

resource "aws_db_instance" "default" {
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
nitrocode marked this conversation as resolved.
Show resolved Hide resolved
count = module.this.enabled ? 1 : 0
count = local.enabled ? 1 : 0

identifier = module.this.id
name = var.database_name
username = var.database_user
password = var.database_password
username = local.database_user
password = local.database_password
port = var.database_port
engine = var.engine
engine_version = var.engine_version
Expand Down Expand Up @@ -92,7 +129,7 @@ resource "aws_db_instance" "default" {
}

resource "aws_db_parameter_group" "default" {
count = length(var.parameter_group_name) == 0 && module.this.enabled ? 1 : 0
count = length(var.parameter_group_name) == 0 && local.enabled ? 1 : 0

name_prefix = "${module.this.id}${module.this.delimiter}"
family = var.db_parameter_group
Expand All @@ -113,7 +150,7 @@ resource "aws_db_parameter_group" "default" {
}

resource "aws_db_option_group" "default" {
count = length(var.option_group_name) == 0 && module.this.enabled ? 1 : 0
count = length(var.option_group_name) == 0 && local.enabled ? 1 : 0

name_prefix = "${module.this.id}${module.this.delimiter}"
engine_name = var.engine
Expand Down Expand Up @@ -145,15 +182,15 @@ resource "aws_db_option_group" "default" {
}

resource "aws_db_subnet_group" "default" {
count = module.this.enabled && local.subnet_ids_provided && ! local.db_subnet_group_name_provided ? 1 : 0
count = local.enabled && local.subnet_ids_provided && ! local.db_subnet_group_name_provided ? 1 : 0

name = module.this.id
subnet_ids = var.subnet_ids
tags = module.this.tags
}

resource "aws_security_group" "default" {
count = module.this.enabled ? 1 : 0
count = local.enabled ? 1 : 0

name = module.this.id
description = "Allow inbound traffic from the security groups"
Expand All @@ -162,7 +199,7 @@ resource "aws_security_group" "default" {
}

resource "aws_security_group_rule" "ingress_security_groups" {
count = module.this.enabled ? length(var.security_group_ids) : 0
count = local.enabled ? length(var.security_group_ids) : 0

description = "Allow inbound traffic from existing Security Groups"
type = "ingress"
Expand All @@ -174,7 +211,7 @@ resource "aws_security_group_rule" "ingress_security_groups" {
}

resource "aws_security_group_rule" "ingress_cidr_blocks" {
count = module.this.enabled && length(var.allowed_cidr_blocks) > 0 ? 1 : 0
count = local.enabled && length(var.allowed_cidr_blocks) > 0 ? 1 : 0

description = "Allow inbound traffic from CIDR blocks"
type = "ingress"
Expand All @@ -186,7 +223,7 @@ resource "aws_security_group_rule" "ingress_cidr_blocks" {
}

resource "aws_security_group_rule" "egress" {
count = module.this.enabled ? 1 : 0
count = local.enabled ? 1 : 0
description = "Allow all egress traffic"
type = "egress"
from_port = 0
Expand All @@ -200,7 +237,7 @@ module "dns_host_name" {
source = "cloudposse/route53-cluster-hostname/aws"
version = "0.12.0"

enabled = length(var.dns_zone_id) > 0 && module.this.enabled
enabled = length(var.dns_zone_id) > 0 && local.enabled
dns_name = var.host_name
zone_id = var.dns_zone_id
records = coalescelist(aws_db_instance.default.*.address, [""])
Expand Down
5 changes: 5 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ output "resource_id" {
value = join("", aws_db_instance.default.*.resource_id)
description = "The RDS Resource ID of this instance."
}

output "instance_user" {
value = local.database_user
description = "RDS Username for the master DB user"
}
Loading