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 グループ認証はプレビュー版です。

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 インスタンスの識別に使用される接続文字列に置き換えます。デフォルトの MySQL ポート以外のポートを使用している場合は、ポート番号を指定します。この文字列の見つけ方および作成方法の詳細については、Cloud SQL Auth Proxy の認証オプションをご覧ください。

    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME
    

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

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

    • HOSTNAME: Cloud SQL Auth Proxy で使用される IP アドレス。デフォルトでは、Cloud SQL Auth Proxy は localhost アドレス 127.0.0.1 を使用しますが、Cloud SQL Auth Proxy の起動時に別の IP アドレスを割り当てることができます。
    • USERNAME: IAM ユーザー アカウントの場合、これはユーザーのメールアドレスから @ 記号とドメイン名を除いたものになります。たとえば、test-user@example.com の場合は「test-user」と入力します。サービス アカウントの場合は、@project-id.iam.gserviceaccount.com サフィックスを除いたサービス アカウントのメールアドレスになります。
    • PORT_NUMBER: 省略可。インスタンスの接続文字列に別のポートを指定した場合は、そのポート番号を指定します。

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

    mysql --host=HOSTNAME \
    --user=USERNAME \
    --port=PORT_NUMBER
    

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

Go

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

	"cloud.google.com/go/cloudsqlconn"
	"github.com/go-sql-driver/mysql"
)

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'
		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())
	}
	mysql.RegisterDialContext("cloudsqlconn",
		func(ctx context.Context, addr string) (net.Conn, error) {
			return d.Dial(ctx, instanceConnectionName, opts...)
		})

	dbURI := fmt.Sprintf("%s:empty@cloudsqlconn(localhost:3306)/%s?parseTime=true",
		dbUser, dbName)

	dbPool, err := sql.Open("mysql", 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 INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
  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:mysql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
    // socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=<DB_USER>&password=<DB_PASS>
    // 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.setJdbcUrl(String.format("jdbc:mysql:///%s", DB_NAME));

    config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.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);
    // 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

// Set up ConnectionFactoryOptions
ConnectionFactoryOptions options =
    ConnectionFactoryOptions.builder()
        .option(DRIVER, "gcp")
        .option(PROTOCOL, "mysql")
        .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 pymysql

import sqlalchemy

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

    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. 'service-account-name'
    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() -> pymysql.connections.Connection:
        conn: pymysql.connections.Connection = connector.connect(
            instance_connection_name,
            "pymysql",
            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(
        "mysql+pymysql://",
        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 を使用せずに接続する手順は次のとおりです。

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

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

gcloud

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

    ユーザー

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

    サービス アカウント

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

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

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

    • HOSTNAME: インスタンスの IP アドレス(パブリック IP アドレスまたはプライベート IP アドレス)。
    • USERNAME: IAM ユーザー アカウントの場合、これはユーザーのメールアドレスから @ 記号とドメイン名を除いたものになります。たとえば、test-user@example.com の場合は「test-user」と入力します。サービス アカウントの場合は、@project-id.iam.gserviceaccount.com サフィックスを除いたサービス アカウントのメールアドレスになります。

      MYSQL_PWD=`gcloud sql generate-login-token` \
      mysql --enable-cleartext-plugin \
      --ssl-ca=server-ca.pem \
      --ssl-cert=client-cert.pem \
      --ssl-key=client-key.pem
      --host=HOSTNAME \
      --user=USERNAME
      

次のステップ