Certificate Authority With Hardware Token [Yubikey]

Published 10-01-2019 11:58:08

OpenSSL Certificate Authority

Install dependencies for working with PKCS11

brew install yubico-piv-tool [email protected] opensc libp11

Generating new Root CA certificate

Definition of Root CA

First of all we need to generate private key to be used to generate public key for our new certificate. In current example used 2048 bits of rsa, this is related to limitation of specific hardware token.

openssl genrsa -out root-ca.pem 2048

We need to describe certificate definition in openssl configuration file root-ca.config:

[ req ]
x509_extensions = v3_ca
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
CN=LetRun Root CA
[ v3_ca ]
subjectKeyIdentifier=hash
basicConstraints=critical,CA:true,pathlen:1
keyUsage=critical,keyCertSign,cRLSign
nameConstraints=critical,@nc
[ nc ]
permitted;otherName=1.3.6.1.5.5.7.8.7;IA5:let.run
permitted;email.0=let.run
permitted;email.1=.let.run
permitted;DNS=let.run
permitted;URI.0=let.run
permitted;URI.1=.let.run
permitted;IP.0=0.0.0.0/255.255.255.255
permitted;IP.1=::/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

Create certificate by using this configruation

echo 01 > root-ca-crt.srl
openssl req -new -sha256 -x509 -set_serial 1 -days 21900 \
    -config root-ca.config \
    -key root-ca.pem \
    -out root-ca-crt.pem

Upload to Yubikey PIV Smart Card

Now we need to upload our private key and generated certificate to yubikey

yubico-piv-tool -k -a import-key -s 9c < root-ca.pem
yubico-piv-tool -k -a import-certificate -s 9c < root-ca-crt.pem

Issue new Intermediate Certificate signed by Root CA

openssl genrsa -out ica-hubcli-key.pem 2048

Create ica-hubcli-csr.config openssl configuration

[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
CN=hubcli Peach Intermediate CA

Generate certificate signature request file (CSR)

openssl req -sha256 -new -config ica-hubcli-csr.config \
    -key ica-hubcli-key.pem \
    -nodes \
    -out ica-hubcli-csr.pem

Generate the Intermediate CA certificate with configuration ica-hubcli-crt.config:

basicConstraints = critical, CA:true, pathlen:0
keyUsage=critical, keyCertSign

To find correct slotes and objects in smart card it is better to list all stored objects in smart card:

pkcs11-tool -O

Sign intermediate certificate authority by Root CA with private key stored in smart card

echo 00 > ica-hubcli-crt.srl
/usr/local/Cellar/[email protected]/1.1.1d/bin/openssl << EOF
engine dynamic \
    -pre SO_PATH:/usr/local/Cellar/libp11/0.4.10/lib/engines-1.1/pkcs11.dylib \
    -pre ID:pkcs11 \
    -pre LIST_ADD:1 \
    -pre LOAD \
    -pre MODULE_PATH:/usr/local/Cellar/opensc/0.19.0_1/lib/opensc-pkcs11.so \
    -pre VERBOSE
x509 -sha256 \
    -engine pkcs11 \
    -CA root-ca-crt.pem \
    -CAkeyform engine \
    -CAkey slot_0-id_2 \
    -req -days 7300 \
    -in ica-hubcli-csr.pem \
    -extfile ica-hubcli-crt.config \
    -out ica-hubcli-crt.pem
EOF

Generate End Certificate

Same as pervious steps we need to generate private keys for end certificate first:

openssl genrsa -out end-hubcli-rpc-server-key.pem 2048

Create openssl request configuration file, it is important to specify real host name for end certificate (ip adress if needed, etc), example of end-hubcli-rpc-server.config:

[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
CN=hubcli.at.lnd.cloud

Create certificate signature request (CSR) for our end certificate:

openssl req -sha256 -new \
    -config end-hubcli-rpc-server-csr.config \
    -key end-hubcli-rpc-server-key.pem \
    -nodes \
    -out end-hubcli-rpc-server-csr.pem

Create signatrue configuration for end certificate:

basicConstraints = critical,CA:false
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=critical,serverAuth
subjectAltName=critical,DNS:hubcli.at.lnd.cloud

And sign it

openssl x509 -sha256 \
    -CA ica-hubcli-crt.pem \
    -CAkey ica-hubcli-key.pem \
    -req -days 730 \
    -in end-hubcli-rpc-server-csr.pem \
    -extfile end-hubcli-rpc-server-crt.config \
    -out end-hubcli-rpc-server-crt.pem

Vault Certificate Authority

Integrate Intermediate CA to Hashicorp Vault

Mount new endpoint for intermediate certificate authority and tune configuration.

For each PKI engine that you enable you’ll need to configure the url values for issuing certificate endpoints and CRL distribution points that will be encoded into issued certificates:

vault secrets enable -path=pki-hcli pki
vault secrets tune -max-lease-ttl=26280h pki-hcli
vault write pki-hcli/config/urls \
    issuing_certificates="https://vault.lnd.cloud:8200/v1/pki-hcli/ca.pem" \
    crl_distribution_points="https://vault.lnd.cloud:8200/v1/pki-hcli/crl"

Generate our intermediate ca-certificate for endpoint.

vault write pki-hcli/intermediate/generate/internal \
    common_name="HubCLI Intermediate Authority" \
    ttl=17520h \
    key_type=ec \
    key_bits=256 

Sign Intermediate ceritficate with Root CA

/usr/local/Cellar/[email protected]/1.1.1d/bin/openssl << EOF
engine dynamic \
    -pre SO_PATH:/usr/local/Cellar/libp11/0.4.10/lib/engines-1.1/pkcs11.dylib \
    -pre ID:pkcs11 \
    -pre LIST_ADD:1 \
    -pre LOAD \
    -pre MODULE_PATH:/usr/local/Cellar/opensc/0.19.0_1/lib/opensc-pkcs11.so \
    -pre VERBOSE
x509 -sha256 \
    -engine pkcs11 \
    -CA root-ca-crt.pem \
    -CAkeyform engine \
    -CAkey slot_0-id_2 \
    -req -days 730 \
    -in ica-vault-csr.pem \
    -extfile ica-hubcli-crt.config \
    -out ica-vault-crt.pem
EOF

Upload signed certificate to secure storage

vault write pki-hcli/intermediate/set-signed [email protected]

Now we need define roles with key usages definitions and allwed domains, first we need to create it for the server

vault write pki-hcli/roles/server-role \
    allowed_domains=at.lnd.cloud,service.consul,localhost \
    allow_subdomains=true \
    allow_bare_domains=false \
    allow_localhost=true \
    max_ttl=120h \
    key_type=ec \
    key_bits=256 \
    generate_lease=true \
    key_usage=DigitalSignature,KeyAgreement,KeyEncipherment \
    ext_key_usage=ExtKeyUsageServerAuth \
    server_flag=true \
    client_flag=false

Then we need role for client certificates

vault write pki-hcli/roles/client-role \
    allow_any_name=true \
    enforce_hostnames=false \
    max_ttl=120h \
    key_type=ec \
    key_bits=256 \
    generate_lease=true \
    key_usage=DigitalSignature,KeyAgreement,KeyEncipherment \
    ext_key_usage=ExtKeyUsageClientAuth \
    server_flag=false \
    client_flag=true