• Task
  • Version · 6.0
  • Create

Connect to Cloud SQL for MySQL using GCP IAM authentication

Last updated: September 29, 2026

Liquibase Secure can authenticate to Cloud SQL for MySQL with a Google Cloud IAM identity instead of a static password. The Cloud SQL Java Connector runs inside Liquibase, opening the secure tunnel and handling TLS for you, so you do not need to run the Cloud SQL Auth Proxy. This capability is included in the Liquibase GCP extension, which ships with Liquibase Secure.

Before you begin

Be sure you have the following:

  • Liquibase Secure 6.0 or later. The Liquibase GCP extension ships with it, so there is no separate extension to install

  • IAM database authentication enabled on your Cloud SQL instance. It is disabled by default and is an instance setting, not something Liquibase can turn on

  • Your instance connection name, in project:region:instance format. Read it with gcloud sql instances describe your_instance_id --format="value(connectionName)"

  • The Google Cloud CLI, if you authenticate from a developer machine

  • A Google Cloud project, and permission to create a service account in it and to grant that service account project-level roles. You can also connect as your own Google account instead, which needs the same roles

  • MySQL Connector/J 8.0.31 or later in the lib directory of your Liquibase installation. Liquibase does not bundle it, so both methods on this page fail without it

Procedure

1

Add the MySQL JDBC driver

Liquibase does not bundle MySQL Connector/J, because its license is not compatible with the way Liquibase is distributed. Download the plain .jar from Maven Central and put it in the lib directory of your Liquibase installation. Use version 8.0.31 or later.

Note: Use lib, not internal/lib. Liquibase loads your own drivers from lib. Without the driver, every MySQL command fails with Cannot find database driver.

liquibase --version

The driver is in place when --version lists it under Libraries.

2

Choose the identity Liquibase will authenticate as

Liquibase connects as whichever Google Cloud identity it finds in Application Default Credentials. That can be your own Google account, which suits local work, or a service account, which is what a pipeline should use. The rest of this article calls it your service account, so substitute your own address throughout if you are connecting as yourself.

You need your project ID for the commands that follow. Read the one your CLI is already set to, or list the projects you can see.

gcloud config get-value project

gcloud projects list

To connect as a service account, create one. Its email address is always the name you choose, followed by @your_project_id.iam.gserviceaccount.com.

Be sure to:

  • Replace your_service_account_name with a name for the service account. For example, my-service-account

  • Replace your_project_id with your Google Cloud project ID. For example, my-project

loading

Confirm the address, which is the value every later step calls your_service_account_email.

gcloud iam service-accounts list --format="value(email)"

Note: Creating a service account does not let you act as it. If you plan to run Liquibase locally under this service account, you also need roles/iam.serviceAccountTokenCreator on it, which the impersonation step below shows how to grant.

3

Grant the Cloud SQL IAM roles

The identity that connects needs two project-level roles. roles/cloudsql.client lets it open a connection through the connector, and roles/cloudsql.instanceUser lets it log in with IAM.

Be sure to:

  • Replace your_project_id with your Google Cloud project ID. For example, my-project

  • Replace your_service_account_email with the service account Liquibase authenticates as. For example, my-service-account@my-project.iam.gserviceaccount.com

Note: To connect as yourself rather than as a service account, use --member=user:your_email instead.

loading
4

Create the IAM database user

Cloud SQL maps a Google Cloud identity to a database user. On MySQL you create the user with the full service account email, but Cloud SQL stores only the local part and that is the name you log in with.

To connect as a person instead of a service account, create the user with --type=CLOUD_IAM_USER and the full email address, such as you@example.com. Cloud SQL shortens that the same way, so you still log in with the local part.

Be sure to:

  • Replace your_service_account_email with the service account Liquibase authenticates as. For example, my-service-account@my-project.iam.gserviceaccount.com

  • Replace your_instance_id with the name of your Cloud SQL instance. For example, my-instance

loading

Confirm the name Cloud SQL stored, which is the value to use as your Liquibase user name.

gcloud sql users list --instance=your_instance_id

Note: A MySQL user name is limited to 32 characters, and Cloud SQL truncates a longer one. Log in with the name this command reports, not with the email you typed.

5

Grant database privileges

An IAM database user can authenticate but starts with no privileges on your database. Connect as an administrative user and grant the privileges Liquibase needs, including the right to create the tracking tables.

Note: Grant to the stored user name, which is the local part of the service account email.

