1.13. 安全性

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

开始前

如果您有一个项目,请将项目添加到 ServiceMeshMemberRoll 资源中

如果您没有项目,请安装 Bookinfo 示例应用程序 并将其添加到 ServiceMeshMemberRoll 资源中。示例应用程序可以帮助演示安全概念。

1.13.1. 关于 mutual Transport Layer Security(mTLS)

Mutual Transport Layer Security(mTLS)是一个协议,可让双方相互验证。在一些协议(IKE、SSH)中,它是身份验证的默认模式,在其他协议中(TLS)是可选的。您可以在不更改应用程序或服务代码的情况下使用 mTLS。TLS 完全由服务网格基础架构处理,并在两个 sidecar 代理之间进行处理。

默认情况下,Red Hat OpenShift Service Mesh 中的 mTLS 被启用并设置为 permissive 模式,Service Mesh 中的 sidecar 接受明文流量和使用 mTLS 加密的连接。如果将网格中的服务配置为使用严格的 mTLS 与网格外的服务通信,则这些服务间的通信可能会中断,因为严格的 mTLS 需要客户端和服务器能够相互验证识别。在将工作负载迁移到 Service Mesh 时使用 permissive 模式。然后,您可以在网格、命名空间或应用程序间启用严格的 mTLS。

在 Service Mesh control plane 级别启用 mTLS 可保护服务网格中的所有流量,而无需重写应用程序和工作负载。您可以在 ServiceMeshControlPlane 资源中的 data plane 级别保护网格中的命名空间。要自定义流量加密连接,请使用 PeerAuthenticationDestinationRule 资源在应用级别上配置命名空间。

1.13.1.1. 在服务网格中启用严格的 mTLS

如果您的工作负载没有与外部服务通信,您可以在网格间快速启用 mTLS,而不中断通信。您可以通过在 ServiceMeshControlPlane 资源中将 spec.security.dataPlane.mtls 设置为 true 来启用它。Operator 会创建所需资源。

apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
spec:
  version: v2.5
  security:
    dataPlane:
      mtls: true

您还可以使用 OpenShift Container Platform Web 控制台启用 mTLS。

流程

  1. 登录到 web 控制台。
  2. Project 菜单,选择安装 Service Mesh control plane 的项目,如 istio-system
  3. OperatorsInstalled Operators
  4. Provided APIs 下的 Service Mesh Control Plane
  5. ServiceMeshControlPlane 资源的名称,例如 basic
  6. Details 页面中,单击 Data Plane SecuritySecurity 部分中的切换。
1.13.1.1.1. 为特定服务的入站连接配置 sidecar

您还可以通过创建策略为各个服务配置 mTLS。

流程

  1. 使用以下示例创建 YAML 文件:

    PeerAuthentication 策略示例 policy.yaml

    apiVersion: security.istio.io/v1beta1
    kind: PeerAuthentication
    metadata:
      name: default
      namespace: <namespace>
    spec:
      mtls:
        mode: STRICT

    1. <namespace> 替换为该服务所在的命名空间。
  2. 运行以下命令,在服务所在的命名空间中创建资源。它必须与您刚才创建的 Policy 资源中的 namespace 字段匹配。

    $ oc create -n <namespace> -f <policy.yaml>
注意

如果您不使用自动 mTLS,并且要将 PeerAuthentication 设置为 STRICT,则必须为您的服务创建一个 DestinationRule 资源。

1.13.1.1.2. 为出站连接配置 sidecar

创建一个目标规则将 Service Mesh 配置为在向网格中的其他服务发送请求时使用 mTLS。

流程

  1. 使用以下示例创建 YAML 文件:

    DestinationRule 示例 destination-rule.yaml

    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: default
      namespace: <namespace>
    spec:
      host: "*.<namespace>.svc.cluster.local"
      trafficPolicy:
       tls:
        mode: ISTIO_MUTUAL

    1. <namespace> 替换为该服务所在的命名空间。
  2. 运行以下命令,在服务所在的命名空间中创建资源。它必须与您刚才创建的 DestinationRule 资源中的 namespace 字段匹配。

    $ oc create -n <namespace> -f <destination-rule.yaml>
