Files
infra-kafka/credentials-access.yaml
Stéphane Tailland 5770f78c99 Declare the classic-models topics and a credentials store
Topics are declared rather than auto-created: the application account has no
Create ACL, so a producer would have been denied, and an auto-created topic
takes broker defaults nobody chose.

The credentials store lets an application namespace read its own KafkaUser
password and the cluster CA from the kafka namespace, so the password stays
generated and rotatable by Strimzi instead of being copied by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 07:34:55 +02:00

69 lines
2.1 KiB
YAML

---
# Letting an application namespace read its own Kafka credentials.
#
# Strimzi writes a KafkaUser's SCRAM password into a Secret in *this* namespace,
# and a Secret cannot be mounted across namespaces. The alternatives are to copy
# the password by hand (it then drifts the first time the user is regenerated)
# or to put it in Vault (a second copy of a credential the cluster already
# owns, kept in sync by nobody).
#
# Instead External Secrets reads it here and materialises it there. The password
# stays generated by, and rotatable by, Strimzi; the copy follows.
#
# The ServiceAccount below can read Secrets in this namespace ONLY, which
# includes every KafkaUser's password. That is the trade: any namespace allowed
# to create an ExternalSecret against this store can pull any Kafka account's
# credentials. Acceptable in a lab with one operator; in a shared cluster,
# narrow the Role with resourceNames and run one store per application.
apiVersion: v1
kind: ServiceAccount
metadata:
name: kafka-credentials-reader
namespace: kafka
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kafka-credentials-reader
namespace: kafka
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kafka-credentials-reader
namespace: kafka
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kafka-credentials-reader
subjects:
- kind: ServiceAccount
name: kafka-credentials-reader
namespace: kafka
---
# External Secrets authenticates as that ServiceAccount rather than as itself,
# so what the store can reach is bounded by the Role above and visible in RBAC
# rather than in the operator's own permissions.
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: kafka-credentials
spec:
provider:
kubernetes:
remoteNamespace: kafka
server:
caProvider:
type: ConfigMap
name: kube-root-ca.crt
key: ca.crt
namespace: kafka
auth:
serviceAccount:
name: kafka-credentials-reader
namespace: kafka