acme
acme copied to clipboard
Check expiry
I hacked together a quick check:
- Check whether
.crt
is present and readable - Parse
.crt
and check whether it's valid for more than a week - Quit
exit(1)
if so
This solves https://github.com/google/acme/issues/30 (for me) (in a quick way)
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).
:memo: Please visit https://cla.developers.google.com/ to sign.
Once you've signed, please reply here (e.g. I signed it!
) and we'll verify. Thanks.
- If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address. Check your existing CLA data and verify that your email is set on your git commits.
- If you signed the CLA as a corporation, please let us know the company's name.
Signed it.
CLAs look good, thanks!
Been thinking about this. Not sure it's the best way because:
- "cert is still valid for more than one week, not renewing" is a bit harsh :) I know many people/orgs re-create certs even 1 month prior to expiry, to have higher availability.
- could be achieved with openssl quite easily, e.g. parse a cert with openssl, check its expiration timestamp and run acme only if needed.
I would think an acme renew
, a new sub command, could do this behind a flag, e.g.:
# request a new cert of a previously authorized domain
acme renew example.com
# renew only if expiring within the next 48 hours
acme renew -e 48h example.com
wdyt?
I like readCrt
func though. Certainly useful for the future acme renew
command.
I'm definitly open on the wording :)
I agree, that a flag like -e
to specify the renew-timeframe (the default value can be somewhere between 1-4 weeks) is a good idea.
Some thoughts on the external openssl
approach: Parsing the expiry date using openssl is not that straightforward, and it requires some shell-scripting (and the openssl
binary).
Not sure if there's a better way, but I ended up using something like this:
expr $(expr $(date '+%s' --date "$(sudo openssl x509 -enddate -noout -in example.com.crt |grep 'notAfter' |cut -d= -f2)") - $(date '+%s')) / 24 / 3600
Especially since it's only a few lines of Go code, without any further dependencies, I'd vote for doing this internally.
Ok, yeah, there's value in doing it internally but I really want to keep commands behavior to a minimum when it comes to a critical decision (e.g. whether to re-issue a cert or not). So, here's what I would do:
- leave
acme cert
as is - add new
acme renew
, which renews an existing cert (there's a specific flow for this in the spec, much easier than new cert), taking into account an-e
flag.
how does that sound?
As the official certbot
client has a renew
sub-command as well, I suppose it's a good idea to follow that, especially if the internal flow is different. So, basically, renew
must be implemented first, right?
Precisely. Or, it could also be an option to the acme cert
command:
# will renew all existing certs which expire within the next 48 hours
acme cert -renew=48h
# renew only specific domain(s)
acme cert -renew=48h one.example.com two.example.com
# renew all using default value
acme cert -renew
Now that I'm looking at it, seems simpler than adding a new acme renew
command. Empty renew, acme cert -renew
could have a sensible default, e.g. 1 week or 1 month.
Do you see any scenarios I'm missing, which would require a separate acme renew
command?
Not sure if this is an issue, but I can think of one reason to split it into two commands:
If you accidently use cert
over and over again, you end up re-issuing the certificate as often as your cronjob runs.
If this is an issue, it might be also be solved by requiring a -force
if cert
is used and the .crt
file is already present.
Besides that, I have no personal preference between acme cert -renew
or acme renew
, unless the preference is to copy the behaviour of certbot
.
Ok, let's go with a separate acme renew
. The command usage text will be simpler, too, as it'll require less flags.
Sounds great.
Thoughts about the "safeguard" for accidently re-issuing an existing certificate with acme cert
?
AFAIK re-issuing a cert does not revoke the existing one, so it should be safe. But, like you said, we can always add '-force' arg to acme cert
in the future, if this turns out to be an issue.
Yeah, the issue would rather be load on the letsencrypt servers than inaccessibility of our services. Let me know if there's a task that I can help you with!
I just started using acme, discovered renewal wasn't implemented, but then found this lovely pull request! What are the chances of a merge and release before my next renewal? 😉
Are these changes likely to land?
@jdub what is it exactly that you'd need? acme cert ...
using an account which was previously granted the authorization for a domain will create a new certificate, effectively doing the renew.
Could you sum-up what the need is, in a bullet list style.
Hmm, that's odd, acme cert
doesn't seem to renew as I'd expect.
-
acme whoami
returns sensible information -
acme cert waugh.id.au -dns waugh.id.au www.waugh.id.au mail.waugh.id.au
responds with:waugh.id.au: acme: identifier authorization failed
- I have another domain for which I need an EC cert and an RSA cert -- it prompts for me to add a new
_acme-challenge
DNS entry.
if you have already issued at least one certificate in the past, the next time invocation of merely acme cert <same list of domains>
, i.e. without additional flags like -dns, will give you the new certificates right away.
Oh, without -dns
. I thought I should tell it how it had been authorised. Unfortunately, that didn't seem to work either:
$ ls .config/acme/waugh.id.au.*
-rw-r--r-- 1 jdub jdub 3.2K Oct 1 12:23 .config/acme/waugh.id.au.crt
-rw------- 1 jdub jdub 227 Oct 1 12:21 .config/acme/waugh.id.au.key
jdub@node:~$ acme cert waugh.id.au www.waugh.id.au mail.waugh.id.au
waugh.id.au: acme: identifier authorization failed
I can't see a verbose option… is there an environment variable, perhaps?
That is strange. I've just done it about 30 min ago. Are you sure you used the same account?
The reason it works is, Let's Encrypt remembers all identifiers (domains) that an account has been previously authorized for. It could be the case though, that by running acme cert -dns ...
a completely new authorization was created, overwriting an existing valid one. So, it might be in a "pending" state now.
What should work is:
- Request a new certificate(s) in the regular way by fulfilling a challenge, e.g. dns.
- Every time you want to renew a cert, just execute
acme cert <domains list>
, without any other option.
It may be arguable that a command like acme renew
could be implemented, actually, as a subset of acme cert
command, just to avoid confusion.
Yeah, the new authorisation theory makes sense. D'oh! I'll have to wait for the next renewal period to try it the right way. Thanks for your help!
(I do think a renew
command, without any parameters like -dns
would help avoid errors like this.)
Three months later… unfortunately:
jdub@node:~$ acme cert waugh.id.au www.waugh.id.au mail.waugh.id.au
waugh.id.au: acme: identifier authorization failed
I'm getting the same identifier authorization failed
message. I suppose this should be a seperate issue?
@chr4 I don't think so. This bug is just a helper to renew the certs easier. But it should already work regardless.
What challenge type are you using?
@x1ddos you're right. This was actually due to a misconfiguration of nginx, the challenges weren't served.
While you're here: Any news on the support for only renewing certificates when they're about to expire? I'm still using my fork to achieve this. Let me know if there's anything that I can help implementing!