Istio安全-證書管理(實操一)


Istio安全-證書管理

注:本章更新至1.8版本

插入現有CA證書

本節展示了管理員如何使用現有的根證書來授權istio證書,簽發證書和密鑰,不使用Istio自動生成的證書。

默認情況下,istio的CA會生成一個自簽的根證書和密鑰,並使用它們簽發負載證書。istio的CA也可以使用管理員指定的證書和密鑰,以及管理員指定的根證書來簽發負載證書。

根CA是網格中所有負載信任的根證書。每個Istio CA會使用一個中間CA來簽發密鑰和證書,該CA由根CA簽發。當一個網格中存在多個Istio CA時,會在CA之間建立起信任層級。

本節展示如何將這些證書和密鑰插入Istio的CA。

插入現有證書和密鑰

在istio的samples/certs目錄下有一套證書,可以比較好地解釋istio的證書交互原理。

  • root-cert.pem: root CA certificate.
  • ca-[cert|key].pem: Citadel intermediate certificate and corresponding private key.
  • cert-chain.pem: certificate trust chain.
  • workload-foo-[cert|key].pem: workload certificate and key for URI SAN spiffe://trust-domain-foo/ns/foo/sa/foo signed by ca-cert.key.
  • workload-bar-[cert|key].pem: workload certificate and key for URI SAN spiffe://trust-domain-bar/ns/bar/sa/bar signed by ca-cert.key.

假如希望使用現有的CA證書ca-cert.pemca-key.pem(root-cert.pem簽發了ca-cert.pem,因此root-cert.pem作為所有負載的根證書)。由於ca-cert.pem不同於root-cert.pem,因此無法直接通過根證書進行校驗,此時需要通過一個cert-chain.pem來指定信任鏈,包含負載到根CA的所有中間CAs。在上述例子中,僅包含了istio的CA簽名證書,因此cert-chain.pemca-cert.pem相同。注意:如果 ca-cert.pemroot-cert.pem是相同的,那么 cert-chain.pem文件應該是空的。

上述證書例子中的證書鏈為:root-cert.pem-->cert-chain.pem(含ca-cert.pem)-->workload-foo-cert.pem/workload-bar-cert.pem,可以使用如下方式進行校驗:

# openssl verify -CAfile <(cat ca-cert.pem root-cert.pem) workload-bar-cert.pem
workload-bar-cert.pem: OK

對於生產環境,最好在一台離線機器上執行如下步驟,確保將根密鑰暴露給盡可能少的人

  1. 創建一個保存證書和密鑰的目錄

    $ mkdir -p certs
    $ pushd certs
    
  2. 生成根證書和密鑰

    $ make -f ../tools/certs/Makefile.selfsigned.mk root-ca
    

    上述命令將生成如下文件:

    • root-cert.pem: 根證書
    • root-key.pem: 根密鑰
    • root-ca.conf: openssl 使用該配置來生成根證書
    • root-cert.csr: 為根證書生成的CSR
  3. 生成中間證書和密鑰

    $ make -f ../tools/certs/Makefile.selfsigned.mk cluster1-cacerts
    

    執行如上命令會生成一個名為cluster1的目錄,包含如下文件,root-cert.pem簽發了ca-cert.pem

    • ca-cert.pem: 中間證書
    • ca-key.pem: 中間密鑰
    • cert-chain.pem: Istiod使用的證書鏈
    • root-cert.pem: 根證書
    • intermediate.conf: openssl 使用該配置來生成中間證書
    • cluster-ca.csr: 為中間證書生成的CSR

    可以將cluster1替換為任何字符串。例如make mycluster-certs將會生成名為mycluster的目錄

    為了配置其他Istio CA,可以重復執行上述步驟來生成不同名稱的證書目錄

  4. 創建一個cacerts secret,包含如下輸入文件ca-cert.pem, ca-key.pem, root-cert.pemcert-chain.pem。需要注意的是創建出來的secret的名稱必須是cacerts,這樣才能被istio正確掛載。

    $ kubectl create namespace istio-system
    $ kubectl create secret generic cacerts -n istio-system \
          --from-file=cluster1/ca-cert.pem \
          --from-file=cluster1/ca-key.pem \
          --from-file=cluster1/root-cert.pem \
          --from-file=cluster1/cert-chain.pem
    
  5. 返回Istio安裝的頂層目錄

    $ popd
    

部署Istio

使用demo profile,Istio會從掛載的secret文件中讀取證書

$ istioctl install --set profile=demo

在下面的例子中,istio的CA證書(ca-cert.pem)與根證書(root-cert.pem)不同,因此負載無法通過根證書驗證工作負載證書,需要使用一個cert-chain.pem來指定信任的證書鏈,該證書鏈包含負載和根CA之間的所有中間CA,在此例子中,它包含了istio的CA簽名證書,因此cert-chain.pemca-cert.pem相同的。注意,如果ca-cert.pemroot-cert.pem相同,那么ca-chain.pem文件應該是空的。

配置示例services

  1. 部署httpbin和sleep示例services

    $ kubectl create ns foo
    $ kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml) -n foo
    $ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
    
  2. 部署一個策略,使得foo命名空間的負載僅接受mutual TLS流量

    $ kubectl apply -n foo -f - <<EOF
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "default"
    spec:
      mtls:
        mode: STRICT
    EOF
    

校驗證書

