关于istio:Istio安全性

14次阅读

共计 11049 个字符,预计需要花费 28 分钟才能阅读完成。

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"]

正文完
 0