Conectar usando o PGAdapter

Este documento descreve como se conectar ao Spanner Omni usando o PGAdapter. Você configura o PGAdapter para estabelecer conexões seguras. O PGAdapter oferece suporte a modos de segurança de texto simples, Transport Layer Security (TLS), e TLS mútuo (mTLS). Esses modos protegem seus dados durante a transmissão, fornecendo níveis variados de criptografia e autenticação. Cada modo de segurança exige configurações específicas do cliente para garantir a integridade de dados e a confidencialidade.

É possível executar o PGAdapter como um processo independente ou integrá-lo diretamente ao aplicativo. Para gerenciamento interativo e execução manual de consultas, conecte-se ao banco de dados usando ferramentas padrão do PostgreSQL, como psql. Para criar aplicativos automatizados, use drivers compatíveis com o PostgreSQL, como os seguintes:

Para exemplos de código que usam alguns desses drivers, consulte exemplo de código em este documento.

Modos de segurança

O PGAdapter do Spanner Omni oferece suporte a três modos de segurança, que definem como a comunicação é criptografada e autenticada entre o PGAdapter e o banco de dados. Para usar esses modos, configure as opções do cliente conforme descrito na tabela a seguir:

Modo de segurança Descrição
Texto simples A comunicação não é criptografada.
TLS A comunicação é criptografada usando o Transport Layer Security (TLS). Esse modo exige que você adicione o certificado de CA do Spanner Omni ao truststore Java padrão.
mTLS A comunicação é criptografada usando o TLS mútuo (mTLS). Esse modo exige que você forneça um certificado e uma chave privada do cliente.

Executar como um processo independente

Execute o PGAdapter como um processo independente para aplicativos não Java e para ferramentas padrão do PostgreSQL, por exemplo, psql, quando precisar de interação manual com o banco de dados. Essa abordagem desvincula o proxy do ciclo de vida do aplicativo, o que permite gerenciá-lo e atualizá-lo de forma independente. Para iniciar o PGAdapter como um processo independente, use os seguintes métodos de configuração com base no modo de segurança selecionado.

Usar o modo de texto simples

Para iniciar o PGAdapter no modo de comunicação de texto simples, execute o seguinte comando:

java -jar pgadapter.jar \
     -d DATABASE_ID \
     -e ENDPOINT \
     -r "isExperimentalHost=true;usePlainText=true"

Substitua:

  • DATABASE_ID: o ID do banco de dados do Spanner Omni, por exemplo, test-db.

  • ENDPOINT: o endpoint da instância do Spanner Omni, por exemplo, localhost:15000.

Usar o modo TLS

Antes de iniciar o PGAdapter no modo TLS com seu aplicativo Java, adicione o certificado de CA do Spanner Omni ao truststore Java padrão. Para adicionar um certificado de CA ao truststore Java, execute o seguinte comando:

sudo keytool -import -trustcacerts -file ~/.spanner/certs/ca.crt -alias spanner-ca -keystore $JAVA_HOME/lib/security/cacerts

Para iniciar o PGAdapter no modo TLS, execute o seguinte comando:

java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
     -Djavax.net.ssl.trustStoreType=JKS \
     -jar pgadapter.jar \
     -d DATABASE_ID \
     -e ENDPOINT \
     -r "isExperimentalHost=true"

Usar o modo mTLS

Antes de iniciar o PGAdapter no modo mTLS, verifique se a chave do cliente está no formato PKCS#8. Para converter uma chave no keystore em um formato PKCS#8, execute o seguinte comando:

openssl pkcs8 -topk8 -in ~/.spanner/certs/client.key -out ~/.spanner/certs/java-client.key -nocrypt

Como alternativa, ao criar o certificado e a chave do cliente usando a CLI do Spanner Omni, forneça o parâmetro --generate-pkcs8-key para gerar a chave no formato PKCS#8.

Para iniciar o PGAdapter no modo mTLS, execute o seguinte comando:

java -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
    -Djavax.net.ssl.trustStoreType=JKS \
    -jar pgadapter.jar \
    -d DATABASE_ID \
    -e ENDPOINT \
    -r "isExperimentalHost=true;clientCertificate=PATH_TO_CLIENT_CERT;clientKey=PATH_TO_CLIENT_KEY"

Substitua:

  • PATH_TO_CLIENT_CERT: o caminho para o arquivo de certificado do cliente.

  • PATH_TO_CLIENT_KEY: o caminho para o arquivo de chave do cliente.

Conectar com psql

Depois de estabelecer uma conexão usando um dos métodos anteriores, execute psql para gerenciar o banco de dados e executar consultas. Para se conectar ao psql, use o seguinte comando:

psql -h PG_HOST -p PG_PORT -U USERNAME -d DATABASE_ID

Substitua:

  • PG_HOST: o nome do host ou o endereço IP da máquina em que o PGAdapter está em execução. Se estiver executando localmente, use localhost.

  • PG_PORT: o número da porta em que o PGAdapter está em execução. Se você não tiver especificado uma porta personalizada, o PGAdapter usará a porta 5432 por padrão.

  • USERNAME: seu nome de usuário do PostgreSQL.

Executar no processo com seu aplicativo

Também é possível iniciar o PGAdapter no processo com seu aplicativo. Para estabelecer a segurança, configure o objeto OptionsMetadata.

Usar o modo de texto simples

Para comunicação de texto simples, como desenvolvimento local ou testes em ambientes seguros em que a sobrecarga de criptografia não é necessária, use a seguinte configuração:

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
    .setEndpoint("ENDPOINT")
    .setUsePlainText();

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

Usar o modo TLS

Para comunicação de texto simples para uso em ambientes como desenvolvimento local ou testes, use a seguinte configuração:

sudo keytool -import -trustcacerts -file /.spanner/certs/ca.crt -alias spanner-ca -keystore $JAVA_HOME/lib/security/cacerts

Para estabelecer uma conexão TLS no processo, use a seguinte configuração:

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
    .setEndpoint("ENDPOINT");

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

Usar o modo mTLS

Antes de iniciar o PGAdapter no modo de processo com seu aplicativo Java, verifique se a chave do cliente está no formato PKCS#8. Para converter uma chave no keystore em um formato PKCS#8, execute o seguinte comando:

openssl pkcs8 -topk8 -in ~/.spanner/certs/client.key -out ~/.spanner/certs/java-client.key -nocrypt

Como alternativa, ao criar o certificado e a chave do cliente usando a CLI do Spanner Omni, forneça o parâmetro --generate-pkcs8-key para gerar a chave no formato PKCS#8.

Para estabelecer uma conexão mTLS no processo, use esta configuração:

OptionsMetadata.Builder builder =
    OptionsMetadata.newBuilder()
    .setEndpoint("ENDPOINT")
    .useClientCert("PATH_TO_CLIENT_CERT", "PATH_TO_CLIENT_KEY");

ProxyServer server = new ProxyServer(builder.build());
server.startServer();
server.awaitRunning();

Exemplo de código

Esta seção fornece um exemplo de código para se conectar a um banco de dados do Spanner Omni usando os seguintes drivers compatíveis com o PostgreSQL:

Substitua o seguinte marcador de posição nas strings de conexão:

  • PASSWORD: a senha do usuário do PostgreSQL.

JDBC

É possível se conectar ao PGAdapter usando o driver JDBC do PostgreSQL como se estivesse se conectando a um banco de dados do PostgreSQL. Para conectar e consultar uma tabela em um banco de dados do Spanner Omni, use o seguinte exemplo de código:

String jdbcUrl =
    "jdbc:postgresql://PG_HOST:PG_PORT/DATABASE_ID";

try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
  // Example: Query data
  try (Statement statement = connection.createStatement();
      ResultSet resultSet = statement.executeQuery("SELECT * FROM Singers")) {

    System.out.println("Query Results:");
    while (resultSet.next()) {
      long id = resultSet.getLong("id");
      String name = resultSet.getString("name");
      System.out.printf("ID: %d, Name: %s\n", id, name);
    }
  } catch (SQLException e) {
    throw new RuntimeException(e);
  }
}

Go (pgx)

É possível se conectar ao PGAdapter usando pgx como se estivesse se conectando a um banco de dados do PostgreSQL. Use o seguinte exemplo de código:

// Database connection string
connString := "postgres://USERNAME:PASSWORD@PG_HOST:PG_PORT/DATABASE_ID?sslmode=disable"
ctx := context.Background()

// Connect to PGAdapter
conn, err := pgx.Connect(ctx, connString)
if err != nil {
  log.Fatalf("Connection error: %s", err.Error())
}
defer conn.Close(ctx)

// Query all rows from the Singers table
rows, err := conn.Query(ctx, "SELECT id, name FROM Singers")
if err != nil {
  log.Fatalf("Query error: %s", err.Error())
}
defer rows.Close()

// Iterate over the result set
fmt.Println("Singers Table Data:")
for rows.Next() {
  var id int
  var name string
  if err := rows.Scan(&id, &name); err != nil {
    log.Fatalf("Scan error: %s", err.Error())
  }
  fmt.Printf("ID: %d, Name: %s\n", id, name)
}

Python (psycopg2 ou psycopg3)

É possível se conectar ao PGAdapter usando psycopg2 ou psycopg3 como se estivesse se conectando a um banco de dados do PostgreSQL. Para conectar e consultar uma tabela em um banco de dados do Spanner Omni, use o seguinte exemplo de código:

# psycopg2
import psycopg2

connection = psycopg2.connect(database="DATABASE_ID",
                              host="PG_HOST",
                              port=PG_PORT)

cursor = connection.cursor()
cursor.execute('SELECT * FROM Singers')
for row in cursor:
  print(row)

cursor.close()
connection.close()


# psycopg3
import psycopg

with psycopg.connect("host=PG_HOST port=PG_PORT dbname=DATABASE_ID sslmode=disable") as conn:
  conn.autocommit = True
  with conn.cursor() as cur:
    cur.execute("SELECT * FROM Singers")
    for row in cur:
      print(row)

Node.js (node-postgres)

É possível se conectar ao PGAdapter usando node-postgres como se estivesse se conectando a um banco de dados do PostgreSQL. Para conectar e consultar uma tabela em um banco de dados do Spanner Omni, use o seguinte exemplo de código:

const { Client } = require('pg');
const client = new Client({
  host: 'PG_HOST',
  port: PG_PORT,
  database: 'DATABASE_ID',
});
await client.connect();
const res = await client.query("SELECT * FROM Singers");
console.log(res.rows);
await client.end();