RFC 9444

Automated Certificate Management Environment (ACME) for Subdomains

πŸ“… published August 2023, from ietf

RFC 9444: Automated Certificate Management Environment (ACME) for Subdomains πŸŽ€

okay bestie, first the paperwork so you know what we're looking at πŸ’…

  • Stream: Internet Engineering Task Force (IETF)
  • RFC number: 9444
  • Title: Automated Certificate Management Environment (ACME) for Subdomains
  • Authors: O. Friel (Cisco), R. Barnes (Cisco), T. Hollebeek (DigiCert), M. Richardson (Sandelman Software Works)
  • Category: Standards Track
  • ISSN: 2070-1721
  • Date: August 2023
  • Obsoletes / Updates: none. This one doesn't obsolete or update any other RFCs 🌸

Abstract ✨

okay so this doc explains how a client can use ACME to get a certificate for a subdomain identifier from a certification authority πŸ¦‹ It also covers something extra-cute: a client can fulfill a challenge against an ancestor domain, and may not need to fulfill one against the explicit subdomain, if the certification authority's policy allows issuing the subdomain certificate without proof of explicit subdomain ownership πŸ’œ

Status of This Memo πŸ“œ

This is an Internet Standards Track document. ✨

This doc is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It went through public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more info on Internet Standards, check out Section 2 of RFC 7841 πŸ“

For the current status of this document, any errata, and how to give feedback on it, go to https://www.rfc-editor.org/info/rfc9444 πŸ”₯

Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved. 🫢

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Revised BSD License. πŸ’…

Table of Contents πŸ—‚οΈ

1.  Introduction
2.  Terminology
3.  ACME Workflow and Identifier Requirements
4.  ACME Issuance of Subdomain Certificates
  4.1.  Authorization Object
  4.2.  Pre-authorization
  4.3.  New Orders
  4.4.  Directory Object Metadata
5.  Illustrative Call Flow
6.  IANA Considerations
  6.1.  Authorization Object Fields Registry
  6.2.  Directory Object Metadata Fields Registry
7.  Security Considerations
  7.1.  Client Account Security
  7.2.  Subdomain Determination
  7.3.  ACME Server Policy Considerations
8.  References
  8.1.  Normative References
  8.2.  Informative References
Authors' Addresses

1. Introduction 🧚

okay so ACME [RFC8555] is a protocol that a certification authority (CA) and an applicant can use to automate two things: checking that they own a domain name, and issuing an X.509v3 (PKIX) [RFC5280] certificate πŸ’– The CA is the ACME server, the applicant is the ACME client, and the client uses ACME to ask the server to issue a certificate.

This doc shows how ACME can be used to issue subdomain certificates without the ACME client having to explicitly fulfill an ownership challenge against the subdomain identifiers. The client only needs to fulfill an ownership challenge against an ancestor domain identifier 🌈

2. Terminology πŸ“–

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. πŸ”₯

These terms come from "DNS Terminology" [RFC8499] and are copied here:

  • Label: An ordered list of zero or more octets that makes up a portion of a domain name. Using graph theory, a label identifies one node in a portion of the graph of all possible domain names. 🌸
  • Domain Name: An ordered list of one or more labels. πŸ¦‹
  • Fully-Qualified Domain Name (FQDN): This is often just a clear way of saying the same thing as "domain name of a node", as outlined above. However, the term is ambiguous. Strictly speaking, a fully-qualified domain name would include every label, including the zero-length label of the root. Such a name would be written www.example.net. (note the terminating dot). But because every name eventually shares the common root, names are often written relative to the root (such as www.example.net) and are still called "fully qualified". This term first appeared in [RFC0819]. In this document, names are often written relative to the root. πŸ’œ

The following definition for "subdomain" comes from "DNS Terminology" [RFC8499] and is copied here. The definition is ambiguous, though, so it gets clarified below:

  • Subdomain: "A domain is a subdomain of another domain if it is contained within that domain. This relationship can be tested by seeing if the subdomain's name ends with the containing domain's name." (Quoted from Section 3.1 of [RFC1034].) For example, in the host name nnn.mmm.example.com, both mmm.example.com and nnn.mmm.example.com are subdomains of example.com. Note that the comparisons here are done on whole labels. That means ooo.example.com is not a subdomain of oo.example.com. πŸŽ€