1.13.1.1.3. 设置最小和最大协议版本

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

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

表 1.5. 有效值

描述

TLS_AUTO

default

TLSv1_0

TLS 版本 1.0

TLSv1_1

TLS 版本 1.1

TLSv1_2

TLS 版本 1.2

TLSv1_3

TLS 版本 1.3

流程

  1. 登录到 web 控制台。
  2. Project 菜单,选择安装 Service Mesh control plane 的项目,如 istio-system
  3. OperatorsInstalled Operators
  4. Provided APIs 下的 Service Mesh Control Plane
  5. ServiceMeshControlPlane 资源的名称,例如 basic
  6. YAML 标签。
  7. 在 YAML 编辑器中插入以下代码片段:将 minProtocolVersion 中的值替换为 TLS 版本值。在本例中,最小 TLS 版本设置为 TLSv1_2

    ServiceMeshControlPlane 代码片段

    kind: ServiceMeshControlPlane
    spec:
      security:
        controlPlane:
          tls:
            minProtocolVersion: TLSv1_2

  8. Save
  9. 单击 Refresh 以验证更改是否已正确更新。

1.13.1.2. 使用 Kiali 验证加密

Kiali 控制台提供了多种方式来验证应用程序、服务和工作负载是否启用了 mTLS 加密。

图 1.5. masthead 图标网格范围 mTLS

启用 mTLS

在 masthead 右侧,Kiali 显示一个锁定图标,当网格为整个服务网格启用了 mTLS 时。这意味着网格中的所有通信都使用 mTLS。

图 1.6. masthead 图标网格范围 mTLS 部分启用

启用 mTLS

当网格以 PERMISSIVE 模式或者网格范围 mTLS 配置出现错误时,Kiali 会显示 hollow 锁定图标。

图 1.7. 安全徽标

安全徽标

Graph 页面有选项,可以在图形边缘上显示 Security badge 来指示启用 mTLS。要在图形上启用安全徽标,请从 Display 菜单的 显示 Badges 下选择 安全 复选框。当边缘显示锁定图标时,它表示至少有一个启用了 mTLS 的请求。如果同时存在 mTLS 和非mTLS 请求,则 side-panel 会显示使用 mTLS 的请求百分比。

Applications details Overview 页会在图形边缘上显示一个 Security 图标,其中至少有一个启用了 mTLS 的请求。

Workloads details Overview 页会在图形边缘上显示一个 Security 图标,其中至少有一个启用了 mTLS 的请求。

Services Details Overview 页会在图形边缘上显示一个 Security 图标,其中至少有一个启用了 mTLS 的请求。另外请注意,Kiali 在 Network 部分显示为 mTLS 配置的端口旁的锁定图标。

1.13.2. 配置基于角色的访问控制(RBAC)

基于角色的访问控制 (RBAC) 对象决定是否允许用户或服务在项目内执行给定的操作。您可以为网格中的工作负载定义 mesh-、namespace- 和工作负载范围访问控制。

要配置 RBAC,在您要配置访问权限的命名空间中创建一个 AuthorizationPolicy 资源。如果要配置网格范围访问,请使用在其中安装 Service Mesh control plane 的项目,如 istio-system

例如,对于 RBAC,您可以创建以下策略:

  • 配置项目内部通信。
  • 允许或拒绝对默认命名空间中所有工作负载的完全访问。
  • 允许或拒绝入口网关访问。
  • 需要令牌才能访问。

授权策略包括选择器、操作和规则列表:

  • selector 字段指定策略的目标。
  • action 字段指定是否允许或拒绝请求。
  • rules 字段指定何时触发操作。

    • from 字段指定请求来源的限制。
    • to 字段指定请求目标和参数的限制。
    • when 字段指定应用该规则的其他条件。

