IAM データベース認証を使用してログインする

このページでは、ユーザーとサービス アカウントが Cloud SQL IAM データベース認証を使用して Cloud SQL データベースにログインする方法について説明します。詳細については、IAM 認証をご覧ください。

始める前に

  • IAM データベース認証を使用するようにインスタンスを構成します。詳しくは、IAM データベース認証に新しいインスタンスを構成するをご覧ください。
  • IAM ユーザー、サービス アカウント、またはグループをデータベースに追加します。詳細については、IAM ユーザーまたはサービス アカウントをデータベースに追加するグループをデータベースに追加するをご覧ください。
  • IAM ユーザー、サービス アカウント、またはグループに roles/cloudsql.instanceUser IAM ロールを追加します。これは必要な Cloud SQL IAM 権限 cloudsql.instances.login を含む事前定義ロールです。IAM データベース認証を使用してデータベース インスタンスにログインするには、この権限が必要です。詳細については、ロールと権限をご覧ください。
  • IAM ユーザーがデータベースに追加されると、デフォルトでは、新しいデータベース ユーザーにはデータベースに対する権限が付与されません。GRANT コマンドを使用して、IAM データベース ユーザーに必要な権限を付与する必要があります。詳細については、IAM ユーザーにデータベース権限を付与するグループにデータベース権限を付与するをご覧ください。

  • IAM グループ認証を使用している場合、IAM ユーザーまたはサービス アカウントは、Cloud SQL インスタンスにログインするための IAM ロールまたは権限が付与されたグループのメンバーである必要があります。ユーザーまたはサービス アカウントがインスタンスに初めてログインした後に、Cloud SQL によってアカウントが作成されます。

IAM データベースの自動認証を使用してログインする

ユーザーまたはアプリケーションに代わって Cloud SQL インスタンスに対する認証を自動的に処理するように Cloud SQL コネクタを構成できます。コネクタには Cloud SQL Auth Proxy、Go コネクタ、Java コネクタ、Python コネクタがあり、どのコネクタも自動 IAM データベース認証をサポートしています。自動 IAM データベース認証で Cloud SQL コネクタを使用する場合、コネクタの起動に使用する IAM アカウントは、データベース認証と同じアカウントにする必要があります。

IAM データベースの自動認証でログインするには:

Cloud SQL Auth Proxy

  1. Google Cloud に対して認証を行います。

    ユーザー

    アプリケーションのデフォルト認証情報(ADC)を使用して Google Cloud に対する認証を行います。

    gcloud auth application-default login コマンドを使用します。詳細については、アプリケーションのデフォルト認証情報を設定するをご覧ください。

    サービス アカウント

    サービス アカウントで ADC を使用して Google Cloud に対する認証を行うには、サービス アカウントの権限借用を使用するか、サービス アカウント キーを使用します。サービス アカウントの権限借用を使用するには、SERVICE_ACCOUNT_EMAIL_ADDRESS を置き換えて次のコマンドを実行します。

    gcloud auth application-default login --impersonate-service-account SERVICE_ACCOUNT_EMAIL_ADDRESS

    詳細については、アプリケーションのデフォルト認証情報を設定するをご覧ください。

  2. --auto-iam-authn フラグを指定して Cloud SQL Auth Proxy を起動します。

    以下を置き換えます。

    • INSTANCE_CONNECTION_NAME: Cloud SQL インスタンスを識別するための接続文字列。デフォルトの PostgreSQL ポート以外のポートを使用する場合は、ポート番号を指定します。この文字列を見つける方法および作成する方法の詳細については、Cloud SQL Auth Proxy の認証オプションをご覧ください。
    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME

    プロキシを開始する方法の詳細については、Cloud SQL Auth Proxy の起動をご覧ください。

  3. Cloud SQL Auth Proxy を使用してインスタンスに接続する準備ができたら、psql クライアントでログインします。

    次のように置き換えます。

    • HOSTNAME: Cloud SQL Auth Proxy で使用される IP アドレス。デフォルトでは、Cloud SQL Auth Proxy は localhost アドレス 127.0.0.1 を使用しますが、Cloud SQL Auth Proxy の起動時に別の IP アドレスを割り振ることができます。
    • USERNAME: IAM の場合、ユーザー名はユーザーの完全なメールアドレスです。サービス アカウントの場合、.gserviceaccount.com ドメイン サフィックスのないサービス アカウントのメールアドレスです。
    • PORT_NUMBER: 省略可。インスタンスの接続文字列に別のポートを指定した場合は、そのポート番号を指定します。
    • DATABASE_NAME: 接続先のデータベースの名前。

    次のコマンドを実行します。

    psql -h HOSTNAME \
     -U USERNAME \
     --port PORT_NUMBER \
     --dbname=DATABASE_NAME
     

    Cloud SQL Auth Proxy に接続する方法の詳細については、psql クライアントと接続するをご覧ください。