The definition is ambiguous because it seems to let a subdomain include the given domain. mmm.example.com ends with mmm.example.com, so it would count as a subdomain of itself. This document reads the first sentence of the definition as "a domain is a subdomain of a different domain if it is contained within that different domain". A domain cannot be a subdomain of itself. For example, mmm.example.com is not a subdomain of mmm.example.com. πŸ™ˆ

These additional terms are used in this document:

  • Certification Authority (CA): An organization that is responsible for the creation, issuance, revocation, and management of Certificates. The term applies equally to both root CAs and subordinate CAs. Refer to [RFC5280] for detailed information on Certification Authorities. πŸ‘‘
  • CSR: Certificate Signing Request, as defined in [RFC2986]. 🧁
  • Ancestor Domain: A domain is an ancestor domain of a subdomain if it contains that subdomain and has fewer labels than that subdomain. A domain cannot be an ancestor domain of itself. For example, for the host name nnn.mmm.example.com, both mmm.example.com and example.com are ancestor domains of nnn.mmm.example.com. However, nnn.mmm.example.com is not an ancestor domain of nnn.mmm.example.com. Note that the comparisons here are done on whole labels. That means oo.example.com is not an ancestor domain of ooo.example.com. 🌷

[RFC8555] defines the following object types, which are used in this document:

  • Order Object: An ACME order object represents a client's request for a certificate. It is used to track the progress of that order through to issuance. πŸ“¦
  • Authorization Object: An ACME authorization object represents a server's authorization for an account to represent an identifier. πŸ”‘
  • Challenge Object: An ACME challenge object represents a server's offer to validate a client's possession of an identifier in a specific way. 🧩

ACME [RFC8555], Section 6.3 introduces the following term, which is used in this document:

  • POST-as-GET Request: When a client wants to fetch a resource from the server, it MUST send a POST request with a signed JSON Web Signature (JWS) body, where the JWS body is specified in ACME [RFC8555], Section 6.2. ACME refers to these as "POST-as-GET" requests. πŸ’…

3. ACME Workflow and Identifier Requirements 🌟

Here's what a typical ACME workflow for issuing certificates looks like, step by step πŸͺ„

  1. The client sends a POST with a newOrder request that contains a set of identifier objects in the identifiers field of the ACME order object.
  2. The server replies with an order object. It contains a set of links to authorization object(s) and a finalize URI.
  3. The client sends POST-as-GET request(s) to retrieve the authorization object(s). The downloaded authorization object(s) contain the identifier the client must prove they control, plus a set of links to associated challenge objects. The client must fulfill one of those challenges.
  4. The client proves control over the identifier in the authorization object by completing one of the specified challenges. For example, it could publish a DNS TXT record.
  5. The client POSTs a CSR to the finalize API.
  6. The server replies with an updated order object that includes a certificate URI.
  7. The client sends a POST-as-GET request to the certificate URI to download the certificate.

ACME puts the following restrictions on identifiers, so pay attention bestie πŸ‘€

  • [RFC8555], Section 7.1.3: "The authorizations required are dictated by server policy; there may not be a 1:1 relationship between the order identifiers and the authorizations required."
  • [RFC8555], Section 7.1.4: The only type of identifier defined by the ACME specification is an FQDN: "The only type of identifier defined by this specification is a fully qualified domain name (type: "dns"). The domain name MUST be encoded in the form in which it would appear in a certificate."
  • [RFC8555], Section 7.4: The identifier in the CSR request must match the identifier in the newOrder request: "The CSR MUST indicate the exact same set of requested identifiers as the initial newOrder request."
  • [RFC8555], Section 8.3: The identifier, or FQDN, in the authorization object must be used when fulfilling challenges via HTTP: "Construct a URL by populating the URL template ... where the domain field is set to the domain name being verified."
  • [RFC8555], Section 8.4: The identifier, or FQDN, in the authorization object must be used when fulfilling challenges via DNS: "The client constructs the validation domain name by prepending the label "_acme-challenge" to the domain name being validated."

