最新消息:在TwitterMastodon獲取專案更新

使用 trust-manager 管理 Kubernetes 中的公眾信任

上次驗證:2023 年 6 月 19 日

在本教學中,我們將逐步介紹如何使用 trust-manager 在 Kubernetes 叢集內部分發公開信任的憑證授權單位 (CA) 憑證。一旦分發完成,我們還會展示

  • 當您的信任捆綁包變更時,如何自動重新載入應用程式
  • 如何強制應用程式使用您分發的 CA 捆綁包

從這裡,我們將使用一個簡單的 curl Pod,來展示如何自動掛載信任的 CA Bundle,以便無需手動設定 curl 即可使用。這模擬了應用程式如何無需任何額外設定即可使用您信任的 CA 憑證捆綁包。

在本教學中,我們將把變更的範圍限制為僅影響 team-a 命名空間。為了充分利用這些功能,您需要移除此限制。

注意: 提供的所有資源都僅供示範,在生產環境中使用之前應仔細審查。

先決條件

💻 軟體

  1. kubectl:Kubernetes 的命令列工具,可讓您設定 Kubernetes 叢集。
  2. helm:Kubernetes 的套件管理器。
  3. yq:用於解析 YAML 的命令列工具,具有有用的色彩標記。

分發公開 CA 信任

讓我們先設定 trust-manager,並將我們的公開 CA 分發到我們的示範命名空間:team-a

設定應用程式與捆綁包

  1. 依照此處的指示安裝 trust-manager。

  2. 建立您的第一個 Bundle 資源,僅包含公開 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,這與 Bundle 資源中的 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 的頂部,這將移除現有的 CA 憑證,這些憑證通常來自容器基礎映像或在 CI 組建期間拉入。

警告: 在此範例中,我們選擇了一個眾所周知的位置,該位置由 alpine 和 curl 用於取得信任的 CA。這不是唯一可以使用的位置,因此容器可能還有其他預設位置。如果您想查看預設 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. 在正在執行的 Pod 中建立 Shell

    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 電話到一個知名的網站,以驗證 curl 是否正常運作,而無需傳遞額外的 --cacert 旗標

    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,您的應用程式可以設定為使用 SSL_CERT_FILESSL_CERT_DIR 來指向預設的 CA 憑證檔案位置。

請參閱此處以瞭解更多詳細資訊,並查看此處以瞭解各種作業系統基礎上的預設位置

// 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.dev.org.tw/issue/12139
"/etc/pki/tls/certs", // Fedora/RHEL
"/

在檢查 Python 時,ssl 程式庫使用相同的兩個環境變數來尋找信任的 CA: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 和任何下列檔案都將受到任何 Python 應用程式執行階段的信任,與 Go 類似

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

類似的內容也可以透過其他語言實現。

自動化與強制執行

現在我們已經手動掛載了 trust-manager 的捆綁包,您可能會想

  • 如果 CA 捆綁包變更,我該如何將該變更傳遞給我的應用程式?
  • 我該如何確保我的 CA 捆綁包掛載到叢集中的所有應用程式,而無需向我的租戶請求變更?

讓我們使用其他開源工具來解決這兩種情況。

推出 CA 捆綁包變更

如果您的 CA 捆綁包變更,這些變更將會非常快速地同步到命名空間。此變更將反映在附加到容器的磁碟區中,但大多數應用程式不會注意到檔案系統變更。常見的方法是透過使用 kubectl rollout restart deployment <DEPLOY_NAME> 來重新啟動用戶端應用程式部署。有一個選項可以透過協力廠商的開源軟體來自動執行此程序。

使用 Stakater Reloader,可以在 ConfigMapSecret 變更時重新載入或部署應用程式。因此,每當 Bundle 的目標同步時,Reloader 元件可以偵測到此變更,並部署掛載這些資源作為磁碟區或環境變數的應用程式。

請注意,您可以在應用程式容器中綁定或編寫許多替代軟體。它們只需監看檔案系統的變更並觸發應用程式程序重新載入。這種方法需要容器映像或程式碼變更,並且對於許多租戶來說可能難以實作。這裡使用 reloader 的優勢在於它是一個通用的解決方案,適用於叢集中運行的所有應用程式。

  1. 繼續使用 reloader,它可以透過 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"

    請注意,有多種配置選項可用於配置 reloader 工具,這僅是最基本的範例。如需更詳細的範例,請參閱文件

  3. 在另一個終端機中監看應用程式部署

    kubectl get po -n team-a -w
  4. 為了測試此變更,我們可以編輯我們的 Bundle 資源,移除所有預設的公開 CA 憑證,而只提供一個 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. 新的 Pod 執行後,使用以下命令確認您只有一個 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

    我們也可以驗證從這個 Pod,我們無法再與 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 配置。透過這種方法,叢集管理員可以設定規則,將相關配置自動插入到每個 Pod 中。這可能有利於強制執行配置,但對於叢集的應用程式團隊或租戶來說可能更不透明。

在本教學中,我們將展示如何使用 Gatekeeper

Gatekeeper

請參閱 Gatekeeper 目錄,其中包含兩個範例 Assign 原則,旨在強制將 CA 憑證包從 trust-manager 在每個命名空間中產生的 configMap 掛載到所有 Pod 上。

  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 命名空間,並建立沒有先前 volumevolumeMount 配置的部署,以查看 Pod 執行後生效的變更

    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. 在 Pod 中執行 Shell,並嘗試與任何公開信任的網站建立 HTTPS 連線,例如:https://bbc.co.uk

    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

    成功看起來像是從網頁返回有效的 200 回應。

    請注意,現在應該可以在沒有任何額外配置的情況下運作。如果在這一點出現 SSL 錯誤,請檢查 volumes 區段中是否參考了正確的 configMap

  7. 最後,我們可以套用一個類似的 Pod,只是這次 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 在叢集層級管理憑證授權單位憑證,以及如何手動或透過使用 Gatekeeper 強制執行來使用此受信任的 Bundle。我們已經了解如何設定應用程式,使其在受信任的 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