Acceder con la autenticación de la base de datos de IAM

En esta página, se describe cómo los usuarios y las cuentas de servicio pueden acceder a las bases de datos de Cloud SQL mediante la autenticación de la base de datos de IAM de Cloud SQL. Para obtener más información, consulta Autenticación de IAM.

Antes de comenzar

Accede con autenticación de base de datos de IAM automática

Puedes configurar un conector de Cloud SQL para manejar de forma automática la autenticación en la instancia de Cloud SQL en nombre de un usuario o una aplicación. Los conectores incluyen el proxy de autenticación de Cloud SQL, el conector de Go, el conector de Java y el conector de Python, los cuales admiten la autenticación automática de la base de datos de IAM. Cuando usas un conector de Cloud SQL con autenticación automática de la base de datos de IAM, la cuenta de IAM que usas para iniciar el conector debe ser la misma que se autentica en la base de datos.

Para acceder con la autenticación automática de la base de datos de IAM, sigue estos pasos:

Proxy de autenticación de Cloud SQL

  1. Autentica en Google Cloud.

    Usuario

    Autentica en Google Cloud con las credenciales predeterminadas de la aplicación (ADC).

    Usa el comando gcloud auth application-default login. Para obtener más información, consulta Configura credenciales predeterminadas de la aplicación.

    Cuenta de servicio

    Para autenticarte en Google Cloud usando ADC con una cuenta de servicio, puedes usar la identidad temporal como cuenta de servicio o usar una clave de cuenta de servicio. Para usar la identidad temporal como cuenta de servicio, reemplaza SERVICE_ACCOUNT_EMAIL_ADDRESS y ejecuta el siguiente comando:

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

    Para obtener más información, consulta Configura credenciales predeterminadas de la aplicación.

  2. Inicia el proxy de autenticación de Cloud SQL con la marca --auto-iam-authn.

    Reemplaza lo siguiente:

    • INSTANCE_CONNECTION_NAME: Es la string de conexión para identificar una instancia de Cloud SQL. Si usas un puerto distinto del puerto predeterminado de PostgreSQL, especifica el número de puerto. Para obtener más información sobre cómo encontrar y crear esta cadena, consulta Opciones para autenticar el proxy de autenticación de Cloud SQL.
    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME

    Para obtener más información sobre cómo iniciar el proxy, consulta Inicia el proxy de autenticación de Cloud SQL.

  3. Cuando estés listo para conectarte a la instancia usando el proxy de autenticación de Cloud SQL, accede con el cliente psql.

    Reemplaza lo siguiente:

    • HOSTNAME: Dirección IP que usa el proxy de autenticación de Cloud SQL. De forma predeterminada, el proxy de autenticación de Cloud SQL usa la dirección del host local de 127.0.0.1, pero puedes asignar una dirección IP diferente cuando inicies el proxy de autenticación de Cloud SQL.
    • USERNAME: Para una IAM, el nombre de usuario es la dirección de correo electrónico completa del usuario. En el caso de las cuentas de servicio, este es el correo electrónico de la cuenta de servicio sin el sufijo de dominio .gserviceaccount.com.
    • PORT_NUMBER: Opcional Si especificaste un puerto diferente en la cadena de conexión de la instancia, especifica ese número de puerto.
    • DATABASE_NAME: El nombre de la base de datos a la que te conectarás.

    Ejecuta el siguiente comando:

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

    Para obtener más información sobre cómo conectarte al proxy de autenticación de Cloud SQL, consulta Conéctate con el cliente 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
}

JDBC de Java

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);
  }
}

R2DBC de Java

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

Accede con autenticación de base de datos manual de IAM

Un usuario o una aplicación puede autenticarse en la base de datos con la IAM solicitando manualmente un token de acceso desde Google Cloud y presentándolo a la base de datos. Con gcloud CLI, puedes solicitar de forma explícita un token de OAuth 2.0 con el permiso de la API de Cloud SQL Admin que se usa para acceder a la base de datos. Cuando accedes como un usuario de la base de datos con la autenticación manual de la base de datos de IAM, usas tu dirección de correo electrónico como nombre de usuario y el token de acceso como contraseña. Puedes usar este método con una conexión directa a la base de datos o con un conector de Cloud SQL.

En estos pasos, debes autenticarte en Google Cloud, solicitar un token de acceso y, luego, conectarte a la base de datos si pasas el token como la contraseña para el usuario de la base de datos de IAM. Sigue estos pasos para conectarte sin el proxy de autenticación de Cloud SQL.

Para estos pasos, debes hacer lo siguiente:

  • Si te conectas a una instancia con una IP pública, autoriza el acceso externo a la instancia. Si deseas obtener más información, consulta Autoriza la dirección IP de tu máquina para obtener una IP pública.
  • Si te conectas a una instancia con IP privada, ejecuta el comando dentro de la red de nube privada virtual (VPC).
  • Usa el comando gcloud sql generate-login-token para generar el token de autenticación.
  • Para acceder con la autenticación manual de la base de datos de IAM:

    gcloud

    1. Autentica en Google Cloud.

      Usuario

      Autentica en IAM mediante gcloud auth login. Para obtener más información, consulta Autoriza el acceso con una cuenta de usuario.

      Cuenta de servicio

      Autentica en IAM mediante gcloud auth activate-service-account. Para obtener más información, consulta Autentica con una cuenta de servicio.

    2. Solicita el token de acceso y accede con un cliente.

      Reemplaza lo siguiente:

      • HOSTNAME: La dirección IP de la instancia, ya sea la dirección IP pública o la privada.
      • USERNAME: Para una IAM, el nombre de usuario es la dirección de correo electrónico completa del usuario. En el caso de las cuentas de servicio, este es el correo electrónico de la cuenta de servicio sin el sufijo de dominio .gserviceaccount.com.
      • DATABASE_NAME: El nombre de la base de datos a la que te conectarás.

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

      Si ssl_mode en tu instancia de Cloud SQL está configurada como TRUSTED_CLIENT_CERTIFICATE_REQUIRED, te recomendamos que accedas con la autenticación automática de la base de datos de IAM para aplicar la validación de identidad del cliente.

    ¿Qué sigue?