Tech-invite3GPPspaceIETFspace
959493929190898887868584838281807978777675747372717069686766656463626160595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100
in Index   Prev   Next

RFC 8555

Automatic Certificate Management Environment (ACME)

Pages: 95
Proposed Standard
Errata
Part 4 of 6 – Pages 53 to 67
First   Prev   Next

Top   ToC   RFC8555 - Page 53   prevText

7.5. Identifier Authorization

The identifier authorization process establishes the authorization of an account to manage certificates for a given identifier. This process assures the server of two things: 1. That the client controls the private key of the account key pair, and 2. That the client controls the identifier in question. This process may be repeated to associate multiple identifiers with an account (e.g., to request certificates with multiple identifiers) or to associate multiple accounts with an identifier (e.g., to allow multiple entities to manage certificates). Authorization resources are created by the server in response to newOrder or newAuthz requests submitted by an account key holder; their URLs are provided to the client in the responses to these requests. The authorization object is implicitly tied to the account key used to sign the request. When a client receives an order from the server in reply to a newOrder request, it downloads the authorization resources by sending POST-as-GET requests to the indicated URLs. If the client initiates authorization using a request to the newAuthz resource, it will have already received the pending authorization object in the response to that request.
Top   ToC   RFC8555 - Page 54
   POST /acme/authz/PAniVnsZcis HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "uQpSjlRb4vQVCjVYAyyUWg",
       "url": "https://example.com/acme/authz/PAniVnsZcis"
     }),
     "payload": "",
     "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps"
   }

   HTTP/1.1 200 OK
   Content-Type: application/json
   Link: <https://example.com/acme/directory>;rel="index"

   {
     "status": "pending",
     "expires": "2016-01-02T14:09:30Z",

     "identifier": {
       "type": "dns",
       "value": "www.example.org"
     },

     "challenges": [
       {
         "type": "http-01",
         "url": "https://example.com/acme/chall/prV_B7yEyA4",
         "token": "DGyRejmCefe7v4NfDGDKfA"
       },
       {
         "type": "dns-01",
         "url": "https://example.com/acme/chall/Rg5dV14Gh1Q",
         "token": "DGyRejmCefe7v4NfDGDKfA"
       }
     ]
   }

7.5.1. Responding to Challenges

To prove control of the identifier and receive authorization, the client needs to provision the required challenge response based on the challenge type and indicate to the server that it is ready for the challenge validation to be attempted.
Top   ToC   RFC8555 - Page 55
   The client indicates to the server that it is ready for the challenge
   validation by sending an empty JSON body ("{}") carried in a POST
   request to the challenge URL (not the authorization URL).

   For example, if the client were to respond to the "http-01" challenge
   in the above authorization, it would send the following request:

   POST /acme/chall/prV_B7yEyA4 HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "Q_s3MWoqT05TrdkM2MTDcw",
       "url": "https://example.com/acme/chall/prV_B7yEyA4"
     }),
     "payload": base64url({}),
     "signature": "9cbg5JO1Gf5YLjjz...SpkUfcdPai9uVYYQ"
   }

   The server updates the authorization document by updating its
   representation of the challenge with the response object provided by
   the client.  The server MUST ignore any fields in the response object
   that are not specified as response fields for this type of challenge.
   Note that the challenges in this document do not define any response
   fields, but future specifications might define them.  The server
   provides a 200 (OK) response with the updated challenge object as its
   body.

   If the client's response is invalid for any reason or does not
   provide the server with appropriate information to validate the
   challenge, then the server MUST return an HTTP error.  On receiving
   such an error, the client SHOULD undo any actions that have been
   taken to fulfill the challenge, e.g., removing files that have been
   provisioned to a web server.

   The server is said to "finalize" the authorization when it has
   completed one of the validations.  This is done by assigning the
   authorization a status of "valid" or "invalid", corresponding to
   whether it considers the account authorized for the identifier.  If
   the final state is "valid", then the server MUST include an "expires"
   field.  When finalizing an authorization, the server MAY remove
   challenges other than the one that was completed, and it may modify
   the "expires" field.  The server SHOULD NOT remove challenges with
   status "invalid".
