Fazer login usando a autenticação do banco de dados do IAM

Nesta página, descrevemos como usuários e contas de serviço podem fazer login nos bancos de dados do Cloud SQL usando a autenticação de banco de dados do Cloud SQL IAM. Para mais informações, consulte Autenticação do IAM.

Antes de começar

Fazer login com autenticação automática do banco de dados do IAM

É possível configurar um conector do Cloud SQL para processar automaticamente a autenticação na instância do Cloud SQL em nome de um usuário ou um aplicativo. Os conectores incluem o proxy do Cloud SQL Auth, o conector Go, o conector Java e o conector Python, todos compatíveis com a autenticação automática de banco de dados do IAM. Ao usar um conector do Cloud SQL com autenticação automática do banco de dados do IAM, a conta do IAM usada para iniciar o conector precisa ser a mesma autenticada no banco de dados.

Para fazer login com a autenticação automática de banco de dados do IAM, faça o seguinte:

Proxy de autenticação do Cloud SQL

  1. Faça a autenticação no Google Cloud.

    Usuário

    Faça a autenticação no Google Cloud usando o Application Default Credentials (ADC).

    Use o comando gcloud auth application-default login. Para mais informações, consulte Configurar o Application Default Credentials.

    Conta de serviço

    Para autenticar no Google Cloud usando o ADC com uma conta de serviço, use a identidade temporária de conta de serviço ou use uma chave de conta de serviço. Para usar a identidade temporária de conta de serviço, substitua SERVICE_ACCOUNT_EMAIL_ADDRESS e execute o seguinte comando:

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

    Para mais informações, consulte Configurar o Application Default Credentials.

  2. Inicie o proxy do Cloud SQL Auth com a sinalização --auto-iam-authn.

    Substitua:

    • INSTANCE_CONNECTION_NAME: a string de conexão para identificar uma instância do Cloud SQL. Se você usar uma porta diferente da padrão do PostgreSQL, especifique o número dela. Para mais informações sobre como encontrar e construir essa string, consulte Opções para autenticar o proxy do Cloud SQL Auth.
    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME

    Para mais informações sobre como iniciar o proxy, consulte Iniciar o proxy de autenticação do Cloud SQL.

  3. Quando você estiver pronto para se conectar à instância usando o proxy do Cloud SQL Auth, faça login com o cliente psql.

    Substitua:

    • HOSTNAME: endereço IP usado pelo proxy do Cloud SQL Auth. Por padrão, o proxy do Cloud SQL Auth usa o endereço localhost de 127.0.0.1, mas é possível atribuir um endereço IP diferente ao iniciar o proxy do Cloud SQL Auth.
    • USERNAME: para um IAM, o nome de usuário é o endereço de e-mail completo do usuário. Para uma conta de serviço, esse é o e-mail da conta de serviço sem o sufixo de domínio .gserviceaccount.com.
    • PORT_NUMBER: opcional. Se você especificou uma porta diferente na string de conexão da instância, especifique o número da porta.
    • DATABASE_NAME: o nome do banco de dados a ser conectado.

    Execute este comando:

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

    Para mais informações sobre como se conectar ao proxy do Cloud SQL Auth, consulte Conectar-se com o 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 do 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);
  }
}

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

Fazer login com autenticação do banco de dados do IAM

Um usuário ou aplicativo pode se autenticar no banco de dados usando o IAM solicitando manualmente um token de acesso do Google Cloud e apresentando-o ao banco de dados. Com a gcloud CLI, é possível solicitar explicitamente um token OAuth 2.0 com o escopo da API Cloud SQL Admin usado para fazer login no banco de dados. Ao fazer login como usuário do banco de dados com a autenticação do banco de dados do IAM, use o endereço de e-mail como nome de usuário e o token de acesso como senha. Use esse método com uma conexão direta com o banco de dados ou com um conector do Cloud SQL.

Nessas etapas, você faz a autenticação no Google Cloud, solicita um token de acesso e se conecta ao banco de dados passando o token como a senha do usuário do banco de dados do IAM. Use estas etapas para se conectar sem o proxy Auth do Cloud SQL.

Para essas etapas, você precisa:

  • Se você estiver se conectando a uma instância com IP público, autorize o acesso externo à instância. Para mais informações, consulte Autorizar o endereço IP da sua máquina para IP público.
  • Se você estiver se conectando a uma instância com IP particular, execute o comando na rede da nuvem privada virtual (VPC).
  • Use o comando gcloud sql generate-login-token para gerar seu token de autenticação.
  • Para fazer login com a autenticação automática de banco de dados do IAM, faça o seguinte:

    gcloud

    1. Faça a autenticação no Google Cloud.

      Usuário

      Autentique-se no IAM usando gcloud auth login. Para mais informações, consulte Autorizar com uma conta de usuário.

      Conta de serviço

      Autentique-se no IAM usando gcloud auth activate-service-account. Para mais informações, consulte Autorizar com uma conta de serviço.

    2. Solicite o token de acesso e faça login com um cliente.

      Substitua:

      • HOSTNAME: o endereço IP da instância, o endereço IP público ou particular.
      • USERNAME: para um IAM, o nome de usuário é o endereço de e-mail completo do usuário. Para uma conta de serviço, esse é o e-mail da conta de serviço sem o sufixo de domínio .gserviceaccount.com.
      • DATABASE_NAME: o nome do banco de dados a ser conectado.

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

      Se o ssl_mode na instância do Cloud SQL estiver configurado para TRUSTED_CLIENT_CERTIFICATE_REQUIRED, recomendamos que você faça login com o IAM automático do banco de dados para aplicar a validação de identidade do cliente.

    A seguir