PostgreSQL 확장과 시크릿 매니저

PostgreSQL 확장과 시크릿 매니저

PostgreSQL 데이터베이스에 연결하기 위한 사용자 자격 증명과 기타 연결 세부 정보를 DuckDB 시크릿 매니저로 저장할 수 있어요. 시크릿을 만들면 ATTACH할 때 자동으로 쓰이고, 여러 데이터베이스 인스턴스를 관리할 수도 있답니다. 알아볼게요.

출처: 문서

본문

다음 문법으로 시크릿을 만들 수 있어요.

CREATE SECRET (
    TYPE postgres,
    HOST '127.0.0.1',
    PORT 5432,
    DATABASE postgres,
    USER 'postgres',
    PASSWORD ''
);

ATTACH가 호출될 때 시크릿의 정보가 사용돼요. PostgreSQL 연결 문자열을 비워 두면 시크릿에 저장된 모든 정보를 사용합니다.

ATTACH '' AS postgres_db (TYPE postgres);

PostgreSQL 연결 문자열을 사용해 개별 옵션을 덮어쓸 수 있어요. 예를 들어 같은 자격 증명을 사용하면서 다른 데이터베이스에 연결하려면, 다음과 같이 데이터베이스 이름만 덮어쓰면 됩니다.

ATTACH 'dbname=my_other_db' AS postgres_db (TYPE postgres);

기본적으로 생성된 시크릿은 임시예요. CREATE PERSISTENT SECRET 명령어를 사용하면 시크릿을 영속화할 수 있어요. 영속 시크릿은 여러 세션에 걸쳐 사용할 수 있습니다.

여러 시크릿 다루기

명명된 시크릿을 사용해 여러 PostgreSQL 데이터베이스 인스턴스에 대한 연결을 관리할 수 있어요. 시크릿은 생성 시 이름을 줄 수 있답니다.

CREATE SECRET postgres_secret_one (
    TYPE postgres,
    HOST '127.0.0.1',
    PORT 5432,
    DATABASE postgres,
    USER 'postgres',
    PASSWORD ''
);

그다음 ATTACHSECRET 파라미터로 시크릿을 명시적으로 참조할 수 있어요.

ATTACH '' AS postgres_db_one (TYPE postgres, SECRET postgres_secret_one);

경고 — 연결 문자열에 자격 증명을 직접 포함하지 마세요. 연결 오류가 발생하면 전체 연결 문자열(자격 증명 포함)이 터미널 출력에 인쇄될 수 있어요. 보안을 위해 DuckDB 관리 시크릿으로 자격 증명을 저장하세요.

시크릿 구성 옵션

postgres 타입의 시크릿은 많은 구성 옵션을 지원해요. 다음 옵션들은 libpq의 해당 연결 옵션 이름을 따릅니다:

  • HOST
  • HOSTADDR
  • PORT
  • DBNAME
  • USER
  • PASSWORD
  • PASSFILE
  • REQUIRE_AUTH
  • CHANNEL_BINDING
  • CONNECT_TIMEOUT
  • CLIENT_ENCODING
  • OPTIONS
  • APPLICATION_NAME
  • FALLBACK_APPLICATION_NAME
  • KEEPALIVES
  • KEEPALIVES_IDLE
  • KEEPALIVES_INTERVAL
  • KEEPALIVES_COUNT
  • TCP_USER_TIMEOUT
  • REPLICATION
  • GSSENCMODE
  • SSLMODE
  • REQUIRESSL
  • SSLNEGOTIATION
  • SSLCOMPRESSION
  • SSLCERT
  • SSLKEY
  • SSLKEYLOGFILE
  • SSLPASSWORD
  • SSLCERTMODE
  • SSLROOTCERT
  • SSLCRL
  • SSLCRLDIR
  • SSLSNI
  • REQUIREPEER
  • SSL_MIN_PROTOCOL_VERSION
  • SSL_MAX_PROTOCOL_VERSION
  • MIN_PROTOCOL_VERSION
  • MAX_PROTOCOL_VERSION
  • KRBSRVNAME
  • GSSLIB
  • GSSDELEGATION
  • SCRAM_CLIENT_KEY
  • SCRAM_SERVER_KEY
  • SERVICE
  • TARGET_SESSION_ATTRS
  • LOAD_BALANCE_HOSTS
  • OAUTH_ISSUER
  • OAUTH_CLIENT_ID
  • OAUTH_CLIENT_SECRET
  • OAUTH_SCOPE

다음 옵션들은 해당 키로 이름이 바뀐 것입니다:

  • DATABASEDBNAME의 별칭
  • HOSTNAMEHOST의 별칭
  • USERNAMEUSER의 별칭

별도의 연결 옵션 대신 전체 연결 URI를 지정할 수도 있어요:

  • URI – 연결 URI

추가 옵션은 AWS RDS IAM 인증에 사용되는데, 아래 섹션에서 자세히 알아볼게요:

  • AWS_RDS_SECRETrds 타입의 시크릿 이름

AWS RDS IAM 인증

RDS/Aurora 서비스에서 실행되는 관리형 PostgreSQL 데이터베이스는 IAM 인증을 사용할 수 있어요. 이 경우 인증 토큰은 AWS SDK로 생성되며 15분마다 갱신되어야 해요.

postgres 확장은 시크릿에 비밀번호를 지정하지 않고 대신 구성된 AWS 자격 증명 제공자 중 하나로 비밀번호를 생성하면 IAM 인증을 지원해요. 이 비밀번호는 postgres 확장이 자동으로 갱신합니다.

명령줄에서 IAM 인증으로 연결

