Skip to content

Commit b918d78

Browse files
filippolmtCopilot
andcommitted
Update variables.tf
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c4feeb8 commit b918d78

File tree

9 files changed

+61
-28
lines changed

9 files changed

+61
-28
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres
77
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88

9+
## [Unreleased]
10+
11+
## [0.5.0] - 2025-11-11
12+
13+
### Added
14+
15+
- Introduced the `permissions_refresh_id` input plus the `null_resource.force_permissions_refresh`/`null_resource.grant_permissions` helpers so you can rerun the proxy/grant scripts without recreating users.
16+
17+
### Changed
18+
19+
- Reworked the resource lifecycles so proxy start/kill and permission scripts are re-executed whenever `permissions_refresh_id` changes.
20+
- Hardened the Cloud SQL proxy helper scripts: better logging, explicit dependency checks (mysql/nc/proxy), use of the v2 proxy CLI syntax, and safer shutdown handling.
21+
- Enhanced `execute_sql.sh` so MySQL 8.0/8.4 users have the `cloudsqlsuperuser` role removed, default roles cleared, and only database-scoped privileges granted.
22+
- Documentation updates: clarify Cloud SQL Auth Proxy v2 requirement, mention MySQL 8.4 support.
23+
924
## [0.4.1] - 2025-02-24
1025

1126
[Compare with previous version](https://github.com/sparkfabrik/terraform-google-gcp-mysql-db-and-user-creation-helper/compare/0.4.0...0.4.1)

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
# Terraform module for creating database and associated user on an existing Google CloudSQL instance
22

3-
This module creates database and users on an existing CloudSQL instance. The structure of the input variable is designed so that the database/user ratio is 1:1, so the module not only takes care of creating the database and its user, but also sets permissions on the user so that it has access to only the database for which it is responsible.
3+
This module creates databases and users on an existing CloudSQL instance. The structure of the input variable enforces a 1:1 database/user ratio. The module both creates each pair and applies the required permissions so that the user can access only its database.
44

5-
To enforce permissions, the module executes SQL commands with the mysql cli, which is therefore a prerequisite (it must be present in the filesystem where terraform apply is executed).
5+
To enforce permissions, the module executes SQL commands through the MySQL CLI, which therefore must be installed on the machine running `terraform apply`. The bundled proxy helper scripts rely on the [Cloud SQL Auth Proxy **v2** command syntax](https://cloud.google.com/sql/docs/mysql/connect-auth-proxy), so make sure you install proxy version 2.x (the newer `${CLOUDSQL_PROXY_BIN} \"${CONNECTION_NAME}\" --port ...` invocation) rather than the legacy 1.x binary that used `-instances=` flags.
66

77
For MySQL 8.x instances, the module automatically removes the default `cloudsqlsuperuser` role, clears any global privileges and assigns the target database as the only default role so that new users are scoped exclusively to their database.
88

9-
If you ever need to rerun all local scripts (start proxy → grant privileges → stop proxy) without recreating the module-managed users, set a different value for the `permissions_refresh_id` variable (use the `YYYYMMDD` format, e.g. `20251110`) and run `terraform apply`; changing the value forces Terraform to recreate the null resources that execute those scripts while keeping the `google_sql_user` resources in place (see `examples/main.tf` for a ready-to-use snippet).
9+
If you ever need to rerun all local scripts (start proxy → grant privileges → stop proxy) without recreating the module-managed users, set a different value for the `permissions_refresh_id` variable (use `YYYYMMDD` or `YYYYMMDDHHMM`, e.g. `20251110` or `202511101030`) and run `terraform apply`; changing the value forces Terraform to recreate the null resources that execute those scripts while keeping the `google_sql_user` resources in place (see `examples/main.tf` for a ready-to-use snippet).
1010

11-
In addition, the script must be able to connect to the CloudSQL instance. In case this is not easily accessible from the terraform cli, the module is able to:
11+
In addition, the module must be able to connect to the CloudSQL instance. If the instance is not directly reachable from the machine running `terraform apply`, the module can:
1212

13-
1. Start an instance of [CloudSQL Auth Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy), for this purpose two null resources will be created for each user added to the database, enabling this option requires the [presence of the proxy executable](https://cloud.google.com/sql/docs/mysql/sql-proxy) in the filesystem where `terraform apply` is executed.
14-
2. Connect from a [CloudSQL Auth Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) instance not present in the filesystem.
13+
1. Start a local instance of [CloudSQL Auth Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy). This creates two null resources per user and requires the [proxy executable](https://cloud.google.com/sql/docs/mysql/sql-proxy) to be present on the machine running `terraform apply`.
14+
2. Connect through an existing [CloudSQL Auth Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) instance that is already running elsewhere (outside this module).
1515

1616
### IMPORTANT
1717

@@ -42,8 +42,8 @@ CloudSQL Auth Proxy needs the CloudSQL instance to expose a public IP address in
4242
| <a name="input_cloudsql_privileged_user_password"></a> [cloudsql\_privileged\_user\_password](#input\_cloudsql\_privileged\_user\_password) | The password of the privileged user of the Cloud SQL instance | `string` | n/a | yes |
4343
| <a name="input_cloudsql_proxy_host"></a> [cloudsql\_proxy\_host](#input\_cloudsql\_proxy\_host) | The host of the Cloud SQL Auth Proxy; if a value other than localhost or 127.0.0.1 (default) is entered, it is assumed that there is a CloudSQL Auth Proxy instance defined and already configured outside this module, and therefore the proxy will not be launched. | `string` | `"127.0.0.1"` | no |
4444
| <a name="input_cloudsql_proxy_port"></a> [cloudsql\_proxy\_port](#input\_cloudsql\_proxy\_port) | Port of the Cloud SQL Auth Proxy | `string` | `"1234"` | no |
45-
| <a name="input_database_and_user_list"></a> [database\_and\_user\_list](#input\_database\_and\_user\_list) | The list with all the databases and the relative user. Please not that you can assign only a database to a single user, the same user cannot be assigned to multiple databases. `user_host` is optional, has a default value of '%' to allow the user to connect from any host, or you can specify it for the given user for a more restrictive access. | <pre>list(object({<br/> user = string<br/> user_host = optional(string, "%")<br/> database = string<br/> }))</pre> | n/a | yes |
46-
| <a name="input_permissions_refresh_id"></a> [permissions\_refresh\_id](#input\_permissions\_refresh\_id) | Optional identifier (use format YYYYMMDD, e.g. 20251110) used only to force Terraform to rerun the proxy/grant scripts without recreating users. Change the value whenever you need to reapply permissions. | `string` | `""` | no |
45+
| <a name="input_database_and_user_list"></a> [database\_and\_user\_list](#input\_database\_and\_user\_list) | The list with all the databases and the relative user. Please note that you can assign only a database to a single user, the same user cannot be assigned to multiple databases. `user_host` is optional, has a default value of '%' to allow the user to connect from any host, or you can specify it for the given user for a more restrictive access. | <pre>list(object({<br/> user = string<br/> user_host = optional(string, "%")<br/> database = string<br/> }))</pre> | n/a | yes |
46+
| <a name="input_permissions_refresh_id"></a> [permissions\_refresh\_id](#input\_permissions\_refresh\_id) | Optional identifier (use format YYYYMMDD or YYYYMMDDHHMM, e.g. 20251110 or 202511101030) used only to force Terraform to rerun the proxy/grant scripts without recreating users. Change the value whenever you need to reapply permissions. | `string` | `""` | no |
4747
| <a name="input_project_id"></a> [project\_id](#input\_project\_id) | The ID of the project in which the resource belongs. | `string` | n/a | yes |
4848
| <a name="input_region"></a> [region](#input\_region) | The region in which the resource belongs. | `string` | n/a | yes |
4949
| <a name="input_terraform_start_cloud_sql_proxy"></a> [terraform\_start\_cloud\_sql\_proxy](#input\_terraform\_start\_cloud\_sql\_proxy) | If `true` terraform will automatically start the Cloud SQL Proxy instance present in the filesystem at the condition that cloudsql\_proxy\_host is set to a supported value. If `false` you have to start the Cloud SQL Proxy manually. This variable is used to prevent the creation of a Cloud SQL Proxy instance even if cloudsql\_proxy\_host has a supported value. | `bool` | `true` | no |

examples/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ module "mysql_additional_users_and_databases" {
7575
project_id = var.project_id
7676
region = var.region
7777
database_and_user_list = var.database_and_user_list
78-
# Change this value (use YYYYMMDD, e.g. 20251110) whenever you need to rerun the proxy/grant scripts without recreating users.
78+
# Change this value (use YYYYMMDD or YYYYMMDDHHMM, e.g. 20251110 or 202511101030) whenever you need to rerun the proxy/grant scripts without recreating users.
7979
permissions_refresh_id = var.permissions_refresh_id
8080
cloudsql_instance_name = google_sql_database_instance.instance.name
8181
cloudsql_privileged_user_name = google_sql_user.admin_user_mysql.name

examples/test.tfvars

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ database_and_user_list = [
1818
}
1919
]
2020

21-
# Bump this value (YYYYMMDD, e.g. 20251110) whenever you need to rerun the proxy/grant scripts without recreating users.
22-
permissions_refresh_id = "20251110"
21+
# Bump this value (YYYYMMDD or YYYYMMDDHHMM, e.g. 20251110 or 202511101030) whenever you need to rerun the proxy/grant scripts without recreating users.
22+
permissions_refresh_id = "202511101030"

examples/variables.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ variable "database_and_user_list" {
2323
variable "permissions_refresh_id" {
2424
type = string
2525
default = ""
26-
description = "Change this date (YYYYMMDD, e.g. 20251110) to force rerunning the proxy/grant scripts."
26+
description = "Change this date or date-time (YYYYMMDD or YYYYMMDDHHMM, e.g. 20251110 or 202511101030) to force rerunning the proxy/grant scripts."
2727
}

scripts/execute_cloud_sql_proxy.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ log() {
1111
printf '[sql-proxy] %s\n' "${1}"
1212
}
1313

14-
PROXY_BIN=""
14+
CLOUDSQL_PROXY_BIN=""
1515
if command -v cloud_sql_proxy >/dev/null 2>&1; then
16-
PROXY_BIN="cloud_sql_proxy"
16+
CLOUDSQL_PROXY_BIN="cloud_sql_proxy"
1717
else
1818
log "Error: cannot find the Cloud SQL Auth Proxy executable cloud_sql_proxy. Please install it or add it to your PATH." >&2
1919
exit 1
@@ -26,9 +26,9 @@ fi
2626

2727
CONNECTION_NAME="${CLOUDSDK_CORE_PROJECT}:${GCLOUD_PROJECT_REGION}:${CLOUDSQL_INSTANCE_NAME}"
2828

29-
if ! pgrep -x "$PROXY_BIN" >/dev/null; then
30-
log "Starting Cloud SQL Auth Proxy (${PROXY_BIN}) for ${CONNECTION_NAME} on localhost:${CLOUDSQL_PROXY_PORT}."
31-
"${PROXY_BIN}" "${CONNECTION_NAME}" --port "${CLOUDSQL_PROXY_PORT}" >/dev/null 2>&1 &
29+
if ! pgrep -x "$CLOUDSQL_PROXY_BIN" >/dev/null; then
30+
log "Starting Cloud SQL Auth Proxy (${CLOUDSQL_PROXY_BIN}) for ${CONNECTION_NAME} on localhost:${CLOUDSQL_PROXY_PORT}."
31+
"${CLOUDSQL_PROXY_BIN}" "${CONNECTION_NAME}" --port "${CLOUDSQL_PROXY_PORT}" >/dev/null 2>&1 &
3232
sleep 1s
3333
else
3434
log "Cloud SQL Auth Proxy already running; skipping start."

scripts/execute_sql.sh

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ log() {
1111
printf '[sql-grant] %s\n' "${1}"
1212
}
1313

14+
mysql_exec() {
15+
MYSQL_PWD="${CLOUDSQL_PRIVILEGED_USER_PASSWORD}" mysql \
16+
--host="${CLOUDSQL_PROXY_HOST}" \
17+
--port="${CLOUDSQL_PROXY_PORT}" \
18+
--user="${CLOUDSQL_PRIVILEGED_USER_NAME}" \
19+
"$@"
20+
}
21+
1422
if ! [ -x "$(command -v mysql)" ]; then
1523
log "Error: the mysql client is not installed or is not in your path. Please add the mysql client executable." >&2
1624
exit 1
@@ -41,7 +49,17 @@ if [ "$READY" -eq 0 ]; then
4149
SQL_COMMANDS="REVOKE ALL PRIVILEGES, GRANT OPTION FROM ${USER_IDENTIFIER}; GRANT ALL PRIVILEGES ON ${DATABASE_IDENTIFIER} TO ${USER_IDENTIFIER};"
4250
;;
4351
MYSQL_8_0*|MYSQL_8_4*)
44-
SQL_COMMANDS="REVOKE cloudsqlsuperuser FROM ${USER_IDENTIFIER}; SET DEFAULT ROLE NONE TO ${USER_IDENTIFIER}; GRANT ALL PRIVILEGES ON ${DATABASE_IDENTIFIER} TO ${USER_IDENTIFIER};"
52+
if ! REVOKE_OUTPUT=$(mysql_exec --execute="REVOKE cloudsqlsuperuser FROM ${USER_IDENTIFIER};" 2>&1); then
53+
if printf '%s' "${REVOKE_OUTPUT}" | grep -qi "Operation REVOKE ROLE failed"; then
54+
log "cloudsqlsuperuser role already absent for ${USER_IDENTIFIER}; continuing."
55+
else
56+
log "ERROR: Failed to revoke cloudsqlsuperuser role for ${USER_IDENTIFIER}:\n${REVOKE_OUTPUT}" >&2
57+
exit 1
58+
fi
59+
else
60+
log "Removed cloudsqlsuperuser role from ${USER_IDENTIFIER}."
61+
fi
62+
SQL_COMMANDS="SET DEFAULT ROLE NONE TO ${USER_IDENTIFIER}; GRANT ALL PRIVILEGES ON ${DATABASE_IDENTIFIER} TO ${USER_IDENTIFIER};"
4563
;;
4664
*)
4765
log "ERROR: Unsupported MySQL version ${MYSQL_VERSION}." >&2
@@ -51,7 +69,7 @@ if [ "$READY" -eq 0 ]; then
5169

5270
printf '[sql-grant] Executing SQL statements:\n%s\n' "${SQL_COMMANDS}"
5371

54-
if ! MYSQL_PWD="${CLOUDSQL_PRIVILEGED_USER_PASSWORD}" mysql --host="${CLOUDSQL_PROXY_HOST}" --port="${CLOUDSQL_PROXY_PORT}" --user="${CLOUDSQL_PRIVILEGED_USER_NAME}" --execute="${SQL_COMMANDS}"; then
72+
if ! mysql_exec --execute="${SQL_COMMANDS}"; then
5573
log "ERROR: Failed to apply privileges for ${USER_IDENTIFIER} on ${DATABASE}." >&2
5674
exit 1
5775
fi

scripts/kill_cloud_sql_proxy.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ log() {
1111
printf '[sql-proxy] %s\n' "${1}"
1212
}
1313

14-
PROXY_BIN="cloud_sql_proxy"
15-
if pgrep -x "$PROXY_BIN" >/dev/null; then
16-
log "Detected running ${PROXY_BIN}; waiting 5 seconds before shutdown to avoid race conditions."
14+
CLOUDSQL_PROXY_BIN="cloud_sql_proxy"
15+
if pgrep -x "$CLOUDSQL_PROXY_BIN" >/dev/null; then
16+
log "Detected running ${CLOUDSQL_PROXY_BIN}; waiting 5 seconds before shutdown to avoid race conditions."
1717
sleep 5s
1818
# Obtain the PID of the running Cloud SQL Auth Proxy and terminate gently.
19-
PID="$(pgrep -x "$PROXY_BIN")"
20-
log "Stopping ${PROXY_BIN} (PID(s): ${PID})."
19+
PID="$(pgrep -x "$CLOUDSQL_PROXY_BIN")"
20+
log "Stopping ${CLOUDSQL_PROXY_BIN} (PID(s): ${PID})."
2121

2222
kill "${PID}" || true
2323
fi

variables.tf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ variable "database_and_user_list" {
4848
user_host = optional(string, "%")
4949
database = string
5050
}))
51-
description = "The list with all the databases and the relative user. Please not that you can assign only a database to a single user, the same user cannot be assigned to multiple databases. `user_host` is optional, has a default value of '%' to allow the user to connect from any host, or you can specify it for the given user for a more restrictive access."
51+
description = "The list with all the databases and the relative user. Please note that you can assign only a database to a single user, the same user cannot be assigned to multiple databases. `user_host` is optional, has a default value of '%' to allow the user to connect from any host, or you can specify it for the given user for a more restrictive access."
5252
}
5353

5454
variable "permissions_refresh_id" {
5555
type = string
5656
default = ""
57-
description = "Optional identifier (use format YYYYMMDD, e.g. 20251110) used only to force Terraform to rerun the proxy/grant scripts without recreating users. Change the value whenever you need to reapply permissions."
57+
description = "Optional identifier (use format YYYYMMDD or YYYYMMDDHHMM, e.g. 20251110 or 202511101030) used only to force Terraform to rerun the proxy/grant scripts without recreating users. Change the value whenever you need to reapply permissions."
5858

5959
validation {
60-
condition = var.permissions_refresh_id == "" || can(regex("^\\d{8}$", var.permissions_refresh_id))
61-
error_message = "Set permissions_refresh_id to an 8-digit date in the form YYYYMMDD (e.g. 20251110) or leave it empty."
60+
condition = var.permissions_refresh_id == "" || can(regex("^\\d{8}(\\d{4})?$", var.permissions_refresh_id))
61+
error_message = "Set permissions_refresh_id to an 8-digit date (YYYYMMDD) or a 12-digit date-time (YYYYMMDDHHMM) such as 20251110 or 202511101030, or leave it empty."
6262
}
6363
}

0 commit comments

Comments
 (0)