搜索

1.13. 安全性

download PDF

如果您的服务网格应用程序由 一 组复杂的微服务组成,您可以使用 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 加密的连接。如果网格中的服务需要与网格外的服务进行通信,则 strict 模式的 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.2
  security:
    dataPlane:
      mtls: true

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

流程

  1. 登录到 web 控制台。
  2. Project 菜单,选择安装 Service Mesh control plane 的项目,如 istio-system
  3. Operators Installed 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.6. 有效值
描述

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. Operators Installed 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 资源示例拒绝来自 bookinfo 命名空间中没有的源的请求。

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

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

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

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

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: bookinfo
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: bookinfo
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: bookinfo
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. 添加外部证书颁发机构密钥和证书

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

先决条件

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

1.13.4.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. 重启 bookinfo 应用程序 pod,以便 sidecar 代理会获取 secret 的更改。使用以下命令重启 pod:

    $ oc -n bookinfo 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 bookinfo

1.13.4.2. 验证您的证书

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

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

    $ sleep 60
    $ oc -n bookinfo 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}' bookinfo-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.4.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
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.