ACME does not require that the identifier in a newOrder request matches the identifiers in authorization objects. πŸ¦‹

The ACME base document [RFC8555] only specifies the "dns" identifier type. More identifiers can be defined and registered in the IANA [ACME-Identifier-Types] registry. For example, [RFC8738] specifies the "ip" identifier type. This document is only relevant for the "dns" identifier type. 🌸

ACME supports several different validation methods that can be used to fulfill challenges and prove ownership of identifiers. Validation methods are registered in the IANA [ACME-Validation-Methods] registry. This document does not require the use of any particular validation method or methods. ACME server policy decides which validation methods are supported. See Section 7.3 for more information on ACME server policy. πŸ’–


4. ACME Issuance of Subdomain Certificates ✨

okay so remember how [RFC8555] doesn't make the identifier in a newOrder request match the identifier in the authorization objects? πŸ€” That means the ACME spec doesn't stop a server from processing newOrder requests and issuing certificates for a subdomain without making you fulfill a challenge against that exact subdomain. Lowkey wild, bestie πŸ’…

Server policy could let a client that only fulfills a challenge for an ancestor domain get a certificate for one of its subdomains. For example, this makes a flow possible where a client proves it owns example.org and then gets a certificate for sub.example.org. πŸ¦‹

Server policy itself is out of scope for this document, but there's some commentary about it in Section 7.3. πŸ“

Clients need a way to tell the ACME server "hey, I want authorization for ALL the subdomains under this domain," instead of just asking for one explicit domain identifier. 🌸 That has to work in both newAuthz and newOrder requests. On the flip side, servers need a way to tell clients that authorization objects are valid for every subdomain under the domain. The next section covers how all of that works. πŸ’–


4.1. Authorization Object

ACME ([RFC8555], Section 7.1.4) defines the authorization object. This document adds a new subdomainAuthAllowed field to it. When server policy allows authorization for subdomains under a domain, the server shows that by including the new subdomainAuthAllowed field in the authorization object for that domain identifier. πŸŽ€

subdomainAuthAllowed (optional, boolean): If present, this field MUST be true for authorizations where ACME server policy allows certificates to be issued for any subdomain subordinate to the domain specified in the identifier field of the authorization object. πŸ‘‘

Here's an example authorization object for example.org, where the authorization covers the subdomains under example.org. ✨

{
  "status": "valid",
  "expires": "2023-09-01T14:09:07.99Z",

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

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

  "subdomainAuthAllowed": true
}

If the subdomainAuthAllowed field isn't included, the assumed default value is false. πŸ™ˆ

If server policy allows certificates with wildcard identifiers under that authorization object, then the server SHOULD include the wildcard field with a value of true, as per [RFC8555], Section 7.1.4. 🌈


4.2. Pre-authorization

The basic ACME workflow creates authorization objects reactively, in response to a certificate order. ACME also allows pre-authorization, where clients get authorization for an identifier proactively, outside of any specific issuance. 🧚 With the ACME pre-authorization flow, a client can pre-authorize a domain once and then send multiple newOrder requests for certificates with identifiers in the subdomains under that domain. Iconic efficiency 😭🫢

ACME ([RFC8555], Section 7.4.1) defines the identifier object for newAuthz requests. This document adds a new subdomainAuthAllowed field to the identifier object:

subdomainAuthAllowed (optional, boolean): An ACME client sets this flag to indicate to the server that it is requesting an authorization for the subdomains subordinate to the specified domain identifier value. πŸ’œ

Clients include the new subdomainAuthAllowed field in the identifier object of newAuthz requests to say they want a subdomain authorization. In this newAuthz payload example, the client is asking for pre-authorization for the subdomains under example.org. πŸ“

"payload": base64url({
  "identifier": {
    "type": "dns",
    "value": "example.org",
    "subdomainAuthAllowed": true
  }
})

