Open cowwoc opened 8 months ago
Renewing the certificate is basically just:
There is nothing more you have to do.
STAR is optional and needs to be supported by the CA. If you don't need short-lived certificates, you can ignore it. If you want to use it, you can skip the order process for renewal and just download the renewed certificate. This difference is rooted in the ACME protocol.
RenewalInfo is optional, needs to be supported by the CA, and only gives suggestions about when it is best to renew your certificate, but otherwise isn't involved in the renewal process.
It seems that you struggle with the low-level nature of the acme4j client. But this is an intentional design decision, so acme4j can used in Spring, JakartaEE, Quarkus, Android, or just in a standalone tool. For a higher-level approach, persistence and asynchronous processes would be needed, which would restrict acme4j to a certain framework.
You are right though that there are two methods Order.getCertificate()
and Order.getAutoRenewalCertificate()
. This is indeed not necessary, and I will merge it into one method in the coming release.
Ah, wait, I start to understand... Your problem is to find out when to renew a certificate.
How would the result you expect look like?
Correct. That was my point.
I was thinking the user would specify what approaches/capabilities to try, and then ask acme4j to check if renewal is necessary. If multiple approaches are equivalent, I would also allow users to specify an order of preference.
The default behavior would have all capabilities enabled for maximum accuracy. Users would disable capabilities to trade accuracy for speed.
Accuracy isn't really a concern here. You should renew the certificate in time (i.e. a few days before expiry) because there could always be network issues, CA issues etc. You wouldn't want to wait to the last minute.
The only information acme4j has for sure is the expiry date of a certificate. It's the individual decision of the user when it's time for renewal before the expiration. If the renewal is too early, the CA might deny it because it had already issued a certificate not too long ago. If the renewal is too late, the certificate could expire before a new one is issued.
Some CAs send RenewalInfo, giving a time window that suggests when it's best to renew the certificate. Other CAs do not send it.
Some CAs support STAR, and also give a time window (or at least a "latest time") when to fetch the renewed certificate. However, this only works if the user has requested a STAR certificate, and if the CA supports it.
So, with all the information acme4j has, it could only give a time window for renewal (if provided by the CA), and the expiry date of the certificate (but then it's too late already).
The unknown factor is your implementation of the renewal process. acme4j does not know about the maximum duration of your renewal process (given you also want to be prepared for unforseen circumstances like network issues), so it cannot really tell you when it's best to do the renewal.
Another approach would be for the user to pick a renewal time and then pass it into a method that would clamp it into the range recommended by the CA. If the CA does not provide any recommendations, return the input value.
Sounds reasonable... Let me think about it a little bit.
I noticed that in the latest documentation you write:
After your order is finalized, you must use Order.getAutoRenewalCertificate() to retrieve a STAR certificate! Do not use Order.getCertificate() here.
I don't see why users should have to make this decision twice... if a STAR certificate was requested and one is available then why not just have getCertificate()
return it? This would simplify the workflow.
Similarly, https://shredzone.org/maven/acme4j/usage/renewal.html#fetching-star-certificates-via-get sounds like an implementation detail that should be abstracted away from the user.
if a STAR certificate was requested and one is available then why not just have
getCertificate()
return it? This would simplify the workflow.
It would make it impossible to access the "classic" certificate if a STAR certificate is available. But you are right, it makes no sense here to make both certificate types available if STAR is enabled. I will change the implementation accordingly.
Renewing a certificate is harder than it should be.
If STAR is supported, we are supposed to do one thing. If RenewalInfo is supported, we are supposed to do a different thing. Otherwise, we are supposed to do a third thing (come up with our own algorithm to check for certificate expiration on a regular basis).
I suggest adding a class that delegates to one of these scenarios under the hood so end-users don't have to play with it themselves.