Skip to content

Commit

Permalink
feat!: Add pwd validation policy for mysql modules (#409)
Browse files Browse the repository at this point in the history
Co-authored-by: Anuhya P <anuhyap@google.com>
  • Loading branch information
anuhyapolisetti and Anuhya P committed Jan 27, 2023
1 parent 3d2cece commit df8accd
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 4 deletions.
14 changes: 11 additions & 3 deletions examples/mysql-ha/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ module "mysql" {
]
}

password_validation_policy_config = {
enable_password_policy = true
complexity = "COMPLEXITY_DEFAULT"
disallow_username_substring = true
min_length = 8
}

backup_configuration = {
enabled = true
binary_log_enabled = true
Expand Down Expand Up @@ -139,19 +146,20 @@ module "mysql" {
]

user_name = "tftest"
user_password = "foobar"
user_password = "Example!12345"
root_password = ".5nHITPioEJk^k}="

additional_users = [
{
name = "tftest2"
password = "abcdefg"
password = "Example!12345"
host = "localhost"
type = "BUILT_IN"
random_password = false
},
{
name = "tftest3"
password = "abcdefg"
password = "Example!12345"
host = "localhost"
type = "BUILT_IN"
random_password = false
Expand Down
2 changes: 2 additions & 0 deletions modules/mysql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Note: CloudSQL provides [disk autoresize](https://cloud.google.com/sql/docs/mysq
| maintenance\_window\_update\_track | The update track of maintenance window for the master instance maintenance. Can be either `canary` or `stable`. | `string` | `"canary"` | no |
| module\_depends\_on | List of modules or resources this module depends on. | `list(any)` | `[]` | no |
| name | The name of the Cloud SQL resources | `string` | n/a | yes |
| password\_validation\_policy\_config | The password validation policy settings for the database instance. | <pre>object({<br> enable_password_policy = bool<br> min_length = number<br> complexity = string<br> disallow_username_substring = bool<br> })</pre> | `null` | no |
| pricing\_plan | The pricing plan for the master instance. | `string` | `"PER_USE"` | no |
| project\_id | The project ID to manage the Cloud SQL resources | `string` | n/a | yes |
| random\_instance\_name | Sets random suffix at the end of the Cloud SQL resource name | `bool` | `false` | no |
Expand All @@ -45,6 +46,7 @@ Note: CloudSQL provides [disk autoresize](https://cloud.google.com/sql/docs/mysq
| read\_replicas | List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption\_key\_name = null | <pre>list(object({<br> name = string<br> name_override = optional(string)<br> tier = string<br> zone = string<br> availability_type = string<br> disk_type = string<br> disk_autoresize = bool<br> disk_autoresize_limit = number<br> disk_size = string<br> user_labels = map(string)<br> database_flags = list(object({<br> name = string<br> value = string<br> }))<br> ip_configuration = object({<br> authorized_networks = list(map(string))<br> ipv4_enabled = bool<br> private_network = string<br> require_ssl = bool<br> allocated_ip_range = string<br> })<br> encryption_key_name = string<br> }))</pre> | `[]` | no |
| region | The region of the Cloud SQL resources | `string` | `"us-central1"` | no |
| replica\_database\_version | The read replica database version to use. This var should only be used during a database update. The update sequence 1. read-replica 2. master, setting this to an updated version will cause the replica to update, then you may update the master with the var database\_version and remove this field after update is complete | `string` | `""` | no |
| root\_password | Mysql password for the root user. If not set, a random one will be generated and available in the root\_password output variable. | `string` | `""` | no |
| secondary\_zone | The preferred zone for the secondary/failover instance, it should be something like: `us-central1-a`, `us-east1-c`. | `string` | `null` | no |
| tier | The tier for the master instance. | `string` | `"db-n1-standard-1"` | no |
| update\_timeout | The optional timout that is applied to limit long database updates. | `string` | `"10m"` | no |
Expand Down
13 changes: 12 additions & 1 deletion modules/mysql/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ resource "google_sql_database_instance" "default" {
region = var.region
encryption_key_name = var.encryption_key_name
deletion_protection = var.deletion_protection
root_password = var.root_password != "" ? var.root_password : null

settings {
tier = var.tier
Expand Down Expand Up @@ -90,6 +91,16 @@ resource "google_sql_database_instance" "default" {
time = lookup(deny_maintenance_period.value, "time", null)
}
}
dynamic "password_validation_policy" {
for_each = var.password_validation_policy_config != null ? [var.password_validation_policy_config] : []

content {
enable_password_policy = lookup(password_validation_policy.value, "enable_password_policy", null)
min_length = lookup(password_validation_policy.value, "min_length", null)
complexity = lookup(password_validation_policy.value, "complexity", null)
disallow_username_substring = lookup(password_validation_policy.value, "disallow_username_substring", null)
}
}
dynamic "ip_configuration" {
for_each = [local.ip_configurations[local.ip_configuration_enabled ? "enabled" : "disabled"]]
content {
Expand Down Expand Up @@ -178,7 +189,7 @@ resource "random_password" "user-password" {
}

length = 32
special = false
special = true
depends_on = [null_resource.module_depends_on, google_sql_database_instance.default]
}

Expand Down
31 changes: 31 additions & 0 deletions modules/mysql/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@ spec:
type: bool
default: true
required: false
- name: deletion_protection_enabled
description: Enables protection of an instance from accidental deletion protection across all surfaces (API, gcloud, Cloud Console and Terraform).
type: bool
default: false
required: false
- name: deny_maintenance_period
description: The Deny Maintenance Period fields to prevent automatic maintenance from occurring during a 90-day time period. See [more details](https://cloud.google.com/sql/docs/mysql/maintenance)
type: |-
list(object({
end_date = string
start_date = string
time = string
}))
default: []
required: false
- name: disk_autoresize
description: Configuration to increase storage size
type: bool
Expand Down Expand Up @@ -231,6 +246,16 @@ spec:
description: The name of the Cloud SQL resources
type: string
required: true
- name: password_validation_policy_config
description: The password validation policy settings for the database instance.
type: |-
object({
enable_password_policy = bool
min_length = number
complexity = string
disallow_username_substring = bool
})
required: false
- name: pricing_plan
description: The pricing plan for the master instance.
type: string
Expand Down Expand Up @@ -260,6 +285,7 @@ spec:
type: |-
list(object({
name = string
name_override = optional(string)
tier = string
zone = string
availability_type = string
Expand Down Expand Up @@ -293,6 +319,11 @@ spec:
type: string
default: ""
required: false
- name: root_password
description: Mysql password for the root user. If not set, a random one will be generated and available in the root_password output variable.
type: string
default: ""
required: false
- name: secondary_zone
description: 'The preferred zone for the secondary/failover instance, it should be something like: `us-central1-a`, `us-east1-c`.'
type: string
Expand Down
17 changes: 17 additions & 0 deletions modules/mysql/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ variable "ip_configuration" {
}
}

variable "password_validation_policy_config" {
description = "The password validation policy settings for the database instance."
type = object({
enable_password_policy = bool
min_length = number
complexity = string
disallow_username_substring = bool
})
default = null
}

// Read Replicas
variable "read_replicas" {
description = "List of read replicas to create. Encryption key is required for replica in different region. For replica in same region as master set encryption_key_name = null"
Expand Down Expand Up @@ -291,6 +302,12 @@ variable "user_host" {
default = "%"
}

variable "root_password" {
description = "Mysql password for the root user. If not set, a random one will be generated and available in the root_password output variable."
type = string
default = ""
}

variable "user_password" {
description = "The password for the default user. If not set, a random one will be generated and available in the generated_user_password output variable."
type = string
Expand Down
18 changes: 18 additions & 0 deletions modules/postgresql/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,21 @@ spec:
type: bool
default: true
required: false
- name: deletion_protection_enabled
description: Enables protection of an instance from accidental deletion protection across all surfaces (API, gcloud, Cloud Console and Terraform).
type: bool
default: false
required: false
- name: deny_maintenance_period
description: The Deny Maintenance Period fields to prevent automatic maintenance from occurring during a 90-day time period. See [more details](https://cloud.google.com/sql/docs/postgres/maintenance)
type: |-
list(object({
end_date = string
start_date = string
time = string
}))
default: []
required: false
- name: disk_autoresize
description: Configuration to increase storage size.
type: bool
Expand Down Expand Up @@ -278,6 +293,7 @@ spec:
type: |-
list(object({
name = string
name_override = optional(string)
tier = string
availability_type = string
zone = string
Expand Down Expand Up @@ -348,6 +364,8 @@ spec:
description: List of maps of additional users and passwords
- name: generated_user_password
description: The auto generated default user password if not input password was provided
- name: iam_user_emails
description: The list of the IAM users with the access to the Cloudsql instance
- name: instance_connection_name
description: The connection name of the master instance to be used in connection strings
- name: instance_first_ip_address
Expand Down
6 changes: 6 additions & 0 deletions test/integration/mysql-ha/mysql_ha_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ func TestMySqlHaModule(t *testing.T) {
assert.Equal(int64(365), op.Get("settings.backupConfiguration.backupRetentionSettings.retainedBackups").Int(), "Expected 365 backupConfigurationRetainedBackups")
assert.Equal("COUNT", op.Get("settings.backupConfiguration.backupRetentionSettings.retentionUnit").String(), "Expected COUNT backupConfigurationRetentionUnit")

// assert password policy settings
assert.True(op.Get("settings.passwordValidationPolicy.enablePasswordPolicy").Bool(), "Expected TRUE enablePasswordPolicy")
assert.Equal("COMPLEXITY_DEFAULT", op.Get("settings.passwordValidationPolicy.complexity").String(), "Expected COMPLEXITY_DEFAULT complexity")
assert.True(op.Get("settings.passwordValidationPolicy.disallowUsernameSubstring").Bool(), "Expected TRUE disallowUsernameSubstring")
assert.Equal(int64(8), op.Get("settings.passwordValidationPolicy.minLength").Int(), "Expected 8 minLength")

// assert users
op = gcloud.Run(t, fmt.Sprintf("sql users list --instance %s --project %s", mySql.GetStringOutput("name"), mySql.GetStringOutput("project_id")))
assert.Equal(3, len(op.Array()), "Expected at least 3 users")
Expand Down

0 comments on commit df8accd

Please sign in to comment.