Acme.sh renew hook - quotes and substitution and backslashes, oh my!

I don’t think this really ought to be the support channel for acme.sh, but I’m not aware of another one other than filing an issue against it–if there’s one that I’m missing, please let me know.

I’m wanting to automate installation of the cert in an iXSystems TrueCommand system. This can be done with a relatively straightforward API call using this command:
curl -l -g --data "{\"args\" : { \"pem\" : \"$(cat fullchain.cer)\", \"key\" : \"$(cat domain.key)\" } }" -u "user:pass" -X GET http://localhost/api/ssl/cert_import

Ordinarily I’d run acme.sh --install-cert -d whatever --renew-hook "long command with arguments". Simple enough in the normal case, but when the command includes, quotes, escaped quotes, command substitution, etc., I’m concerned that it might not get recorded correctly. What would be the best way to do this? Two possibilities come to mind:

  • Write a separate script to run this command (and optionally parse the result), and call that as the renew hook
  • Base64-encode the entire command string, edit .acme.sh/domain/domain.conf, and insert that value for Le_RenewHook Nope, this doesn’t do it–unless there’s an additional trick I’m missing. It simply tries to execute the base64-encoded string
  • Reissue the cert enclosing the command (as suggested by Osiris below) in single quotes

Thoughts between these, or a better way to make this happen?

1 Like

Can’t you just use single quotes for the acme.sh option, as you’re not using single quotes in your curl command.

2 Likes

That seems like it would be a much simpler answer (and carries with it the very real possibility that I was missing something really obvious), but when I tried it, no change was made anywhere. I wonder if the --install-cert command needs to have paths to create copies of at least one of the cert/key/chain files? Seems an odd requirement if so.

1 Like

I am not familiar with acme.sh unfortunately.

1 Like

So in the .conf file, Le_RenewHook is set (by default) to an empty value enclosed by single quotes (''). I pasted in the base64-encoded string, which (as I said above) it tries to execute. But on reviewing the .conf file, I see that the value was changed into a different base64-encoded value, prefixed with __ACME_BASE64__START_ and followed by __ACME_BASE64__END_. I didn’t decode it, but I’d bet it was the original encoded string, re-encoded with base64.

I expect the thing to do here is (as Osiris suggested) simply paste in the command between the single quotes. Since I don’t know of a way to test it without forcing a new cert issuance, I’ll give it a few days before I run it again to avoid any rate limit issues.

You can always put these commands into a bash file and ask acme.sh to execute the bash file instead, right?
According to dev, when using a hook you can also read the path of certificate/keys from env variable.

P.S. You don’t need to reissue one, just request a certificate in staging environment and run that instead.
The renew hook will always be converted to base64 and add the ACME_BASE64_START and End.

Yeah, that’s my first bullet. I’m not too keen on creating an external script just to run a single command, but it would definitely avoid the issues I mentioned.

1 Like

After a few days’ wait, and seeing what happened with the base64-encoded string I’d previously put in the .conf file, I tried a slightly different tactic. I still directly edited the .conf file, but I edited it to Le_RenewHook='curl -l -g --data "{\"args\" : { \"pem\" : \"$(cat /root/.acme.sh/domain.tld/fullchain.cer)\", \"key\" : \"$(cat /root/.acme.sh/domain.tld/domain.tld.key)\" } }" -u "admin:password" -X GET https://domain.tld/api/ssl/cert_import'

Obviously, paths, hostname, and user/password were changed to the actual correct value. Then ran acme.sh --cron -f, it ran and deployed the cert. Checking the .conf file confirms that the command was base64-encoded by acme.sh itself.

For new issuance, I expect @Osiris’ suggestion to simply enclose the entire command in single-quotes as the --renew-hook would be the right way to go. But if the cert’s already been issued, this looks like the way to do it.

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