1.9. 在 Service Mesh 中自定义安全性

如果您的服务网格应用程序由 一 组复杂的微服务组成,您可以使用 Red Hat OpenShift Service Mesh 来定制这些服务间的通信安全性。OpenShift Container Platform 的基础架构以及 Service Mesh 的流量管理功能可帮助您管理应用程序的复杂性,并为微服务提供服务和身份安全。

1.9.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.9.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.9.1.1.1. 为特定服务的入站连接配置 sidecar

您可以通过创建一个策略来为各个服务或命名空间配置 mTLS。

apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "default"
  namespace: <NAMESPACE>
spec:
  peers:
  - mtls: {}

1.9.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.9.1.3. 设置最小和最大协议版本

如果您的环境对服务网格中的加密流量有具体要求您可以通过设置 ServiceMeshControlPlane 资源中的 spec.istio.global.tls.minProtocolVersionspec.istio.global.tls.maxProtocolVersion 来控制允许的加密功能。这些值在 control plane 资源中配置,定义网格组件在通过 TLS 安全通信时使用的最小和最大 TLS 版本。

apiVersion: maistra.io/v1
kind: ServiceMeshControlPlane
spec:
  istio:
    global:
      tls:
        minProtocolVersion: TLSv1_0

默认为 TLS_AUTO,且不指定 TLS 版本。

表 1.14. 有效值

描述

TLS_AUTO

default

TLSv1_0

TLS 版本 1.0

TLSv1_1

TLS 版本 1.1

TLSv1_2

TLS 版本 1.2

TLSv1_3

TLS 版本 1.3

1.9.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, CurveP384CurveP256 设置为比 CurveP384 有更高的优先级。

注意

在配置加密套件时,需要包括 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256TLS_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.9.3. 添加外部证书颁发机构密钥和证书

默认情况下,Red Hat OpenShift Service Mesh 生成自签名 root 证书和密钥,并使用它们为工作负载证书签名。您还可以使用用户定义的证书和密钥使用用户定义的 root 证书为工作负载证书签名。此任务演示了一个将证书和密钥插入 Service Mesh 的示例。

先决条件

  • 您必须已安装了启用了 mutual TLS 配置证书的 Red Hat OpenShift Service Mesh。
  • 本例使用 Maistra 仓库中的证书。对于生产环境,请使用您自己的证书颁发机构提供的证书。
  • 您必须部署 Bookinfo 示例应用程序以按照以下说明验证结果。

1.9.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> 替换为证书的路径。

  1. 创建一个 secret cacert,其中包含输入文件 ca-cert.pemca-key.pemroot-cert.pemcert-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
  2. 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
  3. 要确保工作负载迅速添加新证书,请删除名为 istio.* 的 Service Mesh 生成的 secret。在这个示例中, istio.default。Service Mesh 为工作负载发布新证书。

    $ oc delete secret istio.default

1.9.3.2. 验证您的证书

使用 Bookinfo 示例应用程序验证您的证书被正确挂载。首先,检索挂载的证书。然后,验证 pod 上挂载的证书。

  1. 将 pod 名称存储在 RATINGSPOD 变量中。

    $ RATINGSPOD=`oc get pods -l app=ratings -o jsonpath='{.items[0].metadata.name}'`
  2. 运行以下命令以检索代理上挂载的证书。

    $ 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 证书。

  3. 验证 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

    预期输出为空。

  4. 验证 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

    预期输出为空。

  5. 从 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.9.3.3. 删除证书

要删除您添加的证书,请按照以下步骤操作。

  1. 删除 secret cacert

    $ oc delete secret cacerts -n istio-system
  2. ServiceMeshControlPlane 资源中使用自签名 root 证书重新部署 Service Mesh。

    apiVersion: maistra.io/v1
    kind: ServiceMeshControlPlane
    spec:
      istio:
        global:
          mtls:
            enabled: true
        security:
          selfSigned: true