The short answer is, password is not needed.
What I did:
- created a service account
- gave Cloud SQL Auth Proxy access to the service account by passing the
--credentials-file
flag
- authorized connections from Cloud SQL Auth Proxy to the Cloud SQL instance by granting Cloud SQL Client role (
roles/cloudsql.client
) to the service account
What was missing:
You might also want to restrict access to a specific Cloud SQL instance by adding the following condition for both roles:
resource.name == 'projects/PROJECT_ID/instances/INSTANCE_NAME'
&& resource.service == 'sqladmin.googleapis.com'
Do note, the postgres
user can't be used for IAM database authentication because the database username must match the service account name.
The final result:
docker-compose.yml
:
services:
app:
build: .
command: sleep infinity
init: true
volumes:
- .:/app
depends_on:
- proxy
proxy:
image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.6.0
command:
--address 0.0.0.0
--credentials-file /credentials.json
--auto-iam-authn
PROJECT_ID:europe-central2:myinstance
volumes:
- ./credentials.json:/credentials.json
Dockerfile
:
FROM google/cloud-sdk:435.0.1-alpine
RUN apk add terraform postgresql15-client
WORKDIR /app
main.tf
:
provider "google" {
project = "PROJECT_ID"
}
resource "google_sql_database_instance" "test-auth" {
# deletion_protection = false
name = "myinstance"
region = "europe-central2"
database_version = "POSTGRES_11"
settings {
tier = "db-f1-micro"
database_flags {
name = "cloudsql.iam_authentication"
value = "on"
}
}
}
resource "google_sql_user" "test-auth-built-in" {
name = "postgres"
instance = google_sql_database_instance.test-auth.name
password = 1
}
resource "google_service_account" "test-auth" {
account_id = "myaccount"
}
resource "google_project_iam_member" "test-auth-client" {
project = "PROJECT_ID"
role = "roles/cloudsql.client"
member = "serviceAccount:${google_service_account.test-auth.email}"
condition {
title = "myinstance"
expression = "resource.name == 'projects/PROJECT_ID/instances/myinstance' && resource.service == 'sqladmin.googleapis.com'"
}
}
resource "google_project_iam_member" "test-auth-instance-user" {
project = "PROJECT_ID"
role = "roles/cloudsql.instanceUser"
member = "serviceAccount:${google_service_account.test-auth.email}"
condition {
title = "myinstance"
expression = "resource.name == 'projects/PROJECT_ID/instances/myinstance' && resource.service == 'sqladmin.googleapis.com'"
}
}
resource "google_sql_user" "test-auth-iam" {
name = "myaccount@PROJECT_ID.iam"
instance = google_sql_database_instance.test-auth.name
type = "CLOUD_IAM_SERVICE_ACCOUNT"
}
// replace PROJECT_ID
// uncomment deletion_protection if you're going to destroy the resources after experimenting
$ touch credentials.json
$ docker compose up -d
$ docker compose exec app gcloud auth application-default login
$ docker compose exec app terraform init
$ docker compose exec app terraform apply
// create the service account key
$ mv ... credentials.json
$ docker compose up -d
$ docker compose exec app psql -h proxy -U myaccount@PROJECT_ID.iam postgres
You can use the log to find out what's wrong.
In case you forgot to enable IAM database authentication on an instance (cloudsql.iam_authentication
):
$ gcloud logging read "resource.type=cloudsql_database" --project=PROJECT_ID --limit=10
...
logName: projects/PROJECT_ID/logs/cloudsql.googleapis.com%2Fpostgres.log
resource:
labels:
database_id: PROJECT_ID:myinstance
project_id: PROJECT_ID
region: europe-central2
type: cloudsql_database
severity: INFO
textPayload: |-
2023-08-19 00:33:39.798 UTC [857]: [2-1] db=postgres,user=myaccount@PROJECT_ID.iam DETAIL: Cloud SQL IAM authentication not enabled
Connection matched pg_hba.conf line 21: "local all +cloudsqliamserviceaccount cloudsql-iam-svc-acct"
---
logName: projects/PROJECT_ID/logs/cloudsql.googleapis.com%2Fpostgres.log
resource:
labels:
database_id: PROJECT_ID:myinstance
project_id: PROJECT_ID
region: europe-central2
type: cloudsql_database
severity: ALERT
textPayload: '2023-08-19 00:33:39.798 UTC [857]: [1-1] db=postgres,user=myaccount@PROJECT_ID.iam
FATAL: Cloud SQL IAM service account authentication failed for user "myaccount@PROJECT_ID.iam"'
...
In case you forgot to grant the Cloud SQL Instance User role to your service account:
$ gcloud logging read "resource.type=cloudsql_database" --project=PROJECT_ID --limit=10
...
logName: projects/PROJECT_ID/logs/cloudsql.googleapis.com%2Fpostgres.log
resource:
labels:
database_id: PROJECT_ID:myinstance
project_id: PROJECT_ID
region: europe-central2
type: cloudsql_database
severity: INFO
textPayload: |-
2023-08-19 00:39:21.656 UTC [991]: [2-1] db=postgres,user=myaccount@PROJECT_ID.iam DETAIL: Not authorized to access resource. Possibly missing permission cloudsql.instances.login on resource projects/PROJECT_ID/instances/myinstance.
Connection matched pg_hba.conf line 21: "local all +cloudsqliamserviceaccount cloudsql-iam-svc-acct"
---
logName: projects/PROJECT_ID/logs/cloudsql.googleapis.com%2Fpostgres.log
resource:
labels:
database_id: PROJECT_ID:myinstance
project_id: PROJECT_ID
region: europe-central2
type: cloudsql_database
severity: ALERT
textPayload: '2023-08-19 00:39:21.656 UTC [991]: [1-1] db=postgres,user=myaccount@PROJECT_ID.iam
FATAL: Cloud SQL IAM service account authentication failed for user "myaccount@PROJECT_ID.iam"'
...
For more information see this overview.