Sender Identity for Knative Eventing

Flag name: authentication-oidc

Stage: Alpha, disabled by default

Tracking issue: #6806

Overview

Currently, event delivery within the cluster is unauthenticated, and an addressable event consumer cannot determine the identity of any sender.

Knative Eventing Addressables expose their OIDC Audience in their status as part of their address (e.g. .status.address.audience) and require requests containing an OIDC access token issued for this audience.

Knative Eventing Souces request an OIDC access token for the targets audience and add them to the request. A per-source dedicated Service Account is used as the identity for the request.

Prerequisites

Note

To not provide the access token in cleartext over the wire, transport-encryption should be enabled as well. Take a look at Transport-Encryption, which explains how to enable the transport encryption feature flag.

Compatibility

OIDC authentication is currently supported for the following components:

Sender Identity Configuration

The possible values for authentication-oidc are:

  • disabled
    • No change in behaviour
  • enabled
    • Addressables announce their audience in their status
    • Sources add an Authorization Header to their request containing an access token for their target

For example, to enable sender identity, the config-features ConfigMap will look like the following:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: config-features
  5. namespace: knative-eventing
  6. data:
  7. authentication-oidc: "enabled"

Verifying that the feature is working

Save the following YAML into a file called default-broker-example.yaml

  1. # default-broker-example.yaml
  2. apiVersion: eventing.knative.dev/v1
  3. kind: Broker
  4. metadata:
  5. name: br
  6. ---
  7. apiVersion: eventing.knative.dev/v1
  8. kind: Trigger
  9. metadata:
  10. name: tr
  11. spec:
  12. broker: br
  13. subscriber:
  14. ref:
  15. apiVersion: v1
  16. kind: Service
  17. name: event-display
  18. ---
  19. apiVersion: v1
  20. kind: Service
  21. metadata:
  22. name: event-display
  23. spec:
  24. selector:
  25. app: event-display
  26. ports:
  27. - protocol: TCP
  28. port: 80
  29. targetPort: 8080
  30. ---
  31. apiVersion: v1
  32. kind: Pod
  33. metadata:
  34. name: event-display
  35. labels:
  36. app: event-display
  37. spec:
  38. containers:
  39. - name: event-display
  40. image: gcr.io/knative-releases/knative.dev/eventing/cmd/event_display
  41. imagePullPolicy: Always
  42. ports:
  43. - containerPort: 8080

Apply the default-broker-example.yaml file into a test namespace authentication-oidc-test:

  1. kubectl create namespace authentication-oidc-test
  2. kubectl apply -n authentication-oidc-test -f default-broker-example.yaml

Verify that the Broker announces its audience:

  1. kubectl -n authentication-oidc-test get broker br -o yaml

Example output:

  1. apiVersion: eventing.knative.dev/v1
  2. kind: Broker
  3. metadata:
  4. name: br
  5. namespace: authentication-oidc-test
  6. spec:
  7. config:
  8. # ...
  9. delivery:
  10. # ...
  11. status:
  12. address:
  13. audience: eventing.knative.dev/broker/authentication-oidc-test/br
  14. name: http
  15. url: http://broker-ingress.knative-eventing.svc.cluster.local/authentication-oidc-test/br
  16. annotations:
  17. # ...

Send events to the Broker using OIDC authentication:

  1. Create an OIDC token (access token):

    1. kubectl -n authentication-oidc-test create serviceaccount oidc-test-user; kubectl -n authentication-oidc-test create token oidc-test-user --audience eventing.knative.dev/broker/authentication-oidc-test/br

    Example output:

    1. serviceaccount/oidc-test-user created
    2. eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBWmppNEVJZkVSVDZoYTA4dU1xTWJxSHFYQTgtbE00VU1tMmpFZUNuakUifQ.eyJhdWQiOlsiZXZlbnRpbmcua25hdGl2ZS5kZXYvYnJva2VyL2F1dGhlbnRpY2F0aW9uLW9pZGMtdGVzdC9iciJdLCJleHAiOjE3MDU5MzQyMTQsImlhdCI6MTcwNTkzMDYxNCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJhdXRoZW50aWNhdGlvbi1vaWRjLXRlc3QiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoib2lkYy10ZXN0LXVzZXIiLCJ1aWQiOiJkNGM5MjkzMy1kZThlLTRhNDYtYjkxYS04NjRjNTZkZDU4YzIifX0sIm5iZiI6MTcwNTkzMDYxNCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmF1dGhlbnRpY2F0aW9uLW9pZGMtdGVzdDpvaWRjLXRlc3QtdXNlciJ9.Taqk11LRC7FKMbt_1VvmRjMolJL54CFGbRT85ZgNdG8YT6MXiw_S2rMHxLyC9RyX0hb720szHhiVIPj15jbz597egSBbcuk-f_MCsUFMyK1Nb95blo6UNDFKIQxC5_aleoT-qaGtXlt4OEE6RjA28mFeeSCjcJUCRdLGLuSiQT47lxLqNK5OfKjd4wGMiUsbBzOcXor9ouJc1lr4gFlCzzIMJNLfXU0O_AB8J--yh6wP07Q-2AWwwv7J1CtZCrIqaPBFjWnplLqtBgo33ZNbqomXyYVdO_0HlEN9XtlK_y_2veEvKOkINzpic_ipf5ZhTxEpXWaztZzdkWd-e2mHMg
  2. Send a curl request to the Broker

    1. kubectl -n authentication-oidc-test run curl --image=curlimages/curl -i --tty -- sh
    2. # Send unauthenticated request (should result in a 401)
    3. curl -v http://broker-ingress.knative-eventing.svc.cluster.local/authentication-oidc-test/br -H "Content-Type:application/json" -H "Ce-Id:1" -H "Ce-Source:cloud-event-example" -H "Ce-Type:myCloudEventGreeting" -H "Ce-Specversion:1.0" -d "{\"name\": \"unauthenticated\"}"
    4. # Send authenticated request (should request in 202)
    5. curl -v http://broker-ingress.knative-eventing.svc.cluster.local/authentication-oidc-test/br -H "Content-Type:application/json" -H "Ce-Id:1" -H "Ce-Source:cloud-event-example" -H "Ce-Type:myCloudEventGreeting" -H "Ce-Specversion:1.0" -H "Authorization: Bearer <YOUR-TOKEN-FROM-STEP-1>" -d "{\"name\": \"authenticated\"}"

    Example output:

    1. $ curl -v http://broker-ingress.knative-eventing.svc.cluster.local/authentication-oidc-test/br -H "Content-Type:application/json" -H "Ce-Id:1" -H "Ce-Source:cloud-event-example" -H "Ce-Type:myCloudEventGreeting" -H "Ce-Specversion:1.0" -d "{\"name\": \"unauthenticated\"}"
    2. * Host broker-ingress.knative-eventing.svc.cluster.local:80 was resolved.
    3. * IPv6: (none)
    4. * IPv4: 10.96.110.167
    5. * Trying 10.96.110.167:80...
    6. * Connected to broker-ingress.knative-eventing.svc.cluster.local (10.96.110.167) port 80
    7. > POST /authentication-oidc-test/br HTTP/1.1
    8. > Host: broker-ingress.knative-eventing.svc.cluster.local
    9. > User-Agent: curl/8.5.0
    10. > Accept: */*
    11. > Content-Type:application/json
    12. > Ce-Id:1
    13. > Ce-Source:cloud-event-example
    14. > Ce-Type:myCloudEventGreeting
    15. > Ce-Specversion:1.0
    16. > Content-Length: 27
    17. >
    18. < HTTP/1.1 401 Unauthorized
    19. < Allow: POST, OPTIONS
    20. < Date: Mon, 22 Jan 2024 13:33:57 GMT
    21. < Content-Length: 0
    22. <
    23. * Connection #0 to host broker-ingress.knative-eventing.svc.cluster.local left intact
    24. ~ $ curl -v http://broker-ingress.knative-eventing.svc.cluster.local/authentication-oidc-test/br -H "Content-Type:application/json" -H "Ce-Id:1" -H "Ce-Source:cloud-event-example" -H "Ce-Type:myCloudEventGreeting" -H "Ce-Specversion:1.0" -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBWmppNEVJZkVSV
    25. DZoYTA4dU1xTWJxSHFYQTgtbE00VU1tMmpFZUNuakUifQ.eyJhdWQiOlsiZXZlbnRpbmcua25hdGl2ZS5kZXYvYnJva2VyL2F1dGhlbnRpY2F0aW9uLW9pZGMtdGVzdC9iciJdLCJleHAiOjE3MDU5MzQwMDgsImlhdCI6MTcwNTkzMDQwOCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJhdXRoZW50aWNhdGlvbi1vaWRjLXRlc3QiLCJ
    26. zZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoib2lkYy10ZXN0LXVzZXIiLCJ1aWQiOiI3MTlkMWI3ZC1hZjBkLTQzMDAtOGUxNy1lNTk4YmZmN2VmYTIifX0sIm5iZiI6MTcwNTkzMDQwOCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmF1dGhlbnRpY2F0aW9uLW9pZGMtdGVzdDpvaWRjLXRlc3QtdXNlciJ9.UrleSi54mxgThesyrC4kzG7rO3-Fic1B3kPOY8k1l-oslhvw3dbT0n24bvP96m7Ke4ZGoXE3Efo
    27. 966LZM_61-bfntFbw8kTRe_w6wGXVGpadrBSZsIChVgFYqsPNX_7r1LSNTy5tFXze9phVz6EpO7XeUct_PXyYLASNw0LNXWyqbcEqBNtgWmDKHaS_1pIscFP6MaoGVj968hpVqli8O6okQUQitIoPwFEGAIbaBlIX6Z5ZqlGwL9eqbIiNEMEgjlduv9dyZVmpDc0hsF6GHk2RnAhLeOniUNdUo4VO3z27TJY5JYK7xIMBD6Z5dUAhud9ofA8VWEl7Mziw4fsdCw" -d "{\"name\": \"authenticated\"}"
    28. * Host broker-ingress.knative-eventing.svc.cluster.local:80 was resolved.
    29. * IPv6: (none)
    30. * IPv4: 10.96.110.167
    31. * Trying 10.96.110.167:80...
    32. * Connected to broker-ingress.knative-eventing.svc.cluster.local (10.96.110.167) port 80
    33. > POST /authentication-oidc-test/br HTTP/1.1
    34. > Host: broker-ingress.knative-eventing.svc.cluster.local
    35. > User-Agent: curl/8.5.0
    36. > Accept: */*
    37. > Content-Type:application/json
    38. > Ce-Id:1
    39. > Ce-Source:cloud-event-example
    40. > Ce-Type:myCloudEventGreeting
    41. > Ce-Specversion:1.0
    42. > Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IlZBWmppNEVJZkVSVDZoYTA4dU1xTWJxSHFYQTgtbE00VU1tMmpFZUNuakUifQ.eyJhdWQiOlsiZXZlbnRpbmcua25hdGl2ZS5kZXYvYnJva2VyL2F1dGhlbnRpY2F0aW9uLW9pZGMtdGVzdC9iciJdLCJleHAiOjE3MDU5MzQwMDgsImlhdCI6MTcwNTkzMDQwOCwiaXNzIjoiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJhdXRoZW50aWNhdGlvbi1vaWRjLXRlc3QiLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoib2lkYy10ZXN0LXVzZXIiLCJ1aWQiOiI3MTlkMWI3ZC1hZjBkLTQzMDAtOGUxNy1lNTk4YmZmN2VmYTIifX0sIm5iZiI6MTcwNTkzMDQwOCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmF1dGhlbnRpY2F0aW9uLW9pZGMtdGVzdDpvaWRjLXRlc3QtdXNlciJ9.UrleSi54mxgThesyrC4kzG7rO3-Fic1B3kPOY8k1l-oslhvw3dbT0n24bvP96m7Ke4ZGoXE3Efo966LZM_61-bfntFbw8kTRe_w6wGXVGpadrBSZsIChVgFYqsPNX_7r1LSNTy5tFXze9phVz6EpO7XeUct_PXyYLASNw0LNXWyqbcEqBNtgWmDKHaS_1pIscFP6MaoGVj968hpVqli8O6okQUQitIoPwFEGAIbaBlIX6Z5ZqlGwL9eqbIiNEMEgjlduv9dyZVmpDc0hsF6GHk2RnAhLeOniUNdUo4VO3z27TJY5JYK7xIMBD6Z5dUAhud9ofA8VWEl7Mziw4fsdCw
    43. > Content-Length: 25
    44. >
    45. < HTTP/1.1 202 Accepted
    46. < Allow: POST, OPTIONS
    47. < Date: Mon, 22 Jan 2024 13:34:27 GMT
    48. < Content-Length: 0
    49. <
    50. * Connection #0 to host broker-ingress.knative-eventing.svc.cluster.local left intact
    51. ~ $

    3. Verify the 2nd event reached the event-display pod

    1. kubectl -n authentication-oidc-test logs event-display

    Example output:

    1. ☁️ cloudevents.Event
    2. Context Attributes,
    3. specversion: 1.0
    4. type: myCloudEventGreeting
    5. source: cloud-event-example
    6. id: 1
    7. datacontenttype: application/json
    8. Extensions,
    9. knativearrivaltime: 2024-01-22T13:34:26.032199371Z
    10. Data,
    11. {
    12. "name": "authenticated"
    13. }

Limitations with Istio

You might experience issues with the eventing integration with Istio and having the authentication-oidc feature flag enabeled, when the JWKS URI is represented via an IP. E.g. like in the following case:

  1. $ kubectl get --raw /.well-known/openid-configuration | jq
  2. {
  3. "issuer": "https://kubernetes.default.svc",
  4. "jwks_uri": "https://172.18.0.3:6443/openid/v1/jwks",
  5. ...
  6. }

In this case you need to add the traffic.sidecar.istio.io/excludeOutboundIPRanges: /32 annotation to the pod templates of the following deployments:

  • imc-dispatcher
  • mt-broker-ingress
  • mt-broker-filter

For example:

  1. $ kubectl -n knative-eventing patch deploy imc-dispatcher --patch '{"spec":{"template":{"metadata":{"annotations":{"traffic.sidecar.istio.io/excludeOutboundIPRanges":"172.18.0.3/32"}}}}}'
  2. deployment.apps/imc-dispatcher patched