While I'm implementing ARI, I'm realizing that it might be handy to store the ACME CA's directory URL alongside the certificate as metadata.
I'm already storing the cert URL (as given by the Order object) as metadata just in case the user for some reason needs to re-download the certificate. I was about to store the ARI URL too, but I realized that this (and the cert URL) both come from the Directory object which could change.
Seeing as the directory needs to be manually configured anyway, what are your thoughts on storing the directory URL alongside the certificate also? This way, any requisite URLs could be reconstructed from the CA directory it was obtained from. (If the dir URL changes, the user needs to update their ACME client config anyway.)
Memory hazy but when Let's Encrypt was transitioning from their v1-v2 endpoints, the directory endpoint changed, but didn't the v2 endpoint still return v1 resource URIs for objects created under that system? If so, that would be an argument to store the full ARI URI. Though I suppose the ARI URI isn't quite the same as an account/order URI since it's derived from the cert.
Also, a different ACME provider that has a need to change their directory URL might implement the transition entirely differently to how LE did it. I'd guess most would simply require a hard cutover (new accounts, new orders) from old to new because it's easier. But that uncertainty makes trying to plan around it seems like an exercise in futility.
In any case, I say store whatever makes life easier for you and/or your users.
My library tracks everything in SQL. Every Certificate is linked to an ACME Account, each Account to an ACME Server, and each Server has a Directory URL. We just build out the Directory URL as needed for a user by finding the appropriate Server for the context. IIRC, our directory url field is configured with a unique index; although we use unique human names as public identifiers, they're just a fancy label as the directory is essentially a unique and canonical URL for a single server.
IMHO I think that is the right thing to do.
It sounds like you're doing a flat file storage. If so, I would definitely store the directory URL in the metadata. I would also store the hash/fingerprint of the Account Key used to generate the certificate as well. That would be useful if the directory changed (and therefore the account-url changed) but the Account Key did not change, allowing you to find the new account URL.
The chances of this stuff changing is pretty small though. For simplicity, I think it is fair to consider a new directory URL as indicative of a new ACME Server – as a given domain could potentially host multiple ACME servers. When it comes to SQL based data storage, I found that assumption is much easier to defensively code around than trying to support a directory change for a given server.
Don't you need the directory URI for renewals anyway? Certbot stores it in the metadata from start. You can combine multiple CAs, so without storing the directory URI, you'd suddenly renew a Sectigo cert with a Let's Encrypt cert?
It's safe to store the Certificate URI, because that's returned verbatim inside an Order object and should remain usable for the entire lifetime of that order and/or that certificate.
It's not safe to store the ARI URI, because it is intended to always be constructed from the base path contained in the Directory and the local certificate & issuer data. For example, Let's Encrypt's current ARI base path is https://acme-v02.api.letsencrypt.org/get/draft-ietf-acme-ari-00/renewalInfo/, which is obviously going to change.
It's generally safe to store the Directory URI itself, because it can reasonably be expected to be stable. Technically there are no guarantees that any given directory URL will continue to function for any particular period of time. A user may assume that if they update the directory URL in their config file, then their client will completely cease using the old directory URL. But I think I agree with you that storing the directory URL for the purpose of being able to make ARI queries and revocation requests, even if the user updates their configured directory URL, is a good idea.
Yes. The directory URL is always available when an ACME client is configured (whether it be a default one -- we default to LE and ZeroSSL currently). However, we often have users who have all their certificates (a folder of folders containing certs, keys, and metadata) but not an active ACME client configuration (usually server migrations). Thus the directory URL through which the cert was issued is not necessarily tied to the cert in some cases. I don't know if that's actually problematic, but I am thinking now, "This might be good to have," since certs are not always stored and moved with the ACME client config.
No, because our storage schema organizes certs by their issuers, which for ACME issuers, is the directory URL. However, URLs are not safe for use as filenames, so we have to sanitize the folder name. Given a list of configured/available CAs, we can see which one(s) have a current or expiring certificate, and load accordingly, and renew from the same CA even without the directory URL stored alongside the cert. (Although in future versions we will support round-robin load balancing CAs and renewing from any configured CA regardless of prior CA.)
Awesome, thanks I'll store the directory URI then.
Again, to clarify for other readers: our ACME client does not actually need or use this information, because the directory URI is the one piece of config it needs in order to work in the first place. An ACME client will already have its directory URI configured. But certificates and ACME client configs are not always kept together.