Istio详细使用-安全(三)

Istio详细使用-安全(二)

上篇介绍了流量分发管理、熔断、发布等使用,本章主要介绍了Istio的安全认证以及授权策略。

Istio安全的三大目标:

  • 默认安全(Security by default):应用程序代码和基础结构无需更改。
  • 深度防御(Defense in depth):与现有安全系统集成,提供多层防御。
  • 零信任网络(Zero-trust network):在不受信的网络上,构建安全解决方案。

1. 上层架构

Istio的安全性涉及多个部分:

  • 用于密钥和证书管理的证书颁发机构(CA)
  • 配置API服务器分发给代理
    • 认证策略
    • 鉴权策略
    • 安全命名信息
  • 作为策略执行点的僚机和参数代理,用于客户端和服务端之间的安全通信
  • 一组用于管理遥测和审计的代理扩展

2. Istio 身份

身份是任何安全基础架构的基本概念。在工作负载间通信开始时, 双方必须交换包含身份信息的凭证以进行双向验证。在客户端, 根据安全命名信息检查服务器的标识, 以查看它是否是工作负载授权的运行程序。在服务器端, 服务器可以根据授权策略确定客户端可以访问哪些信息。

Istio 身份模型使用经典的 service identity(服务身份)来确定一个请求源端的身份。可以更灵活,细粒度地表示用户、工作负载或一组负载。

3. 身份和凭证管理

Istio使用X.509提供强身份识别。Istio代理,和Envoy一起运行,配合Istiod一起完成自动化大规模的密钥和证书轮换。

Istio 通过以下流程提供密钥和证书:

  1. istiod 提供 gRPC 服务以接受证书签名请求(CSR)。
  2. istio-agent 在启动时创建私钥和 CSR,然后将 CSR 及其凭据发送到 istiod 进行签名。
  3. istiod CA 验证 CSR 中携带的凭据,成功验证后签署 CSR 以生成证书。
  4. 当工作负载启动时,Envoy 通过 Secret 发现服务(SDS)API 向同容器内的 istio-agent 发送证书和密钥请求。
  5. istio-agent 通过 Envoy SDS API 将从 istiod 收到的证书和密钥发送给 Envoy。
  6. istio-agent 监控工作负载证书的过期时间。上述过程会定期重复进行证书和密钥轮换。

4. 认证

istio有两种认证类型:

  • peer authentication:同行认证用于服务见通信时认证发起连接的客户端。使用双向TLS加密作为全栈解决方案。
  • request authentication:校验请求中携带的凭证认证终端用户。Istio支持JWT认证,以及一些OIDC供应商的定制话认证。
    在所有情况下,Istio 都通过自定义 Kubernetes API 将认证策略存储在 Istio config store。 Istiod 使每个代理保持最新状态, 并在适当时提供密钥。此外,Istio 的认证机制支持宽容模式(permissive mode), 以帮助您在强制实施前了解策略更改将如何影响您的安全状况。

4.1 双向 TLS 认证

Istio 通过客户端和服务器端 PEP 建立服务到服务的通信通道, PEP 被实现为 Envoy 代理。 当一个工作负载使用双向 TLS 认证向另一个工作负载发送请求时, 该请求的处理方式如下:

  1. Istio 将出站流量从客户端重新路由到客户端的本地 Sidecar Envoy。
  2. 客户端 Envoy 与服务器端 Envoy 开始双向 TLS 握手。在握手期间, 客户端 Envoy 还做了安全命名检查, 以验证服务器证书中显示的服务帐户是否被授权运行目标服务。
  3. 客户端 Envoy 和服务器端 Envoy 建立了一个双向的 TLS 连接,Istio 将流量从客户端 Envoy 转发到服务器端 Envoy。
  4. 服务器端 Envoy 授权请求。如果获得授权,它将流量转发到通过本地 TCP 连接的后端服务

4.1.1 宽容模式

Istio 双向 TLS 具有一个宽容模式(permissive mode), 允许服务同时接受纯文本流量和双向 TLS 流量。这个功能极大地提升了双向 TLS 的入门体验。

在运维人员希望将服务移植到启用了双向 TLS 的 Istio 上时, 许多非 Istio 客户端与非 Istio 服务器端之间的通信会产生问题。 通常情况下,运维人员无法同时为所有客户端安装 Istio Sidecar, 甚至在某些客户端上没有这样做的权限。即使在服务器端上安装了 Istio Sidecar, 运维人员也无法在不中断现有连接的情况下启用双向 TLS。

4.2 认证策略

4.2.1 对等认证

对等认证策略指定 Istio 对目标工作负载实施的双向 TLS 模式。支持以下模式:

  • PERMISSIVE:工作负载接受双向 TLS 和纯文本流量。 此模式在迁移因为没有 Sidecar 而无法使用双向 TLS 的工作负载的过程中非常有用。 一旦工作负载完成 Sidecar 注入的迁移,应将模式切换为 STRICT。
  • STRICT:工作负载仅接收双向 TLS 流量。
  • DISABLE:禁用双向 TLS。从安全角度来看,除非您提供自己的安全解决方案,否则请勿使用此模式。

如果模式为 unset,将继承父作用域的模式。unset 模式的网格范围的对等认证策略默认使用 PERMISSIVE 模式。

# https://istio.io/latest/zh/docs/reference/config/security/peer_authentication/
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "example-policy"
  namespace: "foo"
spec:
  mtls:
    mode: STRICT

对于特定于工作负载的对等认证策略,可以为不同的端口指定不同的双向 TLS 模式。 您只能将端口范围的双向 TLS 配置在工作负载声明过的端口上。 以下示例为 app:example-app 工作负载禁用了端口 80 上的双向 TLS, 并对所有其他端口使用命名空间范围的对等认证策略的双向 TLS 设置:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: "example-workload-policy"
  namespace: "foo"
spec:
  selector:
     matchLabels:
       app: example-app
  portLevelMtls:
    80:
      mode: DISABLE

4.2.2 请求认证

请求认证策略指定验证 JSON Web Token(JWT)所需的值。这些值包括:

  • token 在请求中的位置
  • 请求的 issuer
  • 公共 JSON Web Key Set(JWKS)
# https://istio.io/latest/zh/docs/reference/config/security/request_authentication/
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: httpbin
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  jwtRules:
  - issuer: "issuer-foo"
    jwksUri: https://example.com/.well-known/jwks.json
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: httpbin
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  rules:
  - from:
    - source:
        requestPrincipals: ["*"]

5. 授权

Istio 的授权功能为网格中的工作负载提供网格、 命名空间和工作负载级别的访问控制。

5.1 架构

授权策略对服务器端 Envoy 代理的入站流量实施访问控制。 每个 Envoy 代理都运行一个授权引擎,该引擎在运行时授权请求。 当请求到达代理时,授权引擎根据当前授权策略评估请求上下文, 并返回授权结果 ALLOWDENY。 运维人员使用 .yaml 文件指定 Istio 授权策略。

5.2 策略逻辑

stio 按以下顺序检查层中的匹配策略:CUSTOMDENY, 然后是 ALLOW。对于每种类型的操作,Istio 首先检查是否有策略的操作已被应用, 然后检查请求是否匹配策略的规则。如果请求与其中一层中的策略不匹配, 则检查将继续到下一层。

5.3 授权策略

要配置授权策略,请创建一个 AuthorizationPolicy 自定义资源。 一个授权策略包括选择器(selector)、动作(action)和一个规则(rules)列表:

  • selector 字段指定策略的目标
  • action 字段指定允许还是拒绝请求
  • rules 指定何时触发动作
    • rules 下的 from 字段指定请求的来源
    • rules 下的 to 字段指定请求的操作
    • rules 下的 when 字段指定应用规则所需的条件

5.3.1 策略目标

以下示例显示了一个授权策略,该策略允许两个源(服务帐户 cluster.local/ns/default/sa/sleep 和命名空间 dev),在使用有效的 JWT 令牌发送请求时,可以访问命名空间 foo 中带有标签 app: httpbinversion: v1 的工作负载。

# https://istio.io/latest/zh/docs/reference/config/security/authorization-policy/
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/sleep"]
   - source:
       namespaces: ["dev"]
   to:
   - operation:
       methods: ["GET"]
   when:
   - key: request.auth.claims[iss]
     values: ["https://accounts.google.com"]

5.3.2 值匹配

授权策略中的大多数字段都支持以下所有匹配模式:

  • 完全匹配:即完整的字符串匹配。
  • 前缀匹配:"*" 结尾的字符串。例如,"test.abc.*" 匹配 "test.abc.com""test.abc.com.cn""test.abc.org" 等等。
  • 后缀匹配:"*" 开头的字符串。例如,"*.abc.com" 匹配 "eng.abc.com""test.eng.abc.com" 等等。
  • 存在匹配:* 用于指定非空的任意内容。您可以使用格式 fieldname: ["*"] 指定必须存在的字段。这意味着该字段可以匹配任意内容,但是不能为空。 请注意这与不指定字段不同,后者意味着匹配包括空的任意内容。

有一些例外。例如,以下字段仅支持完全匹配:

  • when 部分下的 key 字段
  • source 部分下的 ipBlocks
  • to 部分下的 ports 字段

以下示例策略允许访问前缀为 /test/* 或后缀为 */info 的路径。

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

5.3.3 排除匹配

为了匹配诸如 when 字段中的 notValuessource 字段中的 notIpBlocksto 字段中的 notPorts 之类的否定条件,Istio 支持排除匹配。

以下示例:如果请求路径不是 /healthz,则要求从请求的 JWT 认证中导出的主体是有效的。 因此,该策略从 JWT 身份验证中排除对 /healthz 路径的请求:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: disable-jwt-for-healthz
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        notPaths: ["/healthz"]
    from:
    - source:
        requestPrincipals: ["*"]

5.3.4 自定义条件

您还可以使用 when 部分指定其他条件。 例如,下面的 AuthorizationPolicy 定义包括以下条件: request.headers [version]v1v2。 在这种情况下,key 是 request.headers [version], 它是 Istio 属性 request.headers(这是个字典)中的一项。

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/sleep"]
   to:
   - operation:
       methods: ["GET"]
   when:
   - key: request.headers[version]
     values: ["v1", "v2"]

   转载规则


《Istio详细使用-安全(三)》 by XieJiayi is licensed under a 知识共享署名 4.0 国际许可协议 许可协议。转载请注明来源
 上一篇
K8s的Operator开发(一) K8s的Operator开发(一)
Kubernetes Operator 开发教程(一) 简介:以前开发Operator是以部分开发身份参与,因此想通过一个完整的实例来梳理Operator完整的开发逻辑,因此这次想采用“统一权限控制中心”来定义这个资源,主要控制了k8s的s
下一篇 
Istio详细使用-流量管理(二) Istio详细使用-流量管理(二)
Istio详细使用-流量管理(二)上篇介绍了istio的基础和网关的安装,以及bookInfo的应用用例安装,接下来介绍流量管理,比如熔断器、超时和重试,并且能轻松的设置重要的任务, 如 A/B 测试、金丝雀发布、基于流量百分比切分的分阶段
2023-08-08
  目录