Subject: [Acme] Proposal for adding arbitrary CA-specific name-value pairs to registration object

From: Ray Cheng <[email-masked]>
Date: Tue, 4 Oct 2016 13:11:50 +0000

Hello all,

Background
==========

I would like to begin with a bit of background to put some context around how this ACME change proposal originated.

Entrust has released a beta ACME server to our customers that works with the current certbot client. We have also began developing some knowledge of the certbot code base and we intend to contribute to the certbot project in the future.

One of the implementation challenges we had was that we wanted to pass additional information from the certbot client to our ACME server that would be associated with the registration object. Examples of this may include:
a. account number
b. name of operator running certbot

This proposal has some similarities to ACME pull request #172 (https://github.com/ietf-wg-acme/acme/pull/172) but is intended to be generic. The hope is that these arbitrary name-value pairs would work with any CA in general without introducing very CA-specific tokens into the protocol.

What it may look like
=====================

One way to accomplish this in the protocol is to simply add a "ca-extension" object to the registration object, where the "ca-extension" object is an array of name-value pairs of strings. For example:

{
  "protected": base64url({
   "alg": "ES256",
   "jwk": {...},
   "nonce": "6S8IqOGY7eL2lsGoTZYifg",
   "url": "https://example.com/acme/new-reg"
  })
  "payload": base64url({
   "contact": [
     "mailto:[email-masked]",
     "tel:+12025551212"
   ],
   "ca-extension": [
     "<ca-ext-name-1>": "<ca-ext-value-1>",
     "<ca-ext-name-2>": "<ca-ext-value-2>"
   ]
  }),
  "signature": "RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I"
}

CA's should ignore any <ca-ext-name> in the ca-extension that it does not understand.

Regards,

Ray Cheng
Entrust Datacard

---

From: Hugo Landau <[email-masked]>
Date: Tue, 4 Oct 2016 15:44:26 +0100

>   "signature": "RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I"
Surely vendorized keys would be better:

    {
      "com.example.blorpNo": "BLORP122946"
    }

---

From: Ray Cheng <[email-masked]>
Date: Tue, 4 Oct 2016 17:44:56 +0000

>       "com.example.blorpNo": "BLORP122946"

Can you provide a bit more details on what you mean by "vendorized keys" and how it differs from the arbitrary name-value pairs in the proposal?

It seems the above can be represented as:
   "ca-extension": [
       "com.example.blorpNo": "BLORP122946"
   ]

---

From: Roland Bracewell Shoemaker <[email-masked]>
Date: Tue, 4 Oct 2016 17:04:32 -0700

Do people think there is a need for some concept of extension
criticality? Allowing servers to happily ignore certain extensions feels
like it'll lead to some not great client implementations in the long term.

On 10/04/2016 06:11 AM, Ray Cheng wrote:
> _______________________________________________
> Acme mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/acme
>

---

From: Martin Thomson <[email-masked]>
Date: Wed, 5 Oct 2016 12:22:46 +1100

Now is probably a good time to acknowledge RFC 6648.  In short, if
entrust see value in having an account number, then you should just
add a field "account" and be done with it, otherwise you end up with
prefix-regret.  As for operator, maybe "operator": { "name": "Me",
"email": "[email-masked]" }.

---

From: Ray Cheng <[email-masked]>
Date: Thu, 6 Oct 2016 19:26:21 +0000

RFC 6648 does bring up some interesting points. I can appreciate how problems evolved with the HTTP and mail "X-" headers that may pass through multiple vendor products (both client and server).

I see the proposed "ca-extension" in the registration object more as a place to hold content that a particular CA requires for its workflow. It is up to the CA to distribute to a client what extra info is required.

If a client does not send the list of key-value pairs that a CA requires, it does not mean that the ACME client does not interoperate with that ACME server at a protocol level. It just means that the client needs to "fill out the form" that the CA requires.

Using certbot as an example, possible implementations may include:

1. A new "--reg-ca-ext <key>=<value>" parameter
This parameter would take the <key> and <value> put in into the "ca-extension" object. You can specify multiple key-value pairs by specifying multiple "--reg-ca-ext <key>=<value>" parameters
2. A new "–-reg-ca-ext-file" <property-style file with a list of attributes> parameter

