Istio Security提供了全面的安全解决方案。

Istio安全功能提供强大的身份,强大的策略,透明的TLS加密以及身份验证,授权和审核(AAA)工具,以保护您的服务和数据。 Istio安全性的目标是:

  • 默认情况下的安全性:无需更改应用程序代码和基础结构
  • 深度防御:与现有安全系统集成以提供多层防御
  • 零信任网络:在不受信任的网络上构建安全解决方案

架构

Istio中的安全涉及多个组件:

  • 证书颁发机构(CA),用于密钥和证书管理
  • 配置API服务器分发给代理:
  • 认证策略
  • 授权策略
  • 安全命名信息
  • Sidecar和边界代理充当策略执行点(PEP),以保护客户端和服务器之间的通信。
  • 一组Envoy代理扩展,用于管理遥测和审计

控制平面处理来自API服务器的配置,并在数据平面中配置PEP。 PEP是使用Envoy实现的。下图显示了体系结构。

身份

身份是任何安全基础结构的基本概念。在工作负载到工作负载的通信开始时,双方必须交换凭据与其身份信息以进行相互认证。在客户端,将根据安全命名信息检查服务器的身份,以查看其是否是工作负载的授权运行者。在服务器端,服务器可以根据授权策略确定客户端可以访问哪些信息,审核谁在什么时间访问了哪些信息,根据他们使用的工作负载向客户端收费,并拒绝任何未能支付账单的客户端访问工作量。
Istio身份模型使用一等的service identity来确定请求来源的身份。该模型为服务标识提供了极大的灵活性和粒度,以代表用户,单个工作负荷或一组工作负荷。在没有服务身份的平台上,Istio可以使用其他可以对工作负载实例进行分组的身份,例如服务名称。
以下列表显示了可以在不同平台上使用的服务身份的示例:

  • Kubernetes:Kubernetes服务帐户
  • GKE / GCE:GCP服务帐户
  • GCP:GCP服务帐户
  • AWS:AWS IAM用户/角色帐户
  • 本地(非Kubernetes)用户帐户,自定义服务帐户,服务名称,Istio服务帐户或GCP服务帐户。自定义服务帐户是指现有服务帐户,就像客户的身份目录管理的身份一样。

证书管理

Istio使用X.509证书为每个工作负载安全地设置强身份。与每个Envoy代理一起运行的Istio-agent与istiod一起工作,以自动实现密钥和证书的大规模轮换。下图显示了身份提供流程。

Istio使用以下流程通过secret discovery service (SDS)设置身份:

  1. Istiod提供了一个gRPC服务来接受证书签名请求(CSR)。
  2. Envoy通过Envoy SDS API发送证书和密钥请求。
  3. 收到SDS请求后,Istio agent会先创建私钥和CSR,然后再将CSR及其凭据发送给isidod进行签名。
  4. CA验证CSR中携带的凭据,并对CSR签名以生成证书。
  5. Istio agent通过Envoy SDS API将来自istiod的证书和私钥发送给Envoy。
  6. 对于证书和密钥轮换,上述CSR过程会定期执行。

认证

Istio提供了两种认证类型:

  • 对等身份验证: 用于服务到服务的身份验证,以验证建立连接的客户端。 Istio提供双向TLS作为用于传输身份验证的完整堆栈解决方案,无需更改服务代码即可启用它。 该解决方案为:
  • 为每个服务提供一个强大的标识,以表示其角色,以实现跨集群和云的互操作性。
  • 使服务到服务的通信安全。
  • 提供密钥管理系统以自动执行密钥和证书的生成,分发和轮换。
  • 请求认证: 用于最终用户身份验证,以验证附加到请求的凭据。 Istio使用JSON Web令牌(JWT)验证启用请求级身份验证,可以使用自定义身份验证程序或任何OpenID Connect实现程序, 例如:
  • ORY Hydra
  • Keycloak
  • Auth0
  • Firebase Auth
  • Google Auth

在所有情况下,Istio都会通过自定义的Kubernetes API将身份验证策略存储在Istio config store中。 Istiod会为每个代理保持最新状态,并在适当的地方提供密钥。此外,Istio支持许可模式下的身份验证,以帮助您了解策略更改在实施之前如何影响您的安全状况。

mTLS认证

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

  1. Istio将来自客户端的出站流量重新路由到客户端的本地Sidecar Envoy。
  2. 客户端Envoy与服务器端Envoy开始相互TLS握手。在握手期间,客户端Envoy还会进行安全的命名检查,以验证服务器证书中提供的服务帐户是否有权运行目标服务。
  3. 客户端Envoy和服务器端Envoy建立了双向TLS连接,Istio将流量从客户端Envoy转发到服务器端Envoy。
  4. 授权后,服务器端Envoy通过本地TCP连接将流量转发到服务器服务。

