クライアント TLS/SSL 接続

CloudNativePG が TLS 証明書をサポートする方法の詳細については、ページを参照してください。

CloudNativePG オペレーターは、サーバー側とクライアント側で、転送中の暗号化と認証の両方で TLS/SSL と連携するように設計されています。 CNPG オペレーターを使用して作成されたクラスターには、TLS クライアント証明書を作成して署名するための認証局 (CA) が付属しています。 kubectl の cnpg プラグインを介して、パスワードを使用する代わりにユーザーの認証に使用できる新しい TLS クライアント証明書を発行できます。

cluster-example-pg-hba.yaml .

マニフェスト。構成パラダイムの規則に従って、そのファイルは app というユーザーが所有する app データベースを自動的に作成します (この規則は、bootstrap セクションの initdb 構成で変更できます)。

新しい証明書の発行

kubectl のプラグインの使用方法の詳細については、ページを参照してください。

次のように、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 で作成されます。これは、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.6.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 認証局証明書

それらは、psql (および pgbench のような他の libpq ベースのアプリケーション) が Postgres データベースへの TLS 暗号化接続を確立するために必要とするデフォルト リソースを作成するために使用されます。

デフォルトでは、psql は現在のユーザーの ~/.postgresql ディレクトリ内の証明書を検索しますが、sslkey、sslcert、sslrootcert オプションを使用して、libpq が暗号化マテリアルの実際の場所を指すようにすることができます。上記のファイルの内容は、kubectl の cnpg プラグインを使用して以前に作成されたシークレットから収集されます。

アプリケーションをデプロイします。

kubectl create -f cert-test.yaml

次に、作成した Pod を PostgreSQL クライアントとして使用して、作成したばかりの TLS 証明書を使用して SSL 接続と認証を検証します。

データベース サーバーにアクセスできるときにアプリケーションの準備が整っていることを確認する準備プローブが構成されています。

Pod のコンテナ内でインタラクティブな bash を実行し、必要なオプションを使用して psql を実行することで、接続が機能していることを確認できます。 PostgreSQL サーバーは、読み取り/書き込み Kubernetes サービスを通じて公開されます。このサービスに接続するように 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 15.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.3.1 20191121 (Red Hat
8.3.1-5), 64-bit
(1 row)