Connettiti utilizzando PGAdapter

Questo documento descrive come connettersi a Spanner Omni utilizzando PGAdapter. Configura PGAdapter per stabilire connessioni sicure. PGAdapter supporta le modalità di sicurezza testo normale, Transport Layer Security (TLS) e mutual TLS (mTLS). Queste modalità proteggono i tuoi dati durante la trasmissione fornendo vari livelli di crittografia e autenticazione. Ogni modalità di sicurezza richiede configurazioni client specifiche per garantire l'integrità e la riservatezza dei dati.

Puoi eseguire PGAdapter come processo autonomo o integrarlo direttamente nella tua applicazione. Per la gestione interattiva e l'esecuzione manuale delle query, connettiti al database utilizzando strumenti PostgreSQL standard come psql. Per creare applicazioni automatizzate, utilizza driver compatibili con PostgreSQL come i seguenti:

Per esempi di codice che utilizzano alcuni di questi driver, vedi Esempio di codice in questo documento.

Modalità di sicurezza

Spanner Omni PGAdapter supporta tre modalità di sicurezza, che definiscono come la comunicazione viene criptata e autenticata tra PGAdapter e il database. Per utilizzare queste modalità, configura le opzioni del client come descritto nella tabella seguente:

Modalità di sicurezza Descrizione
Testo normale La comunicazione non è criptata.
TLS La comunicazione è criptata tramite Transport Layer Security (TLS). Questa modalità richiede l'aggiunta del certificato CA Spanner Omni all'archivio attendibile Java predefinito.
mTLS La comunicazione viene criptata utilizzando TLS reciproco (mTLS). Questa modalità richiede di fornire sia un certificato client sia una chiave privata del client.

Esegui come processo autonomo

Esegui PGAdapter come processo autonomo per applicazioni non Java e per strumenti PostgreSQL standard, ad esempio psql, quando hai bisogno di un'interazione manuale con il database. Questo approccio disaccoppia il proxy dal ciclo di vita dell'applicazione, consentendoti di gestirlo e aggiornarlo in modo indipendente. Per avviare PGAdapter come processo autonomo, utilizza i seguenti metodi di configurazione in base alla modalità di sicurezza selezionata.

Utilizzare la modalità di testo normale

Per avviare PGAdapter in modalità di comunicazione in testo normale, esegui questo comando:

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

Sostituisci quanto segue:

  • DATABASE_ID: l'ID del tuo database Spanner Omni, ad esempio test-db.

  • ENDPOINT: l'endpoint dell'istanza Spanner Omni, ad esempio localhost:15000.

Utilizzare la modalità TLS

Prima di poter avviare PGAdapter in-process in modalità TLS con la tua applicazione Java, devi aggiungere il certificato CA Spanner Omni all'archivio attendibilità Java predefinito. Per aggiungere un certificato CA esistente all'archivio attendibile Java, esegui questo comando:

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

Per avviare PGAdapter in modalità TLS, esegui questo 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"

Utilizzare la modalità mTLS

Prima di poter avviare PGAdapter in modalità mTLS, devi assicurarti che la chiave client sia in formato PKCS#8. Per convertire una chiave esistente nel keystore in un formato PKCS#8, esegui questo comando:

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

In alternativa, quando crei il certificato e la chiave client utilizzando Spanner Omni CLI, fornisci il parametro --generate-pkcs8-key per generare la chiave in formato PKCS#8.

Per avviare PGAdapter in modalità mTLS, esegui questo 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"

Sostituisci quanto segue:

  • PATH_TO_CLIENT_CERT: il percorso del file del certificato client.

  • PATH_TO_CLIENT_KEY: il percorso del file della chiave client.

Contatta psql

Dopo aver stabilito una connessione utilizzando uno dei metodi precedenti, esegui psql per gestire il database ed eseguire query. Per connetterti a psql, utilizza il seguente comando:

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

Sostituisci quanto segue:

  • PG_HOST: il nome host o l'indirizzo IP della macchina in cui è in esecuzione PGAdapter. In caso di esecuzione locale, utilizza localhost.

  • PG_PORT: il numero di porta su cui è in esecuzione PGAdapter. Se non hai specificato una porta personalizzata, PGAdapter utilizza per impostazione predefinita la porta 5432.

  • USERNAME: il tuo nome utente PostgreSQL.

Esegui in-process con la tua applicazione

Puoi anche avviare PGAdapter in-process con la tua applicazione. Per stabilire la sicurezza, configura l'oggetto OptionsMetadata.

Utilizzare la modalità di testo normale

Per la comunicazione in testo normale, ad esempio lo sviluppo locale o i test in ambienti sicuri in cui il sovraccarico di crittografia non è necessario, utilizza la seguente configurazione:

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

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

Utilizzare la modalità TLS

Per la comunicazione in testo normale da utilizzare in ambienti come lo sviluppo locale o il test, utilizza la seguente configurazione:

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

Per stabilire una connessione TLS in-processo, utilizza la seguente configurazione:

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

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

Utilizzare la modalità mTLS

Prima di poter avviare PGAdapter in modalità in-process con la tua applicazione Java, devi assicurarti che la chiave client sia in formato PKCS#8. Per convertire una chiave esistente nel keystore in un formato PKCS#8, esegui questo comando:

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

In alternativa, quando crei il certificato e la chiave client utilizzando Spanner Omni CLI, fornisci il parametro --generate-pkcs8-key per generare la chiave in formato PKCS#8.

Per stabilire una connessione mTLS in-process, utilizza questa configurazione:

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

Codice di esempio

Questa sezione fornisce un codice campione per la connessione a un database Spanner Omni utilizzando i seguenti driver compatibili con PostgreSQL:

Sostituisci il seguente segnaposto nelle stringhe di connessione:

  • PASSWORD: la password per l'utente PostgreSQL.

JDBC

Puoi connetterti a PGAdapter utilizzando il driver JDBC di PostgreSQL come se ti stessi connettendo a un database PostgreSQL. Per connetterti a una tabella in un database Spanner Omni ed eseguire query, utilizza il seguente codice campione:

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)

Puoi connetterti a PGAdapter utilizzando pgx come se ti stessi connettendo a un database PostgreSQL. Utilizza il seguente codice campione:

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

Puoi connetterti a PGAdapter utilizzando psycopg2 o psycopg3 come se ti stessi connettendo a un database PostgreSQL. Per connetterti a una tabella in un database Spanner Omni ed eseguire query, utilizza il seguente codice campione:

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

Puoi connetterti a PGAdapter utilizzando node-postgres come se ti stessi connettendo a un database PostgreSQL. Per connetterti a una tabella in un database Spanner Omni ed eseguire query, utilizza il seguente codice campione:

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