Update SSL Certificate from command line



  • I use Letsencrypt wildcard certificates. I need to update the certificate every 90 days. Is there a way to script uploading the new certificate, changing the WebUI to use the new certs, delete the ones and restart the WebUI?

    I'm fairly certain that executing /etc/rc.restart_webgui will restart the UI, but is there any way to transfer the certificates? I found scping the certificates didn't work properly.


  • Rebel Alliance Global Moderator

    doesn't the ACME package take care of all of this for you?



  • I'm sorry for being unclear! The certificates are generated on another machine.


  • Rebel Alliance Global Moderator

    Again why would you not just use the ACME package? Are you saying your pfsense has no access to internet?

    Then why go through all this hassle - every 90 days. Why not just use your own CA, create a cert for 10 years and trust the CA?



  • @johnpoz said in Update SSL Certificate from command line:

    Again why would you not just use the ACME package?

    If you want an example: Not every hosting company supports RFC2136 style DNS updates, in that case it seems you cannot use the ACME package if you want automatic renewals. I did manage to get around that on a different device, but I have no idea if the ACME package for pfSense can be reconfigured for DIY solutions.

    My setup looks like this: Raspberry Pi with certbot-auto, two bash-scripts that deal with the TXT-record for verification and one PHP-script that's on the webserver with the hostingcompany and has access to CMD_API_DNS_CONTROL (Direct Admin).

    The first bash script (started by certbot-auto just before the actual verification) calls the PHP-script to create the TXT-record for DNS verification, the value of that record is placed in a variable by certbot-auto which is picked up by the bash-scripts and put in the url that calls the PHP-script which then creates the TXT-record. Then the script waits till the dig-command can confirm the DNS-server has picked up the just created TXT-record. After the script ends certbot-auto does the actual verification, followed by the execution of bash-script number two that calls the PHP-script to remove the TXT-record.

    Unless the ACME-package can do that, I'd also like to know if it is possible to scp certificates to pfSense from a different device and then reload the webinterface with the new certificates, from console.


  • Netgate

    Get/spin up a DNS service that supports RFC2136 and have all your hosts update that instead of using whatever happens to be available at the various datacenters.

    https://www.netgate.com/docs/pfsense/dns/rfc2136-dynamic-dns.html



  • @derelict said in Update SSL Certificate from command line:

    Get/spin up a DNS service that supports RFC2136 and have all your hosts update that instead of using whatever happens to be available at the various datacenters.

    https://www.netgate.com/docs/pfsense/dns/rfc2136-dynamic-dns.html

    That means setting up a 2nd DNS service, while the current one works just fine, only in a different way. The only thing that needs to be done (in my case that is) is calling a specific url before verification with the value of the TXT-record in it and another url for deletion afterwards. Can't something like that be done by the ACME package?

    And there's still no answer to the original question of this topic ;). After a bunch of Googling I did end up finding https://forum.netgate.com/topic/95774/automating-certificate-imports-with-letencrypt-script , but I can't get sed to work: "extra characters after command", plus I found several more questions (dating back years) about managing certificates from the console.


  • Rebel Alliance Global Moderator

    Who exactly access your pfsense webgui? Why would you not just put in your own cert via your own trust CA, make it good for 10 years and be done with it?


  • Netgate

    Sometimes something off the firewall is the best solution.

    That URL was just an example of how you can do your own. There are services you can buy for sure. I know hurricane is at least thinking about implementing RFC2136.

    Until then their regular dyndns is supported in the ACME package. It's free and don't cost nothin. You don't HAVE to use RFC2136.



  • @johnpoz said in Update SSL Certificate from command line:

    Who exactly access your pfsense webgui? Why would you not just put in your own cert via your own trust CA, make it good for 10 years and be done with it?

    Only me, so I initially started using a certificate signed by pfSense configured as CA, but I do would like to see a solution for this. If someone can explain why the sed command in the other topic is giving the error I mentioned I could use that method to add a wildcard certificate from and requested by the Raspberry Pi to pfSense's config file.



  • Well, I ended up making a script of my own and it looks like I've got it working :) , but I'll check again once there's a newer wildcard certificate. The script I made assumes the current certificate and key are stored in text-files, encoded just like in config.xml. Using the contents of those files, a simple search and replace of the certificate and key can be done. There's no need to look for some kind of pattern in config.xml like the script from the other topic, it's just looking for two specific strings and replace them.

    For those who'd like to try it:

    #!/bin/bash
    host="ipaddress"
    username="username"
    password="password"
    certificate="certificate.pem"
    privatekey="privatekey.pem"
    oldcertificate=$(<certificate.crt.old.txt)
    oldprivatekey=$(<certificate.key.old.txt)
    
    mv $certificate $certificate.combo
    csplit -f $certificate.part $certificate.combo '/-----BEGIN CERTIFICATE-----/' '{*}'
    
    for file in $certificate.part*;
    do echo "Processing $file file..";
    output=$(openssl x509 -noout -subject -in $file);
    if [[ $output = *CN=*.* ]]
    then
            mv $file certificate.pem
    fi
    if [[ $output = *Authority* ]]
    then
            mv $file CA_LetsEncrypt.pem
    fi
    done
    
    cert=$(base64 $certificate)
    cert=$(echo $cert | sed "s/ //g")
    key=$(base64 $privatekey)
    key=$(echo $key | sed "s/ //g")
    
    sshpass -p $password scp $username@$host:/conf/config.xml config.xml
    
    if grep "$cert" config.xml > /dev/null
    then
        echo "Identical certificate found, renewal not required"
    else
        echo "Certificate not found, renewal required"
        sed -i -e "s|$oldcertificate|$cert|g" config.xml
        sed -i -e "s|$oldprivatekey|$key|g" config.xml
        echo $cert > certificate.crt.old.txt
        echo $key > certificate.key.old.txt
        sshpass -p $password scp config.xml $username@$host:/conf/config.xml
        sshpass -p $password ssh $username@$host rm /tmp/config.cache
        sshpass -p $password ssh $username@$host /etc/rc.restart_webgui
        find . -size  0 -name $certificate.part* -print0 |xargs -0 rm --
        rm $certificate.combo
        rm certificate.pem
        rm privatekey.pem
        rm CA_LetsEncrypt.pem
        rm config.xml
    fi