If the server is willing to allow a single authorization for the subdomains and there isn't already an authorization object for the identifier, then it creates an authorization object and includes the subdomainAuthAllowed flag with a value of true. βœ…

If server policy doesn't allow creating subdomain authorizations under that domain, the server can still create an authorization object for the indicated identifier and MAY include the subdomainAuthAllowed flag with a value of false. If the server creates an authorization object and doesn't include the subdomainAuthAllowed flag, the assumed value is false. 🌸

Either way, handling of the pre-authorization follows the process in ACME [RFC8555], Section 7.4.1. Same vibes, no drama πŸ’…


4.3. New Orders

Clients need a way to optionally tell servers whether they're authorized to fulfill challenges against an ancestor domain for a given identifier. πŸ”₯ For example, say a client places an order for the identifier foo.bar.example.org and is authorized to fulfill a challenge against the ancestor domains bar.example.org or example.org. Then the client needs a way to show the ACME server it controls those ancestor domains. πŸ¦‹

To make that happen, this document defines a new ancestorDomain field for the identifier, which goes in order objects. πŸ“

ancestorDomain (optional, string): This is an ancestor domain of the requested identifier. The client MUST be able to fulfill a challenge against the ancestor domain. πŸ‘‘

This field names an ancestor domain of the identifier that the client has DNS control over and can fulfill challenges against. Based on server policy, the server can choose to issue a challenge against any ancestor domain of the identifier up to and including the specified ancestorDomain, and then create a matching authorization object against the chosen identifier. 🧚

In this newOrder payload example, the client requests a certificate for foo.bar.example.org and says it can fulfill a challenge against the ancestor domain bar.example.org. The server can then pick a challenge against either foo.bar.example.org or bar.example.org. πŸ’–

"payload": base64url({
      "identifiers": [
        { "type": "dns",
          "value": "foo.bar.example.org",
          "ancestorDomain": "bar.example.org"  }
      ],
      "notBefore": "2023-09-01T00:04:00+04:00",
      "notAfter": "2023-09-08T00:04:00+04:00"
    })

In this second newOrder payload example, the client requests a certificate for foo.bar.example.org and says it can fulfill a challenge against the ancestor domain example.org. The server can then pick a challenge against any one of foo.bar.example.org, bar.example.org, or example.org. 🌈

"payload": base64url({
      "identifiers": [
        { "type": "dns",
          "value": "foo.bar.example.org",
          "ancestorDomain": "example.org"  }
      ],
      "notBefore": "2023-09-01T00:04:00+04:00",
      "notAfter": "2023-09-08T00:04:00+04:00"
    })

If the client can't fulfill authorizations against an ancestor domain, it should not include the ancestorDomain field. πŸ™ˆ

Server newOrder handling generally follows the process in ACME (Section 7.4 of [RFC8555]). If the server is willing to allow subdomain authorizations for the domain named in ancestorDomain, then it creates an authorization object against that ancestor domain and includes the subdomainAuthAllowed flag with a value of true. ✨

If server policy doesn't allow creating subdomain authorizations against that ancestor domain, the server can create an authorization object for the indicated identifier value and SHOULD NOT include the subdomainAuthAllowed flag. Since the client asked for a subdomain authorization on the ancestor domain and not on the indicated identifier, the server doesn't need to include the subdomainAuthAllowed flag in the authorization object for the indicated identifier. πŸ’…


4.4. Directory Object Metadata

This document defines a new subdomainAuthAllowed ACME directory metadata field. An ACME server can advertise that it supports subdomain authorization by including the subdomainAuthAllowed boolean flag in its "ACME Directory Metadata Fields" registry. πŸŽ€

subdomainAuthAllowed (optional, bool): Indicates whether an ACME server supports authorization of subdomains. 🌸

If it isn't specified, the assumed default value is false. If an ACME server supports authorization of subdomains, it can show that by including this field with a value of "true". 🫢

5. Illustrative Call Flow ✨

