Tutorial: Configure External PKI with Access Server's certool Script
How to set up the Access Server External PKI (Public Key Infrastructure) feature.
Overview
The Access Server external public key infrastructure (PKI) feature integrates Access Server with third-party tools for X509 PKI management instead of using the built-in certificate management capabilities.
When configured for external PKI usage, Access Server doesn't manage client certificates directly; instead, the customer's third-party PKI software generates and distributes client certificate/key pairs to client machines and a server certificate/key pair to the OpenVPN server.
This tutorial shows you how to set up external PKI using Access Server's certool
When you use a third-party tool outside of Access Server, you must refer to the documentation for that software for specific directions. Here we outline the steps and provide an example using Access Server's certool script. With certool, you can create your own new PKI structure, as we do in these instructions.
At a high level, these are the steps for your configuration:
Create certificate/key pair with external PKI tool.
Modify as.conf to set Access Server in external PKI mode.
Create the TLS_auth key.
Generate Diffie Hellman parameters.
Import the necessary certificate and key files.
Provide certificate/key pairs to VPN client and server.
When configuring your Access Server in production, follow these high-level steps using your third-party PKI tool. We provide our example below using Access Server’s certool script, so the steps pertain to that tool.
An installed Access Server.
An external PKI tool.
Console access and the ability to get root access.
An OpenVPN client that supports the macOS Keychain and Windows certificate store.
Note
OpenVPN Connect supports the macOS Keychain and the Windows certificate store as valid sources to fetch the client certificate.
When the user attempts to connect using a profile setup for external PKI, the client backend enumerates the user's host OS certificate store and automatically selects the certificate/key pair issued by OpenVPN Access Server. If more than one certificate/key pair is eligible, the certificate with the latest expiration date is used.
Connect to the Access Server console and get root privileges.
Edit as.conf for external PKI usage:
nano /usr/local/openvpn_as/etc/as.conf
Comment out certs_db:
# certificates database # certs_db=sqlite:///~/db/certs.db
Save and exit the file — ctrl+x, y, then enter.
Access Server no longer uses the certificate database. Instead, an external system must handle this.
Initialize the external PKI files in the epki directory, including the CA cert/key:
cd /usr/local/openvpn_as/scripts mkdir -p epki/root
Create a root cert for signing intermediate CAs:
./certool --dir epki/root --cn "EPKI Root Test" --type ca
Create the intermediate CA:
./certool --dir epki/root --type intermediate --serial 1 --cn "EPKI Intermediate" --name inter cp epki/root/inter.crt epki/ca.crt cp epki/root/inter.key epki/ca.key cat epki/root/ca.crt epki/ca.crt >epki/cabundle.crt
Create a certificate/key pair for the OpenVPN server:
./certool --dir epki --type server --serial 1 --cn server
Create a tls_auth key for the OpenVPN server:
./certool --dir epki --tls_auth
Generate Diffie Hellman parameters for the OpenVPN server:
openssl dhparam -out epki/dh.pem 2048
Load the newly generated files into the Access Server config database:
./sacli --key "external_pki.ta_key" --value_file epki/ta.key ConfigPut ./sacli --key "external_pki.ca_crt" --value_file epki/cabundle.crt ConfigPut ./sacli --key "external_pki.server_crt" --value_file epki/server.crt ConfigPut ./sacli --key "external_pki.server_key" --value_file epki/server.key ConfigPut ./sacli --key "external_pki.dh_pem" --value_file epki/dh.pem ConfigPut
For Access Server 2.7 and newer, you must also generate your auth token and add the generated file:
./certool --dir epki --auth_token ./sacli --key "external_pki.auth_token_key" --value_file epki/auth_token.key ConfigPut
Configure X509 explicit/extended key usage based on RFC3280 TLS Rules:
./sacli --key "external_pki.remote_cert_usage" --value eku ConfigPut
Configure the use of the X509 “role” attribute for the declaration of auto-login permission:
./sacli --key "external_pki.autologin_x509_spec" --value "role,,AUTOLOGIN" ConfigPut
Generate the tls-crypt-v2 key (for Access Server 2.9.0 and higher only):
./certool --dir epki --tls_crypt2_server ./sacli --key "external_pki.tls_cryptv2_server" --value_file epki/tls_crypt2.key ConfigPut
Restart Access Server:
service openvpnas restart
Important
When using an external PKI tool, designate all certificates generated by your PKI management tool as explicitly client or server. This protects against a man-in-the-middle attack where a client certificate could be used to impersonate the server. There are two ways to do this:
X509 explicit/extended key usage based on RFC3280 TLS rules. Configure as follows:
./sacli --key "external_pki.remote_cert_usage" --value eku ConfigPut
Netscape certificate type (deprecated). Configure as follows:
./sacli --key "external_pki.remote_cert_usage" --value ns ConfigPut
or for version 2.9.0 and newer,./sacli --key "external_pki.remote_cert_usage" --value ns-cert ConfigPut
To test our example, we generate a test client, etest.
Sign in to the Admin Web UI.
Click User Management > User Permissions.
Create the new user, etest, and click More Settings to enter a password.
Generate a cert/key pair for etest:
./certool --dir epki --type client --serial 2 --cn etest --cabundle epki/cabundle.crt --pkcs12
The key is encrypted with a password you enter at the prompt, and certool generates the file epki/etest.p12, which contains the cert/key pair.
To test auto-login, generate an auto-login cert/key pair for etest:
./certool --dir epki --type client --serial 3 --cn etest --name etestauto --cabundle epki/cabundle.crt --pkcs12 role=AUTOLOGIN ./sacli --user etest --key prop_autologin --value true UserPropPut
Finally, generate a server-locked profile. The profile will be stored in client.ovpn:
./sacli GetGeneric >client.ovpn
Important
Starting from 2.12.0, certool doesn't allow generating user certificates with empty passphrases. If you still want to generate a user's certificate with an empty passphrase, you can do so using the openssl command-line tool. Or you can remove the passphrase from a generated .p12 file using the openssl command-line tool:
openssl pkcs12 -in epki/etest.p12 -nodes -out epki/temp.pem ## Enter passphrase and press enter openssl pkcs12 -export -in epki/temp.pem -out epki/etest_nopass.p12 ## Press Enter twice rm epki/temp.pem
Copy these three files to the client machine:
epki/etest.p12:
The userlogin cert/key pair for user etest.
epki/etestauto.p12:
The autologin cert/key pair for user etest.
client.ovpn:
The server-locked profile for the Access Server.
Tip
In a production setting, the client cert/key pairs (the .p12 files) are distributed to clients using the external PKI tool. The client.ovpn is distributed in the same manner as existing server-locked profiles:
Using OpenVPN Connect.
Using a client software push capability — for example, on macOS, you can generate a pre-configured client installer, ‘mac_v3’, with the server-locked profile:
For Access Server 2.12.0 and newer:
./sacli --dest_dir=[DESTINATION-DIRECTORY] --itype=mac_v3 --profile_type=serverlocked GenerateInstaller
For Access Server 2.11.x and older:
./sacli --itype mac_v3 -o . GetGenericInstaller
Install the certificate/key pair:
Launch OpenVPN Connect v3.
Import the connection profile, client.ovpn.
Click or tap the Menu icon.
Click Certificate & Tokens.
Under PKCS#12, click Add Certificate.
Select your Client P12 File (etest.p12).
Enter the file's password previously configured and click OK.
Return to the Profiles and click or tap the Edit icon for the profile.
Under Certificate and Key, click or tap Assign.
Select the hardware token and click Confirm.
Click or tap Save.
Click or tap the profile toggle to connect.
Currently, Access Server uses the following client certificate naming conventions:
The Common Name of the certificate must match the username of the connecting client.
Autologin certificates, which don't require username/password authentication (only client certificate authentication), must be tagged to indicate that they hold this right.
Tip
In the example above, the X509 role attribute is set to
AUTOLOGIN
. To enable autologin in Access Server based on this attribute, modify the configuration with the following command:./sacli --key "external_pki.autologin_x509_spec" --value "role,,AUTOLOGIN" ConfigPut
This command tells Access Server to enable autologin if the
role
X509 attribute contains the substringAUTOLOGIN
. If theexternal_pki.autologin_x509_spec
setting is omitted, autologin will be disabled.The
external_pki.autologin_x509_spec
string has the following format:<X509 Attribute>,<optional flags>,<enabling substring in attribute value>
Note that the flags parameter is reserved for future use and isn't currently implemented. For example, if
external_pki.autologin_x509_spec
is set to"role,,AUTOLOGIN"
, Access Server will only allow autologin connections from client certificates where therole
attribute contains the substringAUTOLOGIN
.
Split CA, i.e. using a separate CA chain for client and server certificates
By default, one CA chain is assumed for both client and server certificates. To use a separate chain for each:
Enable split CA mode:
./sacli --key "external_pki.remote_cert_usage" --value split ConfigPut
Replace the following line (from above):
./sacli --key "external_pki.ca_crt" --value_file <CA_CERT_BUNDLE&> ConfigPut
with:
./sacli --key "external_pki.server_ca_crt" --value_file <SERVER_CA_CERT_BUNDLE> ConfigPut ./sacli --key "external_pki.client_ca_crt" --value_file <CLIENT_CA_CERT_BUNDLE> ConfigPut
Then restart the service:
./sacli start
You don’t need to mark certificates as client or server when using split CA mode. Therefore, settings for Netscape certificate type or X509 explicit/extended key usage based on RFC3280 TLS rules can be omitted.
Controlling CN/username requirement
By default, client logins must use a username that matches the Common Name on the client certificate. This requirement may be dropped by disabling the external_pki.cn_username_requirement boolean key:
./sacli -k external_pki.cn_username_requirement -v false ConfigPut
Controlling which certificate store the client uses to fetch the client certificate
By default, the client fetches certificates from the "user" store. This corresponds to the user's ~/Library/Keychains/login.keychain store on Mac and the "MY" store on Windows. On Mac, the store can be selected on the server using the user properties key "cert_store". Set it to "user", "system", or "both" to explicitly control the store that clients use:
user: | use ~/Library/Keychains/login.keychain |
system: | use /Library/Keychains/System.keychain |
both: | try system keychain, then fall back to user |
For example, set the store to "both":
./sacli --user "__DEFAULT__" --key cli_cert_store --value "both" UserPropPut
Error Message
"'Parameter \"external_pki.auth_token_key\" is missing from the configuration database. For more information, please visit the following URL: https://openvpn.net/static-links/documentation-external-pki': util/cdict:286,util/cdict:258,util/cdict:522,util/cdict:555 (exceptions.KeyError)"
Issue: This error occurs when upgrading an Access Server configured for external public key infrastructure (ePKI) from a version lower than 2.7 to version 2.7 and higher. This is expected behavior because this configuration key was missing for versions before 2.7 and must be added after you upgrade. You’ll also see “service failed to start or returned error status” in your log messages.
Resolution: This error can be resolved by running these commands with root privileges:
cd /usr/local/openvpn_as/scripts mkdir epki ./certool --dir epki --auth_token ./sacli --key "external_pki.auth_token_key" --value_file epki/auth_token.key ConfigPut
Then restart the service:
service openvpnas start