Connexion à l'aide de l'authentification IAM pour les bases de données

Cette page explique comment les utilisateurs et les comptes de service peuvent se connecter aux bases de données Cloud SQL à l'aide de l'authentification IAM pour les bases de données Cloud SQL. Pour en savoir plus, consultez la page Authentification IAM.

Avant de commencer

Se connecter à l'aide de l'authentification IAM automatique pour les bases de données

Vous pouvez configurer un connecteur Cloud SQL pour gérer automatiquement l'authentification auprès de l'instance Cloud SQL au nom d'un utilisateur ou d'une application. Les connecteurs incluent le proxy d'authentification Cloud SQL, le connecteur Go, le connecteur Java et le connecteur Python, qui sont tous compatibles avec l'authentification IAM automatique des bases de données. Lorsque vous utilisez un connecteur Cloud SQL avec l'authentification IAM automatique pour les bases de données, le compte IAM que vous utilisez pour démarrer le connecteur doit être le même que celui qui s'authentifie auprès de la base de données.

Pour vous connecter à l'aide de l'authentification IAM automatique pour les bases de données, procédez comme suit :

Proxy d'authentification Cloud SQL

  1. Authentifiez-vous sur Google Cloud.

    Utilisateur

    Authentifiez-vous sur Google Cloud à l'aide des identifiants par défaut de l'application (ADC).

    Exécutez la commande gcloud auth application-default login. Pour en savoir plus, consultez la page Configurer les identifiants par défaut de l'application.

    Compte de service

    Pour vous authentifier sur Google Cloud à l'aide des ADC avec un compte de service, vous pouvez emprunter l'identité d'un compte de service ou utiliser une clé de compte de service. Pour utiliser l'identité de compte de service empruntée, remplacez SERVICE_ACCOUNT_EMAIL_ADDRESS et exécutez la commande suivante :

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

    Pour en savoir plus, consultez la page Configurer les identifiants par défaut de l'application.

  2. Démarrez le proxy d'authentification Cloud SQL avec l'option --auto-iam-authn.

    Remplacez les éléments suivants :

    • INSTANCE_CONNECTION_NAME : chaîne de connexion permettant d'identifier une instance Cloud SQL. Si vous utilisez un port différent du port PostgreSQL par défaut, spécifiez le numéro de port. Pour savoir comment trouver et construire cette chaîne, consultez la section Options d'authentification du proxy d'authentification Cloud SQL.
    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME

    Pour en savoir plus sur le démarrage du proxy, consultez la section Démarrer le proxy d'authentification Cloud SQL.

  3. Lorsque vous êtes prêt à vous connecter à l'instance à l'aide du proxy d'authentification Cloud SQL, connectez-vous avec le client psql.

    Remplacez les éléments suivants :

    • HOSTNAME : adresse IP utilisée par le proxy d'authentification Cloud SQL. Par défaut, le proxy d'authentification Cloud SQL utilise l'adresse localhost de 127.0.0.1, mais vous pouvez attribuer une autre adresse IP lorsque vous démarrez le proxy d'authentification Cloud SQL.
    • USERNAME : pour un service IAM, le nom d'utilisateur est l'adresse e-mail complète de l'utilisateur. Pour un compte de service, il s'agit de l'adresse e-mail du compte de service sans le suffixe de domaine .gserviceaccount.com.
    • PORT_NUMBER : facultatif. Si vous avez spécifié un autre port dans la chaîne de connexion de l'instance, spécifiez ce numéro de port.
    • DATABASE_NAME : nom de la base de données à laquelle se connecter

    Exécutez la commande suivante :

    psql -h HOSTNAME \
     -U USERNAME \
     --port PORT_NUMBER \
     --dbname=DATABASE_NAME
     

    Pour en savoir plus sur la connexion au proxy d'authentification Cloud SQL, consultez la section Se connecter à l'aide du client psql.

Go

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

	"cloud.google.com/go/cloudsqlconn"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/stdlib"
)

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@project-id.iam'
		dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
		usePrivate             = os.Getenv("PRIVATE_IP")
	)

	d, err := cloudsqlconn.NewDialer(context.Background(), cloudsqlconn.WithIAMAuthN())
	if err != nil {
		return nil, fmt.Errorf("cloudsqlconn.NewDialer: %w", err)
	}
	var opts []cloudsqlconn.DialOption
	if usePrivate != "" {
		opts = append(opts, cloudsqlconn.WithPrivateIP())
	}

	dsn := fmt.Sprintf("user=%s database=%s", dbUser, dbName)
	config, err := pgx.ParseConfig(dsn)
	if err != nil {
		return nil, err
	}

	config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
		return d.Dial(ctx, instanceConnectionName, opts...)
	}
	dbURI := stdlib.RegisterConnConfig(config)
	dbPool, err := sql.Open("pgx", 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 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:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
    // socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<DB_IAM_USER>&
    // password=password
    // 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 to connect with.
    config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));

    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.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);
    // Password must be set to a nonempty value to bypass driver validation errors.
    config.addDataSourceProperty("password", "password");
    // 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");


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

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

Java R2DBC

private static final String CONNECTION_NAME = System.getenv("POSTGRES_IAM_CONNECTION_NAME");
private static final String DB_NAME = System.getenv("POSTGRES_DB");
private static final String DB_USER = System.getenv("POSTGRES_IAM_USER");
  // Set up ConnectionFactoryOptions
  ConnectionFactoryOptions options =
      ConnectionFactoryOptions.builder()
          .option(DRIVER, "gcp")
          .option(PROTOCOL, "postgresql")
          // Password must be set to a nonempty value to bypass driver validation errors
          .option(PASSWORD, "password")
          .option(USER, DB_USER)
          .option(DATABASE, DB_NAME)
          .option(HOST, CONNECTION_NAME)
          .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);

Python

import os

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

import sqlalchemy


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

    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. 'sa-name@project-id.iam'
    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()

    def getconn() -> pg8000.dbapi.Connection:
        conn: pg8000.dbapi.Connection = connector.connect(
            instance_connection_name,
            "pg8000",
            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(
        "postgresql+pg8000://",
        creator=getconn,
        # ...
    )
    return pool

Se connecter à l'aide de l'authentification IAM manuelle pour les bases de données

Un utilisateur ou une application peut s'authentifier auprès de la base de données à l'aide d'IAM en demandant manuellement un jeton d'accès à Google Cloud et en le présentant à la base de données. À l'aide de gcloud CLI, vous pouvez explicitement demander un jeton OAuth 2.0 avec le champ d'application de l'API Cloud SQL Admin servant à vous connecter à la base de données. Lorsque vous vous connectez en tant qu'utilisateur de la base de données avec l'authentification IAM manuelle pour les bases de données, vous utilisez votre adresse e-mail comme nom d'utilisateur et le jeton d'accès comme mot de passe. Vous pouvez utiliser cette méthode avec une connexion directe à la base de données ou à travers un connecteur Cloud SQL.

Dans ces étapes, vous vous authentifiez auprès de Google Cloud, demandez un jeton d'accès, puis vous vous connectez à la base de données en transmettant le jeton en tant que mot de passe pour l'utilisateur IAM de la base de données. Suivez ces étapes pour vous connecter sans le proxy d'authentification Cloud SQL.

Pour réaliser ces étapes, vous devez :

  • Si vous vous connectez à une instance avec une adresse IP publique, autorisez l'accès externe à l'instance. Pour en savoir plus, consultez la section Autorisez l'adresse IP de votre machine à utiliser une adresse IP publique.
  • Si vous vous connectez à une instance avec une adresse IP privée, exécutez la commande dans le réseau cloud privé virtuel (VPC).
  • Utilisez la commande gcloud sql generate-login-token pour générer votre jeton d'authentification.
  • Pour vous connecter à l'aide de l'authentification IAM manuelle pour les bases de données, procédez comme suit :

    gcloud

    1. Authentifiez-vous sur Google Cloud.

      Utilisateur

      Authentifiez-vous auprès d'IAM en utilisant gcloud auth login. Pour en savoir plus, consultez la section Autoriser avec un compte utilisateur.

      Compte de service

      Authentifiez-vous auprès d'IAM en utilisant gcloud auth activate-service-account. Pour en savoir plus, consultez la section Autoriser avec un compte de service.

    2. Demandez le jeton d'accès et connectez-vous avec un client.

      Remplacez les éléments suivants :

      • HOSTNAME : adresse IP de l'instance (soit l'adresse IP publique, soit l'adresse IP privée).
      • USERNAME : pour un service IAM, le nom d'utilisateur est l'adresse e-mail complète de l'utilisateur. Pour un compte de service, il s'agit de l'adresse e-mail du compte de service sans le suffixe de domaine .gserviceaccount.com.
      • DATABASE_NAME : nom de la base de données à laquelle se connecter

       PGPASSWORD=`gcloud sql generate-login-token` \
       psql "sslmode=require \
       hostaddr=HOSTNAME \
       user=USERNAME \
       dbname=DATABASE_NAME" \
       --no-password
       

      Si ssl_mode sur votre instance Cloud SQL est configuré sur TRUSTED_CLIENT_CERTIFICATE_REQUIRED, nous vous recommandons de vous connecter avec l'authentification de la base de données IAM automatique pour appliquer la validation de l'identité du client.

    Étapes suivantes