Adding explicit elements like "account" and "operator" can also solve the problem for now. CA's not requiring these elements would simply ignore them. However, let's suppose 6 months from now that we, or another CA, discovers we need to collect another additional piece of registration data. The "ca-extension" object would allow us to do this without changing the client or the protocol.

> -----Original Message-----
> From: Martin Thomson [mailto:[email-masked]]
> Sent: Tuesday, October 04, 2016 9:23 PM
> To: Ray Cheng <[email-masked]>
> Cc: Hugo Landau <[email-masked]>; [email-masked]
> Subject: Re: [Acme] Proposal for adding arbitrary CA-specific name-value
> pairs to registration object
> 
> Now is probably a good time to acknowledge RFC 6648.  In short, if entrust
> see value in having an account number, then you should just add a field
> "account" and be done with it, otherwise you end up with prefix-regret.
> As for operator, maybe "operator": { "name": "Me",
> > Can you provide a bit more details on what you mean by "vendorized keys"
> and how it differs from the arbitrary name-value pairs in the proposal?
> >

---

From: Ron <[email-masked]>
Date: Mon, 10 Oct 2016 13:13:04 +1030

On Thu, Oct 06, 2016 at 07:26:21PM +0000, Ray Cheng wrote:
> RFC 6648 does bring up some interesting points. I can appreciate how
> problems evolved with the HTTP and mail "X-" headers that may pass
> through multiple vendor products (both client and server).
> 
> I see the proposed "ca-extension" in the registration object more as a
> place to hold content that a particular CA requires for its workflow.
> It is up to the CA to distribute to a client what extra info is
> required.

Isn't the whole point of going through this work here (as opposed to
just having each CA invent its own thing), to provide a way for all
of the interested stakeholders to come up with a single interoperable
standard which they think will work for all of them?

So that other people can implement clients to the documented spec,
which will work with any CA that implements that spec.

I think that if your due diligence on this has shown that you'll need
things which aren't already in the spec, then we should talk about
those and add them in an organised and openly thought through way.

If you don't know what they are yet, I think the right answer is that
you should go away and think about that until you do know - not that
we should add a way to create random incompatible extensions that
still call themselves "compatible" with this protocol.

> If a client does not send the list of key-value pairs that a CA
> requires, it does not mean that the ACME client does not interoperate
> with that ACME server at a protocol level.

That's kind of exactly what that means.  Sort of by definition.

> It just means that the client needs to "fill out the form" that the
> CA requires.

Which means they are only "compatible" in the sense that "They both
use JSON".  That's not a very useful definition of "interoperable".

> Adding explicit elements like "account" and "operator" can also solve
> the problem for now. CA's not requiring these elements would simply
> ignore them. However, let's suppose 6 months from now that we, or
> another CA, discovers we need to collect another additional piece of
> registration data. The "ca-extension" object would allow us to do this
> without changing the client or the protocol.

How can you do this without changing the client, if existing clients
won't send the extra fields you've decided to require?

And if you do that, then you *have* changed the protocol.  You've just
done it without having to consult with anyone else, or without even
having to document the incompatible change you made to it.  Which is
like the opposite of interoperable.

I don't think that's a good plan.  If you want to implement proprietary
extensions that only your own client knows or supports, nothing is
stopping you from doing that.  But I think it's harmful to the idea of
ACME as an interoperable spec for you to pretend that is ACME.

If you do later realise there is something missing that is critical
to proper operation (or necessary because of some rule change at the
CABF etc.), then there's no reason people can't bring that back here
and propose that we need a revision to ACME to handle that case.

If that discourages people from adding them on a whim, with very
little thought or peer review, that's probably a Good Thing too.

If you have a real need now for extra fields, we should talk about
those explicitly, and not about adding a way for you to add them
at any time, for any reason, without ever talking to anyone else
about them.

I think your feedback here as a potential server implementor is
potentially very valuable - but that will be wasted if we just 
turn this spec into "anyone can implement their own random list
of required JSON key value pairs and call that ACME compatible",
and you don't talk openly about what extra things you think really
are necessary to make this work achieve its chartered goals.

  Ron

---

From: Ray Cheng <[email-masked]>
Date: Thu, 13 Oct 2016 16:29:08 +0000

> From: Ron [mailto:[email-masked]]
> Sent: Sunday, October 09, 2016 10:43 PM
> Cc: [email-masked]; Martin Thomson <[email-masked]>
> Isn't the whole point of going through this work here (as opposed to just
> having each CA invent its own thing), to provide a way for all of the
> interested stakeholders to come up with a single interoperable standard
> which they think will work for all of them?
> 
> So that other people can implement clients to the documented spec, which
> will work with any CA that implements that spec.

