Menghubungkan menggunakan Cloud SQL Language Connectors

Konektor Cloud SQL adalah library yang menyediakan enkripsi dan otorisasi berbasis Identity and Access Management (IAM) saat terhubung ke instance Cloud SQL. Klien tidak dapat menyediakan jalur jaringan ke instance Cloud SQL jika belum ada.

Cara lain untuk terhubung ke instance Cloud SQL mencakup menggunakan klien database atau Proxy Auth Cloud SQL. Lihat halaman Tentang opsi koneksi untuk mengetahui informasi selengkapnya tentang cara terhubung ke instance Cloud SQL.

Halaman ini membahas Konektor Cloud SQL berikut:

  • Konektor Java Cloud SQL
  • Konektor Python Cloud SQL (Buka di Colab)
  • Konektor Go Cloud SQL
  • Konektor Node.js Cloud SQL

Manfaat

Menggunakan konektor Cloud SQL memberikan manfaat berikut:

  • Otorisasi IAM: Menggunakan izin IAM untuk mengontrol siapa atau apa yang dapat terhubung ke instance Cloud SQL Anda.
  • Kepraktisan: Menghapus persyaratan untuk mengelola sertifikat SSL, mengonfigurasi aturan firewall, atau mengaktifkan jaringan yang diizinkan.

Sebelum memulai

  • Aktifkan Cloud SQL Admin API.

    Enable the API

  • Buat instance Cloud SQL, termasuk mengonfigurasi pengguna default.

    Untuk mengetahui informasi selengkapnya tentang cara membuat instance, lihat Membuat instance.

    Untuk mengetahui informasi selengkapnya tentang cara mengonfigurasi pengguna default, lihat Menyetel sandi untuk akun pengguna default.

  • Konfigurasi peran dan izin yang diperlukan untuk terhubung ke instance Cloud SQL.

Penyiapan

Java

Konektor Java Cloud SQL adalah library yang memberikan otorisasi dan enkripsi berbasis IAM saat terhubung ke instance Cloud SQL. Kode ini tidak dapat menyediakan jalur jaringan ke instance Cloud SQL jika belum ada.

Instal

Guna mengetahui petunjuk tentang cara mem-build dan menggunakan driver untuk JDBC dan R2DBC dengan Konektor Java Cloud SQL, lihat link berikut:

Untuk contoh library ini yang digunakan dalam konteks aplikasi, lihat aplikasi contoh ini.

Autentikasikan

Library ini menggunakan Kredensial Default Aplikasi untuk mengautentikasi koneksi ke server Cloud SQL.

Untuk mengaktifkan kredensial secara lokal, gunakan perintah gcloud berikut:

    gcloud auth application-default login
    

Hubungkan dengan Intellij

Untuk menghubungkan IntelliJ ke instance Cloud SQL Anda, Anda akan perlu untuk menambahkan library sebagai jar dengan dependensi di bagian File Tambahan pada halaman setelan driver. Misalnya, fat jar bawaan dapat ditemukan di halaman Rilis Konektor Java Cloud SQL untuk tujuan ini.

Python

Konektor Python Cloud SQL adalah library yang dapat digunakan bersama driver database agar pengguna dengan izin yang memadai dapat terhubung ke database Cloud SQL tanpa harus memasukkan IP ke daftar yang diizinkan secara manual atau mengelola sertifikat SSL.

Untuk contoh interaktif penggunaan Konektor Python Cloud SQL, buka notebook Konektor Python Cloud SQL.

Driver yang didukung SQL Server adalah pytds.

Instal

Untuk menginstal rilis terbaru Cloud SQL Python Connector, gunakan perintah pip install dan tentukan driver pytds untuk database Anda:

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

Autentikasikan

Library ini menggunakan Kredensial Default Aplikasi untuk mengautentikasi koneksi ke server Cloud SQL.

Untuk mengaktifkan kredensial secara lokal, gunakan perintah gcloud berikut:

    gcloud auth application-default login
    

Go

Konektor Go Cloud SQL adalah konektor Cloud SQL yang dirancang untuk digunakan dengan bahasa Go. Untuk meningkatkan keamanan, konektor ini menggunakan enkripsi TLS 1.3 yang tangguh dan diautentikasi secara manual antara konektor klien dan proxy sisi server, terlepas dari protokol database.

Instal

Anda dapat menginstal repo ini dengan go get:

    go get cloud.google.com/go/cloudsqlconn
    

Node.js

Node.js Connector adalah library yang dirancang untuk digunakan bersama runtime Node.js yang memungkinkan Anda untuk terhubung dengan aman ke instance Cloud SQL Anda.

Instal

Anda dapat menginstal library dengan npm install:

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

Gunakan

Java

Untuk melihat cuplikan ini dalam konteks aplikasi web, lihat README di 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 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 is equivalent to setting the config options below:
    // jdbc:sqlserver://;user=<DB_USER>;password=<DB_PASS>;databaseName=<DB_NAME>;
    // socketFactoryClass=com.google.cloud.sql.sqlserver.SocketFactory;
    // socketFactoryConstructorArg=<INSTANCE_CONNECTION_NAME>

    // 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
        .setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
    config.setUsername(DB_USER); // e.g. "root", "sqlserver"
    config.setPassword(DB_PASS); // e.g. "my-password"
    config.addDataSourceProperty("databaseName", DB_NAME);

    config.addDataSourceProperty("socketFactoryClass",
        "com.google.cloud.sql.sqlserver.SocketFactory");
    config.addDataSourceProperty("socketFactoryConstructorArg", INSTANCE_CONNECTION_NAME);

    // The Java Connector provides SSL encryption, so it should be disabled
    // at the driver level.
    config.addDataSourceProperty("encrypt", "false");

    // ... Specify additional connection properties here.
    // ...

    // Initialize the connection pool using the configuration object.
    return new HikariDataSource(config);
  }
}

Python

Lihat Cara menggunakan Konektor ini untuk petunjuk mendetail tentang menggunakan library. Lihat contoh kode pengujian koneksi di GitHub.

import os

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

import sqlalchemy


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

    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.get("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

    connector = Connector(ip_type)

    connect_args = {}
    # If your SQL Server instance requires SSL, you need to download the CA
    # certificate for your instance and include cafile={path to downloaded
    # certificate} and validate_host=False. This is a workaround for a known issue.
    if os.environ.get("DB_ROOT_CERT"):  # e.g. '/path/to/my/server-ca.pem'
        connect_args = {
            "cafile": os.environ["DB_ROOT_CERT"],
            "validate_host": False,
        }

    def getconn() -> pytds.Connection:
        conn = connector.connect(
            instance_connection_name,
            "pytds",
            user=db_user,
            password=db_pass,
            db=db_name,
            **connect_args
        )
        return conn

    pool = sqlalchemy.create_engine(
        "mssql+pytds://",
        creator=getconn,
        # ...
    )
    return pool

Go

Lihat Penggunaan untuk mengetahui petunjuk mendetail tentang cara menggunakan library. Lihat contoh kode pengujian koneksi di GitHub.

package cloudsql

import (
	"context"
	"database/sql"
	"fmt"
	"log"
	"net"
	"os"

	"cloud.google.com/go/cloudsqlconn"
	mssql "github.com/denisenkom/go-mssqldb"
)

type csqlDialer struct {
	dialer     *cloudsqlconn.Dialer
	connName   string
	usePrivate bool
}

// DialContext adheres to the mssql.Dialer interface.
func (c *csqlDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
	var opts []cloudsqlconn.DialOption
	if c.usePrivate {
		opts = append(opts, cloudsqlconn.WithPrivateIP())
	}
	return c.dialer.Dial(ctx, c.connName, opts...)
}

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

	dbURI := fmt.Sprintf("user id=%s;password=%s;database=%s;", dbUser, dbPwd, dbName)
	c, err := mssql.NewConnector(dbURI)
	if err != nil {
		return nil, fmt.Errorf("mssql.NewConnector: %w", err)
	}
	dialer, err := cloudsqlconn.NewDialer(context.Background())
	if err != nil {
		return nil, fmt.Errorf("cloudsqlconn.NewDailer: %w", err)
	}
	c.Dialer = &csqlDialer{
		dialer:     dialer,
		connName:   instanceConnectionName,
		usePrivate: usePrivate != "",
	}

	dbPool := sql.OpenDB(c)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Node.js

Untuk petunjuk mendetail tentang penggunaan library ini, lihat Penggunaan.

const {Connection} = require('tedious');
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 a TCP connection
// to a Cloud SQL instance of SQL Server.
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.getTediousOptions({
    instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
    ipType: getIpType(),
  });
  const dbConfig = {
    // Please note that the `server` property here is not used and is only
    // defined due to a bug in the tedious driver
    // (ref: https://github.com/tediousjs/tedious/issues/1541)
    // With that in mind, do not try to change this value since it will have no
    // impact in how the connector works, this sample will be updated to remove
    // this property declaration as soon as the tedious driver bug is fixed
    server: '0.0.0.0', // e.g. '127.0.0.1'
    authentication: {
      type: 'default',
      options: {
        userName: process.env.DB_USER, // e.g. 'my-db-user'
        password: process.env.DB_PASS, // e.g. 'my-db-password'
      },
    },
    options: {
      ...clientOpts,
      // Please note that the `port` property here is not used and is only
      // defined due to a bug in the tedious driver
      // (ref: https://github.com/tediousjs/tedious/issues/1541)
      // With that in mind, do not try to change this value since it will have
      // no impact in how the connector works, this sample will be updated to
      // remove this property declaration as soon as the tedious driver bug is
      // fixed
      port: 9999,
      database: process.env.DB_NAME, // e.g. 'my-database'
      useColumnNames: true,
    },
    // ... Specify additional properties here.
    ...config,
  };

  // Establish a connection to the database.
  return new Connection(dbConfig);
};

