How to renew a locally imported cert

I’m having trouble renewing a locally imported cert in FreePBX.

It’s a Let’s Encrypt cert, and I would love to use FreePBX’s built in support for LE, but I need the same cert to have multiple Subject Alt Names, and I don’t think FreePBX’s implementation supports that. So, I have a cron job that renews the cert and then uses a deploy hook to update it in FreePBX as described in the cerbot docs here.

The only problem is I can’t get my deploy hook script to work. After I copy the updated cert and key to /etc/asterisk/keys and set appropriate ownership and permissions, I run fwconsole certificates import. But, I get an error:

No Certificates to import. Try placing a certificate (.crt) and its key (.crt) into /etc/asterisk/keys

I double checked that the correct files are in place, and they are (btw, there is a typo in the error message, one of the example file names should end in .key). I was only able to get it to work after I manually deleted the cert from the UI. But, as far as I can tell, you can’t delete a cert using fwconsole, and even if you could you would still need a way to reselect the new version of the cert in the transport config.

So, is there a way to automatically renew a locally imported cert in FreePBX?

There is no way right now. You can file an issue or add and submit the patch yourself :slight_smile:

Thanks for the confirmation.

I have some PHP/JS experience, so I wouldn’t mind taking a stab at it. Any guidance on where in the code base I should start looking?

What would be the best/easiest way to solve the problem?

  1. Add support for multiple Subject Alt Name (SAN) certs to the built in LE cert manager
  2. Support importing renewed local certs

The console code is all done here: certman/Console/Certman.class.php at release/13.0 · FreePBX/certman · GitHub

importing certificates is done with:

	/**
	 * Validate and import a certificate
	 *
	 * IF any private key has a passphrase this WILL strip the passphrase!!
	 *
	 * @param  string $name              The certificate basename
	 * @param  string $privateKey        RAW Private Key
	 * @param  string $signedCertificate RAW Signed Certificate
	 * @param  string $certificateChain  RAW Certificate Chain
	 * @param  string $passphrase        Passphrase to decrypt private key
	 */
	public function importCertificate($name,$privateKey,$signedCertificate,$certificateChain='',$passphrase='')

so:

FreePBX::Certman->importCertificate($name,$privateKey,$signedCertificate,$certificateChain='',$passphrase='')

If name is the same name as something that already exists it will update it.

As for this we use GitHub - analogic/lescript: Simplified PHP ACME client

Which is slightly out of date now

Thanks @tm1000 for the helpful guidance!

I went ahead and opened a ticket to track this here: https://issues.freepbx.org/browse/FREEPBX-17633

I’ll try to get a PR together on github as soon as I can.

1 Like

Thank you and thank you for the ticket as that will help either way

Question because I am curious. Why use a SAN on a LE cert? Are you behind a proxy that only lets you use a single cert or something?

Because you can have as many LE certs as you want.

Good question. In the FreePBX PJSIP settings, you are only allowed to select a single cert for the TLS transport. I need to the server to be accessible from a couple different URLs, so while I could easily generate an LE cert for each URL, I can only choose one of them to be presented by PJSIP.

1 Like

Thanks for the answer. I do not deal with multi-tenant (only good reason I can think of, you may have another.) systems, so I never have a problem with a single cert for everyone connecting.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.