okay so this section is a walkthrough of the ACME pre-authorization flow using DNS-based proof of ownership πŸ¦‹ bestie, it's giving "one check, then many certs" energy and I am obsessed 😭

The diagram below is the whole story at a glance. Three steps, one client, one ACME server, and one DNS server doing the verifying 🧚

   +--------+                   +------+     +-----+
   | Client |                   | ACME |     | DNS |
   +--------+                   +------+     +-----+
       |                            |           |
    Step 1: Pre-authorization of ancestor domain.
       |                            |           |
       | POST /newAuthz             |           |
       | "example.org"              |           |
       |--------------------------->|           |
       |                            |           |
       | 201 authorizations         |           |
       |<---------------------------|           |
       |                            |           |
       | Publish DNS TXT            |           |
       | "example.org"              |           |
       |--------------------------------------->|
       |                            |           |
       | POST /challenge            |           |
       |--------------------------->|           |
       |                            | Verify    |
       |                            |---------->|
       | 200 status=valid           |           |
       |<---------------------------|           |
       |                            |           |
       | Delete DNS TXT             |           |
       | "example.org"              |           |
       |--------------------------------------->|
       |                            |           |
    Step 2: Place order for sub1.example.org.
       |                            |           |
       | POST /newOrder             |           |
       | "sub1.example.org"         |           |
       |--------------------------->|           |
       |                            |           |
       | 201 status=ready           |           |
       |<---------------------------|           |
       |                            |           |
       | POST /finalize             |           |
       | CSR SAN "sub1.example.org" |           |
       |--------------------------->|           |
       |                            |           |
       | 200 OK status=valid        |           |
       |<---------------------------|           |
       |                            |           |
       | POST /certificate          |           |
       |--------------------------->|           |
       |                            |           |
       | 200 OK                     |           |
       | PEM SAN "sub1.example.org" |           |
       |<---------------------------|           |
       |                            |           |
    Step 3: Place order for sub2.example.org.
       |                            |           |
       | POST /newOrder             |           |
       | "sub2.example.org"         |           |
       |--------------------------->|           |
       |                            |           |
       | 201 status=ready           |           |
       |<---------------------------|           |
       |                            |           |
       | POST /finalize             |           |
       | CSR SAN "sub2.example.org" |           |
       |--------------------------->|           |
       |                            |           |
       | 200 OK status=valid        |           |
       |<---------------------------|           |
       |                            |           |
       | POST /certificate          |           |
       |--------------------------->|           |
       |                            |           |
       | 200 OK                     |           |
       | PEM SAN "sub2.example.org" |           |
       |<---------------------------|           |
  • Step 1: Pre-authorization of ancestor domain. 🌸

So the client sends a newAuthz request for the ancestor domain, and it includes the subdomainAuthAllowed flag in the identifier object. Main character move πŸ‘‘

  POST /acme/new-authz 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/new-authz"
    }),
    "payload": base64url({
      "identifier": {
        "type": "dns",
        "value": "example.org",
        "subdomainAuthAllowed": true
      }
    }),
    "signature": "nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps"
  }

The server creates and returns an authorization object for the identifier that includes the subdomainAuthAllowed flag. The object is initially in "pending" state. Lowkey the vibe is "not yet, babe" πŸ™ˆ

  {
    "status": "pending",
    "expires": "2023-09-01T14:09:07.99Z",

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

    "challenges": [
      {
        "url": "https://example.com/acme/chall/prV_B7yEyA4",
        "type": "dns-01",
        "status": "pending",
        "token": "DGyRejmCefe7v4NfDGDKfA",
        "validated": "2023-08-01T12:05:58.16Z"
      }
    ],

    "subdomainAuthAllowed": true
  }

The example shows the client completing a DNS challenge by publishing a DNS TXT record. Then it posts to the challenge resource to tell the server it can validate the challenge. Iykyk, it's the "check it, I put the record up" moment πŸ’…

Once the server validates the challenge by checking the DNS TXT record, the server will transition the authorization object and associated challenge object status to "valid". Valid means slay ✨

The call flow above shows the ACME server replying to the client's challenge with a status of "valid" after it has validated the DNS challenge. However, the validation flow may take some time. If that's the case, the ACME server may reply to the client's challenge immediately with a status of "processing", and the client will then need to poll the authorization resource to see when it is finalized. Refer to Section 7.5.1 of [RFC8555] for more details. 🧚

  • Step 2: The client places a newOrder for sub1.example.org. πŸŽ€

The client sends a newOrder request to the server and includes the subdomain identifier. Note that the identifier is a subdomain of the ancestor domain that was pre-authorized in Step 1. The client does not need to include the subdomainAuthAllowed field in the identifier object, because it has already pre-authorized the ancestor domain. Efficient and iconic πŸ¦‹

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

  {
    "protected": base64url({
      "alg": "ES256",
      "kid": "https://example.com/acme/acct/evOfKhNU60wg",
      "nonce": "5XJ1L3lEkMG7tR6pA00clA",
      "url": "https://example.com/acme/new-order"
    }),
    "payload": base64url({
      "identifiers": [
        { "type": "dns", "value": "sub1.example.org" }
      ],
      "notBefore": "2023-09-01T00:04:00+04:00",
      "notAfter": "2023-09-08T00:04:00+04:00"
    }),
    "signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g"
  }

As an authorization object already exists for the ancestor domain, the server replies with an order object with a status of "ready" that includes a link to the existing "valid" authorization object. πŸ’œ

  HTTP/1.1 201 Created
  Replay-Nonce: MYAuvOpaoIiywTezizk5vw
  Link: <https://example.com/acme/directory>;rel="index"
  Location: https://example.com/acme/order/TOlocE8rfgo

  {
    "status": "ready",
    "expires": "2023-09-01T14:09:07.99Z",

    "notBefore": "2023-09-01T00:00:00Z",
    "notAfter": "2023-09-08T00:00:00Z",

    "identifiers": [
      { "type": "dns", "value": "sub1.example.org" }
    ],

    "authorizations": [
      "https://example.com/acme/authz/PAniVnsZcis"
    ],

    "finalize": "https://example.com/acme/order/TOlocrfgo/finalize"
  }

The client can proceed to finalize the order by posting a CSR to the finalize resource. Then it can download the certificate for sub1.example.org. Certificate unlocked πŸ”“βœ¨

  • Step 3: The client places a newOrder for sub2.example.org. 🌈

The client sends a newOrder request to the server and includes the subdomain identifier. Note that the identifier is a subdomain of the ancestor domain that was pre-authorized in Step 1. The client does not need to include the subdomainAuthAllowed field in the identifier object, because it has already pre-authorized the ancestor domain. Same energy, new subdomain πŸ’–

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

  {
    "protected": base64url({
      "alg": "ES256",
      "kid": "https://example.com/acme/acct/evOfKhNU60wg",
      "nonce": "5XJ1L3lEkMG7tR6pA00clA",
      "url": "https://example.com/acme/new-order"
    }),
    "payload": base64url({
      "identifiers": [
        { "type": "dns", "value": "sub2.example.org" }
      ],
      "notBefore": "2023-09-01T00:04:00+04:00",
      "notAfter": "2023-09-08T00:04:00+04:00"
    }),
    "signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g"
  }

As an authorization object already exists for the ancestor domain, the server replies with an order object with a status of "ready" that includes a link to the existing "valid" authorization object. 🫢

  HTTP/1.1 201 Created
  Replay-Nonce: MYAuvOpaoIiywTezizk5vw
  Link: <https://example.com/acme/directory>;rel="index"
  Location: https://example.com/acme/order/TOlocE8rfgo

  {
    "status": "ready",
    "expires": "2023-09-01T14:09:07.99Z",

    "notBefore": "2023-09-01T00:00:00Z",
    "notAfter": "2023-09-08T00:00:00Z",

    "identifiers": [
      { "type": "dns", "value": "sub2.example.org" }
    ],

    "authorizations": [
      "https://example.com/acme/authz/PAniVnsZcis"
    ],

    "finalize": "https://example.com/acme/order/ROni7rdde/finalize"
  }