I don't see the proposed "ca-extension" as being incompatible with this goal. If clients implement this extension, they simply have to supply some runtime parameters to work with CA's which have particular parameter requirements.

With respect to client-server interop, this "ca-extension" has some similarities to the "contact" field. For example, a "mailto" URI is optional in the eyes of ACME and certbot. However, a server is entitled to have a policy that say a valid "mailto" URI must be present. If someone using certbot chose not to send the "mailto" URI, the server can legitimately reject the request. The server will accept the request if someone using certbot "fills-in" the email.

> things which aren't already in the spec, then we should talk about those
> and add them in an organised and openly thought through way.

We do know that we have a requirement for a "ca-account" field. This can be added as an optional explicit field, or as a key-value pair in the "ca-extension". Client-server interop is similar in either scenario.

> 
> If you don't know what they are yet, I think the right answer is that you
> should go away and think about that until you do know - not that we should
> add a way to create random incompatible extensions that still call
> themselves "compatible" with this protocol.

I would characterize these extensions as application-specific. X.509 extensions would be an appropriate analogy. Defining a new application-specific X.509 non-critical extension does not break X.509 clients and servers. Introducing new application features (e.g. Certificate Transparency) would be difficult if X.509 did not have extensions and required updates to its specification. 

I am not suggesting that the proposed "ca-extension" as being at the same level of importance to ACME as extensions are to X.509. I just want to point out that an extension mechanism is not necessarily bad for interop.

> > It just means that the client needs to "fill out the form" that the CA
> > requires.
> 
> Which means they are only "compatible" in the sense that "They both use
> JSON".  That's not a very useful definition of "interoperable".

ACME is much more than the JSON that is in the registration object. It provides a lot of useful standardized cert management flow that is crucial to interop.

> How can you do this without changing the client, if existing clients won't
> send the extra fields you've decided to require?

A compliant client does not need to change because it can send any new name-value pair.
It is just a matter of an extra command-line parameter or a config file addition.

> done it without having to consult with anyone else, or without even having
> to document the incompatible change you made to it.  Which is like the
> opposite of interoperable.
> 
> If you do later realise there is something missing that is critical to
> proper operation (or necessary because of some rule change at the CABF
> etc.), then there's no reason people can't bring that back here and
> propose that we need a revision to ACME to handle that case.
> 
> If that discourages people from adding them on a whim, with very little
> thought or peer review, that's probably a Good Thing too.
> 
> 
> If you have a real need now for extra fields, we should talk about those
> explicitly, and not about adding a way for you to add them at any time,
> for any reason, without ever talking to anyone else about them.
> 
> potentially very valuable - but that will be wasted if we just turn this
> spec into "anyone can implement their own random list of required JSON key
> value pairs and call that ACME compatible", and you don't talk openly
> about what extra things you think really are necessary to make this work
> achieve its chartered goals.
> 

As I have cited as examples, we have two known items that we would add to the registration object through the "ca-extension": "ca-account" and "requestor-name". I assume that a CA like Boulder would have no use for these as it does not have the concept of accounts and it has no intention of ever contacting a live person. Whether we add "ca-account" and "requestor-name" as extensions or as explicitly named fields should have no impact on Boulder or other CA's because they are likely to ignore them.

One advantage of explicitly named fields is that usability is improved slightly when running clients like certbot - at least for CA's that cared about them. The reasons are that it can be prompted for in the UI flow and you can have explicitly named command-line parameters. The down-side is that you are adding slightly more complexity for CAs that don't care about them (e.g. prompting for not applicable values and having extra documented parameters that are not needed).

---

From: Ron <[email-masked]>
Date: Sun, 16 Oct 2016 18:28:45 +1030

On Thu, Oct 13, 2016 at 04:29:08PM +0000, Ray Cheng wrote:
> I don't see the proposed "ca-extension" as being incompatible with
> this goal. If clients implement this extension, they simply have to
> supply some runtime parameters to work with CA's which have particular
> parameter requirements.

I think you are confusing 'simple mechanics' with 'interoperability'.
It might be 'simple' to add arbitrary extra fields, but it's impossible
for them to be interoperable if they aren't documented and well defined
as part of the relevant standard.

