PKI Architecture Fundamentals
A self-managed Public Key Infrastructure relies on a hierarchical trust model consisting of three primary tiers:
- Root Certificate Authority: The anchor of trust. Its private key never leaves the secure hardware store and is used exclusively to sign intermediate certificates.
- Intermediate Certificate Authority: A delegated issuer that bridges the gap between the offline root and daily operations. It holds the actual signing power for service endpoints.
- Leaf (End-Entity) Certificate: The final credential bound to a specific hostname or application, distributed to clients for encrypted communications.
OpenSSL Configuration Templaet
Proper credential issuance requires a centralized configuration file that defines routing paths, validation policies, and X.509 extensions. The template below establishes strict enforcement rules and modern cryptographic defaults.
# OpenSSL Policy Configuration
# File: openssl-pki.cnf
[ ca ]
default_ca = CA_intermediate
[ CA_intermediate ]
dir = /opt/pki
database = $dir/index.txt
new_certs_dir = $dir/newcerts
serial = $dir/serial
RANDFILE = $dir/private/.rand
# Intermediate credentials
certificate = $dir/certs/intermediate.cert.pem
private_key = $dir/private/intermediate.key.pem
crlnumber = $dir/crlnumber
crl = $dir/crl/cert.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province
localityName = City or Region
0.organizationName = Organization Name
organizationalUnitName = Division Name
commonName = Common Name
emailAddress = Email Address
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Cert"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Cert"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
authorityKeyIdentifier = keyid:always
[ ocsp ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
Automated Issuance Pipeline
The following workflow encapsulates the credential generation process into a reproducible sequence. By utilizing environment-driven variables, the pipeline remains adaptable across different projects while preserving cryptographic integrity.
#!/usr/bin/env bash
set -euo pipefail
# --- Runtime Parameters ---
PKI_ROOT="/opt/pki"
TARGET_DOMAIN="api.internal.corp"
KEY_SIZE=2048
HASH_ALGO="sha256"
CERT_TTL_DAYS=375
# Initialize directory structure
mkdir -p "${PKI_ROOT}/intermediate/{private,csr,certs,newcerts,crl}"
touch "${PKI_ROOT}/intermediate/index.txt"
echo "1000" > "${PKI_ROOT}/intermediate/serial"
# Step 1: Provision Intermediate Private Key
openssl genrsa \
-aes256 \
-out "${PKI_ROOT}/intermediate/private/${TARGET_DOMAIN}.key.pem" \
${KEY_SIZE}
chmod 400 "${PKI_ROOT}/intermediate/private/${TARGET_DOMAIN}.key.pem"
# Step 2: Construct Certificate Signing Request
openssl req \
-config "${PKI_ROOT}/openssl-pki.cnf" \
-key "${PKI_ROOT}/intermediate/private/${TARGET_DOMAIN}.key.pem" \
-new \
-${HASH_ALGO} \
-out "${PKI_ROOT}/intermediate/csr/${TARGET_DOMAIN}.csr.pem" \
-subj "/O=Internal Operations/CN=${TARGET_DOMAIN}"
# Step 3: Sign Endpoint Credential Against Intermediate CA
openssl ca \
-config "${PKI_ROOT}/openssl-pki.cnf" \
-extensions server_cert \
-days ${CERT_TTL_DAYS} \
-notext \
-md ${HASH_ALGO} \
-in "${PKI_ROOT}/intermediate/csr/${TARGET_DOMAIN}.csr.pem" \
-out "${PKI_ROOT}/intermediate/certs/${TARGET_DOMAIN}.cert.pem"
# Step 4: Validate Cryptographic Chain
cat "${PKI_ROOT}/intermediate/certs/ca-chain.cert.pem" > /tmp/trust-anchor.pem
openssl verify \
-CAfile /tmp/trust-anchor.pem \
"${PKI_ROOT}/intermediate/certs/${TARGET_DOMAIN}.cert.pem"
# Step 5: Display Parsed Certificate Details
openssl x509 -noout -text -in "${PKI_ROOT}/intermediate/certs/${TARGET_DOMAIN}.cert.pem"