Top   ToC   RFC8555 - Page 56
   Usually, the validation process will take some time, so the client
   will need to poll the authorization resource to see when it is
   finalized.  For challenges where the client can tell when the server
   has validated the challenge (e.g., by seeing an HTTP or DNS request
   from the server), the client SHOULD NOT begin polling until it has
   seen the validation request from the server.

   To check on the status of an authorization, the client sends a POST-
   as-GET request to the authorization URL, and the server responds with
   the current authorization object.  In responding to poll requests
   while the validation is still in progress, the server MUST return a
   200 (OK) response and MAY include a Retry-After header field to
   suggest a polling interval to the client.
Top   ToC   RFC8555 - Page 57
   POST /acme/authz/PAniVnsZcis HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "uQpSjlRb4vQVCjVYAyyUWg",
       "url": "https://example.com/acme/authz/PAniVnsZcis"
     }),
     "payload": "",
     "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps"
   }

   HTTP/1.1 200 OK
   Content-Type: application/json
   Link: <https://example.com/acme/directory>;rel="index"

   {
     "status": "valid",
     "expires": "2018-09-09T14:09:01.13Z",

     "identifier": {
       "type": "dns",
       "value": "www.example.org"
     },

     "challenges": [
       {
         "type": "http-01",
         "url": "https://example.com/acme/chall/prV_B7yEyA4",
         "status": "valid",
         "validated": "2014-12-01T12:05:13.72Z",
         "token": "IlirfxKKXAsHtmzK29Pj8A"
       }
     ]
   }

7.5.2. Deactivating an Authorization

If a client wishes to relinquish its authorization to issue certificates for an identifier, then it may request that the server deactivate each authorization associated with it by sending POST requests with the static object {"status": "deactivated"} to each authorization URL.
Top   ToC   RFC8555 - Page 58
   POST /acme/authz/PAniVnsZcis HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "xWCM9lGbIyCgue8di6ueWQ",
       "url": "https://example.com/acme/authz/PAniVnsZcis"
     }),
     "payload": base64url({
       "status": "deactivated"
     }),
     "signature": "srX9Ji7Le9bjszhu...WTFdtujObzMtZcx4"
   }

   The server MUST verify that the request is signed by the account key
   corresponding to the account that owns the authorization.  If the
   server accepts the deactivation, it should reply with a 200 (OK)
   status code and the updated contents of the authorization object.

   The server MUST NOT treat deactivated authorization objects as
   sufficient for issuing certificates.

7.6. Certificate Revocation

To request that a certificate be revoked, the client sends a POST request to the ACME server's revokeCert URL. The body of the POST is a JWS object whose JSON payload contains the certificate to be revoked: certificate (required, string): The certificate to be revoked, in the base64url-encoded version of the DER format. (Note: Because this field uses base64url, and does not include headers, it is different from PEM.) reason (optional, int): One of the revocation reasonCodes defined in Section 5.3.1 of [RFC5280] to be used when generating OCSP responses and CRLs. If this field is not set, the server SHOULD omit the reasonCode CRL entry extension when generating OCSP responses and CRLs. The server MAY disallow a subset of reasonCodes from being used by the user. If a request contains a disallowed reasonCode, then the server MUST reject it with the error type "urn:ietf:params:acme:error:badRevocationReason". The problem document detail SHOULD indicate which reasonCodes are allowed.
Top   ToC   RFC8555 - Page 59
   Revocation requests are different from other ACME requests in that
   they can be signed with either an account key pair or the key pair in
   the certificate.

   Example using an account key pair for the signature:

   POST /acme/revoke-cert HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "JHb54aT_KTXBWQOzGYkt9A",
       "url": "https://example.com/acme/revoke-cert"
     }),
     "payload": base64url({
       "certificate": "MIIEDTCCAvegAwIBAgIRAP8...",
       "reason": 4
     }),
     "signature": "Q1bURgJoEslbD1c5...3pYdSMLio57mQNN4"
   }

   Example using the certificate key pair for the signature:

   POST /acme/revoke-cert HTTP/1.1
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "RS256",
       "jwk": /* certificate's public key */,
       "nonce": "JHb54aT_KTXBWQOzGYkt9A",
       "url": "https://example.com/acme/revoke-cert"
     }),
     "payload": base64url({
       "certificate": "MIIEDTCCAvegAwIBAgIRAP8...",
       "reason": 1
     }),
     "signature": "Q1bURgJoEslbD1c5...3pYdSMLio57mQNN4"
   }
Top   ToC   RFC8555 - Page 60
   Before revoking a certificate, the server MUST verify that the key
   used to sign the request is authorized to revoke the certificate.
   The server MUST consider at least the following accounts authorized
   for a given certificate:

   o  the account that issued the certificate.

   o  an account that holds authorizations for all of the identifiers in
      the certificate.

   The server MUST also consider a revocation request valid if it is
   signed with the private key corresponding to the public key in the
   certificate.

   If the revocation succeeds, the server responds with status code 200
   (OK).  If the revocation fails, the server returns an error.  For
   example, if the certificate has already been revoked, the server
   returns an error response with status code 400 (Bad Request) and type
   "urn:ietf:params:acme:error:alreadyRevoked".

   HTTP/1.1 200 OK
   Replay-Nonce: IXVHDyxIRGcTE0VSblhPzw
   Content-Length: 0
   Link: <https://example.com/acme/directory>;rel="index"

   --- or ---

   HTTP/1.1 403 Forbidden
   Replay-Nonce: lXfyFzi6238tfPQRwgfmPU
   Content-Type: application/problem+json
   Content-Language: en
   Link: <https://example.com/acme/directory>;rel="index"

   {
     "type": "urn:ietf:params:acme:error:unauthorized",
     "detail": "No authorization provided for name example.org"
   }

8. Identifier Validation Challenges

There are few types of identifiers in the world for which there is a standardized mechanism to prove possession of a given identifier. In all practical cases, CAs rely on a variety of means to test whether an entity applying for a certificate with a given identifier actually controls that identifier.
Top   ToC   RFC8555 - Page 61
   Challenges provide the server with assurance that an account holder
   is also the entity that controls an identifier.  For each type of
   challenge, it must be the case that, in order for an entity to
   successfully complete the challenge, the entity must both:

   o  Hold the private key of the account key pair used to respond to
      the challenge, and

   o  Control the identifier in question.

   Section 10 documents how the challenges defined in this document meet
   these requirements.  New challenges will need to document how they
   do.

   ACME uses an extensible challenge/response framework for identifier
   validation.  The server presents a set of challenges in the
   authorization object it sends to a client (as objects in the
   "challenges" array), and the client responds by sending a response
   object in a POST request to a challenge URL.

   This section describes an initial set of challenge types.  The
   definition of a challenge type includes:

   1.  Content of challenge objects

   2.  Content of response objects

   3.  How the server uses the challenge and response to verify control
       of an identifier

   Challenge objects all contain the following basic fields:

   type (required, string):  The type of challenge encoded in the
      object.

   url (required, string):  The URL to which a response can be posted.

   status (required, string):  The status of this challenge.  Possible
      values are "pending", "processing", "valid", and "invalid" (see
      Section 7.1.6).

   validated (optional, string):  The time at which the server validated
      this challenge, encoded in the format specified in [RFC3339].
      This field is REQUIRED if the "status" field is "valid".
Top   ToC   RFC8555 - Page 62
   error (optional, object):  Error that occurred while the server was
      validating the challenge, if any, structured as a problem document
      [RFC7807].  Multiple errors can be indicated by using subproblems
      Section 6.7.1.  A challenge object with an error MUST have status
      equal to "invalid".

   All additional fields are specified by the challenge type.  If the
   server sets a challenge's "status" to "invalid", it SHOULD also
   include the "error" field to help the client diagnose why the
   challenge failed.

   Different challenges allow the server to obtain proof of different
   aspects of control over an identifier.  In some challenges, like HTTP
   and DNS, the client directly proves its ability to do certain things
   related to the identifier.  The choice of which challenges to offer
   to a client under which circumstances is a matter of server policy.

   The identifier validation challenges described in this section all
   relate to validation of domain names.  If ACME is extended in the
   future to support other types of identifiers, there will need to be
   new challenge types, and they will need to specify which types of
   identifier they apply to.

8.1. Key Authorizations

All challenges defined in this document make use of a key authorization string. A key authorization is a string that concatenates the token for the challenge with a key fingerprint, separated by a "." character: keyAuthorization = token || '.' || base64url(Thumbprint(accountKey)) The "Thumbprint" step indicates the computation specified in [RFC7638], using the SHA-256 digest [FIPS180-4]. As noted in [RFC7518] any prepended zero octets in the fields of a JWK object MUST be stripped before doing the computation. As specified in the individual challenges below, the token for a challenge is a string comprised entirely of characters in the URL- safe base64 alphabet. The "||" operator indicates concatenation of strings.
Top   ToC   RFC8555 - Page 63

8.2. Retrying Challenges

ACME challenges typically require the client to set up some network- accessible resource that the server can query in order to validate that the client controls an identifier. In practice, it is not uncommon for the server's queries to fail while a resource is being set up, e.g., due to information propagating across a cluster or firewall rules not being in place. Clients SHOULD NOT respond to challenges until they believe that the server's queries will succeed. If a server's initial validation query fails, the server SHOULD retry the query after some time, in order to account for delay in setting up responses such as DNS records or HTTP resources. The precise retry schedule is up to the server, but server operators should keep in mind the operational scenarios that the schedule is trying to accommodate. Given that retries are intended to address things like propagation delays in HTTP or DNS provisioning, there should not usually be any reason to retry more often than every 5 or 10 seconds. While the server is still trying, the status of the challenge remains "processing"; it is only marked "invalid" once the server has given up. The server MUST provide information about its retry state to the client via the "error" field in the challenge and the Retry-After HTTP header field in response to requests to the challenge resource. The server MUST add an entry to the "error" field in the challenge after each failed validation query. The server SHOULD set the Retry- After header field to a time after the server's next validation query, since the status of the challenge will not change until that time. Clients can explicitly request a retry by re-sending their response to a challenge in a new POST request (with a new nonce, etc.). This allows clients to request a retry when the state has changed (e.g., after firewall rules have been updated). Servers SHOULD retry a request immediately on receiving such a POST request. In order to avoid denial-of-service attacks via client-initiated retries, servers SHOULD rate-limit such requests.

8.3. HTTP Challenge

With HTTP validation, the client in an ACME transaction proves its control over a domain name by proving that it can provision HTTP resources on a server accessible under that domain name. The ACME server challenges the client to provision a file at a specific path, with a specific string as its content.
Top   ToC   RFC8555 - Page 64
   As a domain may resolve to multiple IPv4 and IPv6 addresses, the
   server will connect to at least one of the hosts found in the DNS A
   and AAAA records, at its discretion.  Because many web servers
   allocate a default HTTPS virtual host to a particular low-privilege
   tenant user in a subtle and non-intuitive manner, the challenge must
   be completed over HTTP, not HTTPS.

   type (required, string):  The string "http-01".

   token (required, string):  A random value that uniquely identifies
      the challenge.  This value MUST have at least 128 bits of entropy.
      It MUST NOT contain any characters outside the base64url alphabet
      and MUST NOT include base64 padding characters ("=").  See
      [RFC4086] for additional information on randomness requirements.

   {
     "type": "http-01",
     "url": "https://example.com/acme/chall/prV_B7yEyA4",
     "status": "pending",
     "token": "LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0"
   }

   A client fulfills this challenge by constructing a key authorization
   from the "token" value provided in the challenge and the client's
   account key.  The client then provisions the key authorization as a
   resource on the HTTP server for the domain in question.

   The path at which the resource is provisioned is comprised of the
   fixed prefix "/.well-known/acme-challenge/", followed by the "token"
   value in the challenge.  The value of the resource MUST be the ASCII
   representation of the key authorization.

   GET /.well-known/acme-challenge/LoqXcYV8...jxAjEuX0
   Host: example.org

   HTTP/1.1 200 OK
   Content-Type: application/octet-stream

   LoqXcYV8...jxAjEuX0.9jg46WB3...fm21mqTI

   (In the above, "..." indicates that the token and the JWK thumbprint
   in the key authorization have been truncated to fit on the page.)

   A client responds with an empty object ({}) to acknowledge that the
   challenge can be validated by the server.
Top   ToC   RFC8555 - Page 65
   POST /acme/chall/prV_B7yEyA4
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "UQI1PoRi5OuXzxuX7V7wL0",
       "url": "https://example.com/acme/chall/prV_B7yEyA4"
     }),
     "payload": base64url({}),
     "signature": "Q1bURgJoEslbD1c5...3pYdSMLio57mQNN4"
   }

   On receiving a response, the server constructs and stores the key
   authorization from the challenge "token" value and the current client
   account key.

   Given a challenge/response pair, the server verifies the client's
   control of the domain by verifying that the resource was provisioned
   as expected.

   1.  Construct a URL by populating the URL template [RFC6570]
       "http://{domain}/.well-known/acme-challenge/{token}", where:

       *  the domain field is set to the domain name being verified; and

       *  the token field is set to the token in the challenge.

   2.  Verify that the resulting URL is well-formed.

   3.  Dereference the URL using an HTTP GET request.  This request MUST
       be sent to TCP port 80 on the HTTP server.

   4.  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.

   5.  Verify that key authorization provided by the HTTP server matches
       the key authorization stored by the server.

   The server SHOULD follow redirects when dereferencing the URL.
   Clients might use redirects, for example, so that the response can be
   provided by a centralized certificate management server.  See
   Section 10.2 for security considerations related to redirects.
Top   ToC   RFC8555 - Page 66
   If all of the above verifications succeed, then the validation is
   successful.  If the request fails, or the body does not pass these
   checks, then it has failed.

   The client SHOULD de-provision the resource provisioned for this
   challenge once the challenge is complete, i.e., once the "status"
   field of the challenge has the value "valid" or "invalid".

   Note that because the token appears both in the request sent by the
   ACME server and in the key authorization in the response, it is
   possible to build clients that copy the token from request to
   response.  Clients should avoid this behavior because it can lead to
   cross-site scripting vulnerabilities; instead, clients should be
   explicitly configured on a per-challenge basis.  A client that does
   copy tokens from requests to responses MUST validate that the token
   in the request matches the token syntax above (e.g., that it includes
   only characters from the base64url alphabet).

8.4. DNS Challenge

When the identifier being validated is a domain name, the client can prove control of that domain by provisioning a TXT resource record containing a designated value for a specific validation domain name. type (required, string): The string "dns-01". token (required, string): A random value that uniquely identifies the challenge. This value MUST have at least 128 bits of entropy. It MUST NOT contain any characters outside the base64url alphabet, including padding characters ("="). See [RFC4086] for additional information on randomness requirements. { "type": "dns-01", "url": "https://example.com/acme/chall/Rg5dV14Gh1Q", "status": "pending", "token": "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA" } A client fulfills this challenge by constructing a key authorization from the "token" value provided in the challenge and the client's account key. The client then computes the SHA-256 digest [FIPS180-4] of the key authorization. The record provisioned to the DNS contains the base64url encoding of this digest. The client constructs the validation domain name by prepending the label "_acme-challenge" to the domain name being validated, then provisions a TXT record with the digest value under
Top   ToC   RFC8555 - Page 67
   that name.  For example, if the domain name being validated is
   "www.example.org", then the client would provision the following DNS
   record:

   _acme-challenge.www.example.org. 300 IN TXT "gfj9Xq...Rg85nM"

   A client responds with an empty object ({}) to acknowledge that the
   challenge can be validated by the server.

   POST /acme/chall/Rg5dV14Gh1Q
   Host: example.com
   Content-Type: application/jose+json

   {
     "protected": base64url({
       "alg": "ES256",
       "kid": "https://example.com/acme/acct/evOfKhNU60wg",
       "nonce": "SS2sSl1PtspvFZ08kNtzKd",
       "url": "https://example.com/acme/chall/Rg5dV14Gh1Q"
     }),
     "payload": base64url({}),
     "signature": "Q1bURgJoEslbD1c5...3pYdSMLio57mQNN4"
   }

   On receiving a response, the server constructs and stores the key
   authorization from the challenge "token" value and the current client
   account key.

   To validate a DNS challenge, the server performs the following steps:

   1.  Compute the SHA-256 digest [FIPS180-4] of the stored key
       authorization

   2.  Query for TXT records for the validation domain name

   3.  Verify that the contents of one of the TXT records match the
       digest value

   If all of the above verifications succeed, then the validation is
   successful.  If no DNS record is found, or DNS record and response
   payload do not pass these checks, then the validation fails.

   The client SHOULD de-provision the resource record(s) provisioned for
   this challenge once the challenge is complete, i.e., once the
   "status" field of the challenge has the value "valid" or "invalid".


(next page on part 5)

Next Section