Go

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

	"cloud.google.com/go/cloudsqlconn"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/stdlib"
)

func connectWithConnectorIAMAuthN() (*sql.DB, error) {
	mustGetenv := func(k string) string {
		v := os.Getenv(k)
		if v == "" {
			log.Fatalf("Warning: %s environment variable not set.", 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_IAM_USER")              // e.g. 'service-account-name@project-id.iam'
		dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
		instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
		usePrivate             = os.Getenv("PRIVATE_IP")
	)

	d, err := cloudsqlconn.NewDialer(context.Background(), cloudsqlconn.WithIAMAuthN())
	if err != nil {
		return nil, fmt.Errorf("cloudsqlconn.NewDialer: %w", err)
	}
	var opts []cloudsqlconn.DialOption
	if usePrivate != "" {
		opts = append(opts, cloudsqlconn.WithPrivateIP())
	}

	dsn := fmt.Sprintf("user=%s database=%s", dbUser, dbName)
	config, err := pgx.ParseConfig(dsn)
	if err != nil {
		return nil, err
	}

	config.DialFunc = func(ctx context.Context, network, instance string) (net.Conn, error) {
		return d.Dial(ctx, instanceConnectionName, opts...)
	}
	dbURI := stdlib.RegisterConnConfig(config)
	dbPool, err := sql.Open("pgx", dbURI)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return dbPool, nil
}

Java JDBC

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;

public class ConnectorIamAuthnConnectionPoolFactory 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_IAM_USER = System.getenv("DB_IAM_USER");
  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 URL is equivalent to setting the config options below:
    // jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
    // socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<DB_IAM_USER>&
    // password=password
    // 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 to connect with.
    config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));

    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
    config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);

    // If connecting using automatic database authentication, follow the instructions for
    // connecting using the connector, but set the DB_IAM_USER value to an IAM user or
    // service account that has been given access to the database.
    // See https://cloud.google.com/sql/docs/postgres/iam-logins for more details.
    config.addDataSourceProperty("enableIamAuth", "true");
    config.addDataSourceProperty("user", DB_IAM_USER);
    // Password must be set to a nonempty value to bypass driver validation errors.
    config.addDataSourceProperty("password", "password");
    // Explicitly set sslmode to disable to prevent driver from hanging.
    // The Java Connector will handle SSL so it is unneccesary to enable it at the driver level.
    config.addDataSourceProperty("sslmode", "disable");


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

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

Java R2DBC

private static final String CONNECTION_NAME = System.getenv("POSTGRES_IAM_CONNECTION_NAME");
private static final String DB_NAME = System.getenv("POSTGRES_DB");
private static final String DB_USER = System.getenv("POSTGRES_IAM_USER");
  // Set up ConnectionFactoryOptions
  ConnectionFactoryOptions options =
      ConnectionFactoryOptions.builder()
          .option(DRIVER, "gcp")
          .option(PROTOCOL, "postgresql")
          // Password must be set to a nonempty value to bypass driver validation errors
          .option(PASSWORD, "password")
          .option(USER, DB_USER)
          .option(DATABASE, DB_NAME)
          .option(HOST, CONNECTION_NAME)
          .option(ENABLE_IAM_AUTH, true)
          .build();

  // Initialize connection pool
  ConnectionFactory connectionFactory = ConnectionFactories.get(options);
  ConnectionPoolConfiguration configuration =
      ConnectionPoolConfiguration.builder(connectionFactory).build();

  this.connectionPool = new ConnectionPool(configuration);

