Kafka SASL JAAS Generator
The SASL login module written for a client properties file, a JAAS file, a
broker's KafkaServer stanza or a Kubernetes
secret. No password field: the output references a mounted secret and the
commands that create the credential come with it.
sasl-jaas
updates as you type Common mistakes
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
Mixing the four syntaxes
The same login module is written differently in a JAAS file, in sasl.jaas.config, in a Java system property and in Kubernetes. Copying between them without translating produces a parse error at best.
Instead:Generate for the target, and note that sasl.jaas.config must end with a semicolon inside its quoted value.
Using PLAIN over a plaintext listener
The password crosses the network essentially in the clear.
Instead:SASL_SSL, or SCRAM which never transmits the password.
Putting the JAAS file path in a shared image
Anyone with the image has the credential, and it survives every redeploy.
Instead:Mount it at runtime from a secret.
One login module, four syntaxes, one unhelpful error
The same SASL credential has to be written four different ways depending on where it goes, and only one of them is a Kafka property. When it is wrong the client starts, authentication fails, and the message names the credential rather than the file that could not be parsed.
The semicolon is mandatory and is the usual mistake
A JAAS login module entry ends with a semicolon, and leaving it out is the most common fault in a hand-written line. The error is a JAAS parser complaint about the configuration rather than anything mentioning Kafka or the credential, so it sends people to check the password first. In a properties file the whole entry also has to be on one line: a newline inside sasl.jaas.config splits the property, and the rest of the module becomes a key of its own and is silently ignored.
sasl.jaas.config=org.apache.kafka.common.\
security.scram.ScramLoginModule required \
username="app" password="${file:...}"; The context name is not free text
In a JAAS file each stanza has a name and the name decides who reads it. A client reads KafkaClient, a broker reads KafkaServer, and a broker's ZooKeeper connection reads Client. A stanza under the wrong name parses successfully and is never used, which looks exactly like a credential that does not work. The Client stanza applies to 3.9 and earlier only: ZooKeeper is removed in 4.0, so a 4.0 broker has nothing to authenticate to.
There is no password field here, on purpose
A properties file holding a password is as sensitive as the password, and it ends up in an image layer, a ConfigMap, a Helm values file and a git history. The properties output references a mounted secret through Kafka's own FileConfigProvider instead, and config.providers plus config.providers.file.class are always emitted with it: without those two the reference is not resolved and no error is raised, so the literal string becomes the password and authentication fails against a config that reads correctly.
A JAAS file cannot use a config provider at all
It is read by the JVM rather than by Kafka, so provider references mean nothing in it and the password is a literal in the file. That is why the properties form is the better answer wherever the client supports it, which is everything since 0.10.2, and why the file form is still the only way to configure a broker's own login contexts.
SCRAM and PLAIN differ in where the credential lives
A SCRAM credential is created with kafka-configs.sh and stored by the cluster, so adding or rotating a user takes effect immediately. PLAIN keeps its whole user list inline in the broker's JAAS file, so every change needs a rolling restart. PLAIN also sends the password itself on each connection, which means SASL_SSL and never SASL_PLAINTEXT. For anything long lived, SCRAM.
What this cannot see
Whether the credential exists, whether the mechanism is in the broker's sasl.enabled.mechanisms, and whether the ACLs name the right principal. A SCRAM credential created while its mechanism is disabled is stored and unusable, and the failure looks identical to a wrong password. The JAAS decoder on this site reads a config back and never prints the password.