Knative Eventing 授权¶
追踪问题: #7256
概述¶
在 Knative Eventing 中保护事件传递对于防止未经授权的访问至关重要。为了对事件传递实施精细控制,Knative Eventing 引入了 EventPolicy 自定义资源,允许用户指定哪些实体被授权向命名空间内的特定消费者发送事件。
先决条件¶
- Eventing安装
authentication-oidc功能需要启用。
注意
如 authentication-oidc 中所述,为实现安全认证,transport-encryption 也应启用。请参阅 传输加密,其中解释了如何启用传输加密功能标志。
兼容性¶
授权目前支持以下组件
- Broker
- Channel
- 流
- 其他
默认授权模式¶
管理员可以使用 defaultAuthorizationMode 功能标志设置默认授权模式,当没有 EventPolicy 适用于资源时,Knative Eventing 将使用该模式。可用模式为
allow-all: 允许所有请求。deny-all: 拒绝所有请求,强制创建 EventPolicies。allow-same-namespace: 仅允许来自同一命名空间内主体的请求。(默认)
定义 EventPolicy¶
EventPolicy 通过指定允许哪些主体(服务账户或事件源)向指定事件消费者发送事件来定义事件传递规则。
apiVersion: eventing.knative.dev/v1alpha1
kind: EventPolicy
metadata:
name: my-event-policy
namespace: default
spec:
to:
- ref:
apiVersion: eventing.knative.dev/v1
kind: Broker
name: my-broker
- selector:
apiVersion: eventing.knative.dev/v1
kind: Broker
matchLabels:
app: special-app
from:
- ref:
apiVersion: sources.knative.dev/v1
kind: PingSource
name: my-source
namespace: another-namespace
- sub: system:serviceaccount:default:trusted-app
- sub: "system:serviceaccount:default:other-*"
filters:
- cesql: "type IN ('order.created', 'order.updated', 'order.canceled')"
- exact:
type: com.github.push
指定 EventPolicy 适用的对象¶
.spec.to 部分指定允许事件发送到哪里。此字段是可选的;如果留空,则策略适用于命名空间内的所有资源。通过在 .spec.to 中指定多个目标,EventPolicies 的范围会通过将相同的规则应用于多个目标而扩大。
有两种方法可以定义这些目标
to.ref:- 定义:直接引用特定资源。
- 示例:在上面的
EventPolicy中,直接引用了my-brokerBroker。这意味着EventPolicy适用于此特定Broker。 - 用例:当您想按名称保护特定资源时,使用
to.ref。to: - ref: apiVersion: eventing.knative.dev/v1 kind: Broker name: my-broker
-
to.selector:- 定义:使用标签选择器匹配特定类型的多个资源。
- 示例:
EventPolicy包含一个带有标签匹配app: special-app的Broker。这意味着EventPolicy适用于所有具有这些标签的Broker。 - 用例:当您希望
EventPolicy适用于共享公共标签的一组资源时,使用to.selector。
to: - selector: apiVersion: eventing.knative.dev/v1 kind: Broker matchLabels: app: special-app
指定允许谁发送事件¶
.spec.from 部分指定允许谁将事件发送到 .spec.to 中定义的目标。有两种方法可以定义这些来源
-
from.ref:- 定义:直接引用特定的事件源资源。
- 示例:引用了
another-namespace中的my-sourcePingSource,这意味着此特定来源被允许发送事件。 - 用例:当您想授权特定的事件源时,使用
from.ref。from: - ref: apiVersion: sources.knative.dev/v1 kind: PingSource name: my-source namespace: another-namespace
-
from.sub:- 定义:指定允许发送事件的主体(服务账户名称)。它可以包含通配符模式作为后缀 (
*) 以进行更广泛的匹配。 - 示例:
EventPolicy允许来自默认命名空间中trusted-app服务账户的事件,以及默认命名空间中以other-开头的任何服务账户的事件。 - 用例:使用
from.sub允许特定用户或服务账户,或应用通配符模式以获得更大的灵活性。from: - sub: system:serviceaccount:default:trusted-app - sub: "system:serviceaccount:default:other-*"
- 定义:指定允许发送事件的主体(服务账户名称)。它可以包含通配符模式作为后缀 (
高级 CloudEvent 过滤条件¶
.spec.filters 部分是可选的,并指定事件本身必须满足的其他允许条件。
- 示例: 仅允许
type等于com.github.push且匹配特定 CESQL 表达式的 CloudEvents。 - 用例: 当您想对允许的 CloudEvents 有更精细的条件时,使用
filters。from: filters: - cesql: "type IN ('order.created', 'order.updated', 'order.canceled')" - exact: type: com.github.push
如果指定了过滤器,则事件必须匹配 EventPolicy 的所有指定过滤器(除了其 .spec.from)才能被接受。.spec.filters 接受与 触发器 相同的过滤方言。
注意
过滤器除了 .spec.from 之外也适用。这意味着,一旦 EventPolicy 指定了 .spec.filters,它们必须匹配请求,以及 .spec.from (AND 运算符)。只有这样,EventPolicy 才允许请求。
.spec 字段摘要:¶
to.ref针对特定资源。to.selector根据标签针对一组资源。from.ref授权特定的事件源资源。from.sub授权特定用户、服务账户或账户模式。.spec.filters允许定义高级 CloudEvent 过滤条件
EventPolicy 状态¶
EventPolicy 的状态提供有关已解析来源和就绪情况的信息
status:
from:
- system:serviceaccount:default:my-source-oidc-sources.knative.dev-pingsource
- system:serviceaccount:default:trusted-app
- "system:serviceaccount:default:other-*"
conditions:
- type: Ready
status: "True"
- type: SubjectsResolved
status: "True"
将 EventPolicies 应用于资源¶
事件消费者,例如 Broker,将在其状态中列出应用的 EventPolicies
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
name: my-broker
spec:
...
status:
...
policies:
- name: my-event-policy
apiVersion: v1alpha1
conditions:
- type: Ready
status: "True"
- type: EventPoliciesReady
status: "True"
EventPoliciesReady 条件指示资源的所有适用 EventPolicies 是否已就绪并已成功应用。
拒绝行为¶
如果请求未能通过任何适用的 EventPolicy,它将以 403 Forbidden HTTP 状态码被拒绝,确保未经授权的事件传递被阻止。如果多个策略适用于同一资源,只要事件匹配至少一个适用的 EventPolicies,事件就会被传递。这确保了即使存在严格策略,符合任何策略条件的有效事件仍然可以被处理。
示例¶
接下来,我们将提供一个完整的示例,说明如何为资源配置授权。在此示例中,我们希望通过只允许来自不同命名空间 (namespace-2) 中的 PingSource (pingsource-2) 的请求来保护 namespace-1 中的 Broker (broker)。

首先我们创建命名空间、Broker 和 PingSources
apiVersion: v1
kind: Namespace
metadata:
name: namespace-1
---
apiVersion: v1
kind: Namespace
metadata:
name: namespace-2
---
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
name: broker
namespace: namespace-1
---
apiVersion: sources.knative.dev/v1
kind: PingSource
metadata:
name: pingsource-1
namespace: namespace-1
spec:
data: '{"message": "Hi from pingsource-1 from namespace-1"}'
schedule: '*/1 * * * *'
sink:
ref:
apiVersion: eventing.knative.dev/v1
kind: Broker
name: broker
namespace: namespace-1
---
apiVersion: sources.knative.dev/v1
kind: PingSource
metadata:
name: pingsource-2
namespace: namespace-2
spec:
data: '{"message": "Hi from pingsource-2 from namespace-2"}'
schedule: '*/1 * * * *'
sink:
ref:
apiVersion: eventing.knative.dev/v1
kind: Broker
name: broker
namespace: namespace-1
为了调试,我们还创建了一个事件显示 Kservice 和 Trigger
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: event-display
namespace: namespace-1
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/min-scale: "1"
spec:
containers:
- image: gcr.io/knative-releases/knative.dev/eventing/cmd/event_display
---
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
name: trigger
namespace: namespace-1
spec:
broker: broker
subscriber:
ref:
apiVersion: serving.knative.dev/v1
kind: Service
name: event-display
只要 OIDC 被禁用且没有 EventPolicy,我们应该在事件显示 kservice 中看到来自两个 PingSources 的事件
$ kubectl -n namespace-1 logs event-display-00001-deployment-56cd8dd644-64xl2
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: dev.knative.sources.ping
source: /apis/v1/namespaces/namespace-1/pingsources/pingsource-1
id: 79d7a363-798d-40e2-b95c-6e007c81b05b
time: 2024-08-28T11:33:00.168602384Z
Extensions,
knativearrivaltime: 2024-08-28T11:33:00.194124454Z
Data,
{"message": "Hi from pingsource-1 from namespace-1"}
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: dev.knative.sources.ping
source: /apis/v1/namespaces/namespace-2/pingsources/pingsource-2
id: 94cfefc6-57aa-471c-9ce5-1d8c61370c7e
time: 2024-08-28T11:33:00.287533878Z
Extensions,
knativearrivaltime: 2024-08-28T11:33:00.296630315Z
Data,
{"message": "Hi from pingsource-2 from namespace-2"}
现在启用 OIDC
$ kubectl -n knative-eventing patch cm config-features --type merge --patch '{"data":{"authentication-oidc":"enabled"}}'
并创建以下 EventPolicy
apiVersion: eventing.knative.dev/v1alpha1
kind: EventPolicy
metadata:
name: event-policy
namespace: namespace-1
spec:
to:
- ref:
apiVersion: eventing.knative.dev/v1
kind: Broker
name: broker
from:
- ref:
apiVersion: sources.knative.dev/v1
kind: PingSource
name: pingsource-2
namespace: namespace-2
之后,您可以在 Broker 的状态中看到此 EventPolicy 已应用于它
$ kubectl -n namespace-1 get broker broker -o yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
name: broker
namespace: namespace-1
...
spec:
...
status:
...
conditions:
...
- lastTransitionTime: "2024-08-28T11:53:48Z"
status: "True"
type: EventPoliciesReady
- lastTransitionTime: "2024-08-28T11:26:16Z"
status: "True"
type: Ready
policies:
- apiVersion: eventing.knative.dev/v1alpha1
name: event-policy
在事件显示中,您应该只看到来自 pingsource-2 的事件,因为我们在 EventPolicy event-policy 中引用了它,允许它向 Broker broker 发送事件
$ kubectl -n namespace-1 logs event-display-00001-deployment-56cd8dd644-64xl2
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: dev.knative.sources.ping
source: /apis/v1/namespaces/namespace-2/pingsources/pingsource-2
id: c0b4f5f2-5f95-4c0b-a3c6-6f61b6581a4b
time: 2024-08-28T11:56:00.200782358Z
Extensions,
knativearrivaltime: 2024-08-28T11:56:00.20834826Z
Data,
{"message": "Hi from pingsource-2 from namespace-2"}
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: dev.knative.sources.ping
source: /apis/v1/namespaces/namespace-2/pingsources/pingsource-2
id: 6ab79fb0-2cf6-42a0-a43e-6bcd172558e5
time: 2024-08-28T11:57:00.075390777Z
Extensions,
knativearrivaltime: 2024-08-28T11:57:00.096497595Z
Data,
{"message": "Hi from pingsource-2 from namespace-2"}
现在我们再次删除 EventPolicy 并保持 OIDC 启用,Broker 将回退到默认授权模式,即 allow-same-namespace
$ kubectl -n namespace-1 delete eventpolicy event-policy
这也应该反映在 Broker 的状态中
$ kubectl -n namespace-1 get broker broker -o yaml
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
name: broker
namespace: namespace-1
...
spec:
...
status:
...
conditions:
...
- lastTransitionTime: "2024-08-28T12:00:00Z"
message: Default authz mode is "Allow-Same-Namespace
reason: DefaultAuthorizationMode
status: "True"
type: EventPoliciesReady
- lastTransitionTime: "2024-08-28T11:26:16Z"
status: "True"
type: Ready
我们应该在事件显示中只看到来自 pingsource-1 的事件,因为 pingsource-1 与 broker 在同一命名空间中
$ kubectl -n namespace-1 logs event-display-00001-deployment-56cd8dd644-64xl2
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: dev.knative.sources.ping
source: /apis/v1/namespaces/namespace-1/pingsources/pingsource-1
id: cd173aef-373a-4f2b-915e-43c138ac0602
time: 2024-08-28T12:01:00.2504715Z
Extensions,
knativearrivaltime: 2024-08-28T12:01:00.276151088Z
Data,
{"message": "Hi from pingsource-1 from namespace-1"}
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: dev.knative.sources.ping
source: /apis/v1/namespaces/namespace-1/pingsources/pingsource-1
id: 22665003-fe81-4203-8896-89594077ae6b
time: 2024-08-28T12:02:00.121025501Z
Extensions,
knativearrivaltime: 2024-08-28T12:02:00.13378992Z
Data,
{"message": "Hi from pingsource-1 from namespace-1"}
总结¶
Knative Eventing 中的 EventPolicy 资源提供了一种强大而安全的方式来控制事件传递。通过定义哪些源可以向特定消费者发送事件,用户可以确保只有授权实体在其事件驱动架构中进行交互。