1.12. 在 Service Mesh 中自定义安全性
如果您的服务网格应用程序由 一 组复杂的微服务组成,您可以使用 Red Hat OpenShift Service Mesh 来定制这些服务间的通信安全性。OpenShift Container Platform 的基础架构以及 Service Mesh 的流量管理功能可帮助您管理应用程序的复杂性,并为微服务提供服务和身份安全。
1.12.1. 启用 mutual Transport Layer Security(mTLS)
Mutual Transport Layer Security(mTLS)是一个双方可以同时相互验证对方的协议。在一些协议(IKE、SSH)中,它是身份验证的默认模式,在其他协议中(TLS)是可选的。
MTLS 可在不更改应用程序或服务代码的情况下使用。TLS 完全由服务网格基础架构处理,并在两个 sidecar 代理之间进行处理。
默认情况下,Red Hat OpenShift Service Mesh 设置为 permissive 模式,Service Mesh 的 sidecar 接受明文网络流量以及使用 mTLS 加密的网络连接。如果网格中的服务需要与网格外的服务进行通信,则 strict 模式的 mTLS 可能会破坏这些服务之间的通信。在将工作负载迁移到 Service Mesh 时使用 permissive 模式。
1.12.1.1. 在网格中启用 strict 模式的 mTLS
如果您的工作负载没有与网格之外的服务进行通信,且只接受加密的连接不会破坏这些通信,则可以在您的网格间快速启用 mTLS。在 ServiceMeshControlPlane
资源中将 spec.istio.global.mTLS.enabled
设置为 true
。operator 创建所需资源。
apiVersion: maistra.io/v1 kind: ServiceMeshControlPlane spec: istio: global: mtls: enabled: true
1.12.1.1.1. 为特定服务的入站连接配置 sidecar
您可以通过创建一个策略来为各个服务或命名空间配置 mTLS。
apiVersion: "authentication.istio.io/v1alpha1" kind: "Policy" metadata: name: "default" namespace: <NAMESPACE> spec: peers: - mtls: {}
1.12.1.2. 为出站连接配置 sidecar
创建一个目标规则将 Service Mesh 配置为在向网格中的其他服务发送请求时使用 mTLS。
apiVersion: "networking.istio.io/v1alpha3" kind: "DestinationRule" metadata: name: "default" namespace: <CONTROL_PLANE_NAMESPACE> spec: host: "*.local" trafficPolicy: tls: mode: ISTIO_MUTUAL
1.12.1.3. 设置最小和最大协议版本
如果您的环境对服务网格中的加密流量有具体要求您可以通过设置 ServiceMeshControlPlane
资源中的 spec.istio.global.tls.minProtocolVersion
或 spec.istio.global.tls.maxProtocolVersion
来控制允许的加密功能。这些值在 control plane 资源中配置,定义网格组件在通过 TLS 安全通信时使用的最小和最大 TLS 版本。
apiVersion: maistra.io/v1 kind: ServiceMeshControlPlane spec: istio: global: tls: minProtocolVersion: TLSv1_0
默认为 TLS_AUTO
,且不指定 TLS 版本。
值 | 描述 |
---|---|
| default |
| TLS 版本 1.0 |
| TLS 版本 1.1 |
| TLS 版本 1.2 |
| TLS 版本 1.3 |
1.12.2. 配置密码套件和 ECDH curves(策展)
密码套件和 Elliptic-curve Diffie-Hellman(ECDH 策展)可以帮助您保护服务网格的安全。您可以使用 spec.istio.global.tls.cipherSuites
和 ECDH 策展在 ServiceMeshControlPlane
资源中使用 spec.istio.global.tls.ecdhCurves
定义以逗号隔开的密码套件列表。如果其中任何一个属性为空,则使用默认值。
如果您的服务网格使用 TLS 1.2 或更早版本, cipherSuites
设置就会有效。它在使用 TLS 1.3 时无效。
在以逗号分开的列表中设置密码组合,以优先级顺序进行排列。例如,ecdhCurves: CurveP256, CurveP384
把 CurveP256
设置为比 CurveP384
有更高的优先级。
在配置加密套件时,需要包括 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
或 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
。HTTP/2 的支持至少需要其中一个加密套件。
支持的加密套件是:
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
支持的 ECDH Curves 是:
- CurveP256
- CurveP384
- CurveP521
- X25519
1.12.3. 添加外部证书颁发机构密钥和证书
默认情况下,Red Hat OpenShift Service Mesh 生成自签名 root 证书和密钥,并使用它们为工作负载证书签名。您还可以使用 Operator 指定的证书和密钥使用 Operator 指定的 root 证书为工作负载证书签名。此任务演示了一个将证书和密钥插入 Service Mesh 的示例。
先决条件
- 您必须已安装了启用了 mutual TLS 配置证书的 Red Hat OpenShift Service Mesh。
- 这个示例使用 Maistra repo 中的证书。对于生产环境,请使用您自己的证书颁发机构提供的证书。
- 您必须部署 Bookinfo 示例应用程序以按照以下说明验证结果。
1.12.3.1. 添加一个现有证书和密钥
要使用现有签名(CA)证书和密钥,必须创建一个信任文件链,其中包括 CA 证书、密钥和 root 证书。您必须为每个对应证书使用以下准确文件名称。CA 证书名为 ca-cert.pem
,密钥是 ca-key.pem
,签名 ca-cert.pem
的 root 证书名为 root-cert.pem
。如果您的工作负载使用中间证书,则必须在 cert-chain.pem
文件中指定它们。
按照以下步骤将证书添加到 Service Mesh。本地保存 Maistra repo 中的证书,并将 <path>
替换为您的证书的路径。
创建一个 secret
cacert
,其中包含输入文件ca-cert.pem
、ca-key.pem
、root-cert.pem
和cert-chain.pem
。$ oc create secret generic cacerts -n istio-system --from-file=<path>/ca-cert.pem \ --from-file=<path>/ca-key.pem --from-file=<path>/root-cert.pem \ --from-file=<path>/cert-chain.pem
在
ServiceMeshControlPlane
资源中将global.mtls.enabled
设置为true
,并将security.selfSigned
设置为false
。Service Mesh 从 secret-mount 文件中读取证书和密钥。apiVersion: maistra.io/v1 kind: ServiceMeshControlPlane spec: istio: global: mtls: enabled: true security: selfSigned: false
要确保工作负载迅速添加新证书,请删除名为
istio.*
的 Service Mesh 生成的 secret。在这个示例中,istio.default
。Service Mesh 为工作负载发布新证书。$ oc delete secret istio.default
1.12.3.2. 验证您的证书
使用 Bookinfo 示例应用程序验证您的证书被正确挂载。首先,检索挂载的证书。然后,验证 pod 上挂载的证书。
将 pod 名称存储在
RATINGSPOD
变量中。$ RATINGSPOD=`oc get pods -l app=ratings -o jsonpath='{.items[0].metadata.name}'`
运行以下命令以检索代理上挂载的证书。
$ oc exec -it $RATINGSPOD -c istio-proxy -- /bin/cat /etc/certs/root-cert.pem > /tmp/pod-root-cert.pem
文件
/tmp/pod-root-cert.pem
包含向 pod 传播的根证书。$ oc exec -it $RATINGSPOD -c istio-proxy -- /bin/cat /etc/certs/cert-chain.pem > /tmp/pod-cert-chain.pem
文件
/tmp/pod-cert-chain.pem
包含向 pod 传播的工作负载证书和 CA 证书。验证 root 证书与 Operator 指定证书相同。将
<path>
替换为证书的路径。$ openssl x509 -in <path>/root-cert.pem -text -noout > /tmp/root-cert.crt.txt
$ openssl x509 -in /tmp/pod-root-cert.pem -text -noout > /tmp/pod-root-cert.crt.txt
$ diff /tmp/root-cert.crt.txt /tmp/pod-root-cert.crt.txt
预期输出为空。
验证 CA 证书与 Operator 指定证书相同。将
<path>
替换为证书的路径。$ sed '0,/^-----END CERTIFICATE-----/d' /tmp/pod-cert-chain.pem > /tmp/pod-cert-chain-ca.pem
$ openssl x509 -in <path>/ca-cert.pem -text -noout > /tmp/ca-cert.crt.txt
$ openssl x509 -in /tmp/pod-cert-chain-ca.pem -text -noout > /tmp/pod-cert-chain-ca.crt.txt
$ diff /tmp/ca-cert.crt.txt /tmp/pod-cert-chain-ca.crt.txt
预期输出为空。
从 root 证书到工作负载证书验证证书链。将
<path>
替换为证书的路径。$ head -n 21 /tmp/pod-cert-chain.pem > /tmp/pod-cert-chain-workload.pem
$ openssl verify -CAfile <(cat <path>/ca-cert.pem <path>/root-cert.pem) /tmp/pod-cert-chain-workload.pem
输出示例
/tmp/pod-cert-chain-workload.pem: OK
1.12.3.3. 删除证书
要删除您添加的证书,请按照以下步骤操作。
删除 secret
cacert
。$ oc delete secret cacerts -n istio-system
在
ServiceMeshControlPlane
资源中使用自签名 root 证书重新部署 Service Mesh。apiVersion: maistra.io/v1 kind: ServiceMeshControlPlane spec: istio: global: mtls: enabled: true security: selfSigned: true