Cloud SQL 言語コネクタを使用して接続する

Cloud SQL コネクタは、Cloud SQL インスタンスへの接続時に暗号化と Identity and Access Management(IAM)ベースの承認を行うライブラリです。Cloud SQL インスタンスへのネットワーク パスがまだ存在しない場合に、ネットワーク パスを提供することはできません。

Cloud SQL インスタンスに接続するその他の方法には、データベース クライアントの使用または Cloud SQL Auth Proxy があります。Cloud SQL インスタンスへの接続について詳しくは、接続オプションについてのページをご覧ください。

このページでは、次の Cloud SQL コネクタについて説明します。

  • Cloud SQL Java コネクタ
  • Cloud SQL Python コネクタ(Colab で開く)
  • Cloud SQL Go コネクタ
  • Cloud SQL Node.js コネクタ

利点

Cloud SQL コネクタには、次のような利点があります。

  • IAM 認可: IAM 権限を使用して、Cloud SQL インスタンスに接続できるユーザーや対象を制御します。
  • 簡素化: SSL 証明書の管理、ファイアウォール ルールの構成、承認済みネットワークの有効化が不要になります。

始める前に

  • Cloud SQL Admin API を有効にします。

    Enable the API

  • Cloud SQL インスタンスを作成し、デフォルト ユーザーを構成します。

    インスタンスの作成の詳細については、インスタンスを作成するをご覧ください。

    デフォルト ユーザーの構成の詳細については、デフォルト ユーザー アカウントのパスワードを設定するをご覧ください。

  • Cloud SQL インスタンスへの接続に必要なロールと権限を構成します。

設定

Java

Cloud SQL Java コネクタは、Cloud SQL インスタンスへの接続時に IAM ベースの認可と暗号化を提供するライブラリです。Cloud SQL インスタンスへのネットワーク パスがまだ存在しない場合、ネットワーク パスを提供することはできません。

インストール

JDBC と R2DBC のドライバを Cloud SQL Java コネクタで構築して使用する方法については、次のリンク先をご覧ください。

このライブラリがアプリケーションのコンテキストでどのように使用されるかについては、サンプル アプリケーションをご覧ください。

認証

このライブラリは、アプリケーションのデフォルト認証情報を使用して Cloud SQL サーバーへの接続を認証します。

認証情報をローカルで有効にするには、次の gcloud コマンドを使用します。

    gcloud auth application-default login
    

Intellij との接続

Cloud SQL インスタンスに IntelliJ を接続するためには、ドライバ設定ページの追加のファイル セクションで、ライブラリを依存関係のある jar として追加する必要があります。たとえば、事前にビルドされた fat jar は Cloud SQL Java コネクタのリリースページに表示されます。

Python

Cloud SQL Python コネクタはデータベース ドライバとともに使用できるライブラリです。これにより、十分な権限があるユーザーは IP を手動で許可リストに登録することなく、Cloud SQL データベースに接続できるようになります。SSL 証明書を管理する必要もありません。

Cloud SQL Python コネクタのインタラクティブな使用例については、Cloud SQL Python コネクタ ノートブックをご覧ください。

SQL Server でサポートされているドライバは pytds です。

インストール

Cloud SQL Python コネクタの最新リリースをインストールするには、pip install コマンドを使用して、データベースの pytds ドライバを指定します。

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

認証

このライブラリは、アプリケーションのデフォルト認証情報を使用して Cloud SQL サーバーへの接続を認証します。

認証情報をローカルで有効にするには、次の gcloud コマンドを使用します。

    gcloud auth application-default login
    

Go

Cloud SQL Go コネクタは、Go 言語で使用できるように設計された Cloud SQL コネクタです。セキュリティ強化のため、このコネクタは、データベース プロトコルとは無関係に、クライアント コネクタとサーバー側プロキシの間で、堅牢な手動認証の TLS 1.3 暗号化を使用します。

インストール

このリポジトリは go get でインストールできます。

    go get cloud.google.com/go/cloudsqlconn
    

Node.js

Node.js コネクタは、Node.js ランタイムで使用するために設計されたライブラリであり、Cloud SQL インスタンスに安全に接続できます。

インストール

npm install を使用してライブラリをインストールできます。

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

使用

Java

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。


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

ライブラリを使用する際の詳細な手順については、このコネクタの使用方法をご覧ください。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

ライブラリを使用する際の詳細な手順については、使用方法をご覧ください。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

ライブラリの使用方法については、使用をご覧ください。

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

適用

コネクタの適用を使用すると、Cloud SQL インスタンスへの接続に、Cloud SQL Auth Proxy または Cloud SQL 言語コネクタのみを使用するように強制できます。コネクタの適用を使用すると、Cloud SQL によりデータベースへの直接接続が拒否されます。

Private Service Connect が有効になっているインスタンスを使用している場合は、制限があります。インスタンスでコネクタの適用が有効になっている場合、そのインスタンスにリードレプリカを作成することはできません。同様に、インスタンスにリードレプリカがある場合、そのインスタンスでコネクタの適用を有効にすることはできません。

gcloud

Cloud SQL Auth Proxy または Cloud SQL 言語コネクタのみを使用してインスタンスに接続するように強制するには、gcloud sql instances patch コマンドを使用します。

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

INSTANCE_NAME は、Cloud SQL インスタンスの名前に置き換えます。

REST

リクエストのデータを使用する前に、次のように置き換えます。

  • PROJECT_ID: インスタンスが含まれている Google Cloud プロジェクトの ID またはプロジェクト番号
  • INSTANCE_NAME: Cloud SQL インスタンスの名前

HTTP メソッドと URL:

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

リクエストの本文(JSON):

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

リクエストを送信するには、次のいずれかのオプションを開きます。

次のような JSON レスポンスが返されます。

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

トラブルシューティング

ドライバのバージョン

非互換性の問題を回避するため、最新バージョンの Cloud SQL コネクタとデータベース ドライバを使用してください。一部の古いバージョンのドライバはサポートされていません。

接続パス

Cloud SQL コネクタは接続の承認を提供しますが、接続するための新しいパスを提供しません。たとえば、プライベート IP アドレスを使用して Cloud SQL インスタンスに接続するには、アプリケーションがすでに VPC にアクセスできる必要があります。

接続の問題をデバッグする

接続の問題について詳しくは、トラブルシューティング接続の問題をデバッグするのページをご覧ください。

次のステップ