Accesso a un database con l'autenticazione IAM dei database

Questa pagina descrive come gli utenti e i service account possono accedere ai database Cloud SQL utilizzando l'autenticazione IAM dei database Cloud SQL. Per saperne di più, consulta Autenticazione IAM.

Prima di iniziare

Accedere con l'autenticazione IAM dei database automatica

Puoi configurare un connettore Cloud SQL per gestire automaticamente l'autenticazione all'istanza Cloud SQL per conto di un utente o di un'applicazione. I connettori includono il proxy di autenticazione Cloud SQL, il connettore Go, il connettore Java e il connettore Python, che supportano tutti l'autenticazione IAM dei database automatica. Quando utilizzi un connettore Cloud SQL con l'autenticazione IAM dei database automatica, l'account IAM che utilizzi per avviare il connettore deve essere lo stesso account che esegue l'autenticazione al database.

Per accedere con l'autenticazione IAM dei database automatica:

Proxy di autenticazione Cloud SQL

  1. Esegui l'autenticazione in Google Cloud.

    Utente

    Esegui l'autenticazione a Google Cloud utilizzando le Credenziali predefinite dell'applicazione (ADC).

    Utilizza il gcloud auth application-default login comando. Per saperne di più, consulta Configurare le Credenziali predefinite dell'applicazione.

    Service account

    Per eseguire l'autenticazione in Google Cloud utilizzando le Credenziali predefinite dell'applicazione con un account di servizio, puoi utilizzare la simulazione dell'identità del account di servizio o configurare una chiave del account di servizio. Se vuoi eseguire l'autenticazione con la simulazione dell'identità del account di servizio, sostituisci SERVICE_ACCOUNT_EMAIL_ADDRESS ed esegui il comando seguente:

    gcloud auth application-default login --impersonate-service-account SERVICE_ACCOUNT_EMAIL_ADDRESS

    Per saperne di più, consulta Configurare le Credenziali predefinite dell'applicazione.

  2. Avvia il proxy di autenticazione Cloud SQL con il flag --auto-iam-authn Sostituisci INSTANCE_CONNECTION_NAME con la stringa di connessione utilizzata per identificare l'istanza Cloud SQL. Se utilizzi una porta diversa dalla porta MySQL predefinita, specifica il numero di porta. Per saperne di più su come trovare e creare questa stringa, consulta Opzioni per l'autenticazione del proxy di autenticazione Cloud SQL.

    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME

    Per saperne di più su come avviare il proxy, consulta Avviare il proxy di autenticazione Cloud SQL.

  3. Quando è tutto pronto per connetterti all'istanza utilizzando il proxy di autenticazione Cloud SQL, accedi con il client mysql. Sostituisci quanto segue:

    • HOSTNAME: indirizzo IP utilizzato dal proxy di autenticazione Cloud SQL. Per impostazione predefinita, il proxy di autenticazione Cloud SQL utilizza l'indirizzo localhost 127.0.0.1, ma puoi assegnare un indirizzo IP diverso quando avvii il proxy di autenticazione Cloud SQL.
    • USERNAME: per un account utente IAM, questo è l'indirizzo email dell'utente, senza il simbolo @o il nome di dominio. Ad esempio, per test-user@example.com, inserisci test-user. Per un account di servizio, questo è l'indirizzo email del service account senza il @project-id.iam.gserviceaccount.com suffisso.
    • PORT_NUMBER: (facoltativo) Se hai specificato una porta diversa nella stringa di connessione dell'istanza, specifica il numero di porta.

    Esegui questo comando:

    mysql --host=HOSTNAME \
    --user=USERNAME \
    --port=PORT_NUMBER

    Per saperne di più su come connetterti al proxy di autenticazione Cloud SQL, consulta Connettersi con il client mysql.

Go

import (
	"context"
	"database/sql"
	"fmt"
	"log"
	"net"
	"os"

	"cloud.google.com/go/cloudsqlconn"
	"github.com/go-sql-driver/mysql"
)

