open-mpic / aws-lambda-python

An implementation of the Open MPIC API using AWS-Lambda serverless fucntions written in Python as well as AWS API Gateway.
MIT License
7 stars 4 forks source link

Separation of HTTP-generic and HTTP-ACME #13

Open birgelee opened 1 month ago

birgelee commented 1 month ago

Hi all,

I wanted to open discussion on a change I am proposing to the API spec which I think is overall a very good idea. At launch Open MPIC supported a method called http-generic which allowed for flexibility in the HTTP validation method with the intent of supporting ACME HTTP validation and Agreed‑Upon Change to Website v2.

I recently began developing integration tests for DCV and performed a review of the requirements with the interest of creating a thorough integration test suite. What I found looking over the requirement language is that there are actually substantial differences between how these methods are performed (specifically BR version 2.0.7 methods 3.2.2.4.18 and 3.2.2.4.19). Beyond simply the different paths (.well-known/pki‐validation vs .well-known/acme-challenge) Many of these differences extend into the actual implementation logic.

Below are some of the differences in the methods which I think justify two separate methods in the API:

  1. HTTP vs HTTPS. 3.2.2.4.18 clearly states that the challenge may be accessed over HTTP or HTTPS via an authorized port. Thus an HTTPS URL is perfectly valid and the implementation can communicate directly with this URL via port 443 HTTPS. This is not the case with 3.2.2.4.19 which references RFC 8555. RFC 8555 clearly says "Dereference the URL using an HTTP GET request. This request MUST be sent to TCP port 80 on the HTTP server."
  2. Parsing logic. RFC 8555 says "Verify that the body of the response is a well-formed key authorization. The server SHOULD ignore whitespace characters at the end of the body." Thus, with the exception of trailing white space, the response from the server needs to be a document with only the key in it. In BR it states: "verifying that the Request Token or Random Value is contained in the contents of a file" Thus, we can essentially ignore other file contents and simply check that that the request token is somewhere in the file.

This is in addition to the obvious .well-known/pki‐validation vs .well-known/acme-challenge. To me the above mentioned differences require different implementation logic. For example, if a request for the ACME method 3.2.2.4.19 were sent and contained an HTTPS target URL, I personally think the API should throw an error. However, this is fine if the method is 3.2.2.4.18.

One way to handle this (which I think is not optimal) would be to match on the URL part pki‐validation vs acme-challenge and then apply the appropriate logic. I personally think it would be cleaner to signpost which method a CA is using and then apply the proper parsing logic appropriate to that method. I do not like the idea of URL protocol and parsing logic being determined based on the value of the URL path provided. Additionally, these standards could diverge more in the future. They do not reference each other and are largely defined in separate documents managed by different entities (3.2.2.4.18 is managed solely by the CA/B Forum, 3.2.2.4.19 is managed by the CA/B Forum and the IETF given its external reference to RFC 8555).

sciros commented 1 month ago

So what you're proposing is an addition to the DcvValidationMethod enum, adding some request validation logic in MpicRequestValidator based on the the value of the enum, and then some different logic in the DCV checker, maybe splitting the http validation into two methods, one for ACME and one for non-ACME.

That's perfectly fine with me, I agree with you about that being cleaner than inferring all of this by inspecting part of my_request.dcv_check_parameters.validation_details.http_token_path, for sure.

birgelee commented 1 month ago

essentially. I would probably also change the parameters for http-acme and website-change-v2 (names TBD) which will be the new values for the DcvValidationMethod enum. http-acme could take the token and key authorization and construct the URL appropriately. website-change-v2 may take in a path_extension which is put at the end of .well-known/pki-validation/, a protocol (enum ["http", "https"]) and a value that is checked to make sure is contained in the response.

Essentially we can tailor the parameters in each method to match the language in RFC 8555 and BR sec 3.2.2.4.18 .

I will push a standard update for this shortly in a new branch.

sciros commented 3 weeks ago

Are the semantics different enough from ACME and generic HTTP that even the "challenge value" needs to be referred to differently? or can both inherit from a common DcvValidationDetails object that has challenge_value as a field?

birgelee commented 3 weeks ago

There may be a benefit from referring to the challenge value different in that we can obtain uniformity with the ACME RFC. In the RFC the challenge value is referred to as a "key authorization" and the part of the path after /.well-known/acme-challenge is called a "token". I feel matching this naming and not using different words for the same thing is more beneficial than keeping consistent names between the different validation. I would probably define an abstract class with no properties to represent validation methods and then make the different validation methods different objects. BTW, I am working on the API spec for the different methods in https://github.com/open-mpic/open-mpic-specification/tree/birgelee-new-validation-methods .