본문 바로가기
WIKI 기술 지식 베이스

클라이언트 TLS/SSL 연결

원문 보기 위키 갱신

클라이언트 TLS/SSL 연결 (Client TLS/SSL connections)

:::note[Certificates] CloudNativePG가 TLS 인증서를 지원하는 방법에 대한 자세한 내용은 Certificates를 참조하세요. :::

CloudNativePG 오퍼레이터는 전송 중 암호화와 서버·클라이언트 양쪽의 인증 모두에 TLS/SSL을 사용하도록 설계되었어요. CNPG 오퍼레이터로 만든 클러스터는 TLS 클라이언트 인증서를 생성하고 서명하는 인증 기관(CA)을 함께 제공해요. kubectl용 cnpg 플러그인을 사용하면, 비밀번호 대신 사용자를 인증하는 새로운 TLS 클라이언트 인증서를 발급할 수 있어요.

TLS/SSL 인증서로 인증하는 이 지침은 cluster-example-pg-hba.yaml 매니페스트로 클러스터를 설치했다고 가정해요. 관례-위에-구성(convention-over-configuration) 패러다임에 따라, 이 파일은 app이라는 사용자가 소유한 app 데이터베이스를 생성해요. (bootstrap 섹션의 initdb 구성을 통해 이 관례를 바꿀 수 있어요.)

출처: 문서

본문

새 인증서 발급하기

:::note[CNPG kubectl 플러그인에 관해] kubectl용 플러그인 사용 방법에 대한 자세한 내용은 CloudNativePG 플러그인의 Certificates를 참조하세요. :::

cluster-example PostgreSQL 클러스터에서 app 사용자용 인증서는 다음과 같이 만들 수 있어요:

kubectl cnpg certificate cluster-app \
  --cnpg-cluster cluster-example \
  --cnpg-user app

이제 인증서를 확인할 수 있어요:

kubectl get secret cluster-app \
  -o jsonpath="{.data['tls\.crt']}" \
  | base64 -d | openssl x509 -text -noout \
  | head -n 11

출력:


Certificate:
  Data:
    Version: 3 (0x2)
    Serial Number:
      5d:e1:72:8a:39:9f:ce:51:19:9d:21:ff:1e:4b:24:5d
    Signature Algorithm: ecdsa-with-SHA256
    Issuer: OU = default, CN = cluster-example
    Validity
      Not Before: Mar 22 10:22:14 2021 GMT
      Not After : Mar 22 10:22:14 2022 GMT
    Subject: CN = app

보시다시피 TLS 클라이언트 인증서는 기본적으로 90일 유효기간으로 만들어지며, PostgreSQL에서의 사용자 이름에 해당하는 단순한 CN을 가져요. EXPIRE_CHECK_THRESHOLD와 CERTIFICATE_DURATION 파라미터를 사용해 유효기간과 임계값을 지정할 수 있어요. pg_hba.conf의 hostssl 항목에서 cert 인증 방식을 활용하려면 이것이 필요해요.

TLS 인증서로 연결 테스트하기

다음으로, CloudNativePG 클러스터에 연결하는 데모 클라이언트 애플리케이션을 구성해서 이 클라이언트 인증서를 테스트해 보세요.

cert-test.yaml이라고 하는 다음 매니페스트는 데이터베이스 클러스터가 실행 중인 것과 같은 네임스페이스에 테스트 애플리케이션을 가진 데모 Pod를 생성해요:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cert-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webtest
  template:
    metadata:
      labels:
        app: webtest
    spec:
      containers:
        - image: ghcr.io/cloudnative-pg/webtest:1.7.0
          name: cert-test
          volumeMounts:
            - name: secret-volume-root-ca
              mountPath: /etc/secrets/ca
            - name: secret-volume-app
              mountPath: /etc/secrets/app
          ports:
            - containerPort: 8080
          env:
            - name: DATABASE_URL
              value: >
                sslkey=/etc/secrets/app/tls.key
                sslcert=/etc/secrets/app/tls.crt
                sslrootcert=/etc/secrets/ca/ca.crt
                host=cluster-example-rw.default.svc
                dbname=app
                user=app
                sslmode=verify-full
            - name: SQL_QUERY
              value: SELECT 1
          readinessProbe:
            httpGet:
              port: 8080
              path: /tx
      volumes:
        - name: secret-volume-root-ca
          secret:
            secretName: cluster-example-ca
            defaultMode: 0600
        - name: secret-volume-app
          secret:
            secretName: cluster-app
            defaultMode: 0600

이 Pod는 CloudNativePG 오퍼레이터가 관리하는 시크릿을 마운트하는데, 여기에는 다음이 포함돼요:

  • sslcert – TLS 클라이언트 공개 인증서.
  • sslkey – TLS 클라이언트 인증서 개인 키.
  • sslrootcert – 서버가 인스턴스의 신원을 검증하는 데 사용할, 서버 쪽 인증서에 서명한 TLS CA 인증서.

이들은 psql(과 pgbench 같은 다른 libpq 기반 애플리케이션)이 Postgres 데이터베이스에 TLS 암호화 연결을 설정하는 데 필요한 기본 리소스를 만드는 데 사용돼요.

기본적으로 psql은 현재 사용자의 ~/.postgresql 디렉토리에서 인증서를 검색하지만, sslkey, sslcert, sslrootcert 옵션을 사용해 libpq가 암호화 자료의 실제 위치를 가리키게 할 수 있어요. 이 파일들의 내용은 앞서 kubectl용 cnpg 플러그인으로 생성한 시크릿에서 가져와요.

애플리케이션을 배포하세요:

kubectl create -f cert-test.yaml

그런 다음 생성된 Pod를 PostgreSQL 클라이언트로 사용해서 방금 만든 TLS 인증서로 SSL 연결과 인증을 검증해 보세요.

데이터베이스 서버에 도달할 수 있을 때 애플리케이션이 준비되도록 리드니스 프로브(readiness probe)가 구성되어 있어요.

연결이 작동하는지 확인할 수 있어요. 그러려면 Pod의 컨테이너 안에서 대화형 bash를 실행해 필요한 옵션으로 psql을 실행하면 돼요. PostgreSQL 서버는 읽기-쓰기 쿠버네티스 서비스를 통해 노출돼요. psql 명령이 이 서비스에 연결하도록 가리키세요:

kubectl exec -it cert-test -- bash -c "psql
'sslkey=/etc/secrets/app/tls.key sslcert=/etc/secrets/app/tls.crt
sslrootcert=/etc/secrets/ca/ca.crt host=cluster-example-rw.default.svc dbname=app
user=app sslmode=verify-full' -c 'select version();'"

출력:

                                        version
--------------------------------------------------------------------------------------
------------------
PostgreSQL 18.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.3.1 20191121 (Red Hat
8.3.1-5), 64-bit
(1 row)

TLS 프로토콜 버전에 관해

기본적으로 오퍼레이터는 ssl_min_protocol_version과 ssl_max_protocol_version을 모두 TLSv1.3로 설정해요.

이것은 PostgreSQL 오퍼랜드(operand) 이미지에 TLSv1.3 버전을 지원하는 OpenSSL 라이브러리가 포함되어 있다고 가정해요. 그렇지 않거나 클라이언트 애플리케이션이 더 낮은 프로토콜 버전을 필요로 한다면, 다른 Postgres GUC처럼 PostgreSQL 구성에서 수동으로 설정해야 해요.

더 알아보기 (Learn more)