NEW: プロジェクトの最新情報を入手するにはTwitterMastodon

trust-manager による Kubernetes での公開信頼の管理

最終検証: 2023年6月19日

このチュートリアルでは、trust-manager を使用して、Kubernetes クラスタ内に公開的に信頼された認証局 (CA) 証明書を配布する方法を説明します。配布後、以下についても説明します。

  • 信頼バンドルが変更されたときにアプリケーションを自動的に再読み込みする方法
  • 配布された CA バンドルを使用するようにアプリケーションを強制する方法

次に、シンプルなcurlポッドを使用して、信頼されたCAバンドルを自動的にマウントする方法を示します。これにより、curlを手動で構成する必要なく使用できます。これは、アプリケーションが信頼されたCA証明書バンドルを使用するために追加の設定を必要としない方法を模倣しています。

このチュートリアルでは、変更の影響範囲をteam-a名前空間のみに限定します。これらの機能を最大限に活用するには、この制限を解除する必要があります。

注: 提供されるすべてのリソースはデモンストレーション用であり、本番環境で使用する前に適切にレビューする必要があります。

前提条件

💻 ソフトウェア

  1. kubectl: Kubernetesクラスターを構成するためのKubernetesコマンドラインツール。
  2. helm: Kubernetes用のパッケージマネージャー。
  3. yq: 便利なカラーリングを備えたYAMLを解析するためのコマンドラインツール。

パブリックCA信頼の配布

まず、trust-managerをセットアップし、パブリックCAをデモ名前空間team-aに配布しましょう。

アプリケーションとバンドルのセットアップ

  1. こちらの手順に従ってtrust-managerをインストールします。

  2. パブリックCA証明書のみを含む最初のバンドルリソースを作成します

    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - useDefaultCAs: true
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    kubectl apply -f - <<EOF
    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - useDefaultCAs: true
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    EOF
  3. アプリケーションを実行する名前空間を作成しましょう

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Namespace
    metadata:
    labels:
    trust: enabled
    name: team-a
    EOF

    この名前空間には、trust: enabledというラベルが付いていることに注意してください。これは、バンドルリソースのnamespaceSelector基準に一致します。

    namespaceSelector:
    matchLabels:
    trust: enabled

    : これは、前述のように、信頼バンドルの範囲をteam-a名前空間のみに限定するためのものです。

  4. trust-managerコントローラーがCAバンドルを名前空間に正しく伝播したことを確認します

    kubectl get configmap -n team-a public-bundle -o yaml

    この出力は非常に長くなるはずです。これは、使用するデフォルトのパブリックバンドルに多くのパブリックCAが含まれているためです。

自動使用によるアプリケーションへの信頼バンドルのマウント

信頼されたCAを使用するには、ほとんどのアプリケーションがca-certificates.crtファイルを見つけると予想されるデフォルトの場所にマウントします。このアプローチの利点は、コンテナ内のほとんどのアプリケーションコードがこのファイルをデフォルトで使用し、追加の設定を必要としないことです。さらに、/etc/ssl/certsの上にマウントするため、コンテナのベースイメージから通常存在する、またはCIビルド中にプルインされた既存のCA証明書が削除されるという利点もあります。