流程

  1. 创建 AuthorizationPolicy 资源。以下示例显示了一个更新 ingress-policy AuthorizationPolicy 的资源,以拒绝 IP 地址访问入口网关。

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: ingress-policy
      namespace: istio-system
    spec:
      selector:
        matchLabels:
          app: istio-ingressgateway
      action: DENY
      rules:
      - from:
        - source:
            ipBlocks: ["1.2.3.4"]
  2. 在编写资源以便在命名空间中创建资源后运行以下命令。命名空间必须与 AuthorizationPolicy 资源中的 metadata.namespace 字段匹配。

    $ oc create -n istio-system -f <filename>

后续步骤

考虑以下示例用于其他通用配置。

1.13.2.1. 配置项目内部通信

您可以使用 AuthorizationPolicy 配置 Service Mesh control plane 来允许或拒绝与网格中的网格或服务通信的流量。

1.13.2.1.1. 限制对命名空间外服务的访问

您可以使用以下 AuthorizationPolicy 资源示例拒绝来自 info 命名空间中没有的源的请求。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: info
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["info"]
1.13.2.1.2. 创建 allow-all 和 default deny-all 授权策略

以下示例显示了一个 allow-all 授权策略,允许对 info 命名空间中的所有工作负载进行完全访问。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all
  namespace: info
spec:
  action: ALLOW
  rules:
  - {}

以下示例显示了拒绝对 info 命名空间中所有工作负载的访问的策略。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: info
spec:
  {}

1.13.2.2. 允许或拒绝对入口网关的访问

您可以设置一个授权策略来根据 IP 地址添加 allow 或 deny 列表。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ingress-policy
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
       ipBlocks: ["1.2.3.4", "5.6.7.0/24"]

1.13.2.3. 限制使用 JSON Web 令牌的访问

您可以使用 JSON Web Token(JWT)限制可以访问您的网格的内容。验证后,用户或服务可以访问路由,与该令牌关联的服务。

创建 RequestAuthentication 资源,用于定义工作负载支持的身份验证方法。下面的例子接受由 http://localhost:8080/auth/realms/master 发布的 JWT。

apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "jwt-example"
  namespace: info
spec:
  selector:
    matchLabels:
      app: httpbin
  jwtRules:
  - issuer: "http://localhost:8080/auth/realms/master"
    jwksUri: "http://keycloak.default.svc:8080/auth/realms/master/protocol/openid-connect/certs"

然后,在同一命名空间中创建一个 AuthorizationPolicy 资源,以用于您创建的 RequestAuthentication 资源。以下示例在向 httpbin 工作负载发送请求时,需要在 Authorization 标头中有一个 JWT。

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "frontend-ingress"
  namespace: info
spec:
  selector:
    matchLabels:
      app: httpbin
  action: DENY
  rules:
  - from:
    - source:
        notRequestPrincipals: ["*"]

1.13.3. 配置密码套件和 ECDH curves(策展)

密码套件和 Elliptic-curve Diffie-Hellman(ECDH 策展)可以帮助您保护服务网格的安全。您可以使用 spec.security.controlplane.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.13.4. 配置 JSON Web 密钥设置解析器证书颁发机构

您可以从 ServiceMeshControlPlane (SMCP) spec 配置您自己的 JSON Web Key Sets (JWKS)解析器证书颁发机构(CA)。

流程

  1. 编辑 ServiceMeshControlPlane spec 文件:

    $ oc edit smcp <smcp-name>
  2. 通过将 ServiceMeshControlPlane spec 中的 mtls 字段设置为 true,为数据平面启用 mtls,如下例所示:

    spec:
      security:
        dataPlane:
            mtls: true # enable mtls for data plane
        # JWKSResolver extra CA
        # PEM-encoded certificate content to trust an additional CA
        jwksResolverCA: |
            -----BEGIN CERTIFICATE-----
            [...]
            [...]
            -----END CERTIFICATE-----
    ...
  3. 保存更改。OpenShift Container Platform 会自动应用它们。

一个 ConfigMap(如 pilot-jwks-cacerts-<SMCP name>)是由 CA .pem data 创建的。

ConfigMap pilot-jwks-cacerts-<SMCP name> 示例

kind: ConfigMap
apiVersion: v1
data:
  extra.pem: |
      -----BEGIN CERTIFICATE-----
      [...]
      [...]
      -----END CERTIFICATE-----

1.13.5. 添加外部证书颁发机构密钥和证书

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

前提条件

  • 在启用了 mutual TLS 配置证书的情况下安装 Red Hat OpenShift Service Mesh。
  • 这个示例使用 Maistra 存储库中的证书。对于生产环境,请使用您自己的证书颁发机构提供的证书。
  • 部署 Bookinfo 示例应用程序以按照以下说明验证结果。
  • 需要 openssl 才能验证证书。

1.13.5.1. 添加一个现有证书和密钥

要使用现有签名(CA)证书和密钥,必须创建一个信任文件链,其中包括 CA 证书、密钥和 root 证书。您必须为每个对应证书使用以下准确文件名称。CA 证书名为 ca-cert.pem,密钥是 ca-key.pem,签名 ca-cert.pem 的 root 证书名为 root-cert.pem。如果您的工作负载使用中间证书,则必须在 cert-chain.pem 文件中指定它们。

  1. 本地保存 Maistra repo 中的示例证书,,将 <path> 替换为证书的路径。
  2. 创建名为 cacert 的 secret,其中包含输入文件 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
  3. ServiceMeshControlPlane 资源中将 spec.security.dataPlane.mtls 设置为 true,并配置 certificateAuthority 字段,如下例所示。默认 rootCADir/etc/cacerts。如果在默认位置挂载了密钥和证书,则不需要设置 privateKey。Service Mesh 从 secret-mount 文件中读取证书和密钥。

    apiVersion: maistra.io/v2
    kind: ServiceMeshControlPlane
    spec:
      security:
        dataPlane:
          mtls: true
        certificateAuthority:
          type: Istiod
          istiod:
            type: PrivateKey
            privateKey:
              rootCADir: /etc/cacerts
  4. 创建/更改/取消设置 cacert secret 后,Service Mesh control plane istiodgateway pod 必须重启,以便更改生效。使用以下命令重启 pod:

    $ oc -n istio-system delete pods -l 'app in (istiod,istio-ingressgateway, istio-egressgateway)'

    Operator 会在 pod 被删除后自动重新创建。

  5. 重启 info 应用程序 pod,以便 sidecar 代理获取 secret 的更改。使用以下命令重启 pod:

    $ oc -n info delete pods --all

    您应该看到类似如下的输出:

    pod "details-v1-6cd699df8c-j54nh" deleted
    pod "productpage-v1-5ddcb4b84f-mtmf2" deleted
    pod "ratings-v1-bdbcc68bc-kmng4" deleted
    pod "reviews-v1-754ddd7b6f-lqhsv" deleted
    pod "reviews-v2-675679877f-q67r2" deleted
    pod "reviews-v3-79d7549c7-c2gjs" deleted
  6. 使用以下命令验证 pod 是否已创建并就绪:

    $ oc get pods -n info

1.13.5.2. 验证您的证书

使用 Bookinfo 示例应用程序来验证工作负载证书是否由插入到 CA 的证书签名。这个过程要求您在机器上安装 openssl

  1. 要从 info 工作负载中提取证书,请使用以下命令:

    $ sleep 60
    $ oc -n info exec "$(oc -n bookinfo get pod -l app=productpage -o jsonpath={.items..metadata.name})" -c istio-proxy -- openssl s_client -showcerts -connect details:9080 > bookinfo-proxy-cert.txt
    $ sed -n '/-----BEGIN CERTIFICATE-----/{:start /-----END CERTIFICATE-----/!{N;b start};/.*/p}' info-proxy-cert.txt > certs.pem
    $ awk 'BEGIN {counter=0;} /BEGIN CERT/{counter++} { print > "proxy-cert-" counter ".pem"}' < certs.pem

    运行此命令后,您的工作目录中应当有三个文件: proxy-cert-1.pemproxy-cert-2.pemproxy-cert-3.pem

  2. 验证 root 证书是否与管理员指定证书相同。将 <path> 替换为证书的路径。

    $ openssl x509 -in <path>/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

  3. 验证 CA 证书是否与管理员指定证书相同。将 <path> 替换为证书的路径。

    $ openssl x509 -in <path>/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.

  4. 从 root 证书到工作负载证书验证证书链。将 <path> 替换为证书的路径。

    $ openssl verify -CAfile <(cat <path>/ca-cert.pem <path>/root-cert.pem) ./proxy-cert-1.pem

    您应看到以下结果:./proxy-cert-1.pem: OK

1.13.5.3. 删除证书

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

  1. 删除 secret cacert。在本例中,istio-system 是 Service Mesh control plane 项目的名称。

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

    apiVersion: maistra.io/v2
    kind: ServiceMeshControlPlane
    spec:
      security:
        dataPlane:
          mtls: true

1.13.6. 关于将 Service Mesh 与 cert-manager 和 istio-csr 集成

cert-manager 工具是 Kubernetes 上 X.509 证书管理的解决方案。它提供了一个统一的 API,将应用程序与私钥或公钥基础架构 (PKI) 集成,如 Vault、Google Cloud Certificate Authority Service、Ret 的 Encrypt 和其他供应商。

cert-manager 工具通过尝试在配置的时间尝试续订证书,确保证书有效且最新。

对于 Istio 用户,cert-manager 还提供与 istio-csr 集成,它是一个处理 Istio 代理的证书签名请求 (CSR) 的证书颁发机构 (CA) 服务器。然后,服务器将签名委托给 cert-manager,它将 CSR 转发到配置的 CA 服务器。

注意

红帽支持与 istio-csr 和 cert-manager 集成。红帽不提供对 istio-csr 或社区 cert-manager 组件的直接支持。此处所示的社区 cert-manager 的使用仅用于演示目的。

前提条件

  • 这些 cert-manager 版本之一:

    • cert-manager Operator for Red Hat OpenShift 1.10 或更高版本
    • 社区 cert-manager Operator 1.11 或更高版本
    • cert-manager 1.11 或更高版本
  • OpenShift Service Mesh Operator 2.4 或更高版本
  • istio-csr 0.6.0 或更高版本
注意

为了避免在使用 jetstack/cert-manager-istio-csr Helm chart 安装 istio-csr 服务器时在所有命名空间中创建配置映射,在 istio-csr.yaml 文件中使用以下设置:app.controller.configmapNamespaceSelector: "maistra.io/member-of: <istio-namespace>"

1.13.6.1. 安装 cert-manager

您可以安装 cert-manager 工具来管理 TLS 证书的生命周期,并确保它们有效且最新。如果您在您的环境中运行 Istio,您还可以安装 istio-csr 证书颁发机构 (CA) 服务器,该服务器处理 Istio 代理中的证书签名请求 (CSR)。istio-csr CA 将签名委派给 cert-manager 工具,该工具委托给配置的 CA。

流程

  1. 创建 root 集群签发者:

    cluster-issuer.yaml 示例

    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: selfsigned-root-issuer
      namespace: cert-manager
    spec:
      selfSigned: {}
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: root-ca
      namespace: cert-manager
    spec:
      isCA: true
      duration: 21600h # 900d
      secretName: root-ca
      commonName: root-ca.my-company.net
      subject:
        organizations:
        - my-company.net
      issuerRef:
        name: selfsigned-root-issuer
        kind: Issuer
        group: cert-manager.io
    ---
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: root-ca
    spec:
      ca:
        secretName: root-ca

    注意

    selfsigned-root-issuer issuer 和 root-ca 证书的命名空间是 cert-manager,因为 root-ca 是集群签发者,因此 cert-manager 会在其自己的命名空间中查找引用的 secret。在 Red Hat OpenShift 的 cert-manager Operator 时,命名空间称为 cert-manager。

    1. 使用以下命令创建对象:

      $ oc apply -f cluster-issuer.yaml
    2. 创建 istio-ca 对象,如下例所示:

      istio-ca.yaml 示例

      apiVersion: cert-manager.io/v1
      kind: Certificate
      metadata:
        name: istio-ca
        namespace: istio-system
      spec:
        isCA: true
        duration: 21600h
        secretName: istio-ca
        commonName: istio-ca.my-company.net
        subject:
          organizations:
          - my-company.net
        issuerRef:
          name: root-ca
          kind: ClusterIssuer
          group: cert-manager.io
      ---
      apiVersion: cert-manager.io/v1
      kind: Issuer
      metadata:
        name: istio-ca
        namespace: istio-system
      spec:
        ca:
          secretName: istio-ca

    3. 使用以下命令来创建对象:

      $ oc apply -n istio-system -f istio-ca.yaml
  2. 安装 istio-csr

    $ helm install istio-csr jetstack/cert-manager-istio-csr \
        -n istio-system \
        -f deploy/examples/cert-manager/istio-csr/istio-csr.yaml

    istio-csr.yaml 示例

    replicaCount: 2
    
    image:
      repository: quay.io/jetstack/cert-manager-istio-csr
      tag: v0.6.0
      pullSecretName: ""
    
    app:
      certmanager:
        namespace: istio-system
        issuer:
          group: cert-manager.io
          kind: Issuer
          name: istio-ca
    
      controller:
        configmapNamespaceSelector: "maistra.io/member-of=istio-system"
        leaderElectionNamespace: istio-system
    
      istio:
        namespace: istio-system
        revisions: ["basic"]
    
      server:
        maxCertificateDuration: 5m
    
      tls:
        certificateDNSNames:
        # This DNS name must be set in the SMCP spec.security.certificateAuthority.cert-manager.address
        - cert-manager-istio-csr.istio-system.svc

  3. 部署 SMCP:

    $ oc apply -f mesh.yaml -n istio-system

    mesh.yaml 示例

    apiVersion: maistra.io/v2
    kind: ServiceMeshControlPlane
    metadata:
      name: basic
    spec:
      addons:
        grafana:
          enabled: false
        kiali:
          enabled: false
        prometheus:
          enabled: false
      proxy:
        accessLogging:
          file:
            name: /dev/stdout
      security:
        certificateAuthority:
          cert-manager:
            address: cert-manager-istio-csr.istio-system.svc:443
          type: cert-manager
        dataPlane:
          mtls: true
        identity:
          type: ThirdParty
      tracing:
        type: None
    ---
    apiVersion: maistra.io/v1
    kind: ServiceMeshMemberRoll
    metadata:
      name: default
    spec:
      members:
      - httpbin
      - sleep

注意

当配置了 security.certificateAuthority.type: cert-manager 时必须设置 security.identity.type: ThirdParty

验证

使用示例 httpbin 服务和 sleep 应用程序来检查来自入口网关的 mTLS 流量,并验证安装了 cert-manager 工具。

  1. 部署 HTTP 和 sleep 应用程序:

    $ oc new-project <namespace>
    $ oc apply -f https://raw.githubusercontent.com/maistra/istio/maistra-2.4/samples/httpbin/httpbin.yaml
    $ oc apply -f https://raw.githubusercontent.com/maistra/istio/maistra-2.4/samples/sleep/sleep.yaml
  2. 验证 sleep 是否可以访问 httpbin 服务:

    $ oc exec "$(oc get pod -l app=sleep -n <namespace> \
       -o jsonpath={.items..metadata.name})" -c sleep -n <namespace> -- \
       curl http://httpbin.<namespace>:8000/ip -s -o /dev/null \
       -w "%{http_code}\n"

    输出示例:

    200

  3. 检查来自 ingress 网关到 httpbin 服务的 mTLS 流量:

    $ oc apply -n <namespace> -f https://raw.githubusercontent.com/maistra/istio/maistra-2.4/samples/httpbin/httpbin-gateway.yaml
  4. 获取 istio-ingressgateway 路由:

    INGRESS_HOST=$(oc -n istio-system get routes istio-ingressgateway -o jsonpath='{.spec.host}')
  5. 验证从 ingress 网关到 httpbin 服务的 mTLS 流量:

    $ curl -s -I http://$INGRESS_HOST/headers -o /dev/null -w "%{http_code}" -s

1.13.7. 其他资源

有关如何为 OpenShift Container Platform 安装 cert-manager Operator 的详情,请参考:为 Red Hat OpenShift 安装 cert-manager Operator