许可模式

Istio双向TLS具有允许模式,该模式允许服务同时接受纯文本流量和双向TLS流量。此功能极大地改善了双向TLS的启用体验。

当非Istio客户端与非Istio服务器通信时,当服务器准备启用mTLS的时候,这对运维来说,存在很大的问题。通常,运维无法同时为所有客户端安装Istio Sidecar,甚至没有权限在某些客户端上安装。即使在服务器上安装了Istio Sidecar之后,运维也无法在不中断现有通信的情况下启用双向TLS。

启用许可模式后,服务器将接受纯文本和双向TLS流量。该模式为启用过程提供了更大的灵活性。服务器安装的Istio Sidecar可以立即进行双向TLS流量,而不会破坏现有的纯文本流量。因此,运维可以逐步安装和配置客户端的Istio Sidecar,以发送双向的TLS流量。一旦完成客户端的配置,运维就可以将服务器配置为仅TLS双向模式。有关更多信息,请访问“双向TLS迁移”教程。

安全命名

服务器身份以证书编码,但是通过发现服务或DNS检索服务名称。安全命名信息将服务器身份映射到服务名称。身份A到服务名称B的映射意味着“ A被授权运行服务B”。控制平面监视apiserver,生成安全的命名映射,并将其安全地分发到PEP。以下示例说明了为什么安全命名对于身份验证至关重要。
假设运行服务数据存储的合法服务器仅使用团队内部身份。恶意用户拥有测试团队身份的证书和密钥。恶意用户打算模拟服务以检查从客户端发送的数据。恶意用户使用证书和测试团队身份的密钥来部署伪造的服务器。假设恶意用户成功劫持(通过DNS欺骗,BGP /路由劫持,ARP欺骗等)发送到数据存储区的流量并将其重定向到伪造的服务器。
客户端调用数据存储服务时,它会从服务器的证书中提取测试团队身份,并检查是否允许测试团队运行带有安全命名信息的数据存储。客户端检测到不允许测试团队运行数据存储服务,并且身份验证失败。
安全命名能够防止HTTPS流量受到一般网络劫持。它还可以保护TCP通信免受一般网络劫持。但是,安全命名无法防止DNS欺骗,因为在这种情况下,攻击者会劫持DNS并修改目标IP地址。这是因为TCP流量不包含主机名信息,我们只能依靠IP地址进行路由。实际上,此DNS劫持甚至可能在客户端Envoy

认证架构

您可以使用对等和请求身份验证策略为在Istio网格中接收请求的工作负载指定身份验证要求。网格运维使用.yaml文件来指定策略。部署后,策略将保存在Istio配置存储中。 Istio控制器监视配置存储。
在任何策略更改后,新策略都会转换为适当的配置,告诉PEP如何执行所需的身份验证机制。控制平面可以获取公共密钥,并将其附加到配置中以进行JWT验证。另外,Istiod提供了由Istio系统管理的密钥和证书的路径,并将它们安装到应用程序容器中以实现相互TLS。
Istio将配置异步发送到目标端点。代理收到配置后,新的身份验证要求将立即在该容器上生效。
客户端服务(发送请求的客户端服务)负责遵循必要的身份验证机制。对于请求认证,应用程序负责获取JWT凭证并将其附加到请求。对于对等身份验证,Istio会自动将两个PEP之间的所有流量升级到相互TLS。如果身份验证策略禁用了双向TLS模式,则Istio将继续在PEP之间使用纯文本。要覆盖此行为,请使用目标规则明确禁用双向TLS模式。

认证策略

本节提供有关Istio身份验证策略如何工作的更多详细信息。结合前面的架构部分,身份验证策略适用于服务收到的请求。要在双向TLS中指定客户端身份验证规则,您需要在DestinationRule中指定TLSSettings
与其他Istio配置一样,您可以在.yaml文件中指定身份验证策略。您使用kubectl部署策略。以下示例身份验证策略指定带有app:reviews标签的工作负载的传输身份验证必须使用双向TLS:

apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "example-peer-policy"
  namespace: "foo"
spec:
  selector:
    matchLabels:
      app: reviews
  mtls:
    mode: STRICT

策略存储

Istio将网格范围策略存储在根名称空间中。这些策略包含一个空选择器,适用于网格中的所有工作负载。具有命名空间范围的策略存储在相应的命名空间中。它们仅适用于其命名空间内的工作负载。如果配置选择器字段,则身份验证策略仅适用于与您配置的条件匹配的工作负载。
对等和请求身份验证策略按种类分别存储,分别为PeerAuthenticationRequestAuthentication

