授权政策概览
与可在同一位置运行的单体式应用不同,全球分布式微服务应用会跨网络边界执行调用。这意味着应用的入口点越多,遭遇恶意攻击的机会就越多。由于 Kubernetes pod 使用临时 IP,因此基于 IP 的传统防火墙规则不足以保护工作负载之间的访问。微服务架构需要采用新的安全机制。Cloud Service Mesh 依托于 Kubernetes 服务账号和 Istio 安全政策等多种安全功能,并且提供了更多功能来帮助您保护应用。
本页面为应用运营人员提供了 AuthorizationPolicy
自定义资源 (CR) 概览。授权政策让您可以对应用 (L7) 和传输 (L3/4) 层的工作负载启用访问权限控制。您可以通过配置授权政策来指定权限,即允许服务或用户执行哪些操作?
授权政策
默认情况下,系统允许网格中服务之间(以及最终用户与服务之间)的请求。您可以使用 AuthorizationPolicy
CR 为您的工作负载定义细化政策。应用授权政策后,Cloud Service Mesh 会将这些政策分发给 Sidecar 代理。当请求进入工作负载时,边车代理会检查授权政策,以确定应允许还是拒绝请求。
政策范围
您可以将政策应用于整个服务网格,也可以应用一个命名空间或单个工作负载。
如需应用网格级别的政策,请在
metadata:namespace
字段中指定根命名空间istio-system
:apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "mesh-wide" namespace: istio-system spec: ...
如需将政策应用于命名空间,请在
metadata:namespace
字段中指定命名空间:apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "currencyservice" namespace: currencyservice spec: ...
如需将政策限制于特定工作负载,请添加
selector
字段。apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "frontend" namespace: demo spec: selector: matchLabels: app: frontend ...
基本结构
授权政策包括政策的应用范围、一个 action
和一个 rules
列表:
如上一节中所述,政策的应用范围可以是整个网格、一个命名空间或特定工作负载。如果您添加了
selector
字段,则此字段会指定政策的目标。action
字段指定是ALLOW
还是DENY
请求。如果您未指定操作,则操作默认设置为ALLOW
。为清晰起见,我们建议您始终指定操作。(授权政策还支持AUDIT
和CUSTOM
操作)。rules
指定何时触发操作。
在以下示例中:
政策应用于对
demo
命名空间中frontend
服务发出的请求。如果请求标头中包含“hello:world”,则允许请求;否则,拒绝请求。
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "hello-world"
namespace: demo
spec:
selector:
matchLabels:
app: frontend
action: ALLOW
rules:
- when:
- key: request.headers[hello]
values: ["world"]
对于请求操作的访问权限控制
您可以通过在 rules
下添加 to
部分来控制对特定请求操作(如 HTTP 方法或 TCP 端口)的访问权限。在以下示例中,仅允许 GET
和 POST
HTTP 方法用于 demo
命名空间中的 currencyservice
。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: currencyservice
namespace: demo
spec:
selector:
matchLabels:
app: currencyservice
action: ALLOW
rules:
- to:
- operation:
methods: ["GET", "POST"]
对于经过身份验证的身份的访问权限控制
在前面的示例中,政策允许来自未经身份验证的工作负载的请求。如果您已启用 STRICT
双向 TLS (mTLS),则可以根据 source
部分中请求来自的工作负载或命名空间的身份限制访问权限。
使用
principals
或notPrincipal
字段可控制工作负载级层的访问权限。使用
namespaces
或notNamespaces
字段可控制命名空间级层的访问权限。
以上所有字段都要求您已启用 STRICT
mTLS。如果您无法设置 STRICT
mTLS,请参阅拒绝明文请求以获取替代解决方案。
确定的工作负载
在以下示例中,仅允许从 frontend
服务发出对于 currencyservice
的请求。如果从其他工作负载发出对于 currencyservice
的请求,则会被系统拒绝。
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "currencyservice"
namespace: demo
spec:
selector:
matchLabels:
app: currencyservice
action: ALLOW
rules:
- from:
- source:
principals: ["example-project-1234.svc.id.goog/ns/demo/sa/frontend-sa"]
如需指定服务账号,Cloud Service Mesh 证书授权机构 (Mesh CA) 和 Certificate Authority Service (CA Service) 的 principals
必须采用以下格式:
principals: ["PROJECT_ID.svc.id.goog/ns/NAMESPACE/sa/SERVICE_ACCOUNT_NAME"]
PROJECT_ID.svc.id.goog
是 Mesh CA 的信任网域。如果您使用的是 Istio CA(以前称为 Citadel),则默认信任网域为 cluster.local
。
确定的命名空间
以下示例展示了一项政策,如果来源不是 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"]
值匹配
授权政策中的大多数字段都支持以下全部匹配架构:
- 完全匹配:字符串完全匹配。
- 使用
"*"
通配符的通配符匹配:- 前缀匹配:以
"*"
结尾的字符串。例如,"test.example.*"
与"test.example.com"
或"test.example.com.cn"
匹配。 - 后缀匹配:以
"*"
开头的字符串。例如,"*.example.com"
与"eng.example.com"
或"test.eng.example.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
字段中的 notValues
、source
字段中的 notIpBlocks
和 to
字段中的 notPorts
,Cloud Service Mesh 支持排除匹配。以下示例需要有效的请求 principals
,该请求源自 JWT 身份验证(如果请求路径不是 /healthz
)。因此,该政策会从 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: ["*"]
拒绝明文请求
在 Cloud Service Mesh 中,自动 mTLS 默认处于启用状态。通过自动 mTLS,客户端边车代理会自动检测服务器是否具有 Sidecar。客户端 Sidecar 会将 mTLS 发送到具有 Sidecar 的工作负载,并将纯文本流量发送到没有 Sidecar 的工作负载。为获得最佳安全性,我们建议您启用 STRICT mTLS。
如果您无法为工作负载或命名空间启用 STRICT
模式的 mTLS,您可以:
- 创建授权政策,以明确允许具有非空
namespaces
或非空principals
的流量,或者 - 拒绝具有空
namespaces
或principals
的流量。
由于 namespaces
和 principals
只能通过 mTLS 请求进行提取,因此这些政策实际上会拒绝任何明文流量。
如果请求中的正文为空(明文请求就属于这种情况),则以下政策会拒绝请求。如果主体不为空,则该政策会允许请求。["*"]
表示非空匹配项,如果使用 notPrincipals
,则表示匹配空主体。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-mtls
namespace: NAMESPACE
spec:
action: DENY
rules:
- from:
- source:
notPrincipals: ["*"]
授权政策优先级
您可以配置单独的 ALLOW
和 DENY
授权政策,但您需要了解政策优先级和默认行为,以确保这些政策符合您的要求。下图说明了政策优先级。
以下部分中的示例政策说明了一些默认行为以及一些可能有用的场景。
全部不允许
以下示例展示了与任何内容都不匹配的 ALLOW
政策。默认情况下,如果没有其他 ALLOW
政策,则请求会始终被拒绝。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-nothing
spec:
action: ALLOW
一个不错的安全做法是先从“全部不允许”政策开始,然后逐步添加更多 ALLOW
政策,从而开放更多对工作负载的访问权限。
拒绝所有访问
以下示例展示了匹配所有内容的一个 DENY
政策。由于 DENY
政策会先于 ALLOW
政策进行评估,因此即使有与请求匹配的 ALLOW
政策,所有请求也会遭到拒绝。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
spec:
action: DENY
rules:
- {}
如果您要暂时停用对工作负载的所有访问权限,则“全部拒绝”政策非常有用。
允许所有访问
以下示例展示了一个与所有内容都匹配且允许对工作负载的完整访问权限的 ALLOW
政策。“全部允许”政策会使其他 ALLOW
政策毫无用处,因为该政策始终允许请求。
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-all
spec:
action: ALLOW
rules:
- {}
如果要暂时公开对工作负载的完整访问权限,则“全部允许”政策非常有用。如果存在任何 DENY
政策,则请求可能仍会被拒绝,因为 DENY
政策在 ALLOW
政策之前评估。
最佳做法
为每个服务创建一个 Kubernetes 服务账号,并在 Deployment 中指定服务账号。例如:
apiVersion: v1 kind: ServiceAccount metadata: name: frontend-sa namespace: demo --- apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace:demo spec: selector: matchLabels: app: frontend template: metadata: labels: app: frontend spec: serviceAccountName: frontend-sa ...
从“全部不允许”政策开始,逐步添加更多
ALLOW
政策,从而开放更多对工作负载的访问权限。如果您为服务使用 JWT,请执行以下操作:
创建
DENY
政策以阻止未经身份验证的请求,例如:apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: requireJWT namespace: admin spec: action: DENY rules: - from: - source: notRequestPrincipals: ["*"]
应用“全部不允许”政策。
为每个工作负载定义
ALLOW
政策。如需查看示例,请参阅 JWT 令牌。
后续步骤
详细了解 Cloud Service Mesh 安全功能:
- 配置 Cloud Service Mesh 用户身份验证
- 为服务配置审核政策
- 配置传输安全
- 将 Identity-Aware Proxy 与 Cloud Service Mesh 集成
- 在 GKE 集群上使用 Cloud Service Mesh 出站流量网关的最佳实践
详细了解 Istio 文档中的授权政策: