跳至内容

Knative 事件授权

跟踪问题: #7256

概述

保护 Knative 事件中的事件传递对于防止未经授权的访问至关重要。为了对事件传递实施细粒度控制,Knative 事件引入了EventPolicy 自定义资源,它允许用户指定哪些实体被授权向命名空间内的特定使用者发送事件。

先决条件

注意

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 的范围会通过将相同的规则应用于多个目标而扩大。

有两种方法可以定义这些目标

  1. to.ref:
    • 定义: 直接引用特定资源。
    • 示例: 在上面的EventPolicy 中,直接引用了my-broker Broker。这意味着EventPolicy 应用于此特定Broker
    • 用例: 当您想通过名称保护特定资源时,使用to.ref
      to:
        - ref:
            apiVersion: eventing.knative.dev/v1
            kind: Broker
            name: my-broker
      
  2. 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 中定义的目标发送事件。有两种方法可以定义这些源

  1. from.ref:

    • 定义: 直接引用特定事件源资源。
    • 示例: 引用了another-namespace 中的my-source PingSource,这意味着此特定源被允许发送事件。
    • 用例: 当您想授权特定事件源时,使用from.ref
      from:
        - ref:
            apiVersion: sources.knative.dev/v1
            kind: PingSource
            name: my-source
            namespace: another-namespace
      
  2. 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.fromAND 运算符)匹配。只有这样,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)。

Example Overview

首先,我们创建命名空间、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-1broker 位于同一命名空间

$ 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 资源提供了一种强大的方式来安全地控制事件传递。通过定义哪些源可以将事件发送到特定消费者,用户可以确保只有授权实体在其事件驱动的架构中交互。

我们使用分析和 Cookie 来了解网站流量。有关您使用我们网站的信息将与 Google 共享,以达到此目的。 了解更多。