skip to content

How do you create, list, and delete a SCRAM user with kafka-configs, and what gets stored?

level: middleimportance: must knowfreq 60%

answer

  1. kafka-configs --alter --add-config 'SCRAM-SHA-256=[password=...]'
  2. --entity-type users --entity-name alice
  3. stores salt + iterations + StoredKey + ServerKey, not password
  4. no restart; lives in ZK / KRaft metadata
  5. bootstrap inter-broker SCRAM user before brokers start (--zookeeper or kafka-storage --add-scram)

basics

~10 s

Use kafka-configs.sh --alter --add-config 'SCRAM-SHA-256=[password=secret]' --entity-type users --entity-name alice. Kafka stores a salted, iterated hash (not the password). Delete with --delete-config; list with --describe.

solid answer

~40 s

SCRAM credentials are dynamic per-user configs managed with kafka-configs.sh. To create: `kafka-configs.sh --bootstrap-server b:9092 --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=secret]' --entity-type users --entity-name alice` (add SCRAM-SHA-512 similarly). You can target a specific mechanism or both. Kafka computes and stores the salt, the iterated hashes (StoredKey and ServerKey), and the iteration count — never the cleartext password. List with `--describe --entity-type users --entity-name alice` (the hashes are shown, not the password). Delete with `--alter --delete-config 'SCRAM-SHA-256' ...`. On KRaft clusters point --bootstrap-server at the brokers; on ZooKeeper clusters older Kafka used --zookeeper. No broker restart is needed — changes propagate through metadata. A common gotcha: the broker's own inter-broker user (if using SCRAM for inter-broker) must exist before brokers start, so bootstrap it via --zookeeper or KRaft formatting first.

go deeper

for a junior

Know the basic kafka-configs --alter command shape to add a SCRAM user.

for a middle

Know create/describe/delete syntax, that no restart is needed, and that only salted hashes are stored.

for a senior

Explain StoredKey/ServerKey/salt/iterations storage and the inter-broker bootstrap ordering problem.

for a principal

Design credential provisioning/rotation automation across ZK and KRaft, including format-time --add-scram and iteration-count policy.

## SCRAM credentials are dynamic configs Unlike PLAIN (static JAAS entries), SCRAM users are **entity configurations** of type `users`, managed at runtime with the `kafka-configs.sh` admin tool. They live in ZooKeeper (legacy) or the **KRaft metadata log** and are replicated to all brokers, so **no restart** is required to add, change, or remove a user. ## Create / update a user ``` kafka-configs.sh --bootstrap-server broker:9092 \ --alter \ --add-config 'SCRAM-SHA-256=[iterations=8192,password=alice-secret],SCRAM-SHA-512=[password=alice-secret]' \ --entity-type users --entity-name alice ``` - `--add-config` carries one entry per mechanism. The bracketed value can set `iterations` (>= 4096; default is mechanism-dependent, commonly 4096/8192) and `password`. - Running `--alter` again on the same user with the same mechanism **overwrites** (rotates) the credential. ## What actually gets stored SCRAM (RFC 5802) does not store the password. For each user/mechanism Kafka stores: - a random **salt**, - the **iteration count**, - **StoredKey** = H(ClientKey) and **ServerKey** = HMAC(SaltedPassword, 'Server Key'), where SaltedPassword = PBKDF2(password, salt, iterations). These let the broker verify a client proof and produce a server signature without ever knowing the cleartext. So a leaked metadata store does not directly reveal passwords (only an offline brute-force against the salted hash is possible). ## List / describe ``` kafka-configs.sh --bootstrap-server broker:9092 --describe \ --entity-type users --entity-name alice ``` This prints the stored SCRAM config (salt, iterations, StoredKey, ServerKey as encoded values) — never a usable password. ## Delete ``` kafka-configs.sh --bootstrap-server broker:9092 --alter \ --delete-config 'SCRAM-SHA-256' \ --entity-type users --entity-name alice ``` Deleting all mechanisms for a user effectively removes their ability to authenticate via SCRAM. ## Bootstrapping the inter-broker user (key gotcha) If brokers authenticate to each other with SCRAM (`sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256`), that broker user must exist **before** the brokers come up — otherwise the cluster can't form. On ZooKeeper clusters you create it with `--zookeeper` (works without a running broker). On KRaft you provision it at format time with `kafka-storage.sh format ... --add-scram 'SCRAM-SHA-256=[name=admin,password=...]'`. ## ZooKeeper vs KRaft tooling - ZooKeeper era: `--zookeeper host:2181` could manage users directly. - Modern/KRaft: use `--bootstrap-server` (the broker admin API). The `--zookeeper` flag is deprecated/removed as clusters move to KRaft.

  • If brokers use SCRAM for inter-broker auth, why can a fresh KRaft cluster fail to start, and how do you fix it?
    The inter-broker SCRAM user doesn't exist yet, so brokers can't authenticate to each other. Provision it at format time: kafka-storage.sh format ... --add-scram 'SCRAM-SHA-256=[name=admin,password=...]'. On ZooKeeper you'd create it with --zookeeper before starting brokers.
  • Can someone with read access to ZooKeeper/KRaft metadata recover a user's password?
    Not directly — only the salt, iteration count, StoredKey, and ServerKey are stored, all derived via PBKDF2. They could attempt an offline brute-force/dictionary attack, which higher iteration counts and strong passwords mitigate.

saying these in an interview costs you the question

  • Saying you must restart brokers to add a SCRAM user
  • Claiming the cleartext password is stored in ZooKeeper/KRaft
  • Forgetting that the inter-broker SCRAM user must pre-exist before brokers start
  • Using --describe and expecting to read back the password

context