이 섹션은 DuckDB가 아닌 psql 유틸리티로 과정을 설명해요. 이 방법은 DuckDB 시크릿을 설정하기 전에 구성을 확인하는 데 사용할 수 있습니다.

psql 명령줄 도구로 IAM 인증을 수행할 때, AWS가 권장하는 연결 단계는 다음과 같아요.

  • aws CLI로 인증 토큰을 생성.

  • 이 토큰을 password 연결 옵션으로 전달:

    export RDSHOST="database-1-instance-1.xxx.eu-west-1.rds.amazonaws.com" 
    psql "host=$RDSHOST port=5432 dbname=postgres user=postgres sslmode=require password=$(aws rds generate-db-auth-token --hostname $RDSHOST --port 5432 --username postgres --region eu-west-1)"
    

IAM 인증용 시크릿 구성

postgres 확장의 인증은 psql과 같은 로직을 사용해요:

  • rds 타입의 시크릿은 인증 토큰을 생성하는 데 쓰이며, 위 예시의 aws rds generate-db-auth-token 명령어와 같은 구성 파라미터를 받아요:

    CREATE SECRET aws_rds_secret1 (
        TYPE rds,
        PROVIDER credential_chain,
        CHAIN 'env;sso;',
        REGION 'eu-west-1',
        RDS_USER 'postgres',
        RDS_HOST 'database-1-instance-1.xxxxxxxxxxxx.eu-west-1.rds.amazonaws.com',
        RDS_PORT '5432'
    );
    
  • postgres 타입의 시크릿은 연결 문자열의 나머지를 만드는 데 쓰이며, 위 예시의 psql 유틸리티와 같은 파라미터를 받고(추가적으로 관련 libpq 구성 옵션 포함) 서버에 password로 전달되는 인증 토큰을 생성·주기적으로 (자동) 갱신하는 데 사용되는 rds 시크릿의 이름을 지정해야 해요:

    CREATE SECRET pg_rds_secret1 (
        TYPE postgres,
        HOST 'database-1-instance-1.xxxxxxxxxxxx.eu-west-1.rds.amazonaws.com',
        PORT '5432',
        USER 'postgres',
        DATABASE 'postgres',
        SSLMODE require,
        AWS_RDS_SECRET aws_rds_secret1
    );
    

rds 타입의 시크릿은 aws 확장을 설치해야 하며, s3 타입의 시크릿과 같은 방식으로 AWS Credential Chain을 구성할 수 있어요.

PostgreSQL 데이터베이스 안에 시크릿 저장하기

DuckDB 시크릿 매니저는 플러그 가능한 Storage Provider를 지원해요. postgres 확장은 (어떤 타입이든) 시크릿을 PostgreSQL 데이터베이스 테이블의 레코드로 저장하는 것을 구현합니다.

다음 예시는 시크릿 저장소를 초기화하고 시크릿을 duckdb_secrets 테이블에 삽입해요.

ATTACH 'postgres:' AS p1 (
    SECRET pg_rds_secret1,
    SECRET_STORAGE_TABLE duckdb_secrets
);

CREATE OR REPLACE SECRET s3_secret1 IN postgres_p1 (
    TYPE s3,
    PROVIDER credential_chain,
    CHAIN 'env;sso;',
    PROFILE 'DatabaseAdministrator-⟨account_id⟩',
    REGION 'eu-west-1'
);

CREATE SECRETIN postgres_⟨attached_database⟩ 절을 지정하면, 시크릿이 지정된 attached 데이터베이스의 duckdb_secrets 테이블에 영속화됩니다.

경고 — 시크릿은 암호화되지 않은 바이너리 형식으로 데이터베이스 테이블에 기록돼요. 기밀 자격 증명을 포함하지 않는 시크릿(위 s3 예시처럼)에 이 provider를 쓰는 것이 좋아요. 멀티테넌트 시나리오에서는 Postgres Row-Level Security 정책으로 사용자가 다른 사용자의 시크릿을 볼 수 없게 하는 것이 기대됩니다.

ATTACH 명령의 SECRET_STORAGE_TABLE 파라미터에 다른 테이블 이름(예: 다른 스키마의)을 지정할 수 있어요.

기본 duckdb_secrets 테이블을 사용할 때는 SECRET_STORAGE_TABLE 파라미터를 지정할 필요가 없어요. PostgreSQL 데이터베이스가 attached되면 기본 이름 duckdb_secrets의 테이블이 자동으로 검사되고, 존재하면 그 attached 데이터베이스에 대해 Secret Storage 인스턴스가 등록되어 저장된 모든 시크릿을 현재 세션에서 사용할 수 있게 돼요. 이렇게 하면 duckdb 명령어에 연결 문자열만 지정하는 "direct attach" 시나리오에서도 영속 시크릿을 쓸 수 있어요 (다른 DuckDB 클라이언트는 약간 다른 문법이 필요할 수 있음):

duckdb postgres:postgresql://username:***@127.0.0.1:5432/db1

이 방법은 PostgreSQL 카탈로그와 함께 DuckLake에도 사용할 수 있어요. S3/객체 스토리지 접근 시크릿을 카탈로그 데이터베이스에 저장할 때 말이죠.

duckdb ducklake:postgres:postgresql://username:***@127.0.0.1:5432/db1

특정 attached 데이터베이스에 저장된 시크릿은 다음 쿼리로 나열할 수 있어요.

FROM duckdb_secrets() WHERE storage = 'postgres_⟨attached_database⟩';

PostgreSQL Secret Storage를 완전히 비활성화하려면 SECRET_STORAGE_TABLE 파라미터에 빈 문자열 ''을 전달하세요.

더 알아보기 (Learn more)

  • 시크릿 매니저 전반은 configuration/secrets_manager 문서를 참고해 주세요.