In order for current CAs to be able to migrate to ACME, it's important that ACME have a conceptual model that aligns with those CAs current issuance practices.
Recall that the ACME proceeds roughly as follows:
- Applicant registers an account with the CA
- Applicant proves possession of one or more domains
- Applicant requests issuance of certificates with those domains
That gives us an object ownership model of roughly the following form:
Registration
|
+--* Authorization
|
+--* Certificate
That is, a registration representing a user's account can have multiple authorizations, which can in turn be used to issue multiple certificates belonging to the account.
After talking with current CAs, it appears that there a few gaps between this process and the processes that current CAs follow:
- CAs don't issue instructions for validating names until they get a CSR
- CAs consider authorizations to be scoped to a particular issuance
- CAs bundle multiple CSRs into an "order" (e.g., for RSA and ECDSA certs with the same contents)
- CAs have a "buy" step that is separate from requesting issuance
- CAs consider renewal different from creation of a new certificate
CAs will also probably need a way to bridge between their existing account systems and ACME registrations. However, since this concern is fairly specific to the registration management process, we will save it for another time.
There will also be a need to define some new challenge types to accommodate legacy validation practices, but this should be trivial given the extensibility of the challenge space.
Our goal here is to address these needs while minimizing the additional complexity that is added to the protocol.
Given these requirements, we need more nuance in our object model. For (2), we will need to give authorizations a notion of scope. To address (3), we will need an "order" abstraction, and to address (5), we will need to more clearly separate "certificate requests" from "certificate instances".
This leads us to an object model something like the following:
Registration
|
+--* Authorization
|
+--* Order
|
+--* Authorization
|
+--* CertificateRequest
|
+--* CertificateInstance
Note that "Authorzation" appears twice, since we're accommodating both "global" authorizations and "order" authorizations. The CA can advertise its willingness to create global authorizations by putting a "new-authz" endpoint in its directory. If that appears, the client can use that, but it must also fulfil any new authorizations/challenges that the CA requires of it in a new order.
The separate "buy" step would be represented using an update to an order object, providing any required information. Abstracting over the commercial connotations, I prefer to think of this as "activation" of the order -- converting an existing order into one that is ready to be used for issuance.
As in current ACME, the process would flow down the tree (now with a few more branches):
- Applicant registers an account with the CA
- If the CA offers global authorizations, then the applicant may make some
- Applicant requests issuance by sending in some CSRs to create a new order
- If the order returned by the CA requires more authorizations, the applicant fulfils the required challenges
- Once all required authorizations have been fulfilled, the applicant activates the order (if it is not already active) to issue certificates
In other words:
OLD: Register -> Authorize -> Send CSR -> [CA Issues]
NEW: Register -> Authorize* -> Send CSR -> Authorize* -> Activate? -> [CA Issues]
For CAs that allow global authorizations, this flow reduces to the former flow, assuming that applicants take advantage of global authorizations when they can. The registration and authorization step are the same. The new-certificate step is replaced by a new-order step. If the applicant has done all the necessary authorizations, then the CA can create an order object that is already ready and activated, and has all of the relevant certificates populated.
Another way to handle the "buy" operation (besides having an "activate" step) would be to have any required payment actions be handled via a new challenge. Rather than considering this a "payment" challenge, I would suggest that it be something like an "out-of-band" challenge -- the ACME client needs to have a human visit a web page and get further instructions.
{
"type": "out-of-band",
"href": "https://ca.com/completion/token-for-this-transaction"
}
This model would result in a simpler conceptual model, since everything blocking on the issuance would be a challenge, whether payment or domain validation. However, it could result in some additional complexity in client logic if CAs wanted to be able to only issue challenges after purchase. In that case, you would need to have the set of challenges change over time (with validation challenges added after the payment challenge was fulfilled), and have the client accommodate this possibility.
The major question at this point is whether the expanded new flow is sufficient to meet the needs of a critical mass of existing CAs. For example, is it OK to have the activation/purchase always after the authorization? Or does there need to be an option for it to come sooner?
I have previously given this some thought, I think the above are required but additioanlly CAs will need support for:
For payment challenge, my thinking was I would use 402 (Payment Required) with a JSON message describing accepted payment methods, and an invoice like structure. My thinking was a JWT signed payment message from some "trusted payment" entity could be passed in on resubmission. This message would say what was paid for.
For additional evidence, my thinking was I would use 403 (Authorization Required) with a JSON message describing what additional evidence was needed.