Be sure to:

  • Replace your_database with the name of your database. For example, lbcat

  • Replace your_database_user with the database user you created. For example, my-service-account

loading
6

Provide Google Cloud credentials

Liquibase authenticates with Application Default Credentials (ADC). Credentials come from the environment Liquibase runs in, never from Liquibase configuration files, so there is no credential to set in your properties. Use whichever method fits where Liquibase runs.

Google Cloud CLI (local development): Sign in to create local ADC. Liquibase reuses the resulting credentials automatically, so you do not need a service account key.

gcloud auth application-default login

Workload identity (Google Cloud-hosted workloads such as Cloud Run, GKE, and Compute Engine): Attach a service account to the resource and grant it the roles you granted earlier. Authentication happens automatically with no further configuration.

Service account key file (CI/CD pipelines, containers): Set GOOGLE_APPLICATION_CREDENTIALS to the path of a service account key file.

Be sure to:

  • Replace your_key_file with the path to your service account key file. For example, /etc/liquibase/gcp-key.json

Note: ADC signs in as whoever your browser is signed into, so it is easy to end up authenticated as the wrong Google account. A later cloudsql.instances.get permission error usually means the wrong identity rather than a missing role. Confirm which identity ADC holds before you change any role.

loading
7

Configure the connection

Set the instance connection name and a password value of gcp-cloudsql-iam. The JDBC URL needs no host, because the connector dials the instance named by liquibase.cloudsql.instance rather than a host name.

Be sure to:

  • Replace your_database with the name of your database. For example, lbcat

  • Replace your_database_user with the database user you created. For example, my-service-account

  • Replace your_instance_connection_name with your instance connection name, in project:region:instance format. For example, my-project:us-east1:my-instance

Note: The password value is matched exactly. Letter case and surrounding spaces are ignored, but gcp-cloudsql-iam takes no arguments after a comma, and a value such as gcp-cloudsql-iam,my-project:us-east1:my-instance does not activate IAM authentication. The instance always goes in liquibase.cloudsql.instance.

Liquibase configures TLS on the connection itself, so you do not add an SSL parameter to the JDBC URL. The connector validates the instance's server certificate on your behalf.

8

(Optional) Impersonate a service account

Complete this step only if Liquibase should connect as a service account other than the identity in your ADC. This is the usual arrangement for cross-project access, and for pipelines whose own identity holds no database permissions.

The target service account is the one that reaches the database, so it needs the Cloud SQL roles, and the database user and privileges, from the earlier steps. Your own identity needs permission to act as it.

Be sure to:

  • Replace your_target_service_account with the service account to impersonate. For example, my-target-account@target-project.iam.gserviceaccount.com

  • Replace your_email with the identity your ADC holds. For example, you@example.com

loading

Then name the target in your Liquibase configuration.

liquibase.cloudsql.targetServiceAccount: your_target_service_account

Note: An IAM change can take a few minutes to take effect. Impersonation denied immediately after you grant it is usually propagation rather than a missing role, so wait and try again before changing anything.

9

(Optional) Chain impersonation through delegates

Complete this step only if your identity cannot impersonate the target directly and has to go through one or more intermediate service accounts. Each account in the chain needs roles/iam.serviceAccountTokenCreator on the next one.

Be sure to:

  • Replace your_delegate_service_account with the intermediate service account. For example, my-delegate-account@my-project.iam.gserviceaccount.com

  • Replace your_target_service_account with the service account that reaches the database. For example, my-target-account@target-project.iam.gserviceaccount.com

liquibase.cloudsql.delegates: your_delegate_service_account
liquibase.cloudsql.targetServiceAccount: your_target_service_account

Separate multiple delegates with commas, in the order the chain is traversed.

Note: Delegates apply only alongside a target service account. When liquibase.cloudsql.delegates is set and liquibase.cloudsql.targetServiceAccount is not, Liquibase logs a warning and ignores the delegates.

10

Create a changelog file

Create a changelog file in your project directory and add a changeset. Liquibase accepts XML, SQL, YAML, and JSON.

loading

loading

loading

loading
11

Test your connection

Run status to confirm Liquibase authenticates and reaches your database. It reports which changesets are still pending, so you can verify the connection without applying your changelog.

liquibase --changelog-file=changelog.xml status

Then run update to apply the changeset.

liquibase --changelog-file=changelog.xml update

Liquibase starts the Cloud SQL connector, authenticates with your IAM identity, and creates the DATABASECHANGELOG and DATABASECHANGELOGLOCK tracking tables. The password value is masked in the log.

