Conéctate con PGAdapter

En este documento, se describe cómo conectarse a Spanner Omni con PGAdapter. Configuras PGAdapter para establecer conexiones seguras. PGAdapter admite modos de seguridad de texto sin formato, seguridad de la capa de transporte (TLS) y TLS mutua (mTLS). Estos modos protegen tus datos durante la transmisión, ya que proporcionan diferentes niveles de encriptación y autenticación. Cada modo de seguridad requiere configuraciones específicas del cliente para garantizar la integridad y la confidencialidad de los datos.

Puedes ejecutar PGAdapter como un proceso independiente o integrarlo directamente en tu aplicación. Para la administración interactiva y la ejecución manual de consultas, conéctate a tu base de datos con herramientas estándar de PostgreSQL, como psql. Para compilar aplicaciones automatizadas, usa controladores compatibles con PostgreSQL, como los siguientes:

Para ver muestras de código que usan algunos de estos controladores, consulta el código de muestra en este documento.

Modos de seguridad

Spanner Omni PGAdapter admite tres modos de seguridad, que definen cómo se encripta y autentica la comunicación entre PGAdapter y la base de datos. Para usar estos modos, configura las opciones del cliente como se describe en la siguiente tabla:

Modo de seguridad Descripción
Texto sin formato La comunicación no está encriptada.
TLS La comunicación se encripta con la seguridad de la capa de transporte (TLS). Este modo requiere que agregues el certificado de la CA de Omni de Spanner al almacén de confianza predeterminado de Java.
mTLS La comunicación se encripta con TLS mutua (mTLS). Este modo requiere que proporciones un certificado de cliente y una clave privada del cliente.

Ejecutar como un proceso independiente

Ejecuta PGAdapter como un proceso independiente para aplicaciones que no son de Java y para herramientas estándar de PostgreSQL, por ejemplo, psql, cuando necesites interacción manual con la base de datos. Este enfoque desacopla el proxy del ciclo de vida de tu aplicación, lo que te permite administrarlo y actualizarlo de forma independiente. Para iniciar PGAdapter como un proceso independiente, usa los siguientes métodos de configuración según el modo de seguridad seleccionado.

Cómo usar el modo de texto sin formato

Para iniciar PGAdapter en modo de comunicación de texto simple, ejecuta el siguiente comando:

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

Reemplaza lo siguiente:

  • DATABASE_ID: Es el ID de tu base de datos de Spanner Omni, por ejemplo, test-db.

  • ENDPOINT: Es el extremo de tu instancia de Spanner Omni, por ejemplo, localhost:15000.

Cómo usar el modo TLS

Antes de iniciar PGAdapter en proceso en modo TLS con tu aplicación de Java, debes agregar tu certificado de CA de Spanner Omni al almacén de confianza predeterminado de Java. Para agregar un certificado de CA existente al almacén de confianza de Java, ejecuta el siguiente comando:

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

Para iniciar PGAdapter en modo TLS, ejecuta el siguiente 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"

Usa el modo mTLS

Antes de iniciar PGAdapter en modo mTLS, debes asegurarte de que la clave del cliente esté en formato PKCS#8. Para convertir una clave existente en tu almacén de claves al formato PKCS#8, ejecuta el siguiente comando:

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

Como alternativa, cuando crees tu certificado y clave de cliente con la CLI de Spanner Omni, proporciona el parámetro --generate-pkcs8-key para generar la clave en formato PKCS#8.

Para iniciar PGAdapter en modo mTLS, ejecuta el siguiente 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"

Reemplaza lo siguiente:

  • PATH_TO_CLIENT_CERT: Es la ruta de acceso al archivo del certificado del cliente.

  • PATH_TO_CLIENT_KEY: Es la ruta de acceso al archivo de claves del cliente.

Conéctate con psql

Después de establecer una conexión con uno de los métodos anteriores, ejecuta psql para administrar tu base de datos y ejecutar consultas. Para conectarte a psql, usa el siguiente comando:

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

Reemplaza lo siguiente:

  • PG_HOST: Es el nombre de host o la dirección IP de la máquina en la que se ejecuta PGAdapter. Si ejecutas el código de forma local, usa localhost.

  • PG_PORT: Es el número de puerto en el que se ejecuta PGAdapter. Si no especificaste un puerto personalizado, PGAdapter usa el puerto 5432 de forma predeterminada.

  • USERNAME: Es tu nombre de usuario de PostgreSQL.

Ejecutar en el proceso con tu aplicación

También puedes iniciar PGAdapter en proceso con tu aplicación. Para establecer la seguridad, configura el objeto OptionsMetadata.

Cómo usar el modo de texto sin formato

Para la comunicación de texto simple, como el desarrollo local o las pruebas en entornos seguros en los que la sobrecarga de encriptación es innecesaria, usa la siguiente configuración:

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

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

Cómo usar el modo TLS

Para la comunicación de texto sin formato para usar en entornos como el desarrollo o las pruebas locales, usa la siguiente configuración:

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

Para establecer una conexión TLS en el proceso, usa la siguiente configuración:

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

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

Usa el modo mTLS

Antes de que puedas iniciar el modo en proceso de PGAdapter con tu aplicación de Java, debes asegurarte de que tu clave de cliente esté en formato PKCS#8. Para convertir una clave existente en tu almacén de claves al formato PKCS#8, ejecuta el siguiente comando:

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

Como alternativa, cuando crees tu certificado y clave de cliente con la CLI de Spanner Omni, proporciona el parámetro --generate-pkcs8-key para generar la clave en formato PKCS#8.

Para establecer una conexión mTLS en el proceso, usa esta configuración:

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

Código de muestra

En esta sección, se proporciona código de muestra para conectarse a una base de datos de Spanner Omni con los siguientes controladores compatibles con PostgreSQL:

Reemplaza el siguiente marcador de posición en tus cadenas de conexión:

  • PASSWORD: Es la contraseña de tu usuario de PostgreSQL.

JDBC

Puedes conectarte a PGAdapter con el controlador JDBC de PostgreSQL como si te conectaras a una base de datos de PostgreSQL. Para conectarte a una tabla y consultarla en una base de datos de Spanner Omni, usa el siguiente código de muestra:

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)

Puedes conectarte a PGAdapter con pgx como si te conectaras a una base de datos de PostgreSQL. Usa el siguiente código de muestra:

// 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 o psycopg3)

Puedes conectarte a PGAdapter con psycopg2 o psycopg3 como si te conectaras a una base de datos de PostgreSQL. Para conectarte a una tabla y consultarla en una base de datos de Spanner Omni, usa el siguiente código de muestra:

# 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)

Puedes conectarte a PGAdapter con node-postgres como si te conectaras a una base de datos de PostgreSQL. Para conectarte a una tabla y consultarla en una base de datos de Spanner Omni, usa el siguiente código de muestra:

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