Skip to content

Commit 445f447

Browse files
committed
Refactor authentication mechanism from SCRAM to SASL/PLAIN and update related documentation and configurations
1 parent 583bb25 commit 445f447

16 files changed

Lines changed: 131 additions & 141 deletions

File tree

README.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
A runnable demo of **developer self-service for Apache Kafka**. Application teams
44
discover available topics in Backstage (published as AsyncAPI), then use a scaffolder
55
template to request access. Behind the form, Kong Event Gateway gets a dedicated
6-
**virtual cluster** for the app, **SCRAM (or OAuth) credentials**, and **ACLs** scoped
6+
**virtual cluster** for the app, **credentials (SASL username + password, or OAuth)**, and **ACLs** scoped
77
to exactly the topics requested — delivered via GitOps and reconciled by the **Kong
88
Operator** on Kubernetes.
99

@@ -43,7 +43,7 @@ Operator** on Kubernetes.
4343
│ ├── backstage/ # in-cluster Backstage: Deployment, Service, Postgres, config
4444
│ ├── argocd/ # Argo CD route through the Kong Gateway (+ insecure mode)
4545
│ └── kafka/ # Strimzi Kafka cluster + topics
46-
├── examples/kafka-client/ # SCRAM client config + test commands
46+
├── examples/kafka-client/ # SASL/PLAIN client config + test commands
4747
├── scripts/ # bootstrap, cert, validate
4848
└── docs/ # architecture, flows, prerequisites, secrets, repositories
4949
```
@@ -131,9 +131,9 @@ repo's `catalog-info.yaml` (see `platform/backstage/app-config.configmap.yaml`).
131131

132132
1. A developer opens the **Retail Banking NY** or **Wealth Management LA** API in the
133133
Backstage catalog and reads the AsyncAPI channels (topics).
134-
2. They run **Consume Kafka Topics**, name their app, pick topics, and choose SCRAM or
135-
OAuth. Backstage opens a PR adding `apps/<app>/` to the `kafka-selfservice-gitops`
136-
repo.
134+
2. They run **Consume Kafka Topics**, name their app, pick topics, and choose
135+
SASL/PLAIN or OAuth. Backstage opens a PR adding `apps/<app>/` to the
136+
`kafka-selfservice-gitops` repo.
137137
3. On merge, Argo CD + Kong Operator provision the virtual cluster, credentials, ACLs
138138
and route. The app connects to `bootstrap.<app>.127-0-0-1.sslip.io:9092`.
139139
4. Need more topics later? **Add Topics to Application** changes only the ACL policy.
@@ -149,14 +149,18 @@ See [`docs/flows.md`](docs/flows.md) for sequence diagrams and
149149

150150
## Notes & caveats
151151

152-
- Kong Operator CRD field names for Event Gateway are evolving. The virtual cluster
153-
`apiSpec` mirrors the Konnect / `kongctl` schema. Two spots to confirm against the
154-
CRDs in *your* operator version: the SCRAM principal **password secret-ref** shape,
155-
and whether ACLs are a separate `EventGatewayVirtualClusterPolicy` or inline on the
156-
virtual cluster (`spec.apiSpec.clusterPolicies`). Both are called out in comments.
157-
- SCRAM passwords (and the Backstage/Konnect secrets) are placeholders (`REPLACE_ME`).
158-
For real use, generate them and store via Sealed Secrets or External Secrets — never
159-
commit plaintext. [`docs/secrets.md`](docs/secrets.md) shows worked manifests for both.
152+
- Auth mechanism: the Kong Operator CRD's `saslScram` type does **not** accept inline
153+
username/password (it only carries `algorithm` and resolves principals via Kong
154+
Identity). So the self-contained "issue a user + password, validated and terminated
155+
at the gateway" model uses **`saslPlain`** (`type: saslPlain` + a sibling `saslPlain`
156+
object with `mediation: terminate` and `principals[]`). Native SCRAM or OAuth via
157+
Kong Identity is the enterprise path. Auth and ACL manifests match the installed CRD
158+
schema (`configuration.konghq.com/v1alpha1`): auth is a discriminated union, and ACL
159+
rules use `resourceType` / `operations: [{name}]` / `resourceNames: {type: stat, stat: [{match}]}`.
160+
- Credentials (and the Backstage/Konnect secrets) are placeholders (`REPLACE_ME`).
161+
For real use, use a secret-template / Konnect vault reference for the SASL password,
162+
and store Kubernetes secrets via Sealed Secrets or External Secrets — never commit
163+
plaintext. [`docs/secrets.md`](docs/secrets.md) shows worked manifests.
160164
- The `platform/` Kafka + Event Gateway manifests are adapted from the
161165
`kong-event-gw-kubernetes` reference.
162166

backstage/templates/add-topics-to-app/skeleton/kong/acl-policy.yaml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,22 @@ spec:
2525
config:
2626
rules:
2727
- action: allow
28-
resource_type: topic
28+
resourceType: topic
2929
operations:
3030
- name: describe
3131
- name: read
32-
resource_names:
33-
{%- for topic in values.topics %}
34-
- match: "${{ topic }}"
35-
{%- endfor %}
32+
resourceNames:
33+
type: stat
34+
stat:
35+
{%- for topic in values.topics %}
36+
- match: "${{ topic }}"
37+
{%- endfor %}
3638
- action: allow
37-
resource_type: group
39+
resourceType: group
3840
operations:
3941
- name: describe
4042
- name: read
41-
resource_names:
42-
- match: "${{ values.appName }}.*"
43+
resourceNames:
44+
type: stat
45+
stat:
46+
- match: "${{ values.appName }}.*"

backstage/templates/consume-kafka-topics/skeleton/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ Self-service Kafka access for **${{ values.appName }}**, generated by Backstage.
1616

1717
| File | Purpose |
1818
|------|---------|
19-
| `kong/virtual-cluster.yaml` | Dedicated virtual cluster + authentication + prefix hiding |
19+
| `kong/virtual-cluster.yaml` | Dedicated virtual cluster + authentication (credentials terminated at the gateway) + prefix hiding |
2020
| `kong/acl-policy.yaml` | Read ACLs for the topics above — **edit this to change access** |
2121
| `kong/tlsroute.yaml` | SNI route so clients reach this virtual cluster |
22-
| `kong/scram-credentials.yaml` | SCRAM secret (SCRAM auth only) |
2322
| `catalog-info.yaml` | Backstage Component for this app |
2423

2524
On merge, Argo CD applies `kong/` and Kong Operator reconciles the changes into the

backstage/templates/consume-kafka-topics/skeleton/kong/acl-policy.yaml

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@
44
# topics plus its own consumer groups. Everything else is denied because the virtual
55
# cluster runs in enforce_on_gateway mode.
66
#
7-
# THIS IS THE FILE YOU EDIT LATER. To grant access to more topics, add them to the
8-
# "Add topics" self-service template (or append resource_names below) - nothing else
9-
# about the application changes.
7+
# THIS IS THE FILE YOU EDIT LATER. To grant more topics, re-run "Add Topics to
8+
# Application" (or add entries under resourceNames.stat below) - nothing else about
9+
# the application changes.
1010
#
11-
# NOTE on the CRD kind: this follows the same reference pattern as the
12-
# EventGatewayVirtualClusterConsumePolicy / ...ProducePolicy CRDs. Depending on your
13-
# Kong Operator version, ACLs may instead be expressed inline on the
14-
# EventGatewayVirtualCluster (spec.apiSpec.clusterPolicies) using the identical
15-
# config below. Verify against your installed CRDs and move the block if needed.
11+
# CRD schema: rule fields are camelCase (`resourceType`, `resourceNames`);
12+
# `operations` is a list of `{name: <op>}`; `resourceNames` is one object with a
13+
# `type: stat` discriminator whose `stat` is a list of `{match: <glob>}`.
1614
apiVersion: configuration.konghq.com/v1alpha1
1715
kind: EventGatewayVirtualClusterPolicy
1816
metadata:
@@ -36,19 +34,23 @@ spec:
3634
config:
3735
rules:
3836
- action: allow
39-
resource_type: topic
37+
resourceType: topic
4038
operations:
4139
- name: describe
4240
- name: read
43-
resource_names:
44-
{%- for topic in values.topics %}
45-
- match: "${{ topic }}"
46-
{%- endfor %}
41+
resourceNames:
42+
type: stat
43+
stat:
44+
{%- for topic in values.topics %}
45+
- match: "${{ topic }}"
46+
{%- endfor %}
4747
- action: allow
48-
resource_type: group
48+
resourceType: group
4949
operations:
5050
- name: describe
5151
- name: read
52-
resource_names:
53-
# This app may only use consumer groups it prefixes with its own name.
54-
- match: "${{ values.appName }}.*"
52+
resourceNames:
53+
type: stat
54+
stat:
55+
# This app may only use consumer groups it prefixes with its own name.
56+
- match: "${{ values.appName }}.*"

backstage/templates/consume-kafka-topics/skeleton/kong/kustomization.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,3 @@ resources:
99
- virtual-cluster.yaml
1010
- acl-policy.yaml
1111
- tlsroute.yaml
12-
- scram-credentials.yaml

backstage/templates/consume-kafka-topics/skeleton/kong/scram-credentials.yaml

Lines changed: 0 additions & 31 deletions
This file was deleted.

backstage/templates/consume-kafka-topics/skeleton/kong/virtual-cluster.yaml

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
# - the "${{ values.namespacePrefix }}" broker prefix is hidden from the client
66
# - aclMode: enforce_on_gateway -> principals start with NO access; the ACL policy
77
# in acl-policy.yaml grants read on exactly the requested topics.
8+
#
9+
# Auth is a discriminated union: `type: <x>` + a sibling object named `<x>`.
810
apiVersion: configuration.konghq.com/v1alpha1
911
kind: EventGatewayVirtualCluster
1012
metadata:
@@ -26,33 +28,32 @@ spec:
2628
prefix: "${{ values.namespacePrefix }}"
2729
mode: hide_prefix
2830
authentication:
29-
{%- if values.authMode == "scram" %}
30-
# SASL/SCRAM-SHA-256, terminated at the gateway: the credential is validated
31-
# here and never forwarded to Kafka. The password lives in the Secret rendered
32-
# in scram-credentials.yaml.
33-
# NOTE: the exact password secret-ref shape is operator-version dependent -
34-
# confirm against your installed EventGatewayVirtualCluster CRD. If your
35-
# version only accepts inline principals, copy the password value in directly.
36-
- type: sasl_scram
37-
mediation: terminate
38-
mechanism: SCRAM-SHA-256
39-
principals:
40-
- username: ${{ values.appName }}
41-
password:
42-
type: secretRef
43-
secretRef:
44-
name: ${{ values.appName }}-kafka-scram
45-
key: password
46-
{%- else %}
31+
{%- if values.authMode == "oauth" %}
4732
# OAuth / OIDC: client presents a bearer token; the gateway verifies it against
4833
# the configured auth server (e.g. Kong Identity). The ACL condition in
49-
# acl-policy.yaml matches on the token's principal/subject claim.
34+
# acl-policy.yaml matches on the token principal/subject claim.
5035
# See: https://developer.konghq.com/how-to/event-gateway/kong-identity-oauth/
51-
- type: oauth
52-
mediation: terminate
53-
oauth:
54-
# Replace with your issuer / JWKS endpoint (Kong Identity or external IdP).
55-
issuer: https://<your-kong-identity-issuer>
56-
# The subject/client id that identifies this application in tokens.
57-
audience: ${{ values.appName }}
36+
- type: oauthBearer
37+
oauthBearer:
38+
mediation: terminate
39+
jwks:
40+
# Replace with your issuer's JWKS endpoint (Kong Identity or external IdP).
41+
endpoint: https://<your-issuer>/.well-known/jwks.json
42+
validate:
43+
issuer: https://<your-issuer>
44+
audiences:
45+
- name: ${{ values.appName }}
46+
{%- else %}
47+
# SASL/PLAIN, terminated at the gateway: the username + password are validated
48+
# here and never forwarded to Kafka. (The CRD's saslScram type does not accept
49+
# inline credentials - it needs Kong Identity - so saslPlain is used for the
50+
# self-contained "issue a user + password" model.)
51+
- type: saslPlain
52+
saslPlain:
53+
mediation: terminate
54+
principals:
55+
# Demo uses an inline password. In production use a secret-template
56+
# expression / Konnect vault reference instead of a literal value.
57+
- username: ${{ values.appName }}
58+
password: "REPLACE_ME"
5859
{%- endif %}

backstage/templates/consume-kafka-topics/template.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ metadata:
77
description: |
88
Request self-service access to Northwind Financial Kafka topics through Kong
99
Event Gateway. Provisions a dedicated virtual cluster for your application,
10-
issues SCRAM (or OAuth) credentials, and creates ACLs scoped to exactly the
11-
topics you select. Changes are delivered as a GitOps pull request; on merge,
12-
Kong Operator reconciles the control plane, data plane and access rules.
10+
issues credentials (SASL/PLAIN username + password, or OAuth), and creates ACLs
11+
scoped to exactly the topics you select. Changes are delivered as a GitOps pull
12+
request; on merge, Kong Operator reconciles the control plane, data plane and
13+
access rules.
1314
tags:
1415
- kafka
1516
- event-gateway
@@ -60,10 +61,10 @@ spec:
6061
authMode:
6162
title: Authentication
6263
type: string
63-
default: scram
64-
enum: [scram, oauth]
64+
default: plain
65+
enum: [plain, oauth]
6566
enumNames:
66-
- SASL/SCRAM-SHA-256 (username + password)
67+
- SASL/PLAIN (username + password, terminated at the gateway)
6768
- OAuth / OIDC (bearer token via Kong Identity)
6869
dependencies:
6970
businessUnit:

catalog/specs/retail-banking-ny.asyncapi.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ info:
99
below are exactly what clients use.
1010
1111
To consume any of these channels, use the **Consume Kafka Topics** self-service
12-
template in Backstage. It provisions a virtual cluster, SCRAM (or OAuth)
12+
template in Backstage. It provisions a virtual cluster, SASL (or OAuth)
1313
credentials, and ACLs scoped to the channels you select.
1414
contact:
1515
name: Retail Banking NY Platform Team
@@ -29,7 +29,7 @@ servers:
2929
description: Your provisioned application (virtual cluster) name.
3030
default: your-app
3131
security:
32-
- $ref: "#/components/securitySchemes/scram"
32+
- $ref: "#/components/securitySchemes/saslPlain"
3333
bindings:
3434
kafka:
3535
schemaRegistryUrl: ""
@@ -76,9 +76,9 @@ operations:
7676
$ref: "#/channels/core.accounts.status.v2"
7777
components:
7878
securitySchemes:
79-
scram:
80-
type: scramSha256
81-
description: SASL/SCRAM-SHA-256 over TLS. Credentials are issued per application.
79+
saslPlain:
80+
type: plain
81+
description: SASL/PLAIN over TLS. Credentials are issued per application and terminated at the gateway.
8282
messages:
8383
CardDispatched:
8484
name: CardDispatched

catalog/specs/wealth-management-la.asyncapi.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ servers:
2626
description: Your provisioned application (virtual cluster) name.
2727
default: your-app
2828
security:
29-
- $ref: "#/components/securitySchemes/scram"
29+
- $ref: "#/components/securitySchemes/saslPlain"
3030
channels:
3131
advisor.daily-client-activity.v1:
3232
address: advisor.daily-client-activity.v1
@@ -72,9 +72,9 @@ operations:
7272
$ref: "#/channels/infosec.security.fraud.risk-scores.v3"
7373
components:
7474
securitySchemes:
75-
scram:
76-
type: scramSha256
77-
description: SASL/SCRAM-SHA-256 over TLS. Credentials are issued per application.
75+
saslPlain:
76+
type: plain
77+
description: SASL/PLAIN over TLS. Credentials are issued per application and terminated at the gateway.
7878
messages:
7979
AdvisorActivity:
8080
name: AdvisorActivity

0 commit comments

Comments
 (0)