插入 CA 证书
本任务介绍了系统管理员如何通过根证书、签名证书和密钥来配置 Istio 证书授权(CA)。
默认情况下,Istio CA 会生成一个自签名的根证书和密钥,并使用它们来签署工作负载证书。 为了保护根 CA 密钥,您应该使用在安全机器上离线运行的根 CA,并使用根 CA 向运行在每个集群上的 Istio CA 签发中间证书。Istio CA 可以使用管理员指定的证书和密钥来签署工作负载证书, 并将管理员指定的根证书作为信任根分配给工作负载。
下图展示了在包含两个集群的网格中推荐的 CA 层次结构。
本任务介绍如何生成和插入 Istio CA 的证书和密钥。这些步骤可以重复进行, 为每个集群中运行的 Istio CA 提供证书和密钥。
在集群中插入证书和密钥
在 Istio 安装包的顶层目录下,创建一个目录来存放证书和密钥:
$ mkdir -p certs $ pushd certs
生成根证书和密钥:
$ make -f ../tools/certs/Makefile.selfsigned.mk root-ca
将会生成以下文件:
root-cert.pem
:生成的根证书root-key.pem
:生成的根密钥root-ca.conf
:生成根证书的openssl
配置root-cert.csr
:为根证书生成的 CSR
对于每个集群,为 Istio CA 生成一个中间证书和密钥。 以下是集群
cluster1
的例子:$ make -f ../tools/certs/Makefile.selfsigned.mk cluster1-cacerts
运行以上命令,将会在名为
cluster1
的目录下生成以下文件:ca-cert.pem
:生成的中间证书ca-key.pem
:生成的中间密钥cert-chain.pem
:istiod 使用的生成的证书链root-cert.pem
:根证书
您可以使用一个您选择的字符串来替换
cluster1
。例如,使用cluster2-cacerts
参数, 您可以在一个名为cluster2
的目录中创建证书和密钥。如果您正在离线机器上进行此操作,请将生成的目录复制到可以访问集群的机器上。
在每个集群中,创建一个私密
cacerts
,包括所有输入文件ca-cert.pem
,ca-key.pem
,root-cert.pem
和cert-chain.pem
。例如,在cluster1
集群上:$ 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
返回 Istio 安装的顶层目录:
$ popd
部署 Istio
使用
demo
配置文件部署 Istio。Istio 的 CA 将会从私密安装文件中读取证书和密钥。
$ istioctl install --set profile=demo
部署示例服务
部署
httpbin
和curl
示例服务。$ 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/curl/curl.yaml) -n foo
为
foo
命名空间中的工作负载部署一个策略,使其只接受相互的 TLS 流量。$ kubectl apply -n foo -f - <<EOF apiVersion: security.istio.io/v1 kind: PeerAuthentication metadata: name: "default" spec: mtls: mode: STRICT EOF
验证证书
本节中,验证工作负载证书是否已通过插入到 CA 中的证书签署。验证的前提要求机器上安装有 openssl
。
在检索
httpbin
的证书链之前,请等待 20 秒使mTLS策略生效。由于本例中使用的 CA 证书是自签的, 所以可以预料 openssl 命令返回verify error:num=19:self signed certificate in certificate chain
。$ sleep 20; kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c istio-proxy -n foo -- openssl s_client -showcerts -connect httpbin.foo:8000 > httpbin-proxy-cert.txt
解析证书链上的证书。
$ 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
确认根证书与管理员指定的证书是否相同:
$ openssl x509 -in certs/cluster1/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
验证 CA 证书与管理员指定的证书是否相同:
$ openssl x509 -in certs/cluster1/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
验证从根证书到工作负载证书的证书链:
$ openssl verify -CAfile <(cat certs/cluster1/ca-cert.pem certs/cluster1/root-cert.pem) ./proxy-cert-1.pem ./proxy-cert-1.pem: OK
清理
从本地磁盘中删除证书、密钥和中间文件:
$ rm -rf certs
删除 Secret
cacerts
:$ kubectl delete secret cacerts -n istio-system
从
foo
命名空间中删除身份验证策略:$ kubectl delete peerauthentication -n foo default
删除示例应用
curl
和httpbin
:$ kubectl delete -f samples/curl/curl.yaml -n foo $ kubectl delete -f samples/httpbin/httpbin.yaml -n foo
从集群中卸载 Istio:
$ istioctl uninstall --purge -y
从集群中删除命名空间
foo
和istio-system
:$ kubectl delete ns foo istio-system