警告: この例では、alpineおよびcurlが信頼されたCAのソースとして使用する、よく知られた場所を1つ選択しました。これは使用できる唯一の場所ではないため、コンテナには他のデフォルトの場所がある場合があります。デフォルトのCAがどこにあるかを確認する場合は、paranoiaを使用して、構築されたコンテナイメージを調べることができます。

  1. アプリケーションデプロイメントを適用します

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: sleep-auto
    name: sleep-auto
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: sleep-auto
    strategy: {}
    template:
    metadata:
    labels:
    app: sleep-auto
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    resources: {}
    volumeMounts:
    - mountPath: /etc/ssl/certs/
    name: ca-certificate-only
    readOnly: true
    volumes:
    - name: ca-certificate-only
    configMap:
    name: public-bundle
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    kubectl apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: sleep-auto
    name: sleep-auto
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: sleep-auto
    template:
    metadata:
    labels:
    app: sleep-auto
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    volumeMounts:
    - mountPath: /etc/ssl/certs/
    name: ca-certificate-only
    readOnly: true
    volumes:
    - name: ca-certificate-only
    configMap:
    name: public-bundle
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    EOF
  2. 実行中のポッド内にシェルを作成します

    kubectl exec -n team-a -ti $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- /bin/sh
  3. /etc/ssl/certs/の内容をリストして、信頼されたca-certificates.crtのみが存在することを確認します。

    ls -ltr /etc/ssl/certs/

    出力は次のようになります

    ~ $ ls -ltr /etc/ssl/certs/
    total 0
    lrwxrwxrwx 1 root root 26 Apr 14 15:12 ca-certificates.crt -> ..data/ca-certificates.crt

    通常、このコンテナイメージでは、このディレクトリを上書きするボリュームがない場合、出力は次のようになります。

    ~ $ ls -ltr /etc/ssl/certs/
    total 608
    -rw-r--r-- 1 root root 214222 Apr 14 01:11 ca-certificates.crt
    lrwxrwxrwx 1 root root 52 Apr 14 01:11 ca-cert-vTrus_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_Root_CA.crt
    lrwxrwxrwx 1 root root 56 Apr 14 01:11 ca-cert-vTrus_ECC_Root_CA.pem -> /usr/share/ca-certificates/mozilla/vTrus_ECC_Root_CA.crt
    ...
    lrwxrwxrwx 1 root root 53 Apr 14 01:11 02265526.0 -> ca-cert-Entrust_Root_Certification_Authority_-_G2.pem
    lrwxrwxrwx 1 root root 31 Apr 14 01:11 002c0b4f.0 -> ca-cert-GlobalSign_Root_R46.pem
  4. 既知のサイトにHTTPS呼び出しを行い、追加の--cacertフラグを渡すことなくcurlが動作することを確認します。

    curl -v https://bbc.co.uk/news

    成功すると、次のような有効なTLS接続になります

    * Trying 151.101.0.81:443...
    * Connected to bbc.co.uk (151.101.0.81) port 443 (#0)
    * ALPN: offers h2,http/1.1
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * CAfile: /etc/ssl/certs/ca-certificates.crt
    * CApath: none
    * TLSv1.3 (IN), TLS handshake, Server hello (2):
    * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
    * TLSv1.3 (IN), TLS handshake, Certificate (11):
    * TLSv1.3 (IN), TLS handshake, CERT verify (15):
    * TLSv1.3 (IN), TLS handshake, Finished (20):
    * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.3 (OUT), TLS handshake, Finished (20):
    * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
    * ALPN: server accepted h2
    * Server certificate:
    * subject: C=GB; ST=London; L=London; O=BRITISH BROADCASTING CORPORATION; CN=www.bbc.com
    * start date: Mar 14 06:16:13 2023 GMT
    * expire date: Apr 14 06:16:12 2024 GMT
    * subjectAltName: host "bbc.co.uk" matched cert's "bbc.co.uk"
    * issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign RSA OV SSL CA 2018
    * SSL certificate verify ok.
  1. コンテナを終了します: exit

実際のアプリケーションの構成

上記の例に基づいて、KubernetesはデフォルトのCA証明書バンドルの上にマウントできます。CA証明書を取得するデフォルトの場所がわかっている場合は、これをアプリケーションで使用できます。

たとえば、Goでは、アプリケーションは、デフォルトのCA証明書ファイルの場所を指すSSL_CERT_FILEまたはSSL_CERT_DIRで構成できます。

詳細についてはこちらを参照してください。また、さまざまなOSベースのデフォルトの場所については、こちらを確認してください。

// Possible certificate files; stop after finding one.
var certFiles = []string{
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
"/etc/ssl/cert.pem", // Alpine Linux
}
// Possible directories with certificate files; all will be read.
var certDirectories = []string{
"/etc/ssl/certs", // SLES10/SLES11, https://go.dokyumento.jp/issue/12139
"/etc/pki/tls/certs", // Fedora/RHEL
"/

Pythonを調べたところ、sslライブラリは、信頼されたCAを検索するために、同じ2つの環境変数:SSL_CERT_DIRおよび/SSL_CERT_FILEを使用していることがわかりました。 ドキュメントおよびpython3ランタイムからこれを確認できます

>>> import ssl
>>> ssl.get_default_verify_paths()
DefaultVerifyPaths(cafile=None, capath='/usr/lib/ssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/lib/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/lib/ssl/certs')

これは、ファイルにマウントされたCAと、次のいずれかのファイルが、Goと同様に、すべてのPythonアプリケーションランタイムによって信頼されることを意味します。

  • '/usr/lib/ssl/cert.pem'
  • '/usr/lib/ssl/certs/*'

同様のことは、他の言語でも実現できます。

自動化と強制

これで、trust-managerのバンドルを手動でマウントしました。あなたはこう考えているかもしれません。

  • CAバンドルが変更された場合、その変更をアプリケーションに反映させるにはどうすればよいですか?
  • テナントからの変更を要求することなく、CAバンドルがクラスター内のすべてのアプリケーションにマウントされるようにするにはどうすればよいですか?

追加のオープンソースツールを使用して、これらの両方のシナリオに取り組みましょう。

CAバンドル変更のロールアウト

CAバンドルが変更されると、それらの変更はかなり迅速に名前空間に同期されます。この変更はコンテナにアタッチされたボリュームに反映されますが、ほとんどのアプリケーションはファイルシステムの変更を認識しません。一般的なアプローチは、kubectl rollout restart deployment <DEPLOY_NAME>を使用して、クライアントアプリケーションのデプロイを再起動することです。サードパーティ製のオープンソースソフトウェアを使用して、このプロセスを自動化するオプションがあります。

Stakater Reloaderを使用すると、ConfigMapまたはSecretが変更されるたびに、デプロイメントをリロードまたはロールアウトできます。したがって、バンドルのターゲットが同期されるたびに、Reloaderコンポーネントはこの変更を検出し、それらのリソースをボリュームまたは環境変数としてマウントするアプリケーションをロールアウトできます。

ご注意ください アプリケーションコンテナにバンドルしたり、書き込んだりできる代替ソフトウェアがたくさんあります。それらは単にファイルシステムの変更を監視し、アプリケーションプロセスのリロードをトリガーするだけです。このようなアプローチには、コンテナイメージまたはコードの変更が必要であり、多くのテナントでは実装が難しい場合があります。ここでリローダーを使用する利点は、クラスターで実行されているすべてのアプリケーションに適用できる汎用的なソリューションであることです。

  1. リローダーを続行すると、helmでインストールできます

    helm repo add stakater https://stakater.github.io/stakater-charts
    helm repo update
    helm install reloader stakater/reloader -n stakater-reloader --create-namespace --set fullnameOverride=reloader
  2. 前のセクションのsleep-autoデプロイメントを再利用し、リロード機能を有効にするように構成できます。

    kubectl annotate deployment -n team-a sleep-auto reloader.stakater.com/auto="true"

    注意: リローダーツールを設定するための構成オプションはいくつかありますが、これは最も基本的な例にすぎません。詳細な例については、ドキュメントを参照してください。

  3. 別のターミナルで、アプリケーションのロールアウトを監視してください。

    kubectl get po -n team-a -w
  4. この変更をテストするために、Bundleリソースを編集して、デフォルトのすべてのパブリックCA証明書を削除し、代わりに1つのCA証明書のみを提供するようにします。

    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - inLine: |
    -----BEGIN CERTIFICATE-----
    MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQsw
    CQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMH
    Um9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAw
    MDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290
    IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNp
    Z24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2
    hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9
    DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkm
    DoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDh
    BjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTv
    riBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZp
    hYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
    /zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtm
    GkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFo
    dHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCag
    JIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+
    MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j
    b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RD
    M6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9
    D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtI
    fR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJi
    WOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1Eh
    kluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo
    4HA=
    -----END CERTIFICATE-----
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    kubectl apply -f - <<EOF
    apiVersion: trust.cert-manager.io/v1alpha1
    kind: Bundle
    metadata:
    name: public-bundle
    spec:
    sources:
    - inLine: |
    -----BEGIN CERTIFICATE-----
    MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQsw
    CQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMH
    Um9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAw
    MDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290
    IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNp
    Z24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2
    hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9
    DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkm
    DoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDh
    BjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTv
    riBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZp
    hYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
    /zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtm
    GkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFo
    dHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCag
    JIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+
    MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j
    b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RD
    M6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9
    D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtI
    fR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJi
    WOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1Eh
    kluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo
    4HA=
    -----END CERTIFICATE-----
    target:
    configMap:
    key: "ca-certificates.crt"
    namespaceSelector:
    matchLabels:
    trust: enabled
    EOF

    別のターミナルで、アプリケーションのデプロイメントがすぐにロールアウトされるはずです。

  5. 新しいポッドが実行されたら、以下を使用して、適用したばかりの1つのCA証明書ca-certificates.crtファイルのみがあることを確認します。

    kubectl exec -ti -n team-a $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- cat /etc/ssl/certs/ca-certificates.crt

    正確にこの出力が得られるはずです。

    -----BEGIN CERTIFICATE-----
    MIIETjCCAzagAwIBAgINAe5fFp3/lzUrZGXWajANBgkqhkiG9w0BAQsFADBXMQsw
    CQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UECxMH
    Um9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTE4MDkxOTAw
    MDAwMFoXDTI4MDEyODEyMDAwMFowTDEgMB4GA1UECxMXR2xvYmFsU2lnbiBSb290
    IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNp
    Z24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMJXaQeQZ4Ihb1wIO2
    hMoonv0FdhHFrYhy/EYCQ8eyip0EXyTLLkvhYIJG4VKrDIFHcGzdZNHr9SyjD4I9
    DCuul9e2FIYQebs7E4B3jAjhSdJqYi8fXvqWaN+JJ5U4nwbXPsnLJlkNc96wyOkm
    DoMVxu9bi9IEYMpJpij2aTv2y8gokeWdimFXN6x0FNx04Druci8unPvQu7/1PQDh
    BjPogiuuU6Y6FnOM3UEOIDrAtKeh6bJPkC4yYOlXy7kEkmho5TgmYHWyn3f/kRTv
    riBJ/K1AFUjRAjFhGV64l++td7dkmnq/X8ET75ti+w1s4FRpFqkD2m7pg5NxdsZp
    hYIXAgMBAAGjggEiMIIBHjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
    /zAdBgNVHQ4EFgQUj/BLf6guRSSuTVD6Y5qL3uLdG7wwHwYDVR0jBBgwFoAUYHtm
    GkUNl8qJUC99BM00qP/8/UswPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFo
    dHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjEwMwYDVR0fBCwwKjAooCag
    JIYiaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LmNybDBHBgNVHSAEQDA+
    MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j
    b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBACNw6c/ivvVZrpRCb8RD
    M6rNPzq5ZBfyYgZLSPFAiAYXof6r0V88xjPy847dHx0+zBpgmYILrMf8fpqHKqV9
    D6ZX7qw7aoXW3r1AY/itpsiIsBL89kHfDwmXHjjqU5++BfQ+6tOfUBJ2vgmLwgtI
    fR4uUfaNU9OrH0Abio7tfftPeVZwXwzTjhuzp3ANNyuXlava4BJrHEDOxcd+7cJi
    WOx37XMiwor1hkOIreoTbv3Y/kIvuX1erRjvlJDKPSerJpSZdcfL03v3ykzTr1Eh
    kluEfSufFT90y1HonoMOFm8b50bOI7355KKL0jlrqnkckSziYSQtjipIcJDEHsXo
    4HA=
    -----END CERTIFICATE-----
  6. このCA証明書は、ウェブサイトhttps://bbc.co.ukの信頼性を検証するために使用できます。これは、そのコンテナからcurlを使用して検証できます。

    kubectl exec -ti -n team-a $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- curl -v https://bbc.co.uk

    また、このポッドからgoogle.comに接続できなくなったことも確認できます。

    kubectl exec -ti -n team-a $(kubectl get po -n team-a -l app=sleep-auto -o jsonpath='{.items[0].metadata.name}') -- curl -v https://google.com

    TLSエラーの例

    * Trying 142.250.200.46:443...
    * Connected to google.com (142.250.200.46) port 443 (#0)
    * ALPN: offers h2,http/1.1
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * CAfile: /etc/ssl/certs/ca-certificates.crt
    * CApath: none
    * TLSv1.3 (IN), TLS handshake, Server hello (2):
    * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
    * TLSv1.3 (IN), TLS handshake, Certificate (11):
    * TLSv1.3 (OUT), TLS alert, unknown CA (560):
    * SSL certificate problem: unable to get local issuer certificate
    * Closing connection 0
    curl: (60) SSL certificate problem: unable to get local issuer certificate
    More details here: https://curl.se/docs/sslcerts.html
    curl failed to verify the legitimacy of the server and therefore could not
    establish a secure connection to it. To learn more about this situation and
    how to fix it, please visit the web page mentioned above.
    command terminated with exit code 60

CAバンドルの使用を強制する

GatekeeperKyvernoなどのツールを使用すると、アプリケーションがKubernetesにデプロイされるときに、特定のvolumevolumeMountの構成が強制されるようにできます。この方法を使用すると、クラスター管理者は、すべてのポッドに関連する構成を自動的に挿入するルールを設定できます。これは構成を強制するのに役立つかもしれませんが、クラスターのアプリケーションチームやテナントにとってはより不透明になる可能性があります。

このチュートリアルでは、Gatekeeperの使用方法を示します。

Gatekeeper

Gatekeeperディレクトリには、各名前空間でtrust-managerが生成するconfigMapから、すべてのポッドにCAバンドルがマウントされるように設計された2つのAssignポリシーの例があります。

  1. Gatekeeperをクラスターにインストールします。

    helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
    helm repo update
    helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace --version v3.11.0
  2. team-a名前空間内のすべてのpodリソースに適用されるポリシーを作成します。これにより、必要なvolumes構成が適用されるときに、Podリソースが変更されます。

    apiVersion: mutations.gatekeeper.sh/v1
    kind: Assign
    metadata:
    name: demo-trust-ca-volume
    spec:
    applyTo:
    - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
    match:
    scope: Namespaced
    kinds:
    - apiGroups: ["*"]
    kinds: ["Pod"]
    namespaces: ["team-a"]
    excludedNamespaces: ["kube-system", "public", "kyverno", "gatekeeper-system"]
    # Mounting the volume named "ca-certificates" from ConfigMap
    location: "spec.volumes[name:ca-certificates]"
    parameters:
    assign:
    value:
    name: ca-certificates
    configMap:
    name: public-bundle
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    kubectl apply -f gatekeeper/gatekeeper-trust-pod-ca-volume.yaml
  3. team-a名前空間内のすべてのpodリソースに適用されるポリシーを作成します。これにより、必要なvolumeMounts構成で変更されます。

    apiVersion: mutations.gatekeeper.sh/v1
    kind: Assign
    metadata:
    name: demo-trust-ca-volumemount
    spec:
    applyTo:
    - groups: [""]
    kinds: ["Pod"]
    versions: ["v1"]
    match:
    scope: Namespaced
    kinds:
    - apiGroups: ["*"]
    kinds: ["Pod"]
    namespaces: ["team-a"]
    excludedNamespaces: ["kube-system", "public", "kyverno", "gatekeeper-system"]
    # All containers in a pod mounting to volumeMount named "ca-certificates"
    location: "spec.containers[name:*].volumeMounts[name:ca-certificates]"
    parameters:
    assign:
    value:
    mountPath: /etc/ssl/certs/
    name: ca-certificates
    readOnly: true
    kubectl apply -f gatekeeper/gatekeeper-trust-pod-ca-volumemount.yaml
  4. team-a名前空間に切り替え、以前のvolumeまたはvolumeMount構成なしでデプロイメントを作成し、ポッドが実行されたときに変更が有効になることを確認します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: test-assign
    name: test-assign
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: test-assign
    strategy: {}
    template:
    metadata:
    labels:
    app: test-assign
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    resources: {}
    volumeMounts: []
    volumes: []
    kubectl apply -f gatekeeper/deploy-novol.yaml
  5. 適用後、volumevolumeMountが適用されたことを検証します。

    kubectl get po -n team-a -l app=test-assign -o yaml | yq '.items[0].spec' -
  6. ポッドへのシェルを実行し、公開的に信頼されている任意のウェブサイト(例:https://bbc.co.uk)へのHTTPS接続を試みます。

    kubectl exec -n team-a -ti $(kubectl get pod -n team-a -l app=test-assign -o jsonpath='{.items[0].metadata.name}') -- curl -v https://bbc.co.uk

    成功は、Webページからの有効な200応答のように見えます。

    これは追加の構成なしで動作するはずであることに注意してください。その時点でSSLエラーが発生する場合は、volumesセクションで、正しいconfigMapが参照されていることを確認してください。

  7. 最後に、同様のポッドを適用できますが、今回はCA証明書が明示的にマウントされています。これは、Gatekeeperポリシーを使用すると、関連する構成がすでに存在する場合、アクションが実行されないことを示すためです。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: test-assign-noop
    name: test-assign-noop
    namespace: team-a
    spec:
    replicas: 1
    revisionHistoryLimit: 3
    selector:
    matchLabels:
    app: test-assign-noop
    template:
    metadata:
    labels:
    app: test-assign-noop
    spec:
    containers:
    - command:
    - /bin/sh
    - -c
    - sleep 1d
    image: quay.io/zenlab/curl:latest
    name: curl
    volumeMounts:
    - mountPath: /etc/ssl/certs/
    name: ca-certificates
    readOnly: true
    volumes:
    - name: ca-certificates
    configMap:
    name: example
    defaultMode: 0644
    optional: false
    items:
    - key: ca-certificates.crt
    path: ca-certificates.crt
    kubectl apply -f gatekeeper/deploy-withvol.yaml
    kubectl exec -n team-a -ti $(kubectl get pod -n team-a -l app=test-assign-noop -o jsonpath='{.items[0].metadata.name}') -- curl -v https://bbc.co.uk

注: Assignポリシーリソースに問題がある場合は、Kubernetesイベント(kubectl get events)で問題を確認してください。

trust-managerを使用したパブリック信頼

このチュートリアルでは、trust-managerを使用してクラスターレベルで認証局証明書を管理する方法と、この信頼されたBundleを手動で、またはGatekeeperで強制的に使用する方法を示しました。信頼できるCAの変更に応じて、アプリケーションを自動デプロイする方法を見てきました。

これは、現在環境で「動作する」ものにとっては、より多くの作業のように思えるかもしれませんが、このソリューションが、特定の認証局を信頼しなくなった場合にどのように対応できるかを検討してください。

次回は、プライベート認証局をこの信頼管理プロセスに統合するのがいかに簡単かを見ていきます。

クリーンアップ

このチュートリアルでデプロイされたすべてのリソースを削除するには

kubectl delete deployment -n team-a sleep-auto test-assign test-assign-noop
kubectl delete bundle public-bundle
kubectl delete assign demo-trust-ca-volume demo-trust-ca-volumemount
helm uninstall -n gatekeeper-system gatekeeper
helm uninstall -n stakater-reloader reloader
helm uninstall -n cert-manager trust-manager
helm uninstall -n cert-manager cert-manager
kubectl delete namespace cert-manager team-a stakater-reloader gatekeeper-system
kubectl delete crd -l gatekeeper.sh/system=yes