Identifiers Filter
The identifiers filter controls which domains, IPs, or URIs a client is
allowed to request a certificate for. This is crucial for preventing a
compromised client from requesting a certificate for a sensitive internal
domain.
Type flattening and cn handling
A Certificate Signing Request (CSR) can contain identifiers in multiple places
(Subject Alternative Names (SANs) and the legacy Subject Common Name (CN)).
acme-proxy flattens all of these into a single list of typed identifiers
(dns, ip, email, uri, other, cn).
- Deny applies everywhere: A
denyrule applies to every single type. If you deny*.evil.com, a client cannot sneak it into the Subject Common Name to bypass the filter. - Allow skips
cn:allowrules explicitly skip thecntype (SUBJECT_ONLY_TYPES). A CN is legacy metadata and often contains human labels (e.g.,"rcgen self signed cert"). It is not a true identifier the certificate is for, so it is exempt from strict allow-listing.
What reaches the filter
An order’s dns identifiers are checked for shape before any rule runs: a
value that is not a DNS name is malformed, and one the URL parser would read
as an IPv4 or IPv6 address — 10.0.0.5, but also 2130706433 or 0x7f.1,
which name 127.0.0.1 — is rejectedIdentifier. A rule written for names
therefore never has to anticipate an address spelled as one.
Regex anchoring
All matching is performed via Regular Expressions (Regex).
Security Notice:
acme-proxyautomatically anchors all regexes as^(?:pattern)$and makes them case-insensitive. You do not need to manually anchor your regexes. This prevents substring bypasses (e.g., an unanchoredexample\.comwould accidentally matchexample.com.evil.net).
Configuration
[filter]
rules = ["corp-names-only"]
[filter.check.corp-names]
type = "identifiers"
allowed_types = ["dns", "cn"]
allow = ["*.corp.example.com", "corp.example.com"]
deny = ["secret.corp.example.com"]
allow_wildcards = false
[filter.rule.corp-names-only]
when = "corp-names"
then = "allow"
allow/deny take globs, where * is one label — so *.corp.example.com does
not cover corp.example.com and both are listed, exactly as they would be in a
certificate. allow_regex/deny_regex take anchored regexes and are unioned
with the globs, for what a glob cannot express. The keys and their defaults are
documented under Checks.
Two instances of this type with different lists are ordinary, which is the usual way to say “these names from this network, those names from that one”:
[filter.rule.tenant-a]
when = "tenant-a-net and tenant-a-names"
then = "allow"
[filter.rule.tenant-b]
when = "tenant-b-net and tenant-b-names"
then = "allow"