The client can proceed to finalize the order by posting a CSR to the finalize resource. Then it can download the certificate for sub2.example.org. Two subdomains, one check, zero drama πŸ‘‘


6. IANA Considerations 🌸

6.1. Authorization Object Fields Registry πŸ“

okay so the following field has been added to the "ACME Authorization Object Fields" registry defined in ACME [RFC8555]. Registry glow-up πŸ’…

  +======================+============+==============+===========+
  | Field Name           | Field Type | Configurable | Reference |
  +======================+============+==============+===========+
  | subdomainAuthAllowed | boolean    | false        | RFC 9444  |
  +----------------------+------------+--------------+-----------+

                              Table 1

6.2. Directory Object Metadata Fields Registry 🧚

the following field has been added to the "ACME Directory Metadata Fields" registry defined in [RFC8555]. Same flag, new home πŸ¦‹

          +======================+============+===========+
          | Field Name           | Field Type | Reference |
          +======================+============+===========+
          | subdomainAuthAllowed | boolean    | RFC 9444  |
          +----------------------+------------+-----------+

                               Table 2

7. Security Considerations πŸ”βœ¨

Okay bestie, this section is about who is allowed to do what 🫢. This document tweaks ACME [RFC8555] so the protocol flows get faster when you're issuing certs for subdomains πŸ’…. The big goal of ACME for Subdomains is literally the same as ACME's: managing certificates that attest to identifier/key bindings for these subdomains πŸ”₯. So it has the same two security goals as ACME:

(1) Only an entity that controls an identifier can get an authorization for that identifier. πŸ”’

(2) Once authorized, an account key's authorizations cannot be improperly used by another account. πŸ¦‹

ACME for Subdomains makes no changes to:

  • account or account key management πŸ’œ
  • ACME channel establishment, security mechanisms, or threat model 🌸
  • validation channel establishment, security mechanisms, or threat model 🧚

So, all Security Considerations in ACME in the following areas are equally applicable to ACME for Subdomains πŸ‘‘:

  • Threat Model
  • Integrity of Authorizations
  • Denial-of-Service Considerations
  • Server-Side Request Forgery
  • CA Policy Considerations

The only exception is that, to satisfy goal (1) above, this document assumes that control over a domain may imply control over a subdomain πŸŽ€. That means authorization for certificate issuance for the former may imply authorization for certificate issuance for the latter. In many ecosystems this is a safe assumption, especially because control over the domain can often be leveraged to successfully demonstrate control over subdomains anyway. For example, you could temporarily modify DNS for the subdomain to point to a server the ancestor domain owner controls, and then the distinction is moot πŸ’€. For example, the CA/Browser Forum Baseline Requirements may consider control of an ancestor domain sufficient for issuance of certificates for subdomains, but only if specific processes and procedures are used for validating ownership of the ancestor domain.

In ecosystems where control of an ancestor domain may not imply control over subdomains or authorization for issuance of certificates for subdomains, a more complicated threat analysis and server policy might be needed. Yikes, that's a whole plot twist 😭.

Some additional comments on ACME server policy are given later in this section πŸ“.

7.1. Client Account Security

There may be scenarios where a client wishes to deactivate an authorization object for an ancestor domain or deactivate its account completely πŸ™ˆ. For example, a client may want to do this if an account key is compromised, or if an authorization object covering domains subordinate to an ancestor domain is no longer needed. The client can deactivate an authorization using the mechanism specified in [RFC8555], Section 7.5.2, and can deactivate an account using the mechanism specified in [RFC8555], Section 7.3.6. Main character energy for clean-up arcs ✨.

7.2. Subdomain Determination

The [RFC8499] definition of a subdomain is reproduced in Section 2 πŸ“–. When comparing domains to determine if one is a subdomain of the other, it is important to compare entire labels and not rely on a string prefix match. Relying on string prefix matches may yield incorrect results, and that is so not it πŸ™…β€β™€οΈ.

7.3. ACME Server Policy Considerations

The ACME for Subdomains and the ACME specifications do not mandate any specific ACME server or CA policies, or any specific use cases for issuance of certificates 🌈. For example, an ACME server could be used:

  • to issue Web PKI certificates, where the ACME server must comply with CA/Browser Forum Baseline Requirements [CAB] 🌐.
  • as a Private CA for issuance of certificates within an organization. The organization could enforce whatever policies they desire on the ACME server 🏒.
  • for issuance of Internet of Things (IoT) device certificates. There are currently no IoT device certificate policies that are generally enforced across the industry. Organizations issuing IoT device certificates can enforce whatever policies they desire on the ACME server πŸ€–.

ACME server policy could specify whether:

  • issuance of subdomain certificates is allowed based on proof of ownership of an ancestor domain.
  • issuance of subdomain certificates is allowed, but only for a specific set of ancestor domains.
  • DNS-based or HTTP-based proof of ownership, or both, are allowed.

The CA policy considerations listed in [RFC8555], Section 10.5 are equally applicable here. These include, but are not limited to:

  • Is the claimed identifier syntactically valid?
  • For domain names:
    • Is the name on the Public Suffix List?
    • Is the name a high-value name?
  • Is the key in the CSR sufficiently strong?

Refer to [RFC8555], Section 10.5 for more CA policy considerations πŸ“š.

ACME server policy specification is explicitly out of scope of this document 🚫. Not our problem, bestie πŸ’….

8. References πŸ“š

8.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8499]  Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS
           Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499,
           January 2019, <https://www.rfc-editor.org/info/rfc8499>.

[RFC8555]  Barnes, R., Hoffman-Andrews, J., McCarney, D., and J.
           Kasten, "Automatic Certificate Management Environment
           (ACME)", RFC 8555, DOI 10.17487/RFC8555, March 2019,
           <https://www.rfc-editor.org/info/rfc8555>.

8.2. Informative References

[ACME-Identifier-Types]
           IANA, "ACME Identifier Types",
           <https://www.iana.org/assignments/acme/>.

[ACME-Validation-Methods]
           IANA, "ACME Validation Methods",
           <https://www.iana.org/assignments/acme/>.

[CAB]      CA/Browser Forum, "Baseline Requirements for the Issuance
           and Management of Publicly-Trusted Certificates",
           <https://cabforum.org/baseline-requirements-documents/>.

[RFC0819]  Su, Z. and J. Postel, "The Domain Naming Convention for
           Internet User Applications", RFC 819,
           DOI 10.17487/RFC0819, August 1982,
           <https://www.rfc-editor.org/info/rfc819>.

[RFC1034]  Mockapetris, P., "Domain names - concepts and facilities",
           STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987,
           <https://www.rfc-editor.org/info/rfc1034>.

[RFC2986]  Nystrom, M. and B. Kaliski, "PKCS #10: Certification
           Request Syntax Specification Version 1.7", RFC 2986,
           DOI 10.17487/RFC2986, November 2000,
           <https://www.rfc-editor.org/info/rfc2986>.

[RFC5280]  Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
           Housley, R., and W. Polk, "Internet X.509 Public Key
           Infrastructure Certificate and Certificate Revocation List
           (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
           <https://www.rfc-editor.org/info/rfc5280>.

[RFC8738]  Shoemaker, R.B., "Automated Certificate Management
           Environment (ACME) IP Identifier Validation Extension",
           RFC 8738, DOI 10.17487/RFC8738, February 2020,
           <https://www.rfc-editor.org/info/rfc8738>.

Authors' Addresses πŸ’Œ

Owen Friel
Cisco
Email: ofriel@cisco.com


Richard Barnes
Cisco
Email: rlb@ipv.sx


Tim Hollebeek
DigiCert
Email: tim.hollebeek@digicert.com


Michael Richardson
Sandelman Software Works
Email: mcr+ietf@sandelman.ca

That's the whole spec, bestie. You made it through πŸŒˆβœ¨πŸ’–

πŸ“¦ where this page comes from