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.

    User

    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. Si deseas autenticarte con 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 INSTANCE_CONNECTION_NAME por la cadena de conexión que se usa para identificar la instancia de Cloud SQL. Si usas un puerto distinto del puerto predeterminado de MySQL, 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 mysql. 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: En una cuenta de usuario de IAM, esta es la dirección de correo electrónico del usuario, sin @ ni el nombre de dominio. Por ejemplo, para test-user@example.com, ingresa test-user. En una cuenta de servicio, esta es la dirección de correo electrónico de la cuenta de servicio sin el sufijo @project-id.iam.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.

    Ejecuta el siguiente comando:

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

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

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

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

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

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

R2DBC de Java

// 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(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 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()

    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

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:

Para acceder con la autenticación manual de la base de datos de IAM:

gcloud

  1. Autentica en Google Cloud.

    User

    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: En una cuenta de usuario de IAM, esta es la dirección de correo electrónico del usuario, sin @ ni el nombre de dominio. Por ejemplo, para test-user@example.com, ingresa test-user. En una cuenta de servicio, esta es la dirección de correo electrónico de la cuenta de servicio sin el sufijo @project-id.iam.gserviceaccount.com.

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

    Si ssl_mode en tu instancia de Cloud SQL está configurada como TRUSTED_CLIENT_CERTIFICATE_REQUIRED, incluye un certificado de cliente y una clave de cliente cuando accedas. Además, a fin de permitir que el cliente verifique la identidad del servidor para la autenticación mutua, especifica el certificado del servidor server-ca.pem. Por ejemplo:

     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
     

    Para obtener información sobre cómo crear un certificado de cliente y una clave, consulta Certificados de cliente.

¿Qué sigue?