skip to content

You secure a cross-cluster MM2 link with mutual TLS. How is the Kafka principal derived from the client certificate, and how do you control it with ssl.principal.mapping.rules?

level: seniorimportance: should knowfreq 45%

answer

  1. Default principal = full DN
  2. ssl.principal.mapping.rules = broker-side regex RULE:.../$1/
  3. Extract CN, end with DEFAULT
  4. Each cluster maps independently → must converge
  5. Kerberos analog: kerberos.principal.to.local.rules

basics

~20 s

With mTLS the broker takes the client certificate's full Distinguished Name (DN) as the principal by default, e.g. 'User:CN=mm2,OU=...,O=...'. ssl.principal.mapping.rules lets you rewrite that DN with regex into a shorter principal like 'User:mm2' that your ACLs reference.

solid answer

~40 s

When a client connects with mutual TLS, the broker authenticates it by validating the certificate chain against its truststore, then builds a `KafkaPrincipal` from the certificate's subject **Distinguished Name**. By default the principal is the entire DN: `User:CN=mm2,OU=replication,O=Acme,L=...,C=US`. ACLs must then match that exact string, which is brittle. The broker config `ssl.principal.mapping.rules` is an ordered list of `RULE:` transforms (same syntax family as Kerberos `auth_to_local`) that apply a regex to the DN and emit a normalized principal — typically extracting just the CN: `RULE:^CN=(.*?),.*$/$1/`, ending with `DEFAULT`. So `CN=mm2,OU=...` becomes `User:mm2`, and your ACLs reference `User:mm2`. This is the cross-cluster crux: source and target clusters issue different certs/DNs, so each cluster's mapping rules must converge MM2's identity onto the principal names that its own ACLs grant.

go deeper

for a junior

Know mTLS authenticates the client cert and that the principal comes from the certificate DN.

for a middle

Write a basic RULE to extract CN and understand it ends with DEFAULT.

for a senior

Reason about per-cluster PKIs, broker-side evaluation, and convergence of MM2's principal onto each cluster's ACLs.

for a principal

Standardize DN/SAN conventions and mapping-rule patterns org-wide so identities are stable and auditable across many clusters.

## Background: what mutual TLS authenticates In one-way TLS only the **server** (broker) proves its identity. In **mutual TLS (mTLS)** the **client** also presents a certificate, and the broker validates it against the broker's **truststore** (the set of trusted CA certificates). If the chain validates and isn't expired/revoked, the client is authenticated. But authentication only proves the cert is valid — Kafka still needs to turn the certificate into an **identity it can authorize**. That identity is a `KafkaPrincipal`, written `User:<name>`. ## Default principal = the whole DN A certificate's **subject** is a **Distinguished Name (DN)**: an ordered set of attributes like `CN` (Common Name), `OU` (Organizational Unit), `O` (Organization), `L`, `C`. By default Kafka uses the *entire* DN as the principal name, e.g.: ``` User:CN=mm2,OU=replication,O=Acme Corp,L=NYC,ST=NY,C=US ``` Problems: it's long, it embeds attributes that change when you re-issue certs (new OU, new location), and any drift breaks every ACL that hard-codes the string. ## ssl.principal.mapping.rules This **broker** property (not a client property) post-processes the DN into a clean principal. It's an ordered, comma-separated list of rules: ``` ssl.principal.mapping.rules=RULE:^CN=(.*?),.*$/$1/ , DEFAULT ``` Each `RULE:pattern/replacement/[LU]`: - `pattern` is a regex applied to the DN. - `replacement` builds the principal name using capture groups (`$1`, `$2`). - optional trailing `L` (lowercase) or `U` (uppercase). Rules are tried **in order**; the first match wins. `DEFAULT` (use the full DN) should be last as a fallback. The example above extracts the CN, so `CN=mm2,OU=replication,...` → principal name `mm2` → `KafkaPrincipal` `User:mm2`. ## Why this matters specifically across clusters MM2 connects to **two** clusters that are usually administered separately, with **different PKIs**. The source cluster's CA might issue MM2 a cert with DN `CN=mm2-source,OU=...`, while the target's CA issues `CN=mm2-target,OU=...`. Each cluster: 1. Validates MM2's cert against **its own** truststore (so MM2 may need different keystores per side — `source.ssl.keystore.location` vs `target.ssl.keystore.location`). 2. Maps the DN to a principal via **its own** `ssl.principal.mapping.rules`. 3. Grants ACLs to **that** principal. Getting principal mapping consistent on both ends is the practical core of 'principal mapping across clusters'. If the rule on the target doesn't fire, ACLs written for `User:mm2` silently never match the actual principal `User:CN=mm2-target,...`, and replication fails with authorization errors that look like a missing ACL. ## SASL analog For SASL/GSSAPI (Kerberos) the equivalent is `sasl.kerberos.principal.to.local.rules`. For SASL/SCRAM and PLAIN the principal is simply the username; for OAUTHBEARER it comes from a configurable claim. Each cluster maps independently. ## Edge cases / gotchas - Mapping rules are evaluated **broker-side at authentication time**; changing them requires a broker restart (they're not dynamic). - A too-greedy regex can collapse two distinct certs onto the **same** principal, silently widening access — keep rules tight and test with `kafka-acls`/authorizer logs. - DN attribute **ordering and escaping** (RFC 2253) matters; commas inside values must be accounted for in the regex. - Certificate **revocation** (CRL/OCSP) is separate from principal mapping; a mapped principal still works until the cert is rejected by the chain check.

  • Is ssl.principal.mapping.rules a client or broker config?
    Broker config. The broker derives the principal at authentication time, so the mapping lives on each broker and requires a restart to change. The client only supplies the certificate.
  • What goes wrong if the source and target clusters map MM2's DN to different principal names?
    Nothing inherently — that's expected. You just have to grant the correct per-cluster principal in each cluster's ACLs. The failure mode is forgetting and writing ACLs for a principal the mapping never actually produces.

saying these in an interview costs you the question

  • Claiming the principal is taken from the certificate's CN automatically (it's the full DN unless you add mapping rules)
  • Saying ssl.principal.mapping.rules is a client-side setting
  • Assuming one mapping rule set covers both clusters when they have separate PKIs
  • Using an overly broad regex that collapses multiple identities into one principal

context