Vault Error: 'common name not allowed by this role' When Issuing a PKI Certificate
Fix Vault PKI 'common name not allowed by this role': tune allowed_domains, allow_subdomains, allow_bare_domains and glob matching, SAN restrictions, and TTL caps without using allow_any_name.
- #vault
- #secrets
- #security-hardening
- #troubleshooting
- #errors
Stuck on this HashiCorp Vault error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
$ vault write pki/issue/example-dotcom common_name="app.internal.example.com" ttl="72h"
Error writing data to pki/issue/example-dotcom: Error making API request.
URL: PUT https://vault.example.com:8200/v1/pki/issue/example-dotcom
Code: 400. Errors:
* common name app.internal.example.com not allowed by this role
The same validator rejects alternative names separately:
Code: 400. Errors:
* subject alternate name 10.4.2.19 not allowed by this role
What It Means
Every certificate request in Vault’s PKI secrets engine is validated against a role, which is a named policy describing what the issuing CA is willing to sign. The role holds an allow-list of domains plus a set of switches controlling how those domains may be extended. When you call pki/issue/<role> or pki/sign/<role>, Vault checks the requested common_name against that list before it ever touches the CA key. not allowed by this role means the name failed that check — the request never reached the signing stage, so nothing was issued and no serial was consumed.
The check is stricter than most people expect. allowed_domains=example.com on its own permits nothing at all: it needs allow_bare_domains to permit example.com itself, or allow_subdomains to permit app.example.com, and even then app.internal.example.com is only allowed because allow_subdomains matches at any depth. Subject alternative names are validated by their own fields, so a request can pass the common-name check and still fail on a DNS SAN, IP SAN, URI SAN, or other SAN. Reading the role is almost always faster than guessing which switch is missing.
Common Causes
allowed_domainslists the parent domain butallow_subdomainsis false, so only the exact string would match.- The request uses the bare domain (
example.com) whileallow_bare_domainsis false. - The name lives under a different suffix entirely —
internal.example.comvs anallowed_domainsofexample.net. - A wildcard or pattern was expected to work, but
allow_glob_domainsis false so*inallowed_domainsis treated literally. enforce_hostnamesis on and the requested name is not a valid hostname (underscores, trailing dots, raw IPs).- The name is fine but an
ip_sans,uri_sans, orother_sansvalue is rejected byallowed_ip_sans/allowed_uri_sans/allowed_other_sans.
Diagnostic Commands
Read the role and look at every allow* field together, not just allowed_domains:
vault read pki/roles/example-dotcom
Get the same data as JSON so you can diff it against another environment:
vault read -format=json pki/roles/example-dotcom | jq '.data'
List the roles on the mount in case you are writing to the wrong one:
vault list pki/roles
Reproduce the failure with the exact name and SANs your client sends:
vault write pki/issue/example-dotcom \
common_name="app.internal.example.com" \
alt_names="app.example.com" \
ip_sans="10.4.2.19" \
ttl="72h"
Check the issuing CA’s own expiry, since it caps every leaf certificate:
vault read pki/cert/ca | openssl x509 -noout -subject -dates
Confirm the mount’s TTL ceiling, which caps the role’s max_ttl:
vault read sys/mounts/pki/tune
Step-by-Step Resolution
- Read the role and identify precisely which rule the name violates. Compare the requested name against
allowed_domains, then check whether it is the bare domain, a subdomain, or an unrelated suffix:
vault read pki/roles/example-dotcom
- If the name is a subdomain of an allowed domain, turn on subdomain matching. This is the single most common fix and covers names at any depth beneath the listed domain:
vault write pki/roles/example-dotcom \
allowed_domains="example.com" \
allow_subdomains=true \
max_ttl="720h"
- If you also issue for the apex, add
allow_bare_domains. The two flags are independent — enabling subdomains does not implicitly permitexample.comitself:
vault write pki/roles/example-dotcom \
allowed_domains="example.com" \
allow_subdomains=true \
allow_bare_domains=true \
max_ttl="720h"
- For a name under a distinct internal suffix, add that suffix rather than widening the existing entry.
allowed_domainsaccepts a comma-separated list, and glob patterns requireallow_glob_domains:
vault write pki/roles/internal-services \
allowed_domains="internal.example.com,svc.cluster.local" \
allow_subdomains=true \
allow_glob_domains=true \
allowed_domains_template=false \
max_ttl="720h"
Set allowed_domains_template=true only when you intend allowed_domains to contain identity templating such as {{identity.entity.metadata.domain}}, which resolves per-caller at issue time.
- Fix the SAN rejection separately. Each SAN class has its own allow-list, and an empty list means “none permitted”:
vault write pki/roles/internal-services \
allowed_domains="internal.example.com" \
allow_subdomains=true \
allowed_ip_sans="10.4.0.0/16" \
allowed_uri_sans="spiffe://example.com/*" \
allowed_other_sans="1.3.6.1.4.1.311.20.2.3;utf8:*@example.com"
If the requested name is a raw IP or a non-hostname string, you will also need to consider enforce_hostnames=false — but prefer putting the IP in ip_sans with a proper allowed_ip_sans CIDR, and keep hostname enforcement on. Use allow_localhost=true only for developer or test roles.
- Re-issue and verify what actually came back, including the TTL. A leaf can never outlive the issuing CA, so a request for
8760hagainst a CA with three months left silently returns a shorter certificate:
vault write -format=json pki/issue/internal-services \
common_name="app.internal.example.com" \
ttl="720h" | jq -r '.data.certificate' | openssl x509 -noout -text | head -20
If the issue call now returns a 403 rather than a 400, the role is correct and the problem has moved to the token’s capabilities on pki/issue/* — see Vault error: “permission denied on path”. If clients reject the resulting certificate, the CA chain is the likely culprit rather than the role; Vault error: “certificate signed by unknown authority” covers distributing the issuing chain.
Prevention
- Define one role per domain scope — public web, internal services, mesh workloads — rather than one permissive role for everything.
- Keep roles in Terraform or a versioned script so
allow_subdomainsand friends are reviewed rather than toggled ad hoc in production. - Set
max_ttlon each role well below the issuing CA’s remaining lifetime, and rotate the intermediate before leaf TTLs start being truncated. - Never set
allow_any_name=trueon a role reachable by application tokens; it disables domain validation entirely and turns the CA into a signing oracle for any name a caller invents. - Populate the SAN allow-lists explicitly, including empty ones, so a future request cannot smuggle an unexpected URI or other SAN into a certificate.
- Add a CI check that issues a representative certificate from each role after any change to the PKI mount.
Related Errors
role not found— the role name in the path is wrong or lives on a different PKI mount.ttl is larger than maximum allowed by this role— the request exceededmax_ttlrather than failing name validation.cannot satisfy request, as TTL would result in notAfter which is beyond the expiration of the CA certificate— the issuer, not the role, is the limit.permission denied— the token cannot write topki/issue/<role>at all, so validation never ran.
Frequently Asked Questions
Why does allowed_domains=example.com reject example.com itself? Because the bare apex is governed by allow_bare_domains, which defaults to false. Vault treats “the domain” and “names under the domain” as two separate permissions so you can grant one without the other.
Does allow_subdomains match more than one label deep? Yes. With allowed_domains=example.com and allow_subdomains=true, both app.example.com and app.internal.example.com are accepted. If you need to restrict depth, list the specific intermediate domains instead.
Is allow_any_name ever acceptable? Only on a short-lived, tightly restricted role that no application token can reach — for example a break-glass path guarded by its own policy and audited. On any normal issuing role it removes the main control the PKI engine provides. Reach for extra allowed_domains entries or an additional role first.
Why is my certificate shorter than the TTL I asked for? The effective lifetime is the smallest of the request TTL, the role’s max_ttl, the mount’s tuned max lease TTL, and the issuing CA’s remaining validity. Check the CA’s notAfter before assuming the role is at fault. More PKI and secret-engine fixes are collected in the Vault guides.
Fixed it? Get 500 HashiCorp Vault & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.