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 인스턴스를 식별하기 위한 연결 문자열입니다. 기본 PostgreSQL 포트가 아닌 다른 포트를 사용하는 경우 포트 번호를 지정합니다. 이 문자열을 찾아 구성하는 방법에 대한 자세한 내용은 Cloud SQL 인증 프록시 인증 옵션을 참조하세요.
    ./cloud-sql-proxy --auto-iam-authn INSTANCE_CONNECTION_NAME

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

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

    다음을 바꿉니다.

    • HOSTNAME: Cloud SQL 인증 프록시에 사용되는 IP 주소. 기본적으로 Cloud SQL 인증 프록시는 127.0.0.1의 localhost 주소를 사용하지만 Cloud SQL 인증 프록시를 시작할 때 다른 IP 주소를 할당할 수 있습니다.
    • USERNAME: IAM의 경우 사용자 이름은 사용자의 전체 이메일 주소입니다. 서비스 계정의 경우 .gserviceaccount.com 도메인 서픽스가 없는 서비스 계정의 이메일입니다.
    • PORT_NUMBER: (선택사항) 인스턴스 연결 문자열에 다른 포트를 지정한 경우 해당 포트 번호를 지정합니다.
    • DATABASE_NAME: 연결할 데이터베이스의 이름입니다.

    다음 명령어를 실행합니다.

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

    Cloud SQL 인증 프록시에 연결하는 방법에 대한 자세한 내용은 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
}

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

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

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

  • 공개 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의 경우 사용자 이름은 사용자의 전체 이메일 주소입니다. 서비스 계정의 경우 .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 검증을 시행하는 것이 좋습니다.

    다음 단계