Acme & cPanel/WHM
-
Hello,
I am seeking for a way to automatically copy my Let's Encrypt certificate from my cPanel host to pfSense. cPanel does the auto-renewal for this (wildcard) certificate.
I copied the certificate manually by opening a FTP session to my cPanel host and grabbing the lets-encrypt config file from my domain.
The certificate data is stored as JSON in file /.cpanel/nvdata/letsencrypt-cpanel. This file holds every certificate requested by the Let's encrypt plugin in cPanel. I have manually extracted the private and public key (for my wildcard domain *.lan.domain.com) and inserted these in pfSense. This seems to work great. The router and even my captive portal have a valid certificate now. Great!Next step is to automate the renewal process... Do I need to write a pfSense plugin for this? Or am I overlooking something?
I still have to figure out if I need to copy the private key again after a certificate renewal. I assume that the private key stays the same and I only need the public key to be renewed on pfSense. Which would be easier as I can grab this key from an https request.What would be the best option to automate these renewals with a host running on cPanel/WHM? Any advice?
Sincerely yours, VinzzB
-
I have never developed on freenas or pfSense before so i am searching for good (and easy) ways to accomplish my task.
I just discovered the PHP shell and i made a small script to download the json file from my host. This seems to work just fine.
Now i need to parse this json file and extract the necessary ssl keys (public/private/issuer). This should be an easy one. But the next step is still unknown territory for me.
How can i replace a certificate in pfSense within this PHP shell?
Can i run this script as a cronjob (including the php pfsense tools)?This is the code i have so far (downloading file through FTPS protocol):
<?php $ftp_server = 'ftp.domain.com'; $local_file = '/home/letsencrypt-cpanel'; $server_file = '/.cpanel/nvdata/letsencrypt-cpanel'; $ftp_user_name = 'username'; $ftp_user_pass = 'password'; $conn_id = ftp_ssl_connect($ftp_server); $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); ftp_pasv($conn_id, true); if (!$login_result) die("can't login"); if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) echo "Successfully written to $local_file\n"; else echo "There was a problem\n"; ftp_close($conn_id);
I will update this post when i got more stuff working. (json parser, updating certs on pfsense)
-
I've completed my small php script and it seems to work well.
This is the result in case anyone needs it:// -- CONFIG $certname = 'lan.domain.com'; //a registered FQDN in cPanel with acme let's encrypt enabled (wildcard cert) $pfsense_cert_id = 1; // certificate id in pfsense to overwrite. (The correct ID can be found by hovering over an icon in the cert manager or by looking in the config file. $ftp_server = 'ftp.domain.com'; //ftps location to your domain (cpanel). $ftp_user_name = ''; $ftp_user_pass = ''; $server_file = '/.cpanel/nvdata/letsencrypt-cpanel'; //download file used by cPanel holding every certificate (in JSON format). // -- PROGRAM $conn_id = ftp_ssl_connect($ftp_server); $login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); ftp_pasv($conn_id, true); if (!$login_result) die("can't login"); ob_start(); $dataLoaded = ftp_get($conn_id, "php://output", $server_file, FTP_BINARY); $data = ob_get_contents(); ob_end_clean(); ftp_close($conn_id); if (!$dataLoaded) die("There was a problem downloading the json data from $ftp_server"); $jsonData = json_decode($data, true); $cert = $jsonData['certs'][$certname]; if(empty($cert)) die("Certificate with name $certname not found"); $config['cert'][$pfsense_cert_id ]['prv'] = base64_encode($cert['key']); $config['cert'][$pfsense_cert_id ]['crt'] = base64_encode($cert['cert']); write_config(); exec('/etc/rc.restart_webgui'); //echo 'Certificate:', PHP_EOL, $cert['cert'], PHP_EOL; //echo 'Key:', PHP_EOL, $cert['key'], PHP_EOL; echo 'New certificate for ', $certname, ' is valid untill ', gmdate('r',$cert['cert_expiry']), PHP_EOL; exit;
I've uploaded the file (named sslupdate) to the /etc/phpshellsessions directory in pfsense and I added the following cron job (through the cron package):
0 0 1 1/3 * : /usr/local/sbin/pfSsh.php playback sslupdate