认证策略
通过上一部分认证架构可以了解到,认证策略是对服务收到的请求生效的。要在双向 TLS 中指定客户端认证策略,需要在 DetinationRule 中设置 TLSSettings。使用者可以通过yaml文件来编写认证策略,然后使用 istioctl 进行部署。
例如,要求 reviews 服务必须使用双向 TLS:
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "reviews"
spec:
targets:
- name: reviews
peers:
- mtls: {}
策略存储范围
Istio 可以在命名空间范围或Mesh范围存储中存储身份认证策略。
配置 MeshPolicy
,指定
Mesh
范围策略,名称为
default
:
apiVersion: "authentication.istio.io/v1alpha1"
kind: "MeshPolicy"
metadata:
name: "default"
spec:
peers:
- mtls: {}
配置Policy,指定命名空间范围策略。例如命名空间myns,如不指定,则是默认命名空间:
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: "myns"
spec:
peers:
- mtls: {}
命名空间范围存储中的策略只能影响同一命名空间中的服务。Mesh范围内的策略可以影响Mesh中的所有Istio服务。防止冲突和滥用,只能在Mesh范围存储中定义一个策略。该策略必须命名为 default 并且有一个空的 targets: 部分。
目标选择器
身份认证策略的目标指定策略适用于哪些服务。以下示例展示的是一个 targets: 部分,指定该策略适用于:
- product-page 服务,任意端口
- reviews服务,9000端口
targets:
- name: product-page
- name: reviews
ports:
- number: 9000
如果您未提供 targets: 部分,则 Istio 将策略与策略存储范围内的所有服务匹配。因此,targets: 部分可以帮助您指定策略的范围:
- Mesh范围策略:在Mesh范围存储中定义的策略,没有目标选择器部分。Mesh中最多只能有一个Mesh范围的策略。
- 命名空间范围的策略:在命名空间范围存储中定义的策略,名称为 default 且没有目标选择器部分。每个命名空间最多只能有一个命名空间范围的策略。
- 特定于服务的策略:在命名空间范围存储中定义的策略,具有非空目标选择器部分。命名空间可以具有零个,一个或多个特定于服务的策略。
对于每项服务,Istio 都应用最窄的匹配策略。顺序是:特定服务>命名空间范围>网格范围。如果多个特定于服务的策略与服务匹配,则 Istio 随机选择其中一个。运维人员在配置其策略时必须避免此类冲突。
值得注意的是,为了强制Mesh范围和命名空间范围的策略的唯一性,Istio 每个Mesh只接受一个身份认证策略,每个命名空间只接受一个身份认证策略。Istio 还要求Mesh范围和命名空间范围的策略具有特定名称 default。
传输认证
peers: 部分定义了策略中传输身份验证支持的身份验证方法和相关参数。该部分可以列出多个方法,并且只有一个方法必须满足认证才能通过。但是,从 Istio 0.7 版本开始,当前支持的唯一传输身份验证方法是双向 TLS。如果您不需要传输身份验证,请完全跳过此部分。使用双向 TLS 启用传输身份验证的 peers: 部分:
peers:
- mtls: {}
目前(Istio1.1),双向 TLS 设置不需要任何参数。因此,-mtls: {}、- mtls: 或 - mtls: null 声明被视为相同。将来,双向 TLS 设置可以携带参数以提供不同的双向 TLS 实现。
来源身份认证
origins: 部分定义了原始身份验证支持的身份验证方法和相关参数。Istio 仅支持 JWT 原始身份验证。策略支持多个JWT身份认证,与传输身份验证类似,必须满足身份验证才能通过。例如,该origin接受 Google 发布的 JWT:
origins:
- jwt:
issuer: "https://accounts.google.com"
jwksUri: "https://www.googleapis.com/oauth2/v3/certs"
主认证绑定
主认证关系用键值对的方式存储绑定关系。默认情况下,Istio 使用 peers: 部分中配置的身份验证。如果在 peers: 部分中未配置身份验证,Istio 将保留身份验证。策略编写者可以使用 USE_ORIGIN 值覆盖此行为。此值将 Istio 配置为使用 origin 的身份验证作为主体身份验证。将来,Istio将支持条件绑定,如,当传输体为 X 时为 USE_PEER,否则为 USE_ORIGIN。以下示例显示了 principalBinding 键,其值为 USE_ORIGIN:
principalBinding: USE_ORIGIN
更新认证策略
使用者可以随时更改身份认证策略。Istio 几乎实时地将更改推送到端点。但是,Istio 无法保证所有端点同时收到新策略。以下是在更新身份认证策略时避免中断的建议:
- 启用或禁用双向 TLS:使用带有 mode: 键和 PERMISSIVE 值的临时策略。这会将接收服务配置为接受两种类型的流量:纯文本和 TLS。因此,不会丢弃任何请求。一旦所有客户端切换到预期协议,无论是否有双向 TLS,您都可以将 PERMISSIVE 策略替换为最终策略。
- 对于 JWT 身份验证迁移:在更改策略之前,请求应包含新的 JWT。一旦服务器端完全切换到新策略,旧 JWT(如果有的话)可以被删除。需要更改客户端应用程序才能使这些更改生效。
peers:
- mtls:
mode: PERMISSIVE
授权策略
配置授权策略,需要指定两个Kubernetes CustomResourceDefinition( CRD)对象,ServiceRole 和 ServiceRoleBinding。
- ServiceRole 定义了一组访问服务的权限。
- ServiceRoleBinding 向特定主题授予 ServiceRole,例如用户、组或服务等。
ServiceRole 和 ServiceRoleBinding 的组合规定:允许谁在哪些条件下做什么。对应相关字段:
- 谁对应ServiceRoleBinding 中的 subject 部分。
- 做什么对应ServiceRole 中的 permissions 部分。
- 哪些条件对应ServiceRole 或 ServiceRoleBinding 中使用 Istio 属性指定的 conditions 部分。
ServiceRole
ServiceRole规范包括规则和权限列表等。每条规范的标准字段如下:
- services:服务名称列表。您可以将值设置为 * 以包括指定命名空间中的所有服务。
- methods:HTTP 方法名称列表,对于 gRPC 请求的权限,HTTP默认为POST。您可以将值设置为 * 以包含所有 HTTP 方法。
- paths:HTTP 路径或 gRPC 方法。 gRPC 方法必须采用 /packageName.serviceName/methodName 的形式,并且区分大小写。
ServiceRole 规范仅适用于 metadata 部分中指定的命名空间。规则中需要 services 和 methods 字段。 paths 是可选的。如果未指定规则或将其设置为 *,则它适用于任何实例。例如service-admin角色,以完全访问 default 命名空间中的所有服务:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: service-admin
namespace: default
spec:
rules:
- services: ["*"]
methods: ["*"]
products-viewer角色有读取权限,包括 GET 和 HEAD,能够访问 default 命名空间中的 products.default.svc.cluster.local 服务。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: products-viewer
namespace: default
spec:
rules:
- services: ["products.default.svc.cluster.local"]
methods: ["GET", "HEAD"]
此外,规则还支持所有字段的前缀匹配和后缀匹配。例如,您可以在 default命名空间中定义具有以下权限的 tester 角色:
- 完全访问前缀为 test-* 的所有服务,例如:test-bookstore、test-performance、test-api.default.svc.cluster.local。
- 读取(GET)使用 */reviews 后缀访问的所有路径,例如:在 bookstore .default.svc.cluster.local 服务中的 /books/reviews、/events/booksale/reviews、/reviews。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: tester
namespace: default
spec:
rules:
- services: ["test-*"]
methods: ["*"]
- services: ["bookstore.default.svc.cluster.local"]
paths: ["*/reviews"]
methods: ["GET"]
在 ServiceRole 中,namespace + services + paths + methods 的组合定义了如何访问服务。在某些情况下,您可能需要为规则指定其他条件。例如,规则可能仅适用于服务的某个版本,或仅适用于具有特定标签的服务,如 foo。您可以使用 constraints 轻松指定这些条件。
例如,下面的 ServiceRole 定义在以前的 products-viewer 角色基础之上添加了一个约束:request.headers[version] 为 v1 或 v2 。在约束和属性页面中列出了约束支持的 key 值。在属性值是 map 类型的情况下,例如 request.headers,key 是 map 中的一个条目,例如 request.headers[version]。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: products-viewer-version
namespace: default
spec:
rules:
- services: ["products.default.svc.cluster.local"]
methods: ["GET", "HEAD"]
constraints:
- key: request.headers[version]
values: ["v1", "v2"]
ServiceRoleBinding
ServiceRoleBinding 规范包括两部分:
- roleRef 指的是同一命名空间中的 ServiceRole 资源。
- subjects 分配给角色的列表。
您可以使用 user 或一组 properties 显式指定 *subject*。ServiceRoleBinding subject 中的 property 类似于 ServiceRole 规范中的 *constraint*。 property 还允许您使用条件指定分配给此角色的一组帐户。它包含一个 key 及其允许的*值*。约束支持的 key 值列在约束和属性页面中。
下面的例子显示了一个名为 test-binding-products 的 ServiceRoleBinding,它将两个 subject 绑定到名为 product-viewer 的 ServiceRole 并具有以下 subject
- 代表服务 a 的服务帐户,service-account-a。
- 代表 Ingress 服务的服务帐户 istio-ingress-service-account 并且 它的 JWT 中的 mail 项声明为 a@foo.com。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: test-binding-products
namespace: default
spec:
subjects:
- user: "service-account-a"
- user: "istio-ingress-service-account"
properties:
request.auth.claims[email]: "a@foo.com"
roleRef:
kind: ServiceRole
name: "products-viewer"
如果您想要公开访问服务,可以将 subject 设置为 user:"*" 。此值将 ServiceRole 分配给所有(经过身份验证和未经身份验证的)用户和服务,例如:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: binding-products-allusers
namespace: default
spec:
subjects:
- user: "*"
roleRef:
kind: ServiceRole
name: "products-viewer"
要将 ServiceRole 分配给经过身份验证的用户和服务,请使用 source.principal:"*" 代替,例如:
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
kind: ServiceRoleBinding
metadata:
name: binding-products-all-authenticated-users
namespace: default
spec:
subjects:
- properties:
source.principal: "*"
roleRef:
kind: ServiceRole
name: "products-viewer"
在普通 TCP 协议上使用 Istio 认证
Istio 授权支持使用任何普通 TCP 协议的 service,例如 MongoDB。在这种情况下,您可以像配置 HTTP 服务一样配置 service role 和 service role binding。不同之处在于,某些字段、约束和属性不支持TCP协议的service,这些字段包括:
- service role 配置对象中的 paths 和 methods 字段。
- service role binding 配置对象中的 group 字段。
如果你在TCP service 中使用了任意 HTTP 特有的字段,Istio将会忽略它。您有一个 MongoDB service 在 27017 端口上监听,下面的示例配置了一个 service role 和一个 service role binding,仅允许 Istio 网格中的 `bookinfo-ratings-v2 访问 MongoDB service。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: mongodb-viewer
namespace: default
spec:
rules:
- services: ["mongodb.default.svc.cluster.local"]
constraints:
- key: "destination.port"
values: ["27017"]
---
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: bind-mongodb-viewer
namespace: default
spec:
subjects:
- user: "cluster.local/ns/default/sa/bookinfo-ratings-v2"
roleRef:
kind: ServiceRole
name: "mongodb-viewer"
授权宽容模式
授权宽容模式(authorization permissive mode)是 Istio 1.1 发布版中的实验特性。其接口可能在未来的发布中发生变化,不建议在生产版本使用。授权宽容模式允许您在将授权策略提交到生产环境部署之前对其进行验证。
可以在全局授权配置和单个独立策略中启用授权宽容模式。如果在全局授权配置中设置,所有策略都将切换至授权宽容模式,不管其本身的模式。如果您设置全局授权模式为 ENFORCED,单个策略设置的强制模式将起作用。如果您没有设置任何模式,全局授权配置和单个策略都将默认被设置为 ENFORCED。
要全局启用宽容模式,将全局 Istio RBAC 授权配置中的 enforcement_mode: 设置为 PERMISSIVE,如下面的示例所示。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ClusterRbacConfig
metadata:
name: default
spec:
mode: 'ON_WITH_INCLUSION'
inclusion:
namespaces: ["default"]
enforcement_mode: PERMISSIVE
如要为特定策略启用宽容模式,请将策略配置文件中的 mode: 设置为 PERMISSIVE,如下面的示例所示。
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: bind-details-reviews
namespace: default
spec:
subjects:
- user: "cluster.local/ns/default/sa/bookinfo-productpage"
roleRef:
kind: ServiceRole
name: "details-reviews-viewer"
mode: PERMISSIVE
使用其他授权机制
虽然建议使用Istio 授权机制,但是Istio也支持其他授权插件,比如Mixer组件,它允许你插入自己的身份验证和授权机制。详情请了解Mixer使用和配置。