Terapkan

Dengan menggunakan pemaksaan konektor, Anda dapat mewajibkan penggunaan hanya Proxy Auth Cloud SQL atau Cloud SQL Language Connectors untuk terhubung ke instance Cloud SQL. Dengan penerapan konektor, Cloud SQL akan menolak koneksi langsung ke database.

Jika Anda menggunakan instance yang mengaktifkan Private Service Connect, akan ada batasan. Jika instance mengaktifkan penerapan konektor, Anda tidak dapat membuat replika baca untuk instance tersebut. Demikian pula, jika instance memiliki replika baca, Anda tidak dapat mengaktifkan penerapan konektor untuk instance tersebut.

gcloud

Untuk mewajibkan penggunaan hanya Proxy Auth Cloud SQL atau Cloud SQL Language Connectors untuk terhubung ke instance, gunakan perintah gcloud sql instances patch:

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

Ganti INSTANCE_NAME dengan nama instance Cloud SQL Anda.

REST

Sebelum menggunakan salah satu data permintaan, lakukan penggantian berikut:

  • PROJECT_ID: ID atau nomor project project Google Cloud yang berisi instance
  • INSTANCE_NAME: nama instance Cloud SQL Anda

Metode HTTP dan URL:

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

Meminta isi JSON:

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

Untuk mengirim permintaan Anda, perluas salah satu opsi berikut:

Anda akan melihat respons JSON seperti berikut:

{
  "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"
}

Memecahkan masalah

Versi driver

Pastikan Anda menggunakan versi terbaru Konektor Cloud SQL dan driver database Anda untuk menghindari ketidakcocokan. Beberapa versi driver lama tidak didukung.

Jalur koneksi

Konektor Cloud SQL memberikan otorisasi untuk koneksi, tetapi tidak menyediakan jalur baru ke konektivitas. Misalnya, agar dapat terhubung ke instance Cloud SQL menggunakan alamat IP Pribadi, aplikasi Anda harus sudah memiliki akses VPC.

Men-debug masalah koneksi

Untuk mendapatkan bantuan tambahan terkait masalah koneksi, lihat halaman Memecahkan masalah dan Men-debug masalah koneksi.

Langkah berikutnya