Add documentation for Eventing Authorization (#6104)

* Add documentation for event authorization

* Add example for usage

* Switched from Trigger to Broker

* Add not to enable transport-encryption FF as well as a prerequisite

* Add more details on filters

* Move default auth mode doc up

* Add image for arch of example

* Fix how filters are applied

* Addressed review comments

* Add more details on rejection behavior
This commit is contained in:
Christoph Stäbler 2024-09-05 10:36:33 +02:00 committed by GitHub
parent bb2cede854
commit 3b522f768f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 474 additions and 0 deletions

View File

@ -303,6 +303,7 @@ nav:
- EventType auto creation: eventing/features/eventtype-auto-creation.md
- Transport Encryption: eventing/features/transport-encryption.md
- Sender Identity: eventing/features/sender-identity.md
- Authorization: eventing/features/authorization.md
- Eventing with Istio: eventing/features/istio-integration.md
- Cross Namespace Event Links: eventing/features/cross-namespace-event-links.md
- FAQ: eventing/faq/README.md

View File

@ -11,6 +11,7 @@ plugins:
eventing/experimental-features/eventtype-auto-creation.md: eventing/features/eventtype-auto-creation.md
eventing/experimental-features/transport-encryption.md: eventing/features/transport-encryption.md
eventing/experimental-features/sender-identity.md: eventing/features/sender-identity.md
eventing/experimental-features/authorization.md: eventing/features/authorization.md
eventing/features/new-trigger-filters.md: eventing/triggers/README.md
eventing/broker/kafka-broker/kafka-configmap.md: eventing/configuration/kafka-channel-configuration.md
eventing/broker/create-mtbroker.md: eventing/brokers/create-broker.md

View File

@ -74,6 +74,7 @@ Knative Eventing:
| [Knative reference mapping](kreference-mapping.md) | `kreference-mapping` | Provide mappings from a [Knative reference](https://github.com/knative/specs/blob/main/specs/eventing/overview.md#destination) to a templated URI. | Alpha, disabled by default |
| [Transport encryption](transport-encryption.md) | `transport-encryption` | Enables components to encrypt traffic using TLS by exposing HTTPS URL. | Beta, disabled by default |
| [Sender Identity](sender-identity.md) | `authentication-oidc` | Enables Eventing sources to send authenticated requests and addressables to require authenticated requests. | Alpha, disabled by default |
| [Authorization](authorization.md) | `default-authorization-mode` | Enables Authorization for Eventing sinks. | Alpha, disabled by default |
| [Eventing with Istio](istio-integration.md) | `istio` | Enables Eventing components to communicate with workloads in an Istio mesh. | Beta, disabled by default |
| [Cross Namespace Event Links](cross-namespace-event-links.md) | `cross-namespace-event-links` | Enables subscriptions and triggers to refer to brokers and channels in different namespaces. | Alpha, disabled by default |

View File

@ -0,0 +1,471 @@
# Knative Eventing Authorization
**Tracking issue**: [#7256](https://github.com/knative/eventing/issues/7256)
## Overview
Securing event delivery in Knative Eventing is essential to prevent unauthorized access. To enforce fine-grained control over event delivery, Knative Eventing introduces the `EventPolicy` custom resource, which allows users to specify which entities are authorized to send events to specific consumers within a namespace.
## Prerequisites
- [Eventing installation](./../../../install)
- [`authentication-oidc`](./sender-identity.md) feature to be enabled.
!!! note
As described on the [`authentication-oidc`](./sender-identity.md), `transport-encryption` should be enabled as well for a secure authentication. Take a look at [Transport-Encryption](./transport-encryption.md), which explains how to enable the transport encryption feature flag.
## Compatibility
Authorization is currently supported for the following components:
- Brokers:
- [MTChannelBasedBroker](./../brokers/broker-types/channel-based-broker/)
- [Knative Broker for Apache Kafka](./../brokers/broker-types/kafka-broker/)
- Channels:
- [InMemoryChannel](./../channels/channels-crds.md)
- [KafkaChannel](./../channels/channels-crds.md)
- Flows:
- [Sequence](./../flows/sequence/README.md)
- [Parallel](./../flows/parallel.md)
- Others:
- [KafkaSink](./../sinks/kafka-sink.md)
## Default Authorization Mode
Administrators can set a default authorization mode using the `defaultAuthorizationMode` feature flag, which Knative Eventing will use whenever no `EventPolicy` applies to a resource. The available modes are:
* `allow-all`: All requests are allowed.
* `deny-all`: All requests are denied, enforcing the creation of EventPolicies.
* `allow-same-namespace`: Only requests from subjects within the same namespace are allowed. (Default)
## Defining an EventPolicy
An `EventPolicy` defines rules for event delivery by specifying which subjects (service accounts or event sources) are allowed to send events to designated event consumers.
```yaml
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
```
### Specify for who the `EventPolicy` applies
The `.spec.to` section specifies **where** the events are allowed to be sent. This field is optional; if left empty, the policy applies to all resources within the namespace. By specifying multiple targets in `.spec.to`, the `EventPolicies` scope gets widened by applying the same rules to multiple targets.
There are two ways to define these targets:
1. `to.ref`:
* **Definition**: Directly references a specific resource.
* **Example**: In the `EventPolicy` above, the `my-broker` Broker is directly referenced. This means the `EventPolicy` applies to this specific `Broker`.
* **Use Case**: Use `to.ref` when you want to protect a specific resource by name.
```yaml
to:
- ref:
apiVersion: eventing.knative.dev/v1
kind: Broker
name: my-broker
```
2. `to.selector`:
* **Definition**: Uses a label selector to match multiple resources of a specific type.
* **Example**: The `EventPolicy` includes a `Broker` with labels matching `app: special-app`. This means the `EventPolicy` applies to all `Brokers` with these labels.
* **Use Case**: Use `to.selector` when you want the `EventPolicy` to apply to a group of resources that share common labels.
```yaml
to:
- selector:
apiVersion: eventing.knative.dev/v1
kind: Broker
matchLabels:
app: special-app
```
### Specify who is allowed to send events
The `.spec.from` section specifies **who** is allowed to send events to the targets defined in `.spec.to`. There are two ways to define these sources:
1. `from.ref`:
* **Definition**: Directly references a specific event source resource.
* **Example**: The `my-source` `PingSource` in `another-namespace` is referenced, meaning this specific source is allowed to send events.
* **Use Case**: Use `from.ref` when you want to authorize a specific event source.
```yaml
from:
- ref:
apiVersion: sources.knative.dev/v1
kind: PingSource
name: my-source
namespace: another-namespace
```
2. `from.sub`:
* **Definition**: Specifies a subject (a service account name), that is allowed to send events. It can include wildcard patterns as a postfix (`*`) for broader matching.
* **Example**: The `EventPolicy` allows events from the `trusted-app` service account in the default namespace and any service account in `default` namespace that starts with `other-`.
* **Use Case**: Use `from.sub` to allow specific users or service accounts, or to apply wildcard patterns for more flexibility.
```yaml
from:
- sub: system:serviceaccount:default:trusted-app
- sub: "system:serviceaccount:default:other-*"
```
### Advanced CloudEvent filtering criterias
The `.spec.filters` section is optional and specifies additional criteria that the event itself must meet to be allowed.
* **Example:** Only CloudEvents with the `type` equals to `com.github.push` and matching a certain CESQL expression are allowed.
* **Use Case:** Use `filters` when you want to have more fine grained criterias on allowed CloudEvents.
```yaml
from:
filters:
- cesql: "type IN ('order.created', 'order.updated', 'order.canceled')"
- exact:
type: com.github.push
```
If the filters are specified, an event must match **all** the specified filters of an `EventPolicy` (in addition to its `.spec.from`) to be accepted. `.spec.filters` accepts the same filter dialects as [Triggers](../triggers/README.md#supported-filter-dialects).
!!! note
Filters apply in addition to `.spec.from`. This means, soon as an `EventPolicy` specifies `.spec.filters`, they must match the request, as well as the `.spec.from` (*AND* operand). Only then the `EventPolicy` allows the request.
### Summary of `.spec` fields:
* `to.ref` targets a specific resource.
* `to.selector` targets a set of resources based on labels.
* `from.ref` authorizes a specific event source resource.
* `from.sub` authorizes specific users, service accounts, or patterns of accounts.
* `.spec.filters` allows to define advanced CloudEvent filtering criterias
## EventPolicy status
The status of an `EventPolicy` provides information about resolved sources and readiness:
```yaml
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"
```
## Applying EventPolicies to Resources
Event consumers, such as a `Broker`, will list the applying EventPolicies in their status:
```yaml
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"
```
The `EventPoliciesReady` condition indicates whether all applicable EventPolicies for a resource are ready and have been successfully applied.
## Rejection Behavior
If a request does not pass any applicable `EventPolicy`, it will be rejected with a `403 Forbidden` HTTP status code, ensuring that unauthorized event deliveries are blocked. If multiple policies apply to the same resource, the event will be delivered as long as it matches **at least one** of the applicable `EventPolicies`. This ensures that even if strict policies are in place, valid events that meet the criteria of any policy can still be processed.
## Example
In the following, we give a full example how to configure authorization for resources. In this example, we want to protect a Broker (`broker`) in `namespace-1` by only allowing requests from a PingSource (`pingsource-2`) which is in a different namespace (`namespace-2`).
![Example Overview](./images/authz-example.png)
First we create the Namespaces, Broker and PingSources:
```yaml
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
```
For debugging we also create an event-display Kservice and Trigger:
```yaml
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
```
As long as OIDC is disabled and no EventPolicy is in place, we should see the events from both PingSources in the event-display kservice:
```
$ 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"}
```
Now enable OIDC
```
$ kubectl -n knative-eventing patch cm config-features --type merge --patch '{"data":{"authentication-oidc":"enabled"}}'
```
and create the following EventPolicy
```yaml
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
```
Afterwards you can see in the Brokers status, that this EventPolicy got applied to it:
```
$ 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
```
And in the event-display, you should see only events from `pingsource-2` anymore, as we referenced this in our EventPolicy `event-policy` to be allowed to send events to 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"}
```
When we remove now the EventPolicy again and keep OIDC disabled, the Broker will fall back to the default authorization mode, which is `allow-same-namespace`:
```
$ kubectl -n namespace-1 delete eventpolicy event-policy
```
This should be reflected in the Brokers status too:
```
$ 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
```
And we should see only events from `pingsource-1` in the event-display, as `pingsource-1` is in the same namespace as `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"}
```
## Summary
The `EventPolicy` resource in Knative Eventing offers a powerful way to control event delivery securely. By defining which sources can send events to specific consumers, users can ensure that only authorized entities interact within their event-driven architecture.

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB