Build a Root and Intermediate Certificate Authority with Easy-RSA
📖 This post continues from Part 1: Why Build Your Own Certificate Authority
Root CA Setup
1. Download and Extract Easy-RSA
Optionally rename the directory to root-ca
.
2. Create or Edit the vars
File
set_var EASYRSA_REQ_COUNTRY "VN"
set_var EASYRSA_REQ_PROVINCE "Ho Chi Minh City"
set_var EASYRSA_REQ_CITY "Ho Chi Minh City"
set_var EASYRSA_REQ_ORG "DINHPHU28 Root CA"
set_var EASYRSA_REQ_EMAIL "[email protected]"
set_var EASYRSA_REQ_OU "Community"
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"
set_var EASYRSA_CURVE "secp384r1"
3. Initialize the PKI
./easyrsa init-pki
4. Build the Root CA
./easyrsa build-ca
🔐 Remember the password — this secures your CA.
You now have:
pki/private/ca.key
-
pki/ca.crt
(Root certificate)
5. Create Custom x509 Type for Intermediate CA
Create x509-types/caRestricted
:
basicConstraints = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = critical, cRLSign, keyCertSign
Intermediate CA Setup
Repeat steps 1–3 in a new directory like intermediate-ca
, then update vars
:
set_var EASYRSA_REQ_ORG "DINHPHU28 EC CA"
set_var EASYRSA_REQ_OU "Intermediate"
Initialize and Create Request
./easyrsa init-pki
./easyrsa gen-req intermediate-ca
Transfer intermediate-ca.req
to the offline Root CA.
At the Root CA
./easyrsa import-req /path/to/intermediate-ca.req intermediate-ca
EASYRSA_NO_SAN=1 ./easyrsa sign-req caRestricted intermediate-ca
Back at Intermediate CA
cp /path/to/intermediate-ca.crt pki/ca.crt
cp /path/to/root-ca/pki/ca.crt pki/root-ca.crt
cat pki/ca.crt pki/root-ca.crt > pki/ca-chain.crt
You now have a functional Intermediate CA.
Issue Certificate for Microsoft 365 Authentication
1. Create OpenSSL Config
Save as user_openssl.cnf
:
[ req ]
default_bits = 384
prompt = no
distinguished_name = dn
req_extensions = req_ext
string_mask = utf8only
default_md = sha512
[ dn ]
CN = Dinh Phu Nguyen
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
otherName = 1.3.6.1.4.1.311.20.2.3;UTF8:[email protected]
2. Generate Key and CSR
openssl ecparam -name secp384r1 -genkey -noout -out dinhphu.key
openssl req -new -key dinhphu.key -out dinhphu.csr -config user_openssl.cnf
3. Sign the CSR at Intermediate CA
./easyrsa import-req /full/path/to/dinhphu.csr dinhphu
EASYRSA_CERT_EXPIRE=60 ./easyrsa --subject-alt-name="otherName:1.3.6.1.4.1.311.20.2.3;UTF8:[email protected]" sign-req client dinhphu
4. Verify UPN
openssl x509 -in pki/issued/dinhphu.crt -noout -text | grep -A5 "Subject Alternative Name"
Should contain your UPN like this:
X509v3 Subject Alternative Name:
otherName:1.3.6.1.4.1.311.20.2.3;UTF8:[email protected]
Note: Above client cert dinhphu.crt
is only contain client cert.
To verify the client cert valid, we not only need the Root CA cert but also Intermediate CA (full chain of trust): Root CA -> Intermediate CA -> Client cert
Most of SSL Tools or System use use client cert with fullchain (intermediate-ca -> leaf) to verify the client with only Root CA cert.
cat /path/to/intermediate-ca/pki/ca.crt dinhphu.crt > dinhphu-fullchain.crt
Create PFX Certificate
openssl pkcs12 -export \
-inkey dinhphu.key \
-in dinhphu.crt \
-certfile /path-to/ca-chain.crt \
-out dinhphu.pfx \
-name "Dinh Phu Nguyen"
You’ll be prompted for a password to protect the
.pfx
.
Optional: macOS Conversion
Because of this pfx
using pkcs12 is not compatible with macOS, so we need to convert it to legacy.
openssl pkcs12 -in dinhphu.pfx -out dinhphu.pem
openssl pkcs12 -export -in dinhphu.pem -out dinhphu_macos.pfx -legacy
Microsoft Entra Configuration Notes
Authentication Binding
Certificate Attribute | Value |
---|---|
Policy OID | 1.3.6.1.4.1.311.20.2.2 |
Authentication strength | Multi-factor |
Affinity binding | Low |
Add rule: Policy OID
- Certificate attribute: Policy OID
- Policy OID:
1.3.6.1.4.1.311.20.2.2
- Authentication strength: Mutli-factor authentication
- Affinity binding: Low
Username Binding
Certificate field | Affinity binding | User attribute |
---|---|---|
PrincipalName | Low | userPrincipalName |
RFC822Name | Low | userPrincipalName |
Microsoft Docs – Certificate-Based Authentication
Wrapping Up
You’ve now built a secure, scalable two-tier Certificate Authority using Easy-RSA:
- A Root CA that remains offline for maximum trust
- An Intermediate CA that handles day-to-day certificate issuance
- End-entity certificates for services like Microsoft 365 with UPN-based binding
- Exportable PFX files and compatibility with various systems including macOS
This setup not only strengthens your internal security posture but also gives you complete control over your certificate lifecycle, policies, and trust relationships.
What’s Next?
In the upcoming article, I’ll share how I manage SSH access for a large number of users and servers, using a certificate-based and policy-driven approach to simplify operations and tighten security.
If you’re building out a lab, managing production systems, or exploring PKI for your org — you’re on the right path. Feel free to leave questions or comments below.
Happy cert-ing!
Enjoy Reading This Article?
Here are some more articles you might like to read next: