Knative 事件授权¶
跟踪问题: #7256
概述¶
保护 Knative 事件中的事件传递对于防止未经授权的访问至关重要。为了对事件传递实施细粒度控制,Knative 事件引入了EventPolicy
自定义资源,它允许用户指定哪些实体被授权向命名空间内的特定使用者发送事件。
先决条件¶
- 事件安装
authentication-oidc
功能需要启用。
注意
如 authentication-oidc
中所述,为了安全认证,还应启用transport-encryption
。查看 传输加密,其中解释了如何启用传输加密功能标志。
兼容性¶
目前,以下组件支持授权
- 代理
- 频道
- 流程
- 其他
默认授权模式¶
管理员可以使用defaultAuthorizationMode
功能标志设置默认授权模式,Knative 事件将在没有EventPolicy
应用于资源时使用它。可用的模式是
allow-all
: 允许所有请求。deny-all
: 拒绝所有请求,强制创建事件策略。allow-same-namespace
: 只允许来自同一命名空间中的主体的请求。(默认值)
定义事件策略¶
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-broker
Broker。这意味着EventPolicy
应用于此特定Broker
。 - 用例: 当您想通过名称保护特定资源时,使用
to.ref
。to: - ref: apiVersion: eventing.knative.dev/v1 kind: Broker name: my-broker
-
to.selector
:- 定义: 使用标签选择器匹配特定类型的多个资源。
- 示例:
EventPolicy
包含一个带有标签的Broker
,匹配app: special-app
。这意味着EventPolicy
应用于具有这些标签的所有Brokers
。 - 用例: 当您希望
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-source
PingSource
,这意味着此特定源被允许发送事件。 - 用例: 当您想授权特定事件源时,使用
from.ref
。from: - ref: apiVersion: sources.knative.dev/v1 kind: PingSource name: my-source namespace: another-namespace
-
from.sub
:- 定义: 指定一个主体(服务帐户名称),该主体被允许发送事件。它可以包含通配符模式作为后缀(
*
)以进行更广泛的匹配。 - 示例:
EventPolicy
允许来自默认命名空间中的trusted-app
服务帐户以及default
命名空间中以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
的状态提供有关已解析源和就绪状态的信息
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"
将事件策略应用于资源¶
事件使用者(例如Broker
)将在其状态中列出应用的事件策略
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
条件指示资源的所有适用事件策略是否已准备就绪并已成功应用。
拒绝行为¶
如果请求未通过任何适用的EventPolicy
,它将被拒绝并返回403 Forbidden
HTTP 状态代码,确保阻止未经授权的事件传递。如果多个策略应用于同一资源,则只要事件匹配至少一个适用EventPolicies
,就会传递事件。这确保即使严格的策略到位,满足任何策略条件的有效事件仍然可以被处理。
示例¶
在下面,我们给出了一个完整的示例,说明如何为资源配置授权。在这个示例中,我们希望通过只允许来自不同命名空间 (namespace-2
) 中的 PingSource (pingsource-2
) 的请求来保护namespace-1
中的 Broker (broker
)。
首先,我们创建命名空间、Broker 和 PingSource
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
为了调试,我们还创建了一个 event-display 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 被禁用且没有事件策略到位,我们应该在 event-display kservice 中看到来自两个 PingSource 的事件
$ 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"}}'
并创建以下事件策略
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
之后,您可以在 Brokers 状态中看到,此事件策略已应用于它
$ 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
在 event-display 中,您应该只看到来自pingsource-2
的事件了,因为我们在事件策略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"}
当我们现在再次删除事件策略并保持 OIDC 禁用时,Broker 将回退到默认授权模式,即allow-same-namespace
$ kubectl -n namespace-1 delete eventpolicy event-policy
这也应该反映在 Brokers 状态中
$ 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
我们应该只在 event-display 中看到来自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
资源提供了一种强大的方式来安全地控制事件传递。通过定义哪些源可以将事件发送到特定消费者,用户可以确保只有授权实体在其事件驱动的架构中交互。