> With respect to client-server interop, this "ca-extension" has some
> similarities to the "contact" field. For example, a "mailto" URI is
> optional in the eyes of ACME and certbot. However, a server is
> entitled to have a policy that say a valid "mailto" URI must be
> present. If someone using certbot chose not to send the "mailto" URI,
> the server can legitimately reject the request. The server will accept
> the request if someone using certbot "fills-in" the email.

"There are other fields which are optional" is not a useful similarity.
The important difference is that "contact" is a well known field name
with well defined semantics for implementors.

> We do know that we have a requirement for a "ca-account" field. This
> can be added as an optional explicit field, or as a key-value pair in
> the "ca-extension". Client-server interop is similar in either
> scenario.

The mechanics may be similar, but 'interop' is only possible if you
actually standardise exactly what should go in that field when and why.

I don't particularly care how we add this to the JSON object as long
as it's not totally insane - what I'd want to see is a rationale for why
ACME needs specific additional fields for your implementation, that they
aren't already provided for by some other existing mechanism, and a clear
definition in the standard of how what you need should be done by anyone
who does need it.  We don't get any of the things which are essential for
interop if the solution is just "anyone can add or remove or change their
own extra fields any time they like".

And in the case of something like what I imagine "ca-account" might be
used for, some security consideration and review might be useful too.
What stops me from putting someone else's account details into my
requests for certificates from you?  Surely you need something stronger
than this to securely link an ACME account key to your own billing
account records?

And you're probably not the only CA who might want a solution to that,
so we should have one well thought through solution for ACME, not one
per CA (that possibly one developer invented without review, under
time pressure from their manager to deploy it by tomorrow).

> I would characterize these extensions as application-specific. X.509
> extensions would be an appropriate analogy. Defining a new
> application-specific X.509 non-critical extension does not break X.509
> clients and servers. Introducing new application features (e.g.
> Certificate Transparency) would be difficult if X.509 did not have
> extensions and required updates to its specification. 
> 
> I am not suggesting that the proposed "ca-extension" as being at the
> same level of importance to ACME as extensions are to X.509. I just
> want to point out that an extension mechanism is not necessarily bad
> for interop.

X.509 probably isn't the best example of Good Practice or a model for
good interoperability :)  X.509 version 3 (which added the extensions)
seems more like a case of the ITU throwing its hands in the air in
acknowledgement of their own process limitations, and doing the same
as what was done to Q.931 for QSIG.  We've had a long time to learn
the lessons of how that turned out, and the IETF is open to all
participants, so I don't think we have the need to punt on carefully
considering exactly what this protocol needs to function for all of
its intended users.

I do quite expect that whatever we do today, there probably will be
an ACME v3 eventually as people find bugs and/or limitations or security
vulnerabilities that aren't yet obvious to us.  I'd be happier if that
didn't happen, but I'm realistic enough to expect that it probably will.
So it's a bit early for us to already be giving in to just letting chaos
rule for 'normal' implementations by early adopters.

JSON objects are already inherently extensible, they don't need a special
tag defined for that like ASN.1 does.  The interesting question here is
not "Do we need a mechanism to allow future extension?" (because the
answer to that is 'no, we already have that'), it is "Should we allow
extensions that aren't in themselves standardised?" - And speaking from
my own experience, I think the answer to that should be no too.  That
would be a big mistake to repeat this early in the evolution of ACME.

> ACME is much more than the JSON that is in the registration object. 
> It provides a lot of useful standardized cert management flow that is
> crucial to interop.

Yes.  Which is useful and allows interop precisely because it is
standardised.  If we encourage undocumented proprietary extensions
to it, we lose that value almost immediately.

We can't stop people from doing that anyway.  But that doesn't mean
we shouldn't prefer creating a standard which is complete enough to
not need them for already known users and uses.

> It is just a matter of an extra command-line parameter or a config file addition.

Which is functionally equivalent to saying "we have interop, because an
end user can always edit the source of the client they use, to make it
compatible with a CA using non-standard extensions".  Assuming they
can actually find out the details of those extensions themselves, which
aren't a documented part of ACME.

> As I have cited as examples, we have two known items that we would add
> to the registration object through the "ca-extension": "ca-account"
> and "requestor-name". I assume that a CA like Boulder would have no
> use for these as it does not have the concept of accounts and it has
> no intention of ever contacting a live person. Whether we add
> "ca-account" and "requestor-name" as extensions or as explicitly named
> fields should have no impact on Boulder or other CA's because they are
> likely to ignore them.

Boulder or other CAs aren't the case where interop with your requirements
is necessary.  It's the client software implementors and end users which
want to be able to interop with any ACME using CA who need all of this
to be well standardised.

And they can only do that if these extra things are standardised too.
They don't have to be mandatory for every server to use, but it is
important that CAs which do use them, don't all reinvent the same
wheel differently.

We learnt not to build train lines with different gauge tracks a long
time ago too :)

Let's talk about what "ca-account" and "requestor-name" should do,
and confirm there really isn't some other existing place those
functions should be (or are already) supported in.  And then if we
do really need them because nobody thought of that yet, let's add
the needed mechanism and documentation for them.

> One advantage of explicitly named fields is that usability is improved
> slightly when running clients like certbot - at least for CA's that
> cared about them. The reasons are that it can be prompted for in the
> UI flow and you can have explicitly named command-line parameters. The
> down-side is that you are adding slightly more complexity for CAs that
> don't care about them (e.g. prompting for not applicable values and
> having extra documented parameters that are not needed).

I think we need to not make too many assumptions about UI here, or
design the protocol around what seems 'simple' in one UI idiom or
another.

We should look at what information you need carried in the protocol
to do your job as a CA that isn't already present or supported by
what we have defined so far.  How the client software collects that
information is a problem with many right answers for different users.
The important bit here is that we have just one clear way to send
that same information to all CAs that do require it.

That way the client software doesn't need specialisation for each CA
to send that data, or need to collect essentially the same data in
multiple different forms to suit each CA's quirks in their custom
fields for it.  It then does become the 'simple' matter of "do I
need the content of this field from the user or not".  And they can
safely err on the side of sending it, knowing that CAs which don't
care really will ignore it, and not mistake it for a similarly named
but incompatible field of their own.

  Ron

---

From: Jacob Hoffman-Andrews <[email-masked]>
Date: Thu, 27 Oct 2016 14:27:44 -0700

Hi Ray,

Sorry for the delay in responding. First off, I want to say a big thanks
for implementing ACME and making it interoperate with Certbot. That's a
huge step forward for the ACME protocol, and I know the Certbot folks
look forward to your contributions.

> One way to accomplish this in the protocol is to simply add a "ca-extension" object to the registration object, where the "ca-extension" object is an array of name-value pairs of strings. For examp…
I think this makes a lot of sense, and is in the spirit of the other
places we've intentional left hooks for CA-specific customization, like
OOB challenges. I'm inclined to accept it.

Additionally, your experience as a commercial implementer of ACME may be
valuable to spot places where the current protocol is lacking. For
instance, you need an "account" field, and StartCom needs
(https://github.com/ietf-wg-acme/acme/pull/172) a "token" field. Can we
support those use cases natively in ACME so they don't need to be
extensions? What do you put in the "account" field, and how do you
authenticate the link between the ACME account and the Entrust account.

Thanks,
Jacob

---

From: Jacob Hoffman-Andrews <[email-masked]>
Date: Thu, 27 Oct 2016 15:19:44 -0700

By the way, one specific example: in
https://github.com/ietf-wg-acme/acme/pull/172, because we are specifying
the "external_secret" field explicitly, we can give guidance that
clients should avoid logging that field. Do you have any fields you need
to add that have similar properties?

---

From: Ray Cheng <[email-masked]>
Date: Mon, 31 Oct 2016 15:43:19 +0000

Hi Jacob,

From: Jacob Hoffman-Andrews, Thursday, October 27, 2016 5:28 PM:
> > One way to accomplish this in the protocol is to simply add a "ca-
> extension" object to the registration object, where the "ca-extension"
> object is an array of name-value pairs of strings. For example:

We are effectively using "ca-account-id" and "ca-account-secret" fields to authenticate the link to the Entrust account. Since these fields do not currently exist in draft-03 and certbot, we are embedding them in the URL that a particular customer uses to access our ACME server.

The "external_secret"/"token" is slightly different but is also useful as an "API key" type of authentication.

Although we see value in a "ca-extension" object, we also support adding explicit fields in ACME. There are some advantages to explicit fields - one in particular is the special handling of designated secret fields by clients.

Thanks for your feedback.