本節中會校驗插入到CA中的證書是否簽發了負載證書。

  1. sleep 20s,等待mTLS策略下httpbin的證書鏈生效。由於CA證書是自簽的,因此openssl命令會返回verify error:num=19:self signed certificate in certificate chain錯誤。

    $ sleep 20; kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo -- openssl s_client -showcerts -connect httpbin.foo:8000 > httpbin-proxy-cert.txt
    
  2. 解析證書鏈中的證書

    $ sed -n '/-----BEGIN CERTIFICATE-----/{:start /-----END CERTIFICATE-----/!{N;b start};/.*/p}' httpbin-proxy-cert.txt > certs.pem
    $ awk 'BEGIN {counter=0;} /BEGIN CERT/{counter++} { print > "proxy-cert-" counter ".pem"}' < certs.pem
    
  3. 校驗根證書與管理員指定的證書相同

    $ openssl x509 -in samples/certs/root-cert.pem -text -noout > /tmp/root-cert.crt.txt
    $ openssl x509 -in ./proxy-cert-3.pem -text -noout > /tmp/pod-root-cert.crt.txt
    $ diff -s /tmp/root-cert.crt.txt /tmp/pod-root-cert.crt.txt
    Files /tmp/root-cert.crt.txt and /tmp/pod-root-cert.crt.txt are identical
    
  4. 校驗CA證書與管理員指定的相同

    $ openssl x509 -in samples/certs/ca-cert.pem -text -noout > /tmp/ca-cert.crt.txt
    $ openssl x509 -in ./proxy-cert-2.pem -text -noout > /tmp/pod-cert-chain-ca.crt.txt
    $ diff -s /tmp/ca-cert.crt.txt /tmp/pod-cert-chain-ca.crt.txt
    Files /tmp/ca-cert.crt.txt and /tmp/pod-cert-chain-ca.crt.txt are identical
    
  5. 校驗從根證書到負載證書的證書鏈。下面使用中間證書和根證書組成的證書鏈來校驗其簽發了負載證書

    $ openssl verify -CAfile <(cat samples/certs/ca-cert.pem samples/certs/root-cert.pem) ./proxy-cert-1.pem
    ./proxy-cert-1.pem: OK
    

卸載

卸載證書cacertfoo以及istio-system命名空間

$ kubectl delete secret cacerts -n istio-system
$ kubectl delete ns foo istio-system

Istio的DNS證書管理

本節展示如何使用 Chiron提供和管理DNS證書,Chiron是一個與istiod相連的輕量型組件,它使用kubernetes的CA API簽發證書,無需管理私鑰。有如下優勢:

  • 與isitod不同,這種方式無需維護簽發的私鑰,增強了安全性
  • 簡化了將根證書分發到TLS客戶端。客戶端不再需要等待istiod生成並分發其CA證書

首先使用istioctl安裝istio,並配置DNS證書,當istiod啟動后會讀取該配置:

$ cat <<EOF > ./istio.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    certificates:
      - secretName: dns.example1-service-account
        dnsNames: [example1.istio-system.svc, example1.istio-system]
      - secretName: dns.example2-service-account
        dnsNames: [example2.istio-system.svc, example2.istio-system]
EOF
$ istioctl install -f ./istio.yaml

可以看到在istio-system下生成了兩個secret:

# kubectl get secret -n istio-system |grep dns
dns.example1-service-account                       istio.io/dns-key-and-cert             3      81s
dns.example2-service-account                       istio.io/dns-key-and-cert             3      81s

DNS證書的提供和管理

Istio根據用戶的配置為DNS證書提供了DNS名字和secret名稱。DNS證書由kubernetes CA簽發,並根據配置保存到secret中。istio也管理着DNS證書的生命周期,包括證書滾動和重新生成。

配置DNS證書

可以在 istioctl install 命令中使用IstioControlPlane用戶資源對istio進行配置。dnsNames字段用於設定證書中的DNS名稱,secretName字段指定保存證書和密鑰的kubernetes secret的名稱。

檢查提供的DNS證書

在配置istio生成DNS證書並保存到secret后,需要校驗提供的證書是否能夠正確運行。

為了校驗istio前面例子中生成的dns.example1-service-account的DNS證書,以及校驗該證書是否包含配置的DNS名稱,需要獲取kubernetes的secret,解析並對其解碼,查看其具體內容:

$ kubectl get secret dns.example1-service-account -n istio-system -o jsonpath="{.data['cert-chain\.pem']}" | base64 --decode | openssl x509 -in /dev/stdin -text -noout

輸出的文本包括:

X509v3 Subject Alternative Name:
    DNS:example1.istio-system.svc, DNS:example1.istio-system

重新生成DNS證書

istio可以在DNS證書被錯刪的情況下重新生成證書。

  1. 刪除前面保存的DNS證書

    $ kubectl delete secret dns.example1-service-account -n istio-system
    
  2. 校驗istio重新生成了刪除的DNS證書,且證書包含配置的DNS名稱。需要從kubernetes獲取secret,解析並對其解碼,獲取其內容:

    $sleep 10; kubectl get secret dns.example1-service-account -n istio-system -o jsonpath="{.data['cert-chain\.pem']}" | base64 --decode | openssl x509 -in /dev/stdin -text -noout
    

輸出包括

X509v3 Subject Alternative Name:
    DNS:example1.istio-system.svc, DNS:example1.istio-system

卸載

$ kubectl delete ns istio-system


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM