Part VI: Running PKI · Chapter 22
A CA of your own: private two-tier PKI
In one sentence
A private CA lets you issue certificates for internal systems under your own rules, built safely as an offline root plus an online issuing CA with clear policies and templates.
Who is this for
Level: Expert
On this page
The idea
- Beginner
Public CAs issue certificates that every browser trusts, but only for public names they can check, and only under the public rules of the CA/Browser Forum. Many certificates are not for the public at all. They protect internal websites, APIs between services, databases, VPN and Wi-Fi logins, devices and mutual TLS between machines.
For these, many organisations run a private CA: a certificate authority of their own, whose root certificate they install on their own devices. Nobody else trusts it, and that is the point. Inside your organisation you decide the rules: which names, which lifetimes, which key types, who may ask for what. You also carry the whole responsibility. If your private CA is careless, everything that trusts it is exposed (see Who do we trust?).
A well-built private PKI has three parts:
- A hierarchy. An offline root that is used only rarely, and an online issuing CA that does the daily work. This is the classic two-tier PKI.
- Written rules. A certificate policy (CP) says what must be true. A certification practice statement (CPS) says how your CA makes it true.
- Templates or profiles, which turn the rules into settings: what each kind of certificate may contain and who may request it.
Done well, a private CA is as trustworthy as a public one for its purpose. Done badly, it is a quiet way to let anyone inside your network impersonate anyone else.
How it really works
- Developer
- Expert
Why two tiers?
Microsoft’s AD CS documentation puts the reason plainly: “If your root CA is compromised, all CAs in the hierarchy and all certificates issued from it are considered compromised. You can maximize the security of the root CA by keeping it disconnected from the network and by using subordinate CAs to issue certificates.” A disconnected root is called an offline root.
- The root CA is self-signed and long-lived. Its key sits in an HSM or on protected media in a safe (see Guarding the keys). It signs only issuing CA certificates and its own CRLs, in short ceremonies.
- The issuing CA is online and signs end-entity certificates every day. Its certificate carries
pathLenConstraint0, which “indicates that no non-self-issued intermediate CA certificates may follow” it (RFC 5280 section 4.2.1.9), so it cannot create further CAs.
If the issuing CA is compromised, you revoke it from the root and build a new one. The root, and the trust you installed on every device, survive. Large organisations sometimes add a middle tier of policy CAs, but two tiers suit most.
One operational detail catches many teams out. The offline root still publishes a CRL for the CA certificates it issued, and that CRL has a nextUpdate date. If nobody brings the root out to sign a fresh CRL in time, clients that check revocation start to reject the whole hierarchy. Put the root’s CRL schedule in the calendar of the people who hold the keys.
What are the CP and the CPS?
Both follow the framework of RFC 3647, the same outline that public CAs and the CA/Browser Forum’s own requirements use. RFC 3647 defines them:
- A certificate policy is “a named set of rules that indicates the applicability of a certificate to a particular community and/or class of application with common security requirements.”
- A certification practice statement is “a statement of the practices that a certification authority employs in issuing, managing, revoking, and renewing or re-keying certificates.”
Section 3.5 sums up the difference: the CP establishes “what participants must do”, and the CPS discloses “how the participants perform their functions and implement controls”. Both use the same nine sections: introduction; publication and repository; identification and authentication; certificate life-cycle operations; facility, management and operational controls; technical security controls; certificate, CRL and OCSP profiles; compliance audit; and other business and legal matters. A small organisation often writes one combined CP/CPS. What matters is that it is written down, approved and followed.
What belongs in a template or profile?
A template turns policy into settings for one kind of certificate:
- key type and size, and whether the key is generated by the requester or kept in hardware;
- lifetime;
- key usage and extended key usage: server authentication, client authentication or code signing, and nothing more than needed;
- where the names come from: from your directory, or typed in by the requester;
- who may enrol, and whether a person must approve each request;
- CRL and AIA addresses, so that clients can find the chain and the revocation status.
The name source is the most important line. A template that lets requesters choose any subject name can let them impersonate others, including administrators, wherever that CA is trusted. Restrict it. Take names from the directory wherever you can. If a template must accept names from the request, limit who may enrol, require a person to approve each request, and check every name before it is approved.
How do name constraints limit a CA?
A CA certificate can carry a Name Constraints extension, which “MUST be used only in a CA certificate” and “indicates a name space within which all subject names in subsequent certificates in a certification path MUST be located” (RFC 5280 section 4.2.1.10). Permitted subtrees list what is allowed; excluded subtrees list what is forbidden. An issuing CA constrained to corp.example cannot produce a certificate for www.example.com that clients which enforce name constraints will accept, even if its key is misused. The RFC says CAs “MUST mark this extension as critical”; the Baseline Requirements allow non-critical marking only “if compatibility with certain legacy applications that do not support Name Constraints is necessary” (section 7.1.2.10.8). The lab below shows the effect.
What does this look like in AD CS?
Active Directory Certificate Services (AD CS) is the most common private CA in Windows networks. The usual design is a standalone root CA that stays offline and an enterprise issuing CA joined to the domain. Microsoft notes that “Stand-alone CAs don’t require AD DS, and they don’t use certificate templates”, while enterprise CAs issue from templates and can enrol computers and users automatically.
Templates are where most AD CS risk sits. Microsoft’s guidance on managing templates says: “Prefer identity information from AD DS. If you enable Supply in the request, restrict enrollment and validate every permitted identity value because the requester supplies subject information.” The same page warns that a CA-wide setting, EDITF_ATTRIBUTESUBJECTALTNAME2, lets requesters add alternative names regardless of the template, so confirm that it is disabled. Microsoft Defender for Identity calls the Supply in the request setting “one of the most common misconfigurations”. Its fixes include turning that setting off or turning on CA certificate manager approval for such templates.
Windows domain controllers have also tightened how they map certificates to accounts. Under KB5014754, mappings “are considered strong if they are based on identifiers that you cannot reuse”, and since February 2025, domain controllers deny certificate sign-in when a certificate cannot be strongly mapped to an account. Certificates from older templates or third-party CAs may need the new mapping before they work for sign-in.
Private ACME and short-lived certificates
A private CA does not have to mean manual requests. Many private CA products speak ACME, so the same clients that renew public certificates can renew internal ones. smallstep’s step-ca, for example, issues certificates with “much shorter 24 hour lifetimes” by default. Short lifetimes suit internal PKI well: services renew automatically, and a stolen key stops working soon even where nobody checks revocation (see Revocation).
Managed private CAs move the HSM, the availability and much of the auditing to a provider. AWS Private CA, for example, “enables creation of private certificate authority (CA) hierarchies, including root and subordinate CAs, without the investment and maintenance costs of operating an on-premises CA” (AWS). Google Cloud offers a similar Certificate Authority Service. You still own the policy, the templates and the decision of who may request what.
When should you not run your own CA?
- For anything the public reaches. Browsers and customers’ devices will not trust your root, and asking them to install it is a security risk in itself. Use a public CA with ACME.
- When nobody will own it. A private CA needs key custodians, ceremonies, a CRL schedule, monitoring, backups and documentation for years. If you cannot staff that, use a managed service.
- To save money on public certificates. Public DV certificates are free through ACME. A private CA is for names and uses that public CAs cannot or should not cover.
- For partners and customers. If they have to trust your root, constrain it to your names, or use publicly trusted certificates instead.
At work
- Developer
- IT ops
Build a lab two-tier PKI with name constraints
This lab uses OpenSSL with keys in files, which is fine for learning and wrong for production, where the root key belongs in an HSM and is created in a ceremony. The issuing CA’s extension file sets pathlen:0 and limits it to corp.example:
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign
nameConstraints = critical, permitted;DNS:corp.example
Create the root, then let it sign the issuing CA:
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-384 -nodes \
-keyout root.key -out root.pem -days 3650 -subj "/CN=Example Lab Root" \
-addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
-keyout issuing.key -out issuing.csr -subj "/CN=Example Lab Issuing CA"
openssl x509 -req -in issuing.csr -CA root.pem -CAkey root.key -CAcreateserial \
-out issuing.pem -days 1825 -extfile issuing.ext
openssl x509 -in issuing.pem -noout -subject -issuer -ext basicConstraints,nameConstraints
subject=CN=Example Lab Issuing CA
issuer=CN=Example Lab Root
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Name Constraints: critical
Permitted:
DNS:corp.example
The issuing CA then signed two server certificates in the same way: one for app.corp.example and one for www.example.com. Verifying both against the root shows the constraint at work:
openssl verify -CAfile root.pem -untrusted issuing.pem app.pem
openssl verify -CAfile root.pem -untrusted issuing.pem www.pem
app.pem: OK
CN=www.example.com
error 47 at 0 depth lookup: permitted subtree violation
error www.pem: verification failed
The CA signed the second certificate without complaint. The client refused it, because the name lies outside the CA’s permitted space. Leave out -CAfile root.pem, so that the root is not trusted, and you get the most common private-CA error of all:
CN=Example Lab Issuing CA
error 20 at 1 depth lookup: unable to get local issuer certificate
error app.pem: verification failed
The chain checker shows the same path step by step:
How do I distribute the root?
Every client that should trust your CA needs the root in its trust store. First compare its SHA-256 fingerprint with the one in the ceremony report. Then, for example:
# Debian and Ubuntu: the file must end in .crt
sudo cp root.pem /usr/local/share/ca-certificates/example-lab-root.crt
sudo update-ca-certificates
# Java (asks for the cacerts password)
keytool -importcert -cacerts -alias example-lab-root -file root.pem
# Windows, as administrator; in a domain, use Group Policy instead
Import-Certificate -FilePath root.cer -CertStoreLocation Cert:\LocalMachine\Root
Node.js reads extra roots from NODE_EXTRA_CA_CERTS, and Python’s requests uses its own bundle unless told otherwise. Each runtime that is missing the root fails in its own words: OpenSSL error 20, curl’s self-signed certificate in chain, Java’s PKIX path building failed and Go’s unknown authority. The fix is always to add the root, never to switch verification off.
To inspect a root you were given before you install it, paste it into the decoder:
Common mistakes
- “A private CA is less secure than a public one.” It is exactly as secure as you run it. With an offline root, an HSM, clear templates and monitoring, it can be very strong. Without them, it is weak.
- “The CP and the CPS are the same document.” The CP says what must be true. The CPS says how this CA makes it true. They may be combined in one file, but both questions need answers.
- “Keeping the root online is more convenient.” It is, for attackers too. Keep it offline and bring it out only for ceremonies, including its CRL updates.
- “Requesters can type any name; the CA will check.” A CA signs what its template allows. Take names from the directory, or restrict enrolment and require approval.
- “Internal services can skip verification.” Distribute the root instead. Turning verification off removes the protection the CA exists to give.
Why it matters to the business
- Leader
Check yourself
Why is the root CA in a two-tier PKI kept offline?
RightNot quite The answer is B: So that its key is rarely exposed; a compromised issuing CA can be revoked and replaced while the root survives
- What happened
- The root is used only to sign issuing CAs and its CRLs, in ceremonies.
- Why
- If the root is compromised, the whole hierarchy is. If an issuing CA is compromised, the root can revoke it.
- The rule
- Offline root, online issuing CA, and the root's CRL renewed on schedule.
Show answer
Answer B So that its key is rarely exposed; a compromised issuing CA can be revoked and replaced while the root survives
- What happened
- The root is used only to sign issuing CAs and its CRLs, in ceremonies.
- Why
- If the root is compromised, the whole hierarchy is. If an issuing CA is compromised, the root can revoke it.
- The rule
- Offline root, online issuing CA, and the root's CRL renewed on schedule.
A certificate template lets requesters type any subject name and issues without approval. What is the risk?
RightNot quite The answer is B: Requesters can obtain certificates in other people's names and impersonate them
- What happened
- The CA signs whatever names the template allows the requester to supply.
- Why
- Systems that trust the CA accept those certificates as proof of identity.
- The rule
- Take names from the directory, or restrict enrolment and require approval.
Show answer
Answer B Requesters can obtain certificates in other people's names and impersonate them
- What happened
- The CA signs whatever names the template allows the requester to supply.
- Why
- Systems that trust the CA accept those certificates as proof of identity.
- The rule
- Take names from the directory, or restrict enrolment and require approval.
An issuing CA is name-constrained to corp.example. It signs a certificate for www.example.com. What happens when a client that enforces name constraints verifies it?
RightNot quite The answer is B: The client rejects it with a permitted subtree violation
- What happened
- The name lies outside the CA's permitted name space, so path validation fails.
- Why
- Name constraints in a CA certificate apply to every certificate below it in the chain.
- The rule
- Constrain issuing CAs to the names they really need.
Show answer
Answer B The client rejects it with a permitted subtree violation
- What happened
- The name lies outside the CA's permitted name space, so path validation fails.
- Why
- Name constraints in a CA certificate apply to every certificate below it in the chain.
- The rule
- Constrain issuing CAs to the names they really need.
Go deeper
- RFC 3647: the framework for certificate policies and practice statements.
- RFC 5280 sections 4.2.1.9 and 4.2.1.10: basic constraints, path length and name constraints.
- Microsoft: Certification Authority role: offline roots, standalone and enterprise CAs.
- Microsoft: Manage certificate templates: safe template settings.
- KB5014754: strong certificate mapping on domain controllers.
- Baseline Requirements: a complete example of a CP structured by RFC 3647, written for public CAs.
The crash course covers private PKI in lesson 9, Running PKI.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.