Alternative: use an IAM token as the password

If you cannot use the Cloud SQL Java Connector, Liquibase can instead mint a short-lived Google Cloud access token through ADC and send it as the database password. Set the password to gcp-cloudsql-iam-token and leave liquibase.cloudsql.instance unset. The connector method above stays the recommended one.

Two things the connector would otherwise handle become yours. You provide the network path to the instance, and you configure TLS yourself on the JDBC URL. Liquibase checks the URL's SSL settings before it sends the token and refuses to send one over a connection that permits an unencrypted downgrade.

Set sslMode to REQUIRED, VERIFY_CA, or VERIFY_IDENTITY, or pair useSSL=true with requireSSL=true. A bare useSSL=true is rejected, because Connector/J treats it as sslMode=PREFERRED, which allows an unencrypted downgrade. The parameter name is case-sensitive, so sslmode on a MySQL URL counts as absent. Declaring the same SSL parameter twice is also rejected, even when the last value is the secure one.

loading

This method does not work through the Cloud SQL Auth Proxy on MySQL. Connector/J refuses to send a token as the password unless the driver itself negotiated the encryption, and the proxy hands it an unencrypted local connection. No setting changes this. Connect directly to the instance over TLS instead, or use the Cloud SQL Java Connector method above, which is not affected.

The earlier steps still apply. The roles, the database user, and the privileges are the same, and credentials still come from ADC.

Note: This method requires a Liquibase Secure license. Without one the command fails rather than falling back to another form of authentication.

Troubleshooting

liquibase.cloudsql.instance is required when password is gcp-cloudsql-iam

The password activated IAM authentication but no instance was configured. Set liquibase.cloudsql.instance to your instance connection name, in project:region:instance format.

An ordinary connection error, as though the password were never recognized

IAM authentication engages only for a jdbc:postgresql: or jdbc:mysql: URL. With any other scheme Liquibase does not activate it at all and simply tries an ordinary connection, so the error you see comes from the driver rather than from IAM authentication. This capability covers Cloud SQL for PostgreSQL and Cloud SQL for MySQL. A jdbc:mariadb URL does not work as a substitute for jdbc:mysql.

JDBC URL scheme does not match Cloud SQL instance

Before connecting, Liquibase asks the Cloud SQL Admin API what engine the instance runs, and the answer disagrees with your URL. The message names both. Point liquibase.cloudsql.instance at the right instance, or correct the URL scheme. The same check reports a Cloud SQL for SQL Server instance by name, because SQL Server is not supported.

Cloud SQL connection failed

The message names what to check: that liquibase.cloudsql.instance is correct, and that the authenticating identity holds roles/cloudsql.client and roles/cloudsql.instanceUser. Liquibase deliberately does not repeat the underlying error, so that credentials cannot reach the log.

When the roles are right, the usual cause is that ADC belongs to a different Google account than you expect. Confirm the identity before changing roles.

Service account impersonation failed

The identity in your ADC cannot act as the target service account. Grant it roles/iam.serviceAccountTokenCreator on that account, and allow a few minutes for the change to take effect. The target service account is masked in this message.

Cannot find database driver

MySQL Connector/J is not on the classpath. Put the plain .jar, version 8.0.31 or later, in the lib directory of your Liquibase installation, not internal/lib.

Access denied for user

The user name is probably the full service account email. On MySQL, log in with the local part only, which is the name gcloud sql users list reports. Cloud SQL stores nothing after the @. Liquibase reports this underneath the Cloud SQL connection failed message, so read the whole error rather than only its first line.

Access denied to the database

Authentication succeeded and authorization did not. Confirm the privileges were granted to the stored user name.

SSL connection required for plugin "mysql_clear_password"

This is the token-as-password method reaching MySQL over an unencrypted connection, which is what happens through the Cloud SQL Auth Proxy. Connector/J sends a token only over a connection it encrypted itself. Connect directly to the instance over TLS, or use the Cloud SQL Java Connector method, which is not affected.

The driver suggests checking sslMode. That does not help here. There is no TLS session between your machine and the proxy for the setting to apply to, so no value of sslMode makes this connection work.

The password value is ignored

Liquibase reads the trigger from liquibase.command.password. A command-specific key such as liquibase.command.update.password resolves first and never reaches IAM authentication. Set the general key instead.

Connection times out

Do not point the JDBC URL at the instance's IP address. The connector reaches the instance through the connection name, so the URL needs no host at all.