-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem
OpenVPN clients cannot connect when the Certificate Revocation List (CRL) expires:
VERIFY ERROR: depth=0, error=CRL has expired
TLS Error: TLS handshake failed
The CRL has a 180-day expiration (EASYRSA_CRL_DAYS 180 in vars.erb), but Puppet only generates it once during initial setup and never regenerates it.
Root Cause
Issue 1: CRL is only generated once
In modules/profile/manifests/openvpn_server/config.pp (lines 147-158):
exec { 'generate_gen_crl':
command => "/usr/share/easy-rsa/easyrsa --vars=${openvp_config_directory}/vars gen-crl",
cwd => $openvp_config_directory,
creates => $openvpn_crl_path, # <-- Only runs if file doesn't exist
require => [...]
}The creates parameter means this exec only runs once when the file doesn't exist. After the initial CRL is created, Puppet never regenerates it, even after it expires 180 days later.
Issue 2: Missing CA passphrase configuration
The vars.erb template is missing the EASYRSA_PASSIN variable needed for automated CRL regeneration:
Current vars.erb (lines 166-167):
set_var EASYRSA_BATCH true
set_var EASYRSA_NO_PASS 1Missing:
set_var EASYRSA_PASSIN "file:<%= @openvp_config_directory %>/ca_passphrase"Without this, any attempt to regenerate the CRL manually prompts for the CA passphrase:
root@ip-10-1-3-120:/etc/openvpn# /usr/share/easy-rsa/easyrsa gen-crl
Enter pass phrase for /etc/openvpn/pki/private/ca.key:Impact
- Severity: High - All OpenVPN clients lose connectivity when CRL expires
- Frequency: Every 180 days (~6 months)
- Workaround: Manual CRL regeneration by ops team
Observed Behavior
root@ip-10-1-3-120:/etc/openvpn# openssl crl -in /etc/openvpn/pki/crl.pem -noout -text
Certificate Revocation List (CRL):
Last Update: Jun 27 21:05:32 2025 GMT
Next Update: Dec 24 21:05:32 2025 GMT # EXPIREDCurrent date: January 2, 2026 - CRL expired 9 days ago.
Proposed Solution
1. Add EASYRSA_PASSIN to vars.erb template
set_var EASYRSA_BATCH true
set_var EASYRSA_NO_PASS 1
set_var EASYRSA_PASSIN "file:<%= @openvp_config_directory %>/ca_passphrase"2. Add automated CRL regeneration via cron
In modules/profile/manifests/openvpn_server/config.pp, add:
cron { 'regenerate_openvpn_crl':
command => "cd ${openvp_config_directory} && /usr/share/easy-rsa/easyrsa --vars=${openvp_config_directory}/vars gen-crl && systemctl reload openvpn-server@server",
user => 'root',
hour => 3,
minute => 0,
monthday => 1, # Run on the 1st of each month
require => Exec['generate_gen_crl'],
}Alternatively, replace the creates parameter with a check that validates CRL expiration and regenerates when needed.
Temporary Workaround
Manual CRL regeneration (requires SSH access to OpenVPN server):
cd /etc/openvpn
cat /etc/openvpn/ca_passphrase | /usr/share/easy-rsa/easyrsa --vars=/etc/openvpn/vars gen-crl
systemctl restart openvpn-server@serverQuestions
- How did the CRL get generated initially without the passphrase? Was the CA created manually outside of Puppet?
- Should we also increase
EASYRSA_CRL_DAYSto reduce regeneration frequency?
Environment
- Puppet module:
profile::openvpn_server - Affected files:
modules/profile/manifests/openvpn_server/config.ppmodules/profile/templates/openvpn_server/vars.erb
- OpenVPN server: Ubuntu Noble (24.04)
- Easy-RSA version: 3.x