<a id="tls-principal-mapping"></a>

# Use Principal Mapping in Confluent Platform

Principal mapping transforms long or complex identities from Transport
Layer Security (TLS) certificates into short, user-friendly principal
names in Confluent Platform. When a client connects, Confluent Platform extracts the identity from
the certificate and applies mapping rules to produce a principal. The
principal can represent a user or service account for authentication,
authorization, and quota enforcement.

## Uses for mapped principals

* **Access control lists (ACLs) and role-based access control (RBAC):** Enforces permissions using the
  shortened principal name instead of the raw certificate string.
* **Client quotas:** Enforces [client quotas](../../../kafka/post-deployment.md#quotas) on the mapped
  principal identity.
* **Simplified certificate management:** Allows managing client permissions by
  mapped identity rather than tracking individual certificates.
* **External system integration:** Maps certificate identities directly to
  user accounts or service roles in external identity providers.

Mapping a certificate to a principal involves three steps:

1. Identify whether the certificate source is the
   [Subject DN](#distinguished-name-attributes) or the
   [SAN URI](#subject-alternative-name-san-uri).
2. Define mapping rules using `RULE:` or `SANURIRULE:` syntax. For
   details, see [Principal mapping rules format](#principal-mapping-rules-format).
3. Apply the rules to your component configuration. For details, see
   [Configure principal mapping rules per component](#configure-principal-mapping-rules-per-component).

Before configuring principal mapping, set up mutual TLS (mTLS) authentication as described in
[Use TLS Authentication in Confluent Platform](overview.md#tls-authentication).

<a id="distinguished-name-attributes"></a>

## Distinguished Name (DN) attributes

A Distinguished Name (DN) is a sequence of X.500 attributes that uniquely
identifies the subject of a TLS certificate.

Example DN:

```properties
CN=writeuser,OU=Engineering,O=Confluent,L=Palo Alto,ST=CA,C=US
```

When parsing a DN, Confluent Platform evaluates X.500 attributes in the following order:

| Key   | Attribute name (X.520)   | Example value   |
|-------|--------------------------|-----------------|
| `CN`  | commonName               | `writeuser`     |
| `OU`  | organizationalUnitName   | `Engineering`   |
| `O`   | organizationName         | `Confluent`     |
| `L`   | localityName             | `Palo Alto`     |
| `ST`  | stateOrProvinceName      | `CA`            |
| `C`   | countryName              | `US`            |

You can add custom DN mapping rules to the `ssl.principal.mapping.rules`
property in your component configuration files. For example,
`broker.properties`, `controller.properties`, or `server.properties`.
For rule syntax, see [Principal mapping rules format](#principal-mapping-rules-format).

Rules are evaluated in order. The first rule that matches a DN maps the
principal, and Confluent Platform ignores later rules.

<a id="subject-alternative-name-san-uri"></a>

## Subject Alternative Name (SAN) URI

A Subject Alternative Name (SAN) is a certificate extension that specifies
more identities for the subject. While SAN extensions can contain Domain
Name System (DNS) names or Internet Protocol (IP) addresses, Confluent Platform
principal mapping specifically supports URI-type SAN entries.

Example SAN URI entry:

```text
URI:aprn:myorg:certmgr:::person-v2:/pid/123456/uv/
```

Use a SAN URI as the identity source when:

* The certificate’s Subject DN doesn’t contain a usable identity.
* Your organization formats client identities as URIs, such as Amazon
  Resource Names (ARNs), SPIFFE (Secure Production Identity Framework For
  Everyone) IDs, or custom URI schemes.

A certificate can contain zero, one, or multiple URI SAN entries. Confluent Platform
extracts all URI SAN entries from the leaf certificate and evaluates your
`SANURIRULE:` expressions against each entry, in order, until one
matches. For rule syntax, see [Principal mapping rules format](#principal-mapping-rules-format).
Blank or malformed entries are ignored.

#### NOTE
Only URI-type SAN entries with `GeneralName` type 6 are supported.
Other SAN types are not read for principal mapping. This includes
DNS names, IP addresses, and `otherName` entries such as SPIFFE or
X.509-SVID identifiers.

<a id="principal-mapping-rules-format"></a>

## Principal mapping rules format

Specify mapping rules as a comma-separated list in
`ssl.principal.mapping.rules`. Each rule starts with a tag indicating
which part of the certificate it targets:

* `RULE:` matches against the Subject DN. This is the default rule type. Untagged rules
  and `DEFAULT` target the Subject DN, preserving backward compatibility for
  existing configurations.
* `SANURIRULE:` matches against a URI-type SAN entry. Use this tag to map identities stored
  in the certificate’s SAN extension instead of its Subject DN.

Both rule types share the same syntax, and you can mix `RULE:` and
`SANURIRULE:` entries in the same property value. Each rule type is only
tested against matching candidate strings. `SANURIRULE:` is never tested
against a Subject DN, and `RULE:` is never tested against a SAN URI.

### Principal mapping rule syntax

A rule follows the format: `TAG:pattern/replacement/[LU]`

* **Shorthand character classes:** Use double backslashes for shorthand
  character classes. For example, `\\d` for digits, `\\w` for word
  characters, `\\s` for whitespace, and `\\p{L}` for Unicode letters.
* **Escaping special characters:** Escape literal regex special characters with
  an extra backslash. For example, `\\.` for a literal dot.
* **Escaping forward slashes:** Because `/` delimits the rule sections,
  escape literal forward slashes in patterns:
  * **\`\`.properties\`\` files:** Use a double backslash. For example,
    `https:\\/`.
  * **YAML files:** Use a single backslash for components such as Flink and
    Confluent Manager for Apache Flink. For example, `https:\/`.
* **Case conversion:** Append `/U` or `/L` to the end of the rule to force
  the output to uppercase or lowercase.

Example rules:

```text
RULE:^CN=(.*?),OU=ServiceUsers.*$/$1/,
RULE:^CN=(.*?),OU=(.*?),O=(.*?),L=(.*?),ST=(.*?),C=(.*?)$/$1@$2/L,
RULE:^.*[Cc][Nn]=([a-zA-Z0-9.]*).*$/$1/L,
DEFAULT
```

These rules translate the following DNs into mapped principals:

| Certificate DN                                                            | Mapped principal   |
|---------------------------------------------------------------------------|--------------------|
| `CN=serviceuser,OU=ServiceUsers,O=Unknown,L=Unknown,ST=Unknown,C=Unknown` | `serviceuser`      |
| `CN=adminUser,OU=Admin,O=Unknown,L=Unknown,ST=Unknown,C=Unknown`          | `adminuser@admin`  |

<a id="rule-evaluation-order-for-mixed-rule-types"></a>

### Rule evaluation order for mixed rule types

Confluent Platform evaluates rules strictly in the order listed. The first matching
rule of either type wins, even when a certificate contains both a
Subject DN and one or more SAN URIs as candidate strings.

To order a mixed list of rules, follow these guidelines:

* **List specific rules first:** Place narrow, explicit regular expressions
  before broader ones.
* **Order by preferred source:** If you prefer SAN URIs over Subject
  DNs when both exist, list all `SANURIRULE:` entries before your `RULE:`
  entries.
* **Include a fallback rule:** End rule lists with a fallback, such as
  `DEFAULT` for Subject DN or a catch-all `SANURIRULE:`, so unmatched
  certificates map predictably rather than failing authentication.

<a id="san-uri-mapping-rule-examples"></a>

### SAN URI mapping rule examples

The following examples show how SAN URI mapping rules extract a principal
from different certificate SAN entry formats. The `URI:` prefix in the
“Certificate SAN entry” column is a display label, not part of the value.
`SANURIRULE:` patterns match the URI value alone, without that prefix.

| Rule                                                                                            | Certificate SAN entry                                                                     | Extracted principal     |
|-------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|-------------------------|
| `SANURIRULE:^aprn:myorg:certmgr:::person-v2:\\/pid\\/(\\d+)\\/uv\\/$/$1/`                       | `URI:aprn:myorg:certmgr:::person-v2:/pid/123456/uv/`                                      | `123456`                |
| `SANURIRULE:^arn:aws:iam::\\d+:role\\/(.+)$/$1/`                                                | `URI:arn:aws:iam::123456789012:role/PaymentsServiceRole`                                  | `PaymentsServiceRole`   |
| `SANURIRULE:^https:\\/\\/api\\.github\\.com\\/repos\\/([^\\/]+)\\/([^\\/]+)\\/issues.*$/$1-$2/` | `URI:https://api.github.com/repos/confluentinc/ce-kafka/issues?state=open`                | `confluentinc-ce-kafka` |
| `SANURIRULE:^https:\\/\\/([^:]+):[^@]+@.*$/$1/`                                                 | `URI:https://alice:pass@confluent.io:8443/api/v1/users?id=42&active=true#profile-section` | `alice`                 |

<a id="configure-principal-mapping-rules-per-component"></a>

## Configure principal mapping rules per component

Set principal mapping rules using the appropriate property for each
component or feature:

| Component or feature                 | Configuration property                                       |
|--------------------------------------|--------------------------------------------------------------|
| mTLS per listener                    | `listener.name.<listener-name>.ssl.principal.mapping.rules`  |
| RBAC, through Metadata Service (MDS) | `confluent.metadata.server.auth.ssl.principal.mapping.rules` |
| Confluent Schema Registry            | `confluent.schema.registry.auth.ssl.principal.mapping.rules` |
| Confluent REST Proxy                 | `confluent.rest.auth.ssl.principal.mapping.rules`            |

To set default rules for all listeners on a broker, configure
`ssl.principal.mapping.rules` in the broker configuration files, such as
`server.properties`.

All listed components support Subject DN mapping. To view components that
support SAN URI mapping, see [SAN URI mapping support by component](#tls-principal-mapping-san-uri-components).

<a id="tls-principal-mapping-san-uri-components"></a>

## SAN URI mapping support by component

SAN URI mapping (`SANURIRULE:`) works on all Confluent Platform components that
authenticate clients using mTLS:

* Apache Kafka® broker
* Schema Registry
* Confluent REST Proxy
* Kafka Connect
* ksqlDB
* Metadata Service (MDS)
* Apache Flink®, through Confluent Manager for Apache Flink

#### NOTE
SAN URI mapping only applies to certificate-based mTLS authentication
and has no effect on non-certificate authentication mechanisms such as
OAuth/OpenID Connect (OIDC) or the Lightweight Directory Access Protocol
(LDAP).

<a id="security-considerations"></a>

## Security considerations for SAN URI principal mapping

* **Truststore governance:** A SAN URI is only as trustworthy as the
  certificate authority (CA) that issued it. Enable `SANURIRULE:` mapping
  only on listeners or components whose truststore you control and trust.
* **Fail-closed processing:** If a SAN entry is malformed or unparsable,
  Confluent Platform drops the entry rather than assigning an unverified identity.
* **Log sanitization:** Confluent Platform sanitizes SAN values before writing them to
  logs to prevent log injection.
