skip to content

How does Kafka derive a principal from a client certificate, and how do ssl.principal.mapping.rules let you customize it?

level: seniorimportance: must knowfreq 55%

answer

  1. default = full DN principal
  2. auth_to_local-style RULE:regex/repl/L
  3. ordered, first-match-wins
  4. extract CN to stay stable
  5. watch principal collisions

basics

~20 s

By default the principal is the full certificate Subject DN, e.g. User:CN=svc,OU=apps,O=Acme. ssl.principal.mapping.rules is an ordered list of RULE: regex transforms (like Kerberos auth_to_local) that rewrite the DN into a shorter principal such as User:svc.

solid answer

~50 s

After a successful mTLS handshake Kafka builds the principal from the client cert's Subject DN. With the default `ssl.principal.mapping.rules=DEFAULT`, the principal is the **entire DN** (RFC 2253 form), e.g. `User:CN=payments,OU=apps,O=Acme,C=US` — which is verbose and brittle for ACLs. You override this on the broker with `ssl.principal.mapping.rules`, a comma-separated, ordered list of rules in the form `RULE:pattern/replacement/[LU]` plus an optional final `DEFAULT`. Each rule applies a regex to the DN; the first matching rule wins. For example `RULE:^CN=([^,]+).*$/$1/L` extracts the CN and lowercases it, turning that DN into `User:payments`. This keeps ACLs short and stable across cert reissues as long as the CN is preserved. Because rules are evaluated in order and the first match applies, you put specific rules before broad ones, and you must ensure the mapped principals are unique to avoid two certs collapsing to the same identity.

code

properties · 1 line
properties
ssl.principal.mapping.rules=RULE:^CN=([^,]+),OU=apps.*$/$1/L,RULE:^CN=([^,]+).*$/$1/,DEFAULT

go deeper

for a junior

Know that without customization the principal is the whole certificate DN.

for a middle

Read a RULE:regex/replacement/L and predict the resulting principal for a given DN.

for a senior

Design ordered, collision-free rules that survive cert rotation, and debug DN-format mismatches.

for a principal

Set fleet-wide mapping policy, enforce CN/SAN naming conventions in cert issuance, and audit for principal collisions.

## Where the principal comes from A **principal** is Kafka's notion of 'who' — the identity ACLs are written against, like `User:payments`. With mTLS, that identity is extracted from the authenticated client certificate's **Subject Distinguished Name (DN)**. A DN is a comma-separated set of attributes, e.g. `CN=payments-service, OU=apps, O=Acme, C=US`, where `CN` = Common Name, `OU` = Organizational Unit, `O` = Organization, `C` = Country. ## The default: full DN With `ssl.principal.mapping.rules=DEFAULT` (the default), Kafka uses the **whole DN** as the principal name: `User:CN=payments-service,OU=apps,O=Acme,C=US`. Drawbacks: - ACLs become long and fragile. - If the cert is reissued with even a reordered/added attribute, the DN — and thus the principal — changes, breaking ACLs. ## Customizing with ssl.principal.mapping.rules This broker config borrows the syntax of Kerberos `auth_to_local`. It is an **ordered list** of rules, comma-separated. Each rule: ``` RULE:<regex>/<replacement>/[LU] ``` - `<regex>` is matched against the DN string. - `<replacement>` builds the principal name, using `$1`, `$2`… for capture groups. - Trailing `L` lowercases the result, `U` uppercases it (optional). - A bare `DEFAULT` token means 'use the full DN' and is typically the last fallback. **Evaluation is ordered and first-match-wins.** The first rule whose regex matches the DN produces the principal; later rules are not tried. ### Example ```properties ssl.principal.mapping.rules=RULE:^CN=([^,]+),OU=apps.*$/$1/L,RULE:^CN=([^,]+).*$/$1/,DEFAULT ``` - DN `CN=Payments,OU=apps,O=Acme` → first rule matches → `payments` (lowercased) → principal `User:payments`. - DN `CN=admin,OU=ops,O=Acme` → first rule fails (OU isn't apps), second matches → `admin` → `User:admin`. - Anything else → `DEFAULT` → full DN. ## Edge cases and pitfalls - **Ordering matters:** put specific rules before general ones, or a broad rule will swallow DNs you wanted handled specially. - **Uniqueness:** if your regex collapses multiple distinct certs to the same name (e.g. all `CN=...` to a constant), several services share one principal — a security hole. Make the extraction discriminating. - **DN string format:** Kafka uses the RFC 2253 canonical form. Attribute order and spacing in that canonical string matter for your regex; test with the actual rendered DN, not what you typed into openssl. - **It's broker-side:** mapping rules are a broker config; clients don't set them. All brokers must agree, or the same cert maps to different principals on different brokers. - **SAN vs Subject:** by default mapping uses the Subject DN. (Newer versions also expose SAN-based extraction, but DN mapping is the classic mechanism.) - **No mapping ≠ no auth:** even with DEFAULT you are authenticated; mapping only changes the *name*, not whether auth succeeded. ## Why senior-level Getting this wrong silently broadens identities (collision) or breaks ACLs on every cert rotation (full-DN brittleness). Designing stable, unique, rotation-resilient principal mapping is the crux of operating cert-based auth at scale.

  • Why is using the full DN as the principal risky across certificate renewals?
    If a renewed cert has any DN difference (reordered or added attribute, different OU), the principal name changes, so all ACLs referencing the old DN stop matching. Mapping to a stable field like CN avoids this.
  • What happens if two different service certs both map to the same principal name?
    They become indistinguishable to ACLs — both get whatever permissions that principal has. It's a privilege-separation failure; mapping rules must keep distinct services distinct.
  • Are ssl.principal.mapping.rules set on the client or the broker?
    On the broker. The broker performs the certificate-to-principal mapping; clients only present certs. All brokers should share identical rules.

saying these in an interview costs you the question

  • Thinking principal mapping is a client-side config — it's broker-side.
  • Writing a single greedy rule that collapses many certs into one principal.
  • Assuming the DN string you typed in openssl is byte-identical to Kafka's RFC 2253 canonical form used by the regex.
  • Believing mapping affects whether authentication succeeds — it only renames the authenticated identity.

context