func connectWithConnectorIAMAuthN() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Warning: %s environment variable not set.", k)
		}
		return v
	}
	// Note: Saving credentials in environment variables is convenient, but not
	// secure - consider a more secure solution such as
	// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
	// keep secrets safe.
	var (
		dbUser                 = mustGetenv("DB_IAM_USER")              // e.g. 'service-account-name'
		dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
		usePrivate             = os.Getenv("PRIVATE_IP")
	)

	// WithLazyRefresh() Option is used to perform refresh
	// when needed, rather than on a scheduled interval.
	// This is recommended for serverless environments to
	// avoid background refreshes from throttling CPU.
	d, err := cloudsqlconn.NewDialer(
		context.Background(),
		cloudsqlconn.WithIAMAuthN(),
		cloudsqlconn.WithLazyRefresh(),
	)
	if err != nil {
		return nil, fmt.Errorf("cloudsqlconn.NewDialer: %w", err)
	}
	var opts []cloudsqlconn.DialOption
	if usePrivate != "" {
		opts = append(opts, cloudsqlconn.WithPrivateIP())
	}
	mysql.RegisterDialContext("cloudsqlconn",
		func(ctx context.Context, addr string) (net.Conn, error) {
			return d.Dial(ctx, instanceConnectionName, opts...)
		})

	dbURI := fmt.Sprintf("%s:empty@cloudsqlconn(localhost:3306)/%s?parseTime=true",
		dbUser, dbName)

	dbPool, err := sql.Open("mysql", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Java JDBC

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;

public class ConnectorIamAuthnConnectionPoolFactory extends ConnectionPoolFactory {

  // Note: Saving credentials in environment variables is convenient, but not
  // secure - consider a more secure solution such as
  // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
  // keep secrets safe.
  private static final String INSTANCE_CONNECTION_NAME =
      System.getenv("INSTANCE_CONNECTION_NAME");
  private static final String INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
  private static final String DB_IAM_USER = System.getenv("DB_IAM_USER");
  private static final String DB_NAME = System.getenv("DB_NAME");


  public static DataSource createConnectionPool() {
    // The configuration object specifies behaviors for the connection pool.
    HikariConfig config = new HikariConfig();

    // The following URL is equivalent to setting the config options below:
    // jdbc:mysql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
    // socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=<DB_USER>&password=<DB_PASS>
    // See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
    // https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

    // Configure which instance and what database user to connect with.
    config.setJdbcUrl(String.format("jdbc:mysql:///%s", DB_NAME));

    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
    config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);

    // If connecting using automatic database authentication, follow the instructions for
    // connecting using the connector, but set the DB_IAM_USER value to an IAM user or
    // service account that has been given access to the database.
    // See https://cloud.google.com/sql/docs/postgres/iam-logins for more details.
    config.addDataSourceProperty("enableIamAuth", "true");
    config.addDataSourceProperty("user", DB_IAM_USER);
    // Explicitly set sslmode to disable to prevent driver from hanging.
    // The Java Connector will handle SSL so it is unneccesary to enable it at the driver level.
    config.addDataSourceProperty("sslmode", "disable");

    // cloudSqlRefreshStrategy set to "lazy" is used to perform a
    // refresh when needed, rather than on a scheduled interval.
    // This is recommended for serverless environments to
    // avoid background refreshes from throttling CPU.
    config.addDataSourceProperty("cloudSqlRefreshStrategy", "lazy");


    // ... Specify additional connection properties here.
    // ...

    // Initialize the connection pool using the configuration object.
    return new HikariDataSource(config);
  }
}

Java R2DBC

// Set up ConnectionFactoryOptions
ConnectionFactoryOptions options =
    ConnectionFactoryOptions.builder()
        .option(DRIVER, "gcp")
        .option(PROTOCOL, "mysql")
        .option(USER, DB_USER)
        .option(DATABASE, DB_NAME)
        .option(HOST, CONNECTION_NAME)
        .option(IP_TYPES, IP_TYPE)
        .option(ENABLE_IAM_AUTH, true)
        .build();

// Initialize connection pool
ConnectionFactory connectionFactory = ConnectionFactories.get(options);
ConnectionPoolConfiguration configuration =
    ConnectionPoolConfiguration.builder(connectionFactory).build();

this.connectionPool = new ConnectionPool(configuration);

Node.js

const mysql = require('mysql2/promise');
const {Connector} = require('@google-cloud/cloud-sql-connector');

// In case the PRIVATE_IP environment variable is defined then we set
// the ipType=PRIVATE for the new connector instance, otherwise defaults
// to public ip type.
const getIpType = () =>
  process.env.PRIVATE_IP === '1' || process.env.PRIVATE_IP === 'true'
    ? 'PRIVATE'
    : 'PUBLIC';

// connectWithConnectorAutoIAMAuthn initializes a connection pool for a Cloud SQL instance
// of MySQL using the Cloud SQL Node.js Connector.
const connectWithConnectorAutoIAMAuthn = async config => {
  // Note: Saving credentials in environment variables is convenient, but not
  // secure - consider a more secure solution such as
  // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
  // keep secrets safe.
  const connector = new Connector();
  const clientOpts = await connector.getOptions({
    instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
    ipType: getIpType(),
    authType: 'IAM',
  });
  const dbConfig = {
    ...clientOpts,
    user: process.env.IAM_DB_USER, // e.g. 'service-account-name'
    database: process.env.DB_NAME, // e.g. 'my-database'
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return mysql.createPool(dbConfig);
};

Python

import os

from google.cloud.sql.connector import Connector, IPTypes
import pymysql

import sqlalchemy


def connect_with_connector_auto_iam_authn() -> sqlalchemy.engine.base.Engine:
    """
    Initializes a connection pool for a Cloud SQL instance of MySQL.

    Uses the Cloud SQL Python Connector with Automatic IAM Database Authentication.
    """
    # Note: Saving credentials in environment variables is convenient, but not
    # secure - consider a more secure solution such as
    # Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
    # keep secrets safe.
    instance_connection_name = os.environ[
        "INSTANCE_CONNECTION_NAME"
    ]  # e.g. 'project:region:instance'
    db_iam_user = os.environ["DB_IAM_USER"]  # e.g. 'service-account-name'
    db_name = os.environ["DB_NAME"]  # e.g. 'my-database'

    ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

    # initialize Cloud SQL Python Connector object
    connector = Connector(refresh_strategy="LAZY")

    def getconn() -> pymysql.connections.Connection:
        conn: pymysql.connections.Connection = connector.connect(
            instance_connection_name,
            "pymysql",
            user=db_iam_user,
            db=db_name,
            enable_iam_auth=True,
            ip_type=ip_type,
        )
        return conn

    # The Cloud SQL Python Connector can be used with SQLAlchemy
    # using the 'creator' argument to 'create_engine'
    pool = sqlalchemy.create_engine(
        "mysql+pymysql://",
        creator=getconn,
        # ...
    )
    return pool

Accedere con l'autenticazione IAM dei database manuale

Un utente o un'applicazione può eseguire l'autenticazione al database utilizzando IAM richiedendo manualmente un token di accesso da Google Cloud e presentandolo a l database. Utilizzando la gcloud CLI, puoi richiedere esplicitamente un token OAuth 2.0 con l' ambito dell'API Cloud SQL Admin utilizzato per accedere al database. Quando accedi come utente del database con l'autenticazione IAM dei database manuale, utilizzi il tuo indirizzo email come nome utente e il token di accesso come password. Puoi utilizzare questo metodo con una connessione diretta al database o con un connettore Cloud SQL.

In questa procedura, esegui l'autenticazione in Google Cloud, richiedi un token di accesso, e poi ti connetti al database passando il token come password per l'utente del database IAM. Segui questi passaggi per connetterti senza il proxy di autenticazione Cloud SQL.

Per questi passaggi, devi:

Per accedere con l'autenticazione IAM dei database manuale:

gcloud

  1. Esegui l'autenticazione in Google Cloud.

    Utente

    Esegui l'autenticazione a IAM utilizzando gcloud auth login. Per saperne di più, consulta Autorizzare con un account utente.

    Service account

    Esegui l'autenticazione a IAM utilizzando gcloud auth activate-service-account. Per saperne di più, consulta Autorizzare con un service account.

  2. Richiedi il token di accesso e accedi con un client.

    Sostituisci quanto segue:

    • HOSTNAME: l'indirizzo IP dell'istanza, ovvero l'indirizzo IP pubblico o l'indirizzo IP privato.
    • USERNAME: per un account utente IAM, questo è l' indirizzo email dell'utente, senza il simbolo @ o il nome di dominio. Ad esempio, per test-user@example.com, inserisci test-user. Per un account di servizio, questo è l'indirizzo email del service account senza il @project-id.iam.gserviceaccount.com suffisso.

     export MYSQL_PWD=`gcloud sql generate-login-token` \
     mysql --enable-cleartext-plugin \
     --ssl-mode=REQUIRED \
     --host=HOSTNAME \
     --user=USERNAME
     

    Se ssl_mode sull'istanza Cloud SQL è configurato su TRUSTED_CLIENT_CERTIFICATE_REQUIRED, includi un certificato client e una chiave client quando accedi. Inoltre, per consentire al client di verificare l'identità del server per l'autenticazione reciproca, specifica il certificato del server server-ca.pem. Ad esempio:

     export MYSQL_PWD=`gcloud sql generate-login-token` \
     mysql --enable-cleartext-plugin \
     --ssl-mode=VERIFY_CA \
     --ssl-ca=server-ca.pem \
     --ssl-cert=client-cert.pem \
     --ssl-key=client-key.pem \
     --host=HOSTNAME \
     --user=USERNAME
     

    Per informazioni su come creare un certificato e una chiave client, consulta Certificati client.

Passaggi successivi