Python

import os

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

import sqlalchemy


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

    Uses the Cloud SQL Python Connector with Automatic IAM Database Authentication.
    """
    # 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_iam_user = os.environ["DB_IAM_USER"]  # e.g. 'sa-name@project-id.iam'
    db_name = os.environ["DB_NAME"]  # e.g. 'my-database'

    ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC

    # initialize Cloud SQL Python Connector object
    connector = Connector()

    def getconn() -> pg8000.dbapi.Connection:
        conn: pg8000.dbapi.Connection = connector.connect(
            instance_connection_name,
            "pg8000",
            user=db_iam_user,
            db=db_name,
            enable_iam_auth=True,
            ip_type=ip_type,
        )
        return conn

    # The Cloud SQL Python Connector can be used with SQLAlchemy
    # using the 'creator' argument to 'create_engine'
    pool = sqlalchemy.create_engine(
        "postgresql+pg8000://",
        creator=getconn,
        # ...
    )
    return pool

手動 IAM データベース認証を使用してログインする

ユーザーまたはアプリケーションは、Google Cloud から手動でアクセス トークンをリクエストしてデータベースに提示することで、IAM を使用してデータベースを認証できます。gcloud CLI を使用すると、データベースにログインするための Cloud SQL Admin API スコープで OAuth 2.0 トークンを明示的にリクエストできます。手動 IAM データベース認証でデータベース ユーザーとしてログインする場合は、メールアドレスをユーザー名として使用し、アクセス トークンをパスワードとして使用します。この方法は、データベースへの直接接続または Cloud SQL コネクタで使用できます。

この手順では、Google Cloud に対して認証を行い、アクセス トークンをリクエストします。このトークンを IAM データベース ユーザーのパスワードとして渡してデータベースに接続します。Cloud SQL Auth Proxy を使用せずに接続する手順は次のとおりです。

以下のことを行う必要があります。

  • パブリック IP を使用してインスタンスに接続する場合は、インスタンスへの外部アクセスを承認する。詳細については、マシンの IP アドレスをパブリック IP として承認するをご覧ください。
  • プライベート IP を使用してインスタンスに接続する場合は、Virtual Private Cloud(VPC)ネットワーク内でコマンドを実行する。
  • gcloud sql generate-login-token コマンドを使用して認証トークンを生成する。
  • 手動 IAM データベース認証でログインするには:

    gcloud

    1. Google Cloud に対して認証を行います。

      ユーザー

      IAM 認証に gcloud auth login を使用します。詳細については、ユーザー アカウントを使用して承認するをご覧ください。

      サービス アカウント

      IAM 認証に gcloud auth activate-service-account を使用します。詳細については、サービス アカウントを使用して承認するをご覧ください。

    2. アクセス トークンをリクエストして、クライアントでログインします。

      次のように置き換えます。

      • HOSTNAME: インスタンスの IP アドレス(パブリック IP アドレスまたはプライベート IP アドレス)。
      • USERNAME: IAM の場合、ユーザー名はユーザーの完全なメールアドレスです。サービス アカウントの場合、.gserviceaccount.com ドメイン サフィックスのないサービス アカウントのメールアドレスです。
      • DATABASE_NAME: 接続先のデータベースの名前。

       PGPASSWORD=`gcloud sql generate-login-token` \
       psql "sslmode=require \
       hostaddr=HOSTNAME \
       user=USERNAME \
       dbname=DATABASE_NAME" \
       --no-password
       

      Cloud SQL インスタンスの ssl_modeTRUSTED_CLIENT_CERTIFICATE_REQUIRED に構成されている場合は、自動 IAM データベース認証でログインして、クライアント ID の検証を適用することをおすすめします。

    次のステップ