Skip to content
This repository has been archived by the owner on Apr 24, 2020. It is now read-only.

Remove GET requests #445

Merged
merged 11 commits into from
Sep 24, 2018
Merged

Remove GET requests #445

merged 11 commits into from
Sep 24, 2018

Conversation

bifurcation
Copy link
Contributor

This is one option for resolving the privacy concerns raised in Adam's and Ben's AD reviews.

send a POST request with a JWS body as described above, with the
following differences:

* The JWS Protected Header MUST contain a "typ" field with the value

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be "type", not "typ"?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that there exists a JWS header called "typ", but that's supposed to be a media type. Is it ok to redefine "typ" for ACME?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamroach pointed out to me that the typ header parameter is tied to media types, though, so we'll have to pick a different signal here. Because application/GET isn't a thing.

@@ -790,7 +806,7 @@ externalAccountRequired (optional, boolean):
new-account requests include an "externalAccountBinding" field associating the
new account with an external account.

Clients access the directory by sending a GET request to the directory URL.
Clients access the directory by sending a POST-as-GET request to the directory URL.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be GET, as this is about the directory (which is explicitly mentioned as GET above).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. Overzealous search-and-replace :)

@jsha
Copy link
Collaborator

jsha commented Aug 30, 2018

I think we don't need to require a "typ" field. I think we just need to update the semantics for each resource so that POSTs are always allowed, and a POST with the literal contents {} is a request to echo the current contents of that resource. This is what we already do for retrieving account objects, so we should mirror that.

send a POST request with a JWS body as described above, with the
following differences:

* The JWS Protected Header MUST contain a "typ" field with the value
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

following differences:

* The JWS Protected Header MUST contain a "typ" field with the value
"GET"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need IANA considerations to register this header parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; in fact, I chose typ because it was already registered. However, as noted above, that'll need to change.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow I thought we had a registry of values that the "typ" field could take. Which, I guess we do, if it's media types, but I was clearly confused about it.

| Poll for status | POST-as-GET order | 200 |
| Finalize order | POST order finalize | 200 |
| Poll for status | POST-as-GET order | 200 |
| Download certificate | POST order certificate | 200 |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm feeling particularly dense today (jet lag), but why is this POST and not POST-as-GET?

"alg": "ES256",
"kid": "https://example.com/acme/acct/1",
"nonce": "uQpSjlRb4vQVCjVYAyyUWg",
"url": "https://example.com/acme/new-authz",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "url" header value is not correct for a POST to /acme/cert/asdf

"alg": "ES256",
"kid": "https://example.com/acme/acct/1",
"nonce": "uQpSjlRb4vQVCjVYAyyUWg",
"url": "https://example.com/acme/new-authz",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "url" header value is not correct for a POST to /acme/authz/1234

"alg": "ES256",
"kid": "https://example.com/acme/acct/1",
"nonce": "uQpSjlRb4vQVCjVYAyyUWg",
"url": "https://example.com/acme/new-authz",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "url" header value is not correct for a POST to /acme/authz/1234

@cpu
Copy link
Collaborator

cpu commented Aug 31, 2018

I think we don't need to require a "typ" field. I think we just need to update the semantics for each resource so that POSTs are always allowed, and a POST with the literal contents {} is a request to echo the current contents of that resource. This is what we already do for retrieving account objects, so we should mirror that.

@jsha the POST to initiate a challenge throws a 🔧 into this plan. Specifically the server needs a way to differentiate a POST to an authorization's challenge as a POST to initiate the challenge validation process or a POST-AS-GET to poll the challenge. Both types of POST would be using a {} body and without the typ header or equivalent I don't think it would be possible to know which was intended.

One option is to change the "start the challenge" POST to include a marker field in the body instead of using a "typ" header in the JWS and reserving the empty body as a marker for POST-AS-GET.

Copy link
Collaborator

@cpu cpu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few more comments.

I think "7.3.7. Account Deactivation" needs to be updated to make it clear that under this new proposed authenticated POST-as-GET scheme you would lose access to all authorization, challenge, order and certificate information associated with the account that is deactivated. Previously you could continue to GET all of these resources post-deactivation and this may be a surprising outcome for folks that aren't aware of it before deactivating (especially since ACME does not provide a mechanism to "re-activate").


* The JWS Protected Header MUST contain a "typ" field with the value
"GET"
* The payload MUST be an empty JSON object ({})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should the server return to the client if this isn't true? A urn:ietf:params:acme:error:unauthorized type problem? urn:ietf:acme:error:malformedRequest?


We will refer to these as "POST-as-GET" requests. On receiving such
a request, the server MUST authenticate the sender and verify any
access control rules. Otherwise, the server MUST treat this request
Copy link
Collaborator

@cpu cpu Aug 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should the server return to the client if the POST-as-GET authentication fails? A urn:ietf:params:acme:error:unauthorized type problem? urn:ietf:acme:error:malformedRequest?

Otherwise, if a client wishes to fetch a resource from
the server (which would otherwise be done with a GET), then it MUST
send a POST request with a JWS body as described above, with the
following differences:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should the server return if it receives a GET to a resource? SHOULD (MUST?) return a urn:ietf:acme:error:malformedRequest problem with status 405?

Copy link
Collaborator

@cpu cpu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bifurcation Thanks for the iteration. It's looking better. Few small things to flag.

Otherwise, the server MUST treat this request as having the same
semantics as a GET request for the same resource.

The server MUST allow GET requests for the following resources(see
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: resources(see) -> resources (see)


The server MUST allow GET requests for the following resources(see
{{resources}}, in addition to POST-as-GET requests for these
resources:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think the second "these resources" in this sentence is redundant.

* The newNonce resource
* Certificate resources

Allowing GET requests for the directory and newNonce resourcse
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "resourcse" -> "resource"

@@ -1616,7 +1639,9 @@ orders or authorization transactions based on a change of account key.

A client can deactivate an account by posting a signed update to the server with
a status field of "deactivated." Clients may wish to do this when the account
key is compromised or decommissioned.
key is compromised or decommissioned. A deactivated account an no longer request
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "an no longer" -> "can no longer"

"url": "https://example.com/acme/authz/1234",
"typ": "GET"
}),
"payload": base64url({}),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be "payload": null, now since its replacing a GET to this authz with a POST-as-GET?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should actually be "payload": "", since JSON distinguishes between an empty string (or equivalently, zero-length payload) and the null value.

"url": "https://example.com/acme/authz/1234",
"typ": "GET"
}),
"payload": base64url({}),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto here RE: the null payload.

cpu pushed a commit to letsencrypt/pebble that referenced this pull request Aug 31, 2018
This is an experimental implementation of the acme draft protocol change
proposed in ACME PR 445[0]. When Pebble is run with `-strict` it will no
longer allow unauthenticated GET requests to Orders, Authorizations or
Challenges. Support is added for "POST-as-GET" requests as an
authenticated alternative.

[0] - ietf-wg-acme/acme#445
certificate chain. (See {{?I-D.ietf-acme-star}} for more advanced
cases.) A server that allows GET requests for certificate resources
can still provide them a degree of access control by assigning them
capability URLs them capability URLs

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"them capability URLs" is there twice.

Copy link
Contributor

@yaronf yaronf Sep 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also please add a reference for "capability URLs", https://www.w3.org/TR/capability-urls/ (the same reference that's listed below).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest to add: The server MAY choose to allow GET requests to certain certificate resources but not to others. The server can base this decision on out-of-band knowledge (e.g., to allow GET requests to certificates owned by a certain account) or on order-specific information, such as the extension defined in {{?I-D.ietf-acme-star}}.

| Poll for status | POST-as-GET order | 200 |
| Finalize order | POST order finalize | 200 |
| Poll for status | POST-as-GET order | 200 |
| Download certificate | GET order certificate | 200 |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the "Download certificate" row be "GET or POST-as-GET"?


For example, suppose that the CA uses highly structured URLs that
with several low-entropy fields:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "For example" sentence above is incomplete.

@bifurcation
Copy link
Contributor Author

@yaronf Which case do you mean? GETs are clearly allowed for certificate resources, just at the MAY level.

@yaronf
Copy link
Contributor

yaronf commented Sep 6, 2018 via email

@richsalz
Copy link
Member

richsalz commented Sep 6, 2018

I think we need to give the WG a chance to object to this. Yes there has been some discussion, but I'll do a formal 'call' email. Don't let that delay merging, we can always revert. :)

for these resources. This enables clients to bootstrap into the
ACME authentication system.

The server MAY allow GET requests for certificate resources, in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nit: I don't think the comma after "resources" is required here.

process, e.g., the web server that will use the referenced
certificate chain. (See {{?I-D.ietf-acme-star}} for more advanced
cases.) A server that allows GET requests for certificate resources
can still provide them a degree of access control by assigning them
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "can still provide them a degree" -> "can still provide a degree"

key is compromised or decommissioned.
key is compromised or decommissioned. A deactivated account can no longer request
certificate issuance or access resources related to the account, such as orders
or authorizations.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add one more sentence that explicitly says "If a server receives a POST or POST-as-GETs from a deactivated account it MUST return a urn:ietf:params:acme:error:unauthorized problem"?

order to allow certificates to be fetched by a lower-privileged
process, e.g., the web server that will use the referenced
certificate chain. (See {{?I-D.ietf-acme-star}} for more advanced
cases.) A server that allows GET requests for certificate resources
can still provide them a degree of access control by assigning them
can still provide a degree of access control by assigning them
capability URLs them capability URLs {{?W3C.WD-capability-urls-20140218}}.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"them capability URLs" they really are a-happen-ing ... twice.

@bifurcation bifurcation merged commit aca1171 into master Sep 24, 2018
cpu added a commit to letsencrypt/pebble that referenced this pull request Sep 25, 2018
This is an implementation of the acme draft protocol change added
in ACME PR 445[0]. When Pebble is run with `-strict` it will no
longer allow unauthenticated GET requests to Orders, Authorizations or
Challenges. Support is added for "POST-as-GET" requests as an
authenticated alternative.

[0] - ietf-wg-acme/acme#445
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants