IAM 데이터베이스 인증을 사용하여 로그인

이 페이지에서는 사용자 및 서비스 계정이 Cloud SQL IAM 데이터베이스 인증을 사용하여 Cloud SQL 데이터베이스에 로그인하는 방법을 설명합니다. 자세한 내용은 IAM 인증을 참조하세요.

시작하기 전에

  • IAM 데이터베이스 인증을 사용하도록 인스턴스를 구성합니다. 자세한 내용은 IAM 데이터베이스 인증을 위한 인스턴스 구성을 참조하세요.
  • IAM 사용자, 서비스 계정 또는 그룹을 데이터베이스에 추가합니다. 자세한 내용은 데이터베이스에 IAM 사용자 또는 서비스 계정 추가데이터베이스에 그룹 추가를 참조하세요.
  • roles/cloudsql.instanceUser IAM 역할을 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 인증 프록시, Go 커넥터, 자바 커넥터, Python 커넥터가 포함됩니다. 이러한 커넥터는 모두 자동 IAM 데이터베이스 인증을 지원합니다. 자동 IAM 데이터베이스 인증에 Cloud SQL 커넥터를 사용할 때 커넥터 시작을 위해 사용되는 IAM 계정은 데이터베이스에 인증을 수행하는 것과 동일한 계정이어야 합니다.

자동 IAM 데이터베이스 인증을 사용하여 로그인하려면 다음 안내를 따르세요.

Cloud SQL 인증 프록시

  1. Google Cloud에 인증합니다.

    사용자(User)

    애플리케이션 기본 사용자 인증 정보(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 인증 프록시를 시작합니다. INSTANCE_CONNECTION_NAME을 Cloud SQL 인스턴스를 식별하는 데 사용되는 연결 문자열로 바꾸세요. 기본 MySQL 포트가 아닌 다른 포트를 사용하는 경우 포트 번호를 지정합니다. 이 문자열을 찾아 작성하는 방법에 대한 자세한 내용은 Cloud SQL 인증 프록시 인증 옵션을 참조하세요.

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

    프록시를 시작하는 방법에 대한 자세한 내용은 Cloud SQL 인증 프록시 시작을 참조하세요.

  3. Cloud SQL 인증 프록시를 사용하여 인스턴스에 연결할 준비가 되면 mysql 클라이언트로 로그인합니다. 다음을 바꿉니다.

    • HOSTNAME: Cloud SQL 인증 프록시에 사용되는 IP 주소. 기본적으로 Cloud SQL 인증 프록시는 127.0.0.1의 localhost 주소를 사용하지만 Cloud SQL 인증 프록시를 시작할 때 다른 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 인증 프록시에 연결하는 방법에 대한 자세한 내용은 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
}

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

자바 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 인증 프록시를 사용하지 않고 연결하려면 다음 단계를 수행합니다.

이러한 단계를 수행하려면 다음을 수행해야 합니다.

  • --enable-cleartext-plugin mysql 옵션을 사용합니다.
  • 공개 IP가 있는 인스턴스에 연결하는 경우에는 인스턴스에 대한 외부 액세스를 승인합니다. 자세한 내용은 공개 IP에 대한 머신의 IP 주소 승인을 참조하세요.
  • 비공개 IP가 있는 인스턴스에 연결하는 경우 가상 프라이빗 클라우드(VPC) 네트워크 내에서 명령어를 실행합니다.
  • gcloud sql generate-login-token 명령어를 사용하여 인증 토큰을 생성합니다.

수동 IAM 데이터베이스 인증을 사용하여 로그인하려면 다음 안내를 따르세요.

gcloud

  1. Google Cloud에 인증합니다.

    사용자(User)

    gcloud auth login를 사용하여 IAM에 인증합니다. 자세한 내용은 사용자 계정으로 승인을 참조하세요.

    서비스 계정

    gcloud auth activate-service-account를 사용하여 IAM에 인증합니다. 자세한 내용은 서비스 계정을 사용하여 승인을 참조하세요.

  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-mode=REQUIRED \
     --host=HOSTNAME \
     --user=USERNAME
     

    Cloud SQL 인스턴스의 ssl_modeTRUSTED_CLIENT_CERTIFICATE_REQUIRED로 구성된 경우 로그인할 때 클라이언트 인증서와 클라이언트 키를 포함합니다. 또한 클라이언트가 상호 인증을 위해 서버 ID를 확인할 수 있게 하려면 서버 인증서 server-ca.pem을 지정합니다. 예를 들면 다음과 같습니다.

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

    클라이언트 인증서 및 키를 만드는 방법에 대한 자세한 내용은 클라이언트 인증서를 참조하세요.

다음 단계