Estabeleça ligação através dos conectores de linguagem do Cloud SQL

Os conetores do Cloud SQL são bibliotecas que fornecem encriptação e autorização baseada na gestão de identidade e de acesso (IAM) quando se ligam a uma instância do Cloud SQL. Não podem fornecer um caminho de rede para uma instância do Cloud SQL se ainda não existir.

Outras formas de estabelecer ligação a uma instância do Cloud SQL incluem a utilização de um cliente de base de dados ou o proxy Auth do Cloud SQL. Consulte a página Acerca das opções de ligação para ver mais informações sobre como estabelecer ligação a uma instância do Cloud SQL.

Esta página aborda os seguintes conetores do Cloud SQL:

  • O conector Java do Cloud SQL
  • O conector Python do Cloud SQL (abrir no Colab)
  • O conector Go do Cloud SQL
  • O conector Node.js do Cloud SQL

Vantagens

A utilização de um conetor do Cloud SQL oferece as seguintes vantagens:

  • Autorização da IAM: usa autorizações da IAM para controlar quem ou o quê pode ligar-se às suas instâncias do Cloud SQL.
  • Comodidade: remove o requisito de gerir certificados SSL, configurar regras de firewall ou ativar redes autorizadas.
  • Autenticação de base de dados da IAM: oferece suporte para a funcionalidade de autenticação de base de dados da IAM automática do Cloud SQL.

Antes de começar

  • Ative a API Admin do Cloud SQL.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  • Criar uma instância do Cloud SQL, incluindo a configuração do utilizador predefinido.

    Para mais informações sobre como criar instâncias, consulte o artigo Crie instâncias.

    Para mais informações sobre a configuração do utilizador predefinido, consulte o artigo Defina a palavra-passe da conta de utilizador predefinida.

  • Configure as funções e as autorizações necessárias para estabelecer ligação a uma instância do Cloud SQL.

Configuração

Java

O conetor Java do Cloud SQL é uma biblioteca que fornece autorização e encriptação baseadas na IAM quando se liga a uma instância do Cloud SQL. Não pode fornecer um caminho de rede para uma instância do Cloud SQL se ainda não existir nenhuma.

Instalação

Para obter instruções sobre como criar e usar os controladores para JDBC e R2DBC com o conetor Java do Cloud SQL, consulte os seguintes links:

Para ver exemplos desta biblioteca a ser usada no contexto de uma aplicação, consulte estas aplicações de exemplo.

Autenticar

Esta biblioteca usa as Credenciais padrão da aplicação para autenticar a ligação ao servidor do Cloud SQL.

Para ativar as credenciais localmente, use o seguinte comando gcloud:

    gcloud auth application-default login
    

Associe ao Intellij

Para ligar o IntelliJ à sua instância do Cloud SQL, tem de adicionar a biblioteca como um JAR com dependências na secção Ficheiros adicionais na página de definições do controlador. Por exemplo, pode encontrar arquivos JARs completos pré-criados na página Versões do conector Java do Cloud SQL para este fim.

Python

O conetor Python do Cloud SQL é uma biblioteca que pode ser usada juntamente com um controlador de base de dados para permitir que os utilizadores com autorizações suficientes se liguem a uma base de dados do Cloud SQL sem terem de adicionar manualmente IPs à lista de autorizações nem gerir certificados SSL.

Para ver exemplos interativos da utilização do conetor Python do Cloud SQL, abra o bloco de notas do conetor Python do Cloud SQL.

Os controladores suportados pelo PostgreSQL são pg8000 e asyncpg.

Instalação

Para instalar a versão mais recente do conetor Python do Cloud SQL, use o comando pip install e especifique o controlador pg8000 ou asyncpg para a sua base de dados:

    pip install "cloud-sql-python-connector[pg8000]"
    

ou

    pip install "cloud-sql-python-connector[asyncpg]"
    

Autenticar

Esta biblioteca usa as Credenciais padrão da aplicação para autenticar a ligação ao servidor do Cloud SQL.

Para ativar as credenciais localmente, use o seguinte comando gcloud:

    gcloud auth application-default login
    

Ir

O conetor Go do Cloud SQL é um conetor do Cloud SQL concebido para utilização com a linguagem Go. Para maior segurança, este conetor usa uma encriptação TLS 1.3 robusta e autenticada manualmente entre o conetor do cliente e o proxy do lado do servidor, independentemente do protocolo da base de dados.

Instalação

Pode instalar este repositório com go get:

    go get cloud.google.com/go/cloudsqlconn
    

Node.js

O conetor do Node.js é uma biblioteca concebida para utilização com o tempo de execução do Node.js, que lhe permite ligar-se em segurança à sua instância do Cloud SQL.

Instalação

Pode instalar a biblioteca com npm install:

    npm install @google-cloud/cloud-sql-connector
    

Utilizar

Java

Para ver este fragmento no contexto de uma app Web, consulte o ficheiro README no GitHub.

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

public class ConnectorConnectionPoolFactory 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_USER = System.getenv("DB_USER");
  private static final String DB_PASS = System.getenv("DB_PASS");
  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_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:postgresql:///%s", DB_NAME));
    config.setUsername(DB_USER); // e.g. "root", _postgres"
    config.setPassword(DB_PASS); // e.g. "my-password"

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


    // The ipTypes argument can be used to specify a comma delimited list of preferred IP types
    // for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
    // SocketFactory to connect with an instance's associated private IP.
    config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");

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

Python

Consulte o artigo Como usar este conetor para ver instruções detalhadas sobre como usar a biblioteca. Veja um exemplo de código de teste de ligação no GitHub.

import os

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

import sqlalchemy


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

    Uses the Cloud SQL Python Connector package.
    """
    # 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_user = os.environ["DB_USER"]  # e.g. 'my-db-user'
    db_pass = os.environ["DB_PASS"]  # e.g. 'my-db-password'
    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() -> pg8000.dbapi.Connection:
        conn: pg8000.dbapi.Connection = connector.connect(
            instance_connection_name,
            "pg8000",
            user=db_user,
            password=db_pass,
            db=db_name,
            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

Ir

Consulte a secção Utilização para ver instruções detalhadas sobre a utilização da biblioteca. Veja um exemplo de código de teste de ligação no GitHub.

package cloudsql

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 connectWithConnector() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Fatal Error in connect_connector.go: %s environment variable not set.\n", 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 passwords and other secrets safe.
	var (
		dbUser                 = mustGetenv("DB_USER")                  // e.g. 'my-db-user'
		dbPwd                  = mustGetenv("DB_PASS")                  // e.g. 'my-db-password'
		dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
		usePrivate             = os.Getenv("PRIVATE_IP")
	)

	dsn := fmt.Sprintf("user=%s password=%s database=%s", dbUser, dbPwd, dbName)
	config, err := pgx.ParseConfig(dsn)
	if err != nil {
		return nil, err
	}
	var opts []cloudsqlconn.Option
	if usePrivate != "" {
		opts = append(opts, cloudsqlconn.WithDefaultDialOptions(cloudsqlconn.WithPrivateIP()))
	}
	// 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.
	opts = append(opts, cloudsqlconn.WithLazyRefresh())
	d, err := cloudsqlconn.NewDialer(context.Background(), opts...)
	if err != nil {
		return nil, err
	}
	// Use the Cloud SQL connector to handle connecting to the instance.
	// This approach does *NOT* require the Cloud SQL proxy.
	config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
		return d.Dial(ctx, instanceConnectionName)
	}
	dbURI := stdlib.RegisterConnConfig(config)
	dbPool, err := sql.Open("pgx", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Node.js

Para ver instruções detalhadas sobre a utilização da biblioteca, consulte a secção Utilização.

const Knex = require('knex');
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';

// connectWithConnector initializes connection pool for a Cloud SQL instance
// of Postgres using the Cloud SQL Node.js Connector.
const connectWithConnector = 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(),
  });
  const dbConfig = {
    client: 'pg',
    connection: {
      ...clientOpts,
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
    },
    // ... Specify additional properties here.
    ...config,
  };
  // Establish a connection to the database.
  return Knex(dbConfig);
};

Aplicar

Ao usar a aplicação de conetores, pode aplicar a utilização apenas do proxy Auth do Cloud SQL ou dos conetores de linguagem do Cloud SQL para ligar a instâncias do Cloud SQL. Com a aplicação do conetor, o Cloud SQL rejeita ligações diretas à base de dados.

Se estiver a usar uma instância ativada com o Private Service Connect, existe uma limitação. Se a instância tiver a aplicação de conetores ativada, não pode criar réplicas de leitura para a instância. Da mesma forma, se a instância tiver réplicas de leitura, não pode ativar a aplicação do conector para a instância.

gcloud

Para aplicar a utilização apenas do proxy Auth do Cloud SQL ou dos conetores de linguagem do Cloud SQL para ligar a uma instância, use o comando gcloud sql instances patch:

gcloud sql instances patch INSTANCE_NAME \
--connector-enforcement=REQUIRED

Substitua INSTANCE_NAME pelo nome da sua instância do Cloud SQL.

REST

Antes de usar qualquer um dos dados do pedido, faça as seguintes substituições:

  • PROJECT_ID: o ID ou o número do projeto do Google Cloud projeto que contém a instância
  • INSTANCE_NAME: o nome da sua instância do Cloud SQL

Método HTTP e URL:

PATCH https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_NAME

Corpo JSON do pedido:

{
  "kind": "sql#instance",
  "name": INSTANCE_NAME,
  "project": PROJECT_ID,
  "settings": {
  "connectorEnforcement": "REQUIRED",
  "kind": "sql#settings"
  }
}

Para enviar o seu pedido, expanda uma destas opções:

Deve receber uma resposta JSON semelhante à seguinte:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_NAME",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "UPDATE",
  "name": "OPERATION_ID",
  "targetId": "INSTANCE_NAME",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/operations/OPERATION_ID",
  "targetProject": "PROJECT_ID"
}

Resolver problemas

Versões dos controladores

Certifique-se de que está a usar a versão mais recente dos conetores do Cloud SQL e do controlador da base de dados para evitar incompatibilidades. Algumas versões mais antigas dos controladores não são suportadas.

Caminhos de ligação

Os conetores do Cloud SQL fornecem autorização para ligações, mas não fornecem novos caminhos para a conetividade. Por exemplo, para se ligar a uma instância do Cloud SQL através de um endereço IP privado, a sua aplicação já tem de ter acesso à VPC.

Resolva problemas de ligação

Para obter ajuda adicional com problemas de ligação, consulte as páginas Resolva problemas e Resolva problemas de ligação.

O que se segue?