How can you force the Acme.sh Client Plugin to run via cron?

Started by Mr_Flibble, May 16, 2023, 08:47:22 PM

Previous topic - Next topic
I have the Acme Client plugin, I installed it following this tutorial:

https://forum.opnsense.org/index.php?topic=23339.0

It works fine with one caveat. I am not running a "normal" 90 day letsencrypt sort of cert. Instead, I am running a SmallStep CA of my own on a Raspberry Pi. This means my certificates only last 24 hours. (Passive Revocation)

Details Here:
https://smallstep.com/blog/build-a-tiny-ca-with-raspberry-pi-yubikey/

On my other systems, I force acme.sh to run with the --force flag (or I use certbot) this way, I can update the certificate every 10 hours.

For the Acme Plugin for Opnsense, it refuses to renew my certificate based on the cron job because it assumes it does not need to as it ran less than 10 hours prior. For my TrueNAS (BSD based) system, I just changed the acme.sh parameters to include the "--force" flag, and it now runs as expected via cron.

The acme plugin for OPNsense does not appear to do that - or not give me a way to handle that. I can't seem to figure out where to add flags in the GUI. I could go to the shell and edit this - but that feels like a kludge, and I am not sure if the plugin updates it will maintain any changed I would make.

When I try to trigger the cron job to update the certificate I get:

  • 2023-05-16T10:00:00-07:00   opnsense   AcmeClient: issue/renewal not required for certificate: opnsense.home.lan

It should be possible to add the --force flag to the acme plugin.

Does anyone know how to do that?

So, if I am reading this correctly (and with my PHP skills being terrible, I am not certain I am).

This is the code that controls when the plugin runs, and it does contain a "force" option:

https://github.com/opnsense/plugins/blob/master/security/acme-client/src/opnsense/mvc/app/library/OPNsense/AcmeClient/LeCertificate.php

What I am (so far) unable to figure out is if this code is rejecting the re-issue, or if it is acme.sh itself.

As far as I can tell, changing the public function boolean from false to true in line 53 should enable force:

public function __construct(string $uuid, bool $force = false, bool $cron = false)

But it does not seem to do so. Maybe I am reading the code wrong and it is defined elsewhere.

Looking at the acme log - it seems like acme isn't being called by the PHP code, because I see no acme logs. But I do see acme client logs:

2023-05-17T09:53:00-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:52:58-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:52:30-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:50:34-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:36:50-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:09:52-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:08:37-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:08:34-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:01:42-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T09:01:06-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-17T00:10:00-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan
2023-05-16T18:39:50-07:00 opnsense AcmeClient: issue/renewal not required for certificate: opnsense.home.lan


It all seems related to this post, which was for a different issue.

https://forum.opnsense.org/index.php?topic=25797.0

In case anyone is wondering, this is the header of the certificate as I post this at 10 am on May 17 2023
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            5d:2d:4e:d0:c2:d4:15:51:31:f9:2e:4e:55:38:37:8c
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN = Tiny Intermediate CA
        Validity
            Not Before: May 16 20:58:27 2023 GMT
            Not After : May 17 20:59:27 2023 GMT
        Subject: CN = opnsense.home.lan
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
                Modulus:



I guess I have not figured out how to properly set the force flag - now that I know it is actually in the code.



*EDIT*

Yes, it is within this PHP code - I just need to figure out how to ensure the force flag gets enabled:


        // Decide whether or not to continue.
        if (!($this->needsRenewal()) and !($this->force)) {
            // Renewal not required. Do nothing.
            LeUtils::log("issue/renewal not required for certificate: " . (string)$this->config->name);
            return false;
        }


Ok, so commenting out the code like so:


        // Decide whether or not to continue.
        //if (!($this->needsRenewal()) and !($this->force)) {
            // Renewal not required. Do nothing.
        //    LeUtils::log("issue/renewal not required for certificate: " . (string)$this->config->name);
        //    return false;
        //}


Works now - this is the sanity check that exists to prevent spamming I provider. In my case, since I am the provider I am ok with spamming my own service. However, I think this is a terrible hack - if you can even call it that because sanity checks are a good idea.

Anyone know where `force` is properly set? I would have assumed config.xml, but it seems not to be so - or I don't understand OPNSense enough yet.

Well, here is a fun one to revisit this. I logged into OPNsense today, and found that my above hack wasn't seeming to work anymore. Probably because of updates. Makes sense. I upgraded to 25.1, and it seems that the entire codebase has changed (again, makes sense) but now I cannot renew my certificates because OPNsense does not seem to believe that they need to be - even though they expire after 24 hours.


New files seen here:
https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/mvc/app/controllers/OPNsense/AcmeClient

You could just increase your certificate lifetime a bit? 24 hours is a bit arbitrary. I'm not sure how I feel about this passive revocation concept, but the fact that you have to use a force option is a rather large clue that the tooling wasn't designed for it....

Quote from: dseven on February 01, 2025, 11:02:46 AMYou could just increase your certificate lifetime a bit? 24 hours is a bit arbitrary. I'm not sure how I feel about this passive revocation concept, but the fact that you have to use a force option is a rather large clue that the tooling wasn't designed for it....

I am using passive revocation, so unfortunately I cannot increase my certificate lifetime. However, since switching to 25.1 the problem seems to happen less often. At least so far. It still fails, but I set the cron job to try to run every 6 hours, instead of every 12 hours, and now it seems to fail for the first run, then succeed on the second, and continue like that.