Allow verify_and_map to derive identity from any certificate attribute, not just email/SAN/DN

Author: edjeffreysCreated Jul 17, 2026Updated Sep 12, 2026
Labelsstaleproposal

Proposed change

verify_and_map currently derives a client's identity from a fixed precedence — email address, then SAN, then Distinguished Name - and matches the result literally against a configured user. This proposes making verify_and_map accept a template string (Go text/template) as an alternative to true:

verify_and_map: "{{ first .OrganizationalUnit }}"

The template is executed against the peer certificate's Subject and SAN fields (CN, O, OU, L, ST, C, SerialNumber, DNS names, emails, IPs, URIs), plus two helpers for multi-valued attributes: has (membership test) and first (first value). Fields can be combined with the language's own and/or/eq to derive an identity from more than one attribute, e.g.:

verify_and_map: '{{if and (has "infra" .OrganizationalUnit) (has "GB" .Country)}}infra-gb{{end}}'

This is fully backward compatible: verify_and_map: true/false keep their exact current behavior unchanged, the template form is opt-in, and a template referencing a nonexistent field is rejected at config load rather than failing silently on first connect.

Use case

Today, every distinct client certificate has to be individually enumerated as a configured user, even when a whole group of certificates should share the same access - e.g. any certificate issued to an "infrastructure" OU, or a specific team/service tier. There's no way to grant access by an attribute of the certificate rather than by the certificate's exact identity, which doesn't scale for organisations issuing many individual mTLS certificates (one per service or person) that should nonetheless share a single set of permissions.

Being able to map on OU (or a combination of attributes) lets an operator authorise "anyone with a cert from this OU" once, instead of maintaining a per-certificate user list that has to be updated every time a certificate is issued, rotated, or revoked for an individual within that group.

Contribution

Yes; I have a draft contribution #8392