跳到内容

Knative Eventing 授权

追踪问题: #7256

概述

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

先决条件

注意

authentication-oidc 中所述,为实现安全认证,transport-encryption 也应启用。请参阅 传输加密,其中解释了如何启用传输加密功能标志。

兼容性

授权目前支持以下组件

默认授权模式

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

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

  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 包含一个带有标签匹配 app: special-appBroker。这意味着 EventPolicy 适用于所有具有这些标签的 Broker
    • 用例:当您希望 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 服务账户的事件,以及默认命名空间中以 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)。

Example Overview

首先我们创建命名空间、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-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 共享以达到此目的。了解更多。