标签选择

对等和请求身份验证策略使用选择器字段来指定该策略适用的工作负载的标签。以下示例显示了适用于带有app:product-page标签的工作负载的策略的选择器字段:

selector:
  matchLabels:
    app: product-page

如果没有为选择器字段提供值,则Istio会将策略与策略存储范围内的所有工作负载进行匹配。因此,选择器字段可帮助您指定策略的范围:

  • 整个mesh级别的策略: 为根名称空间指定的策略,不带或带有空选择器字段。
  • 命名空间级别的策略: 为没有或没有空选择器字段的非根名称空间指定的策略。
  • 工作负载策略: 在常规名称空间中定义的策略,带有非空选择器字段。

对等和请求身份验证策略对选择器字段遵循相同的层次结构原则,但是Istio以稍微不同的方式组合并应用它们。

每个命名空间只能有一个网格范围的对等身份验证策略,并且只能有一个命名空间范围的对等身份验证策略。当您为同一网格或命名空间配置多个网格范围或命名空间范围的对等身份验证策略时,Istio会忽略较新的策略。当多个特定于工作负载的对等身份验证策略匹配时,Istio将选择最旧的策略。

Istio使用以下顺序为每个工作负载应用最窄的匹配策略:

  1. 工作负载策略
  2. 命名空间级别的策略
  3. 整个mesh级别的策略

Istio可以将所有匹配的请求身份验证策略组合起来,就像它们来自单个请求身份验证策略一样。因此,您可以在网格或命名空间中具有多个网格范围或命名空间范围的策略。但是,避免使用多个网格范围或命名空间范围的请求身份验证策略仍然是一个好习惯。

对等认证

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

  • PERMISSIVE: 工作负载接受双向TLS和纯文本流量。当没有Sidecar的工作负载无法使用双向TLS时,此模式在迁移过程中最有用。通过使用sidecar注入迁移工作负载后,您应该将模式切换为STRICT。
  • STRICT: 工作负载仅接受双向TLS通信。
  • DISABLE: 双向TLS已禁用。从安全角度来看,除非您提供自己的安全解决方案,否则不应使用此模式。

取消设置模式时,将继承父作用域的模式。默认情况下,未设置模式的网格范围对等身份验证策略使用PERMISSIVE模式。
以下对等身份验证策略要求名称空间foo中的所有工作负载都使用双向TLS:

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

上面的对等身份验证策略仅起作用是因为下面的服务配置将来自example-app工作负载的请求绑定到example-service的端口80:

apiVersion: v1
kind: Service
metadata:
  name: example-service
  namespace: foo
spec:
  ports:
  - name: http
    port: 8000
    protocol: TCP
    targetPort: 80
  selector:
    app: example-app

请求认证

请求身份验证策略指定验证JSON Web令牌(JWT)所需的值。这些值包括:

  • 令牌在请求中的位置
  • 请求的issuer
  • 公用JSON Web密钥集(JWKS)

Istio会根据请求身份验证策略中的规则检查提供的令牌(如果已提供),并拒绝具有无效令牌的请求。当请求不带有令牌时,默认情况下将接受它们。要拒绝没有令牌的请求,请提供授权规则,该规则指定对特定操作(例如,路径或操作)的限制。
如果请求认证策略使用唯一的位置,则它们可以指定多个JWT。当多个策略与工作负载匹配时,Istio会将所有规则组合起来,就好像它们被指定为单个策略一样。此行为对于编程工作负载以接受来自不同提供程序的JWT很有用。但是,不支持具有多个有效JWT的请求,因为此类请求的输出主体未定义。

授权

Istio的授权功能为网格中的工作负载提供了网格,命名空间和工作负载范围的访问控制。这种控制级别具有以下优点:

  • 工作负载到工作负载和最终用户工作负载授权。
  • 一个简单的API:它包括一个简单的AuthorizationPolicy CRD,它易于使用和维护。
  • 灵活的语义:运维可以在Istio属性上定义自定义条件,并使用DENY和ALLOW动作。
  • 高性能:Istio授权在Envoy上本地执行。
  • 高兼容性:本机支持gRPC,HTTP,HTTPS和HTTP2,以及任何普通的TCP协议。

架构

每个Envoy代理都运行一个授权引擎,该引擎在运行时对请求进行授权。当请求到达代理时,授权引擎会根据当前的授权策略评估请求上下文,并返回授权结果ALLOWDENY。运维使用.yaml文件指定Istio授权策略。

隐式启用

您无需明确启用Istio的授权功能。只需将授权策略应用于工作负载即可实施访问控制。对于未应用授权策略的工作负载,Istio不会强制执行允许所有请求的访问控制。

授权策略支持ALLOW和DENY动作。拒绝策略优先于允许策略。如果将任何允许策略应用于工作负载,则默认情况下将拒绝对该工作负载的访问,除非策略中的规则明确允许。当您将多个授权策略应用于同一工作负载时,Istio会将它们附加应用。

授权策略

要配置授权策略,请创建AuthorizationPolicy自定义资源。授权策略包括选择器,操作和规则列表:

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

以下示例显示了一个授权策略,该策略允许两个源(cluster.local/ns/default/sa/sleep服务帐户和dev名称空间)访问foo命名空间中具有app:httpbinversion:v1标签的工作负载,并且请求必须携带合法JWT token。

apiVersion: security.istio.io/v1beta1
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"]

以下示例显示了一个授权策略,如果源不是foo名称空间,该策略将拒绝请求:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin-deny
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: DENY
 rules:
 - from:
   - source:
       notNamespaces: ["foo"]

拒绝策略优先于允许策略。如果匹配允许策略的请求与拒绝策略匹配,则可以拒绝这些请求。 Istio首先评估拒绝政策,以确保允许政策不会绕过拒绝政策。

策略目标

您可以通过元数据/命名空间字段和可选的选择器字段来指定策略的范围或目标。策略适用于元数据/命名空间字段中的命名空间。如果将其值设置为根名称空间,则该策略将应用于网格中的所有命名空间。根命名空间的值是可配置的,默认值是istio-system。如果设置为任何其他命名空间,则该策略仅适用于指定的命名空间。
您可以使用选择器字段来进一步限制策略以应用于特定工作负载。选择器使用标签选择目标工作负载。选择器包含{key:value}对的列表,其中key是标签的名称。如果未设置,则授权策略将与授权策略应用于同一命名空间中的所有工作负载。
例如,允许读取策略允许使用默认命名空间中的app:products标签通过“ GET”和“ HEAD”访问工作负载。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-read
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
         methods: ["GET", "HEAD"] 

值匹配

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

  • 完全匹配:即完整的字符串匹配。
  • 前缀匹配:"*" 结尾的字符串。例如,"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/v1beta1
kind: AuthorizationPolicy
metadata:
  name: tester
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: ALLOW
  rules:
  - to:
    - operation:
        paths: ["/test/*", "*/info"]

排除匹配

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

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

apiVersion: security.istio.io/v1beta1
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: ["*"]

下面的示例拒绝到/admin路径且不带请求主体的请求:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: enable-jwt-for-admin
  namespace: default
spec:
  selector:
    matchLabels:
      app: products
  action: DENY
  rules:
  - to:
    - operation:
        paths: ["/admin"]
    from:
    - source:
        notRequestPrincipals: ["*"]

全部允许和默认全部拒绝授权策略

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

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

以下示例显示了一个策略,该策略不允许任何对 admin 命名空间工作负载的访问。

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

自定义条件

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

apiVersion: security.istio.io/v1beta1
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"]

条件页面中列出了支持的条件 key 值。

认证与未认证身份

如果要使工作负载可公开访问,则需要将 source 部分留空。这允许来自所有(经过认证和未经认证)的用户和工作负载的源,例如:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: ALLOW
 rules:
 - to:
   - operation:
       methods: ["GET", "POST"] 

要仅允许经过认证的用户,请将 principal 设置为 "*",例如:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: httpbin
 namespace: foo
spec:
 selector:
   matchLabels:
     app: httpbin
     version: v1
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["*"]
   to:
   - operation:
       methods: ["GET", "POST"]

在纯TCP协议上使用Istio授权

Istio授权使用任何简单的TCP协议(例如MongoDB)支持工作负载。在这种情况下,您可以按照与HTTP工作负载相同的方式配置授权策略。区别在于某些字段和条件仅适用于HTTP工作负载。这些字段包括:

  • 授权策略对象源部分的request_principals 字段
  • 授权策略对象操作部分的 hosts, methodspaths 字段

支持的条件可以在条​​件页面中查阅。如果将任何仅HTTP字段用于TCP工作负载,则Istio将忽略授权策略中的仅HTTP字段。

假设您在端口27017上具有MongoDB服务,以下示例将授权策略配置为仅允许Istio网格中的bookinfo-ratings-v2服务访问MongoDB工作负载。

apiVersion: "security.istio.io/v1beta1"
kind: AuthorizationPolicy
metadata:
  name: mongodb-policy
  namespace: default
spec:
 selector:
   matchLabels:
     app: mongodb
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/bookinfo-ratings-v2"]
   to:
   - operation:
       ports: ["27017"]

iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。