RFC 8555 - Environnement de gestion automatique des certificats (ACME)
- Statut: Proposed Standard
- Publié: March 2019
- Stream: IETF
- Errata: Pas d'errata
Résumé
Les certificats de l'infrastructure à clés publiques utilisant X.509 (PKIX) sont utilisés à plusieurs fins, dont la plus importante est l'authentification des noms de domaine. Ainsi, les autorités de certification (CA) dans le PKI Web sont chargées de vérifier qu'un demandeur de certificat représente légitimement le(s) nom(s) de domaine figurant dans le certificat. Au moment de la rédaction, cette vérification est effectuée par une collection de mécanismes ad hoc. Ce document décrit un protocole qu'une CA et un demandeur peuvent utiliser pour automatiser le processus de vérification et d'émission de certificats. Le protocole fournit également des fonctionnalités pour d'autres fonctions de gestion des certificats, telles que la révocation de certificats.
Statut de ce mémo
Il s'agit d'un document de l'Internet Standards Track.
Ce document est un produit de l'Internet Engineering Task Force (IETF). Il représente le consensus de la communauté IETF. Il a fait l'objet d'un examen public et a été approuvé pour publication par l'Internet Engineering Steering Group (IESG).
Caractéristiques principales
Avantages du protocole ACME:
- ⚡ Entièrement automatisé: Aucune intervention manuelle de la demande au renouvellement
- 🔄 Mises à jour fréquentes: Prend en charge les certificats de courte durée (Let's Encrypt par défaut: 90 jours)
- 💰 Réduction des coûts: Élimine les coûts des processus manuels
- 🔒 Sécurité renforcée: Les certificats de courte durée réduisent le risque d'exposition
Flux de travail ACME typique:
Client (Client ACME) Serveur ACME (CA)
| |
| 1. Créer un compte |
|--------------------------------------->|
| <-- URL du compte |
| |
| 2. Soumettre une commande |
|--------------------------------------->|
| <-- Objet commande + Défis |
| |
| 3. Compléter la validation |
| (HTTP-01 ou DNS-01) |
|--------------------------------------->|
| <-- Validation réussie |
| |
| 4. Finaliser (Soumettre CSR) |
|--------------------------------------->|
| <-- URL du certificat |
| |
| 5. Télécharger le certificat |
|--------------------------------------->|
| <-- Chaîne de certificats PEM |
Composants principaux
Types de ressources
- Directory: Répertoire des points de terminaison de l'API du serveur
- Account: Informations du compte client
- Order: Commande de certificat
- Authorization: Autorisation de domaine
- Challenge: Défi de validation
- Certificate: Certificat émis
Méthodes de validation
- Défi HTTP-01: Provisionner un fichier à un chemin HTTP spécifique
- Défi DNS-01: Provisionner un enregistrement DNS TXT spécifique
Clients ACME populaires
- Certbot (EFF Officiel)
- acme.sh (Script Shell)
- Lego (Langage Go)
- win-acme (Windows)
RFC connexes
- RFC 7515 - JSON Web Signature
- RFC 5280 - Certificats X.509
- RFC 6797 - HSTS
- RFC 7807 - Problem Details pour les API HTTP
Références
- RFC officiel: RFC 8555
- IETF DataTracker: RFC 8555 DataTracker
- Let's Encrypt: https://letsencrypt.org/fr/docs/
Pour les spécifications techniques détaillées, veuillez consulter le document RFC 8555 officiel.
1. Introduction
Les certificats dans la Web PKI (Infrastructure à Clé Publique du Web) [RFC5280] sont le plus souvent utilisés pour authentifier des noms de domaine (Domain Names). Par conséquent, les autorités de certification (Certification Authorities, CAs) de la Web PKI sont approuvées pour vérifier que les demandeurs de certificats représentent légitimement les noms de domaine figurant dans ces certificats.
Différents types de certificats reflètent différents niveaux de vérification par la CA des informations sur le sujet du certificat. Les certificats à « validation de domaine » (Domain Validation, DV) sont de loin le type le plus courant. Dans le processus de délivrance d'un certificat DV, la seule vérification que la CA doit effectuer est de confirmer que le demandeur contrôle effectivement le nom de domaine [CABFBR]. La CA n'est pas tenue de tenter de vérifier l'identité réelle du demandeur. (Cela contraste avec les certificats à « validation d'organisation » (Organization Validation, OV) et à « validation étendue » (Extended Validation, EV), dont le processus vise également à vérifier l'identité réelle du demandeur.)
Les autorités de certification de la Web PKI existantes ont tendance à utiliser un ensemble de protocoles ad hoc (Ad Hoc Protocols) pour la délivrance de certificats et la vérification d'identité. Pour les certificats DV, l'expérience utilisateur typique est la suivante :
-
Générer une demande de signature de certificat (Certificate Signing Request, CSR) PKCS#10 [RFC2986].
-
Copier-coller la CSR dans la page Web de la CA.
-
Prouver la propriété du nom de domaine dans la CSR par l'une des méthodes suivantes :
-
Placer un défi (Challenge) fourni par la CA à un emplacement spécifique sur le serveur Web.
-
Placer un défi fourni par la CA dans un enregistrement DNS correspondant au domaine cible.
-
Recevoir un défi fourni par la CA à une adresse e-mail (de préférence contrôlée par l'administrateur) correspondant au nom de domaine, puis répondre sur la page Web de la CA.
-
-
Télécharger le certificat délivré et l'installer sur le serveur Web de l'utilisateur.
À l'exception de la CSR elle-même et du certificat délivré, il s'agit de procédures entièrement ad hoc, accomplies en demandant à des utilisateurs humains de suivre les instructions en langage naturel de la CA, plutôt que par des protocoles publiés et implémentés par des machines. Dans de nombreux cas, ces instructions sont difficiles à suivre et entraînent une frustration et une confusion considérables. Des tests d'utilisabilité informels menés par les auteurs indiquent que les administrateurs de sites Web ont généralement besoin de 1 à 3 heures pour obtenir et installer un certificat pour un nom de domaine. Même dans le meilleur des cas, l'absence de mécanisme standardisé et publié entrave le déploiement généralisé de HTTPS et d'autres systèmes reposant sur PKIX, car cela inhibe la mécanisation des tâches liées à la délivrance, au déploiement et à la révocation des certificats.
Ce document décrit un cadre extensible pour automatiser le processus de délivrance de certificats et de validation de domaine, permettant ainsi aux serveurs et aux logiciels d'infrastructure d'obtenir des certificats sans intervention humaine. L'utilisation de ce protocole devrait considérablement simplifier le déploiement de HTTPS, ainsi que l'utilité de l'authentification basée sur PKIX dans d'autres protocoles basés sur TLS (Transport Layer Security) [RFC8446].
Il convient de noter que, bien que ce document se concentre sur la validation des noms de domaine pour la délivrance de certificats dans la Web PKI, ACME prend en charge des extensions permettant l'utilisation d'autres identifiants dans d'autres contextes PKI. Par exemple, au moment de la rédaction de ce document, des travaux sont en cours pour utiliser ACME afin de délivrer des certificats Web PKI attestant des adresses IP [ACME-IP] et des certificats STIR (Secure Telephone Identity Revisited) attestant des numéros de téléphone [ACME-TELEPHONE].
ACME peut également être utilisé pour automatiser certains aspects de la gestion des certificats, même dans les cas où des processus non automatisés sont encore nécessaires. Par exemple, la fonctionnalité de liaison de compte externe (External Account Binding) (voir section 7.3.4) peut permettre à un compte ACME d'utiliser des autorisations accordées à un compte externe non-ACME. Cela permet à ACME de gérer des scénarios de délivrance qui ne peuvent pas encore être entièrement automatisés, comme la délivrance de certificats à « validation étendue ».
2. Modèle de déploiement et expérience opérateur
Le cas d'utilisation directeur d'ACME est l'obtention de certificats pour des sites Web (HTTPS [RFC2818]). Dans ce contexte, un serveur Web est destiné à représenter un ou plusieurs noms de domaine, et le processus de délivrance de certificats vise à vérifier que ce serveur Web représente bien ces noms de domaine.
La validation des certificats DV vérifie généralement les déclarations d'attributs liés au contrôle du nom de domaine — des attributs que l'émetteur du certificat peut observer lors d'interactions menées entièrement en ligne. Cela signifie que, dans le cas typique, toutes les étapes du processus de demande, de validation et de délivrance peuvent être représentées et exécutées via des protocoles Internet, sans intervention humaine hors bande.
Avant ACME, lors du déploiement d'un serveur HTTPS, l'opérateur du serveur recevait généralement une invite pour générer un certificat auto-signé (Self-Signed Certificate). Si l'opérateur déployait plutôt un serveur HTTPS avec ACME, l'expérience serait la suivante :
-
Le client ACME de l'opérateur invite l'opérateur à saisir les noms de domaine prévus que le serveur Web doit représenter.
-
Le client ACME présente à l'opérateur une liste de CA auprès desquelles un certificat peut être obtenu. (Cette liste évoluera dans le temps en fonction des capacités des CA et des mises à jour de la configuration ACME.) Le client ACME peut à ce stade inviter l'opérateur à fournir des informations de paiement.
-
L'opérateur choisit une CA.
-
En arrière-plan, le client ACME contacte la CA et lui demande de délivrer un certificat pour les noms de domaine prévus.
-
La CA vérifie que le client contrôle les noms de domaine demandés en lui demandant d'effectuer certaines opérations qui ne peuvent être accomplies que par une entité contrôlant ces domaines. Par exemple, la CA peut demander au client qui demande example.com de configurer un enregistrement DNS sous example.com ou une ressource HTTP sous
http://example.com. -
Une fois la CA satisfaite, elle délivre le certificat, que le client ACME télécharge et installe automatiquement, en notifiant éventuellement l'opérateur par e-mail, SMS, etc.
-
Le client ACME contacte périodiquement la CA pour obtenir des certificats mis à jour, des réponses OCSP (Online Certificate Status Protocol) agrafées [RFC6960], ou tout autre élément nécessaire au bon fonctionnement du serveur Web et à la mise à jour de ses identifiants.
De cette façon, le déploiement avec un certificat délivré par une CA devient presque aussi simple que l'utilisation d'un certificat auto-signé. De plus, la maintenance du certificat délivré par cette CA nécessitera une intervention manuelle minimale. Cette intégration étroite d'ACME avec le serveur HTTPS permet un déploiement automatique immédiat lors de la délivrance du certificat, libérant les administrateurs humains de la majeure partie du travail chronophage décrit dans la section précédente.
3. Terminologie
Les mots-clés « MUST » (DOIT), « MUST NOT » (NE DOIT PAS), « REQUIRED » (REQUIS), « SHALL » (DEVRA), « SHALL NOT » (NE DEVRA PAS), « SHOULD » (DEVRAIT), « SHOULD NOT » (NE DEVRAIT PAS), « RECOMMENDED » (RECOMMANDÉ), « NOT RECOMMENDED » (NON RECOMMANDÉ), « MAY » (PEUT) et « OPTIONAL » (OPTIONNEL) dans ce document doivent être interprétés comme décrit dans BCP 14 [RFC2119] [RFC8174], lorsqu'ils apparaissent en majuscules, comme indiqué ici.
Les deux rôles principaux dans ACME sont le « client » (Client) et le « serveur » (Server). Le client ACME utilise le protocole pour demander des opérations de gestion de certificats, telles que la délivrance ou la révocation. Un client ACME peut s'exécuter sur un serveur Web, un serveur de messagerie ou tout autre système serveur nécessitant un certificat X.509 valide. Il peut également s'exécuter sur un serveur distinct qui n'utilise pas lui-même le certificat, mais qui est autorisé à répondre aux défis fournis par la CA. Le serveur ACME s'exécute au niveau de l'autorité de certification et répond aux demandes des clients, en exécutant les opérations demandées si le client y est autorisé.
Le client ACME s'authentifie auprès du serveur via une « paire de clés de compte » (Account Key Pair). Le client signe tous les messages envoyés au serveur avec la clé privée de cette paire de clés. Le serveur utilise la clé publique pour vérifier l'authenticité et l'intégrité des messages provenant du client.
5. Encodage des caractères
Toutes les requêtes et réponses envoyées via HTTP par les clients ACME, les serveurs ACME et les serveurs de validation, ainsi que toute entrée pour les calculs de condensats, DOIVENT être encodées en utilisant le jeu de caractères UTF-8 [RFC3629]. Notez que les identifiants apparaissant dans les certificats peuvent avoir leurs propres considérations d'encodage (par exemple, les noms DNS contenant des caractères non-ASCII sont représentés sous forme d'étiquettes A plutôt que d'étiquettes U). Toute considération d'encodage de ce type DEVRAIT être appliquée avant l'encodage UTF-8 mentionné ci-dessus.
6. Transport des messages
La communication entre les clients ACME et les serveurs ACME s'effectue via HTTPS, en utilisant la signature Web JSON (JSON Web Signature, JWS) [RFC7515] pour fournir des propriétés de sécurité supplémentaires aux messages envoyés du client vers le serveur. HTTPS assure l'authentification du serveur et la confidentialité. Grâce à quelques extensions spécifiques à ACME, JWS fournit l'authentification des charges utiles des requêtes client, la protection contre la relecture, ainsi que l'intégrité de l'URL de la requête HTTPS.
6.1. Requêtes HTTPS
Chaque fonctionnalité ACME est accomplie par le client envoyant une série de requêtes HTTPS au serveur [RFC2818], transportant des messages JSON [RFC8259]. L'utilisation de HTTPS est REQUISE. Chaque sous-section de la section 7 ci-dessous décrit le format des messages utilisés par cette fonctionnalité et l'ordre dans lequel les messages sont envoyés.
Dans la plupart des transactions HTTPS utilisées par ACME, le client ACME est le client HTTPS et le serveur ACME est le serveur HTTPS. Le serveur ACME agit en tant que client lors de la validation des défis : il est client HTTP lors de la validation du défi 'http-01', client DNS lors de la validation de 'dns-01', etc.
Les serveurs ACME DEVRAIENT suivre les recommandations de [RFC7525] lors de la configuration de leur implémentation TLS. Les serveurs ACME prenant en charge TLS 1.3 PEUVENT autoriser les clients à envoyer des données anticipées (0-RTT). Cela est sécurisé car le protocole ACME lui-même inclut une protection contre la relecture dans tous les cas où elle est nécessaire (voir section 6.5). Il n'y a donc aucune restriction sur les données ACME pouvant être transportées en 0-RTT.
Les clients ACME DOIVENT envoyer un champ d'en-tête User-Agent conformément à [RFC7231]. En plus du nom et de la version du logiciel client HTTP sous-jacent, ce champ d'en-tête DEVRAIT inclure le nom et la version du logiciel ACME.
Les clients ACME DEVRAIENT envoyer un champ d'en-tête Accept-Language conformément à [RFC7231], pour permettre la localisation des messages d'erreur.
Les serveurs ACME destinés à être universellement accessibles doivent utiliser le partage de ressources entre origines multiples (Cross-Origin Resource Sharing, CORS) pour être accessibles depuis des clients basés sur navigateur [W3C.REC-cors-20140116]. Ces serveurs DEVRAIENT définir le champ d'en-tête Access-Control-Allow-Origin à la valeur « * ».
Les champs binaires dans les objets JSON utilisés par ACME sont encodés en utilisant l'encodage base64url décrit à la section 5 de [RFC4648], selon le profil spécifié dans la section 2 de JSON Web Signature [RFC7515]. Cet encodage utilise un jeu de caractères sécurisé pour les URL. Les caractères de remplissage '=' de fin DOIVENT être supprimés. Les valeurs encodées contenant des caractères '=' de fin DOIVENT être rejetées comme mal encodées.
6.2. Authentification des requêtes
Toutes les requêtes ACME ayant un corps non vide DOIVENT encapsuler leur charge utile dans un objet JWS (JSON Web Signature) [RFC7515], signé avec la clé privée du compte, sauf indication contraire. Le serveur DOIT valider le JWS avant de traiter la requête. L'encapsulation du corps de la requête dans un JWS fournit l'authentification de la requête.
Les objets JWS envoyés comme corps de requête ACME DOIVENT satisfaire les critères supplémentaires suivants :
-
Le JWS DOIT utiliser la sérialisation JSON aplatie (Flattened JSON Serialization) [RFC7515]
-
Le JWS NE DOIT PAS avoir plusieurs signatures
-
L'option de charge utile non encodée JWS (JWS Unencoded Payload Option) [RFC7797] NE DOIT PAS être utilisée
-
L'en-tête non protégé JWS (JWS Unprotected Header) [RFC7515] NE DOIT PAS être utilisé
-
La charge utile JWS NE DOIT PAS être détachée
-
L'en-tête protégé JWS DOIT inclure les champs suivants :
-
« alg » (algorithme, Algorithm)
- Ce champ NE DOIT PAS contenir « none » ni un algorithme de code d'authentification de message (Message Authentication Code, MAC) (par exemple, les algorithmes dont la description dans le registre des algorithmes mentionne MAC/HMAC).
-
« nonce » (défini à la section 6.5)
-
« url » (défini à la section 6.4)
-
« jwk » (clé Web JSON, JSON Web Key) ou « kid » (identifiant de clé, Key ID), comme décrit ci-dessous
-
Les serveurs ACME DOIVENT implémenter l'algorithme de signature « ES256 » [RFC7518] et DEVRAIENT implémenter l'algorithme de signature « EdDSA » [RFC8037] utilisant la variante « Ed25519 » (indiquée par « crv »).
Les champs « jwk » et « kid » sont mutuellement exclusifs. Le serveur DOIT rejeter les requêtes contenant les deux.
Pour les requêtes newAccount et les requêtes revokeCert authentifiées par la clé du certificat, il DOIT y avoir un champ « jwk ». Ce champ DOIT contenir la clé publique correspondant à la clé privée utilisée pour signer le JWS.
Pour toutes les autres requêtes, la requête est signée avec un compte existant et il DOIT y avoir un champ « kid ». Ce champ DOIT contenir l'URL du compte reçue via POST vers la ressource newAccount.
Si un client envoie un JWS signé avec un algorithme non pris en charge par le serveur, le serveur DOIT retourner le code de statut 400 (Bad Request) et une erreur de type « urn:ietf:params:acme:error:badSignatureAlgorithm ». Le document de problème retourné avec l'erreur DOIT inclure un champ « algorithms » contenant un tableau des valeurs « alg » prises en charge. Voir la section 6.7 pour plus de détails sur la structure des réponses d'erreur.
Si le serveur prend en charge l'algorithme de signature « alg » mais ne prend pas en charge ou choisit de rejeter la clé publique « jwk », le serveur DOIT retourner le code de statut 400 (Bad Request) et une erreur de type « urn:ietf:params:acme:error:badPublicKey ». Les détails du document de problème DEVRAIENT décrire la raison du rejet de la clé publique ; quelques exemples de raisons :
-
« alg » est « RS256 » mais le module « n » est trop petit (par exemple, 512 bits)
-
« alg » est « ES256 » mais « jwk » ne contient pas une clé publique P-256 valide
-
« alg » est « EdDSA » et « crv » est « Ed448 », mais le serveur ne prend en charge que « EdDSA » avec « Ed25519 »
-
La clé privée correspondante est connue pour avoir été compromise
Étant donné que les requêtes client dans ACME transportent des objets JWS en sérialisation JSON aplatie, elles DOIVENT définir le champ d'en-tête Content-Type à « application/jose+json ». Si une requête ne satisfait pas cette exigence, le serveur DOIT retourner une réponse avec le code de statut 415 (Unsupported Media Type).
6.3. Requêtes GET et POST-as-GET
Notez que l'authentification via un corps de requête JWS signé signifie que les requêtes sans corps d'entité ne sont pas authentifiées, en particulier les requêtes GET. Sauf dans les cas décrits dans cette section, si le serveur reçoit une requête GET, il DOIT retourner le code de statut 405 (Method Not Allowed) et une erreur de type « malformed ».
Si un client souhaite récupérer une ressource auprès du serveur (ce qui serait normalement accompli avec un GET), il DOIT envoyer une requête POST avec un corps JWS comme décrit ci-dessus, où la charge utile du JWS est une chaîne d'octets de longueur zéro. En d'autres termes, le champ « payload » de l'objet JWS DOIT être présent et défini à la chaîne vide (« »).
Nous appelons ces requêtes « POST-as-GET ». À la réception d'une requête avec une charge utile de longueur zéro (donc non-JSON), le serveur DOIT authentifier l'expéditeur et vérifier toute règle de contrôle d'accès. Sinon, le serveur DOIT traiter cette requête comme ayant la même sémantique qu'une requête GET vers la même ressource.
Le serveur DOIT autoriser les requêtes GET vers les ressources directory et newNonce (voir section 7.1), ainsi que les requêtes POST-as-GET vers ces ressources. Cela permet aux clients de s'amorcer dans le système d'authentification ACME.
6.4. Intégrité de l'URL de la requête
Dans les déploiements, il est courant que l'entité qui termine le TLS pour HTTPS soit différente de celle qui exploite le serveur HTTPS logique, avec une couche de « routage des requêtes » entre les deux. Par exemple, une CA ACME peut avoir un réseau de distribution de contenu qui termine les connexions TLS des clients afin de pouvoir inspecter les requêtes clients pour la protection contre les attaques par déni de service (Denial-of-Service, DoS).
Ces intermédiaires peuvent également modifier des valeurs de requête non signées dans les requêtes HTTPS, telles que l'URL de la requête et les champs d'en-tête. ACME utilise JWS pour fournir un mécanisme d'intégrité qui empêche les intermédiaires de modifier l'URL de la requête vers une autre URL ACME.
Comme décrit à la section 6.2, tous les objets de requête ACME transportent un paramètre d'en-tête « url » dans leur en-tête protégé. Ce paramètre d'en-tête encode l'URL vers laquelle le client dirige la requête. À la réception d'un tel objet dans une requête HTTP, le serveur DOIT comparer le paramètre d'en-tête « url » avec l'URL de la requête. S'ils ne correspondent pas, le serveur DOIT rejeter la requête comme non autorisée.
À l'exception de la ressource directory, toutes les ressources ACME sont adressées à l'aide d'URL fournies par le serveur au client. Dans les requêtes POST envoyées à ces ressources, le client DOIT définir le paramètre d'en-tête « url » à la chaîne exacte fournie par le serveur (sans effectuer de ré-encodage de l'URL). Le serveur DEVRAIT effectuer une vérification d'égalité de chaîne correspondante, en configurant pour chaque ressource la chaîne d'URL fournie au client, et en demandant à la ressource de vérifier que la requête a la même chaîne dans son paramètre d'en-tête « url ». Si la vérification d'égalité de chaîne échoue, le serveur DOIT rejeter la requête comme non autorisée.
6.4.1. Paramètre d'en-tête JWS « url »
Le paramètre d'en-tête « url » spécifie l'URL [RFC3986] à laquelle cet objet JWS est destiné. Le paramètre d'en-tête « url » DOIT être transporté dans l'en-tête protégé du JWS. La valeur du paramètre d'en-tête « url » DOIT être une chaîne représentant l'URL cible.
6.5. Protection contre la relecture
Pour protéger les ressources ACME contre toute attaque par relecture possible, les requêtes ACME POST disposent d'un mécanisme anti-relecture obligatoire. Ce mécanisme est basé sur le fait que le serveur maintient une liste des nonces qu'il a émis et exige que toute requête signée du client transporte l'un de ces nonces.
Le serveur ACME fournit des nonces aux clients via le champ d'en-tête HTTP Replay-Nonce, comme décrit à la section 6.5.1. Le serveur DOIT inclure un champ d'en-tête Replay-Nonce dans chaque réponse réussie à une requête POST, et DEVRAIT également le fournir dans les réponses d'erreur.
Chaque JWS envoyé par un client ACME DOIT inclure un paramètre d'en-tête « nonce » dans son en-tête protégé, dont le contenu est défini à la section 6.5.2. Dans le cadre de la validation JWS, le serveur ACME DOIT vérifier que la valeur de l'en-tête « nonce » est une valeur que le serveur a précédemment fournie dans un champ d'en-tête Replay-Nonce. Une fois qu'une valeur de nonce apparaît dans une requête ACME, le serveur DOIT la considérer comme invalide, comme s'il ne l'avait jamais émise.
Lorsque le serveur rejette une requête en raison d'une valeur de nonce inacceptable (ou absente), il DOIT fournir le code de statut HTTP 400 (Bad Request) et indiquer le type d'erreur ACME « urn:ietf:params:acme:error:badNonce ». Une réponse d'erreur avec le type d'erreur « badNonce » DOIT contenir un champ d'en-tête Replay-Nonce avec un nonce frais que le serveur acceptera lors d'une nouvelle tentative de la requête originale (et éventuellement dans d'autres requêtes, selon la politique de portée des nonces du serveur). À la réception d'une telle réponse, le client DEVRAIT réessayer la requête avec le nouveau nonce.
La méthode précise utilisée pour générer et suivre les nonces est laissée à la discrétion du serveur. Par exemple, le serveur peut générer une valeur aléatoire de 128 bits pour chaque réponse, conserver une liste des nonces émis et supprimer les nonces de cette liste lorsqu'ils sont utilisés.
En dehors des contraintes ci-dessus concernant les nonces émis dans les réponses « badNonce », ACME ne limite pas la façon dont le serveur délimite la portée des nonces. Les clients PEUVENT supposer que les nonces ont une portée large, par exemple en utilisant un seul pool de nonces pour toutes les requêtes. Cependant, lors d'une nouvelle tentative suite à une erreur « badNonce », le client DOIT utiliser le nonce fourni dans la réponse d'erreur. Les serveurs DEVRAIENT délimiter la portée des nonces suffisamment largement pour que les nouvelles tentatives ne soient pas fréquemment nécessaires.
6.5.1. Champ d'en-tête Replay-Nonce
Le champ d'en-tête HTTP Replay-Nonce contient une valeur générée par le serveur que le serveur peut utiliser pour détecter les relectures non autorisées dans les futures requêtes client. Le serveur DOIT générer les valeurs fournies dans le champ d'en-tête Replay-Nonce de manière à ce qu'elles soient uniques pour chaque message avec une haute probabilité, et imprévisibles pour toute entité autre que le serveur. Par exemple, la génération aléatoire de Replay-Nonces est acceptable.
La valeur du champ d'en-tête Replay-Nonce DOIT être une chaîne d'octets encodée selon l'encodage base64url décrit à la section 2 de [RFC7515]. Les clients DOIVENT ignorer les valeurs Replay-Nonce invalides. La syntaxe ABNF [RFC5234] du champ d'en-tête Replay-Nonce est la suivante :
base64url = ALPHA / DIGIT / "-" / "_"
Replay-Nonce = 1*base64url
Le champ d'en-tête Replay-Nonce NE DEVRAIT PAS être inclus dans les messages de requête HTTP.
6.5.2. Paramètre d'en-tête JWS « nonce »
Le paramètre d'en-tête « nonce » fournit une valeur unique permettant au vérificateur du JWS d'identifier quand une relecture se produit. Le paramètre d'en-tête « nonce » DOIT être transporté dans l'en-tête protégé du JWS.
La valeur du paramètre d'en-tête « nonce » DOIT être une chaîne d'octets encodée selon l'encodage base64url décrit à la section 2 de [RFC7515]. Si la valeur du paramètre d'en-tête « nonce » est invalide selon cet encodage, le vérificateur DOIT rejeter le JWS comme mal formé.
6.6. Limites de débit
Les serveurs ACME PEUVENT imposer des limites de débit sur la création de ressources pour garantir une utilisation équitable et prévenir les abus. Une fois qu'une limite de débit est dépassée, le serveur DOIT répondre avec une erreur de type « urn:ietf:params:acme:error:rateLimited ». De plus, le serveur DEVRAIT envoyer un champ d'en-tête Retry-After [RFC7231] indiquant quand la requête actuelle pourrait à nouveau réussir. S'il y a plusieurs limites de débit, c'est le moment où toutes les limites de débit permettraient à la requête actuelle avec exactement les mêmes paramètres d'accéder à nouveau.
En plus du champ « detail » lisible par l'humain de la réponse d'erreur, le serveur PEUT envoyer une ou plusieurs relations de lien dans un champ d'en-tête Link [RFC8288], en utilisant le type de relation de lien « help » pour pointer vers la documentation sur la limite de débit spécifique déclenchée.
6.7. Erreurs
Les erreurs peuvent être signalées au niveau HTTP et dans les objets de défi, comme défini à la section 8. Les serveurs ACME PEUVENT retourner des réponses avec des codes de réponse d'erreur HTTP (4XX ou 5XX). Par exemple, si un client soumet une requête en utilisant une méthode non autorisée par ce document, le serveur PEUT retourner le code de statut 405 (Method Not Allowed).
Lorsque le serveur répond avec un statut d'erreur, il DEVRAIT fournir des informations supplémentaires en utilisant un document de problème [RFC7807]. Pour faciliter les réponses automatisées aux erreurs, ce document définit les jetons standard suivants pour le champ « type » (dans l'espace de noms URN ACME « urn:ietf:params:acme:error: ») :
| Type | Description |
|---|---|
| accountDoesNotExist | Le compte spécifié dans la requête n'existe pas |
| alreadyRevoked | Le certificat spécifié pour révocation a déjà été révoqué |
| badCSR | La CSR est inacceptable (par exemple, en raison d'une clé trop courte) |
| badNonce | Le client a envoyé un nonce anti-relecture inacceptable |
| badPublicKey | Le JWS a été signé par une clé publique non prise en charge par le serveur |
| badRevocationReason | La raison de révocation fournie n'est pas autorisée par le serveur |
| badSignatureAlgorithm | Le JWS a été signé avec un algorithme non pris en charge par le serveur |
| caa | Un enregistrement CAA (Certification Authority Authorization) interdit à la CA de délivrer le certificat |
| compound | Des conditions d'erreur spécifiques sont indiquées dans le tableau « subproblems » |
| connection | Le serveur n'a pas pu se connecter à la cible de validation |
| dns | Un problème est survenu lors d'une requête DNS pendant la validation de l'identifiant |
| externalAccountRequired | La requête doit inclure une valeur pour le champ « externalAccountBinding » |
| incorrectResponse | La réponse reçue ne correspond pas aux exigences du défi |
| invalidContact | L'URL de contact du compte est invalide |
| malformed | Le message de requête est mal formé |
| orderNotReady | La requête tente de finaliser une commande qui n'est pas encore prête à être finalisée |
| rateLimited | La requête dépasse une limite de débit |
| rejectedIdentifier | Le serveur ne délivrera pas de certificat pour cet identifiant |
| serverInternal | Le serveur a rencontré une erreur interne |
| tls | Le serveur a reçu une erreur TLS lors de la validation |
| unauthorized | Le client ne dispose pas d'une autorisation suffisante |
| unsupportedContact | L'URL de contact du compte utilise un schéma de protocole non pris en charge |
| unsupportedIdentifier | L'identifiant est d'un type non pris en charge |
| userActionRequired | Accéder à l'URL « instance » et y effectuer l'action spécifiée |
Cette liste n'est pas exhaustive. Les serveurs PEUVENT retourner des erreurs dont le champ « type » est défini à des URI autres que ceux définis ci-dessus. Les serveurs NE DOIVENT PAS utiliser l'espace de noms URN ACME pour des erreurs non répertoriées dans le registre IANA correspondant (voir section 9.6). Les clients DEVRAIENT afficher le champ « detail » de toutes les erreurs.
Dans le reste de ce document, nous utilisons les jetons du tableau ci-dessus pour faire référence aux types d'erreurs, plutôt que l'URN complet. Par exemple, « une erreur de type 'badCSR' » fait référence à un document d'erreur dont la valeur « type » est « urn:ietf:params:acme:error:badCSR ».
6.7.1. Sous-problèmes
Parfois, une CA peut avoir besoin de retourner plusieurs erreurs en réponse à une seule requête. De plus, une CA peut avoir besoin d'attribuer des erreurs à des identifiants spécifiques. Par exemple, une requête newOrder peut contenir plusieurs identifiants pour lesquels la CA ne peut pas délivrer de certificat. Dans ce cas, le document de problème ACME PEUT contenir un champ « subproblems », contenant un tableau JSON de documents de problème, chacun pouvant contenir un champ « identifier ». S'il est présent, le champ « identifier » DOIT contenir un identifiant ACME (section 9.7.7).
Le champ « identifier » NE DOIT PAS apparaître au niveau supérieur d'un document de problème ACME. Il ne peut apparaître que dans les sous-problèmes. Les sous-problèmes n'ont pas besoin d'avoir tous le même type, et ils n'ont pas besoin de correspondre au type de niveau supérieur.
Les clients ACME PEUVENT choisir d'utiliser le champ « identifier » d'un sous-problème comme indication que l'opération réussirait si cet identifiant était omis. Par exemple, si une commande contient dix identifiants DNS et que la requête newOrder retourne un document de problème avec deux sous-problèmes (référençant deux de ces identifiants), le client ACME PEUT choisir de soumettre une autre commande contenant uniquement les huit identifiants non répertoriés dans le document de problème.
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Link: `https://example.com/acme/directory`;rel="index"
{
"type": "urn:ietf:params:acme:error:malformed",
"detail": "Some of the identifiers requested were rejected",
"subproblems": [
{
"type": "urn:ietf:params:acme:error:malformed",
"detail": "Invalid underscore in DNS name \"_example.org\"",
"identifier": {
"type": "dns",
"value": "_example.org"
}
},
{
"type": "urn:ietf:params:acme:error:rejectedIdentifier",
"detail": "This CA will not issue for \"example.net\"",
"identifier": {
"type": "dns",
"value": "example.net"
}
}
]
}
7. Gestion des certificats
Dans cette section, nous décrivons les fonctionnalités de gestion des certificats activées par ACME :
- Création de compte (Account Creation)
- Commande d'un certificat (Ordering a Certificate)
- Autorisation d'identifiant (Identifier Authorization)
- Délivrance de certificat (Certificate Issuance)
- Révocation de certificat (Certificate Revocation)
7.1. Ressources
ACME est construit comme une application basée sur HTTP, avec les types de ressources suivants :
- Ressources de compte (Account Resources), représentant les informations sur un compte (sections 7.1.2, 7.3)
- Ressources de commande (Order Resources), représentant les demandes de délivrance de certificat d'un compte (section 7.1.3)
- Ressources d'autorisation (Authorization Resources), représentant l'autorisation d'un compte à agir sur un identifiant (section 7.1.4)
- Ressources de défi (Challenge Resources), représentant les défis pour prouver le contrôle d'un identifiant (sections 7.5, 8)
- Ressources de certificat (Certificate Resources), représentant les certificats délivrés (section 7.4.2)
- La ressource « directory » (section 7.1.1)
- La ressource « newNonce » (section 7.2)
- La ressource « newAccount » (section 7.3)
- La ressource « newOrder » (section 7.4)
- La ressource « revokeCert » (section 7.6)
- La ressource « keyChange » (section 7.3.5)
Le serveur DOIT fournir les ressources « directory » et « newNonce ».
ACME utilise des URL différentes pour différentes fonctions de gestion. Chaque fonction est répertoriée dans le répertoire avec son URL correspondante, de sorte que les clients n'ont besoin de configurer que l'URL du répertoire. Ces URL sont reliées par plusieurs relations de lien différentes [RFC8288].
La relation de lien « up » est utilisée avec les ressources de défi pour indiquer la ressource d'autorisation à laquelle appartient le défi. Pour certains types de médias, elle est également utilisée depuis les ressources de certificat pour indiquer la ressource à partir de laquelle le client peut obtenir la chaîne de certificats CA pouvant être utilisée pour valider le certificat dans la ressource d'origine.
La relation de lien « index » apparaît sur toutes les ressources sauf le répertoire et indique l'URL du répertoire.
Le diagramme suivant illustre les relations entre les ressources sur un serveur ACME. Dans la plupart des cas, ces relations sont représentées par des URL fournies sous forme de chaînes dans la représentation JSON des ressources. Les lignes avec des étiquettes entre guillemets représentent des relations de lien HTTP.
directory
|
+--> newNonce
|
+----------+----------+-----+-----+------------+
| | | | |
| | | | |
V V V V V
newAccount newAuthz newOrder revokeCert keyChange
| | |
| | |
V | V
account | order --+--> finalize
| | |
| | +--> cert
| V
+---> authorization
| ^
| | "up"
V |
challenge
ACME Resources and Relationships
Le tableau suivant illustre la séquence typique de requêtes nécessaires pour établir un nouveau compte auprès du serveur, prouver le contrôle d'un identifiant, délivrer un certificat et obtenir un certificat mis à jour quelque temps après la délivrance. « -> » est un mnémonique pour le champ d'en-tête Location pointant vers la ressource créée.
| Opération | Requête | Réponse |
|---|---|---|
| Obtenir le répertoire | GET directory | 200 |
| Obtenir un nonce | HEAD newNonce | 200 |
| Créer un compte | POST newAccount | 201 -> account |
| Soumettre une commande | POST newOrder | 201 -> order |
| Récupérer les défis | POST-as-GET order's authorization urls | 200 |
| Répondre aux défis | POST authorization challenge urls | 200 |
| Interroger le statut | POST-as-GET order | 200 |
| Finaliser la commande | POST order's finalize url | 200 |
| Interroger le statut | POST-as-GET order | 200 |
| Télécharger le certificat | POST-as-GET order's certificate url | 200 |
Le reste de cette section fournit des détails sur la façon dont ces ressources sont construites et comment le protocole ACME les utilise.
7.1.1. Répertoire (Directory)
Pour aider les clients à configurer les URL correctes pour chaque opération ACME, le serveur ACME fournit un objet répertoire. Cela devrait être la seule URL nécessaire pour configurer un client. C'est un objet JSON dont les noms de champs proviennent du registre des ressources (section 9.7.5) et dont les valeurs sont les URL correspondantes.
| Champ | URL dans la valeur |
|---|---|
| newNonce | Nouveau nonce |
| newAccount | Nouveau compte |
| newOrder | Nouvelle commande |
| newAuthz | Nouvelle autorisation |
| revokeCert | Révocation de certificat |
| keyChange | Changement de clé |
L'URL du répertoire n'est soumise à aucune contrainte, sauf qu'elle devrait être différente des URL des autres ressources du serveur ACME et ne devrait pas entrer en conflit avec d'autres services. Par exemple :
- Un hôte servant à la fois de serveur ACME et de serveur Web peut souhaiter réserver le chemin racine « / » pour la « page d'accueil » HTML et placer le répertoire ACME sous le chemin « /acme ».
- Un hôte servant uniquement de serveur ACME peut placer le répertoire sous le chemin « / ».
Si le serveur ACME n'implémente pas la pré-autorisation (Pre-authorization) (section 7.4.1), il DOIT omettre le champ « newAuthz » du répertoire.
L'objet PEUT également contenir un champ « meta ». S'il est présent, il DOIT être un objet JSON ; chaque champ de l'objet est un élément de métadonnées lié au service fourni par le serveur ACME.
Les éléments de métadonnées suivants sont définis (section 9.7.6), tous OPTIONNELS :
termsOfService (optionnel, chaîne) : URL identifiant les conditions d'utilisation actuelles.
website (optionnel, chaîne) : URL HTTP ou HTTPS localisant un site Web fournissant plus d'informations sur le serveur ACME.
caaIdentities (optionnel, tableau de chaînes) : Noms d'hôtes que le serveur ACME reconnaît comme se référant à lui-même, à des fins de validation des enregistrements CAA tels que définis dans [RFC6844]. Chaque chaîne DOIT représenter la même séquence de points de code ASCII que le « nom de domaine de l'émetteur » (Issuer Domain Name) que le serveur s'attend à voir dans les étiquettes d'attribut CAA issue ou issuewild. Cela permet aux clients de déterminer le nom de domaine d'émetteur correct à utiliser lors de la configuration des enregistrements CAA.
externalAccountRequired (optionnel, booléen) : Si ce champ est présent et défini à « true », la CA exige que toutes les requêtes newAccount incluent un champ « externalAccountBinding » associant le nouveau compte à un compte externe.
Les clients accèdent au répertoire en envoyant une requête GET à l'URL du répertoire.
HTTP/1.1 200 OK
Content-Type: application/json
{
"newNonce": "https://example.com/acme/new-nonce",
"newAccount": "https://example.com/acme/new-account",
"newOrder": "https://example.com/acme/new-order",
"newAuthz": "https://example.com/acme/new-authz",
"revokeCert": "https://example.com/acme/revoke-cert",
"keyChange": "https://example.com/acme/key-change",
"meta": {
"termsOfService": "https://example.com/acme/terms/2017-5-30",
"website": "https://www.example.com/",
"caaIdentities": ["example.com"],
"externalAccountRequired": false
}
}
7.1.2. Objets de compte (Account Objects)
Une ressource de compte ACME représente un ensemble de métadonnées associées à un compte. La ressource de compte a la structure suivante :
status (requis, chaîne) : Le statut de ce compte. Les valeurs possibles sont « valid », « deactivated » et « revoked ». La valeur « deactivated » devrait être utilisée pour indiquer une désactivation initiée par le client, tandis que « revoked » devrait être utilisée pour indiquer une désactivation initiée par le serveur. Voir section 7.1.6.
contact (optionnel, tableau de chaînes) : Tableau d'URL que le serveur peut utiliser pour contacter le client concernant des problèmes liés à ce compte. Par exemple, le serveur peut souhaiter informer le client d'une révocation initiée par le serveur ou de l'expiration d'un certificat. Voir section 7.3 pour les informations sur les schémas d'URL pris en charge.
termsOfServiceAgreed (optionnel, booléen) : L'inclusion de ce champ avec la valeur true dans une requête newAccount indique que le client accepte les conditions d'utilisation. Ce champ ne peut pas être mis à jour par le client.
externalAccountBinding (optionnel, objet) : L'inclusion de ce champ dans une requête newAccount indique que le titulaire d'un compte non-ACME existant approuve la liaison de ce compte à ce compte ACME. Ce champ ne peut pas être mis à jour par le client (voir section 7.3.4).
orders (requis, chaîne) : URL à partir de laquelle une liste des commandes soumises par ce compte peut être récupérée via une requête POST-as-GET, comme décrit à la section 7.1.2.1.
{
"status": "valid",
"contact": [
"mailto:[email protected]",
"mailto:[email protected]"
],
"termsOfServiceAgreed": true,
"orders": "https://example.com/acme/orders/rzGoeA"
}
7.1.2.1. Liste des commandes (Orders List)
Chaque objet de compte contient une URL « orders » à partir de laquelle une liste des commandes créées par le compte peut être récupérée via une requête POST-as-GET. Le résultat de la requête DOIT être un objet JSON dont le champ « orders » est un tableau d'URL, chacune identifiant une commande appartenant à ce compte. Le serveur DEVRAIT inclure les commandes en attente et NE DEVRAIT PAS inclure les commandes invalides dans le tableau d'URL. Le serveur PEUT retourner une liste incomplète, ainsi qu'un champ d'en-tête Link avec une relation de lien « next » indiquant où d'autres entrées peuvent être récupérées.
HTTP/1.1 200 OK
Content-Type: application/json
Link: `https://example.com/acme/directory`;rel="index"
Link: `https://example.com/acme/orders/rzGoeA?cursor=2`;rel="next"
{
"orders": [
"https://example.com/acme/order/TOlocE8rfgo",
"https://example.com/acme/order/4E16bbL5iSw",
/* more URLs not shown for brevity */
"https://example.com/acme/order/neBHYLfw0mg"
]
}
7.1.3. Objets de commande (Order Objects)
Un objet de commande ACME représente la demande d'un client pour un certificat et est utilisé pour suivre la progression de cette commande jusqu'à la délivrance. L'objet contient donc des informations sur le certificat demandé, les autorisations que le serveur exige que le client accomplisse, et tout certificat résultant de cette commande.
status (requis, chaîne) : Le statut de cette commande. Les valeurs possibles sont « pending », « ready », « processing », « valid » et « invalid ». Voir section 7.1.6.
expires (optionnel, chaîne) : Horodatage après lequel le serveur considérera cette commande comme invalide, encodé au format spécifié dans [RFC3339]. Ce champ est REQUIS pour les objets dont le champ status est « pending » ou « valid ».
identifiers (requis, tableau d'objets) : Tableau d'objets identifiants concernés par la commande.
-
type (requis, chaîne) : Le type de l'identifiant. Ce document définit le type d'identifiant « dns ». Voir le registre défini à la section 9.7.7 pour tout autre type.
-
value (requis, chaîne) : L'identifiant lui-même.
notBefore (optionnel, chaîne) : Valeur demandée pour le champ notBefore du certificat, au format de date défini dans [RFC3339].
notAfter (optionnel, chaîne) : Valeur demandée pour le champ notAfter du certificat, au format de date défini dans [RFC3339].
error (optionnel, objet) : L'erreur survenue lors du traitement de la commande, le cas échéant. Ce champ est structuré comme un document de problème [RFC7807].
authorizations (requis, tableau de chaînes) : Pour les commandes en attente, les autorisations que le client doit accomplir avant que le certificat demandé puisse être délivré (voir section 7.5), y compris les autorisations non expirées que le client a accomplies précédemment pour les identifiants spécifiés dans la commande. Les autorisations requises sont déterminées par la politique du serveur ; il peut ne pas y avoir de correspondance 1:1 entre les identifiants de la commande et les autorisations requises. Pour les commandes finales (en statut « valid » ou « invalid »), les autorisations accomplies. Chaque entrée est une URL à partir de laquelle une autorisation peut être récupérée avec une requête POST-as-GET.
finalize (requis, chaîne) : Une fois que toutes les autorisations de la commande sont satisfaites, la CSR DOIT être envoyée en POST à cette URL pour finaliser la commande. Le résultat d'une finalisation réussie sera l'URL du certificat renseignée dans la commande.
certificate (optionnel, chaîne) : URL du certificat délivré en réponse à cette commande.
{
"status": "valid",
"expires": "2016-01-20T14:09:07.99Z",
"identifiers": [
{ "type": "dns", "value": "www.example.org" },
{ "type": "dns", "value": "example.org" }
],
"notBefore": "2016-01-01T00:00:00Z",
"notAfter": "2016-01-08T00:00:00Z",
"authorizations": [
"https://example.com/acme/authz/PAniVnsZcis",
"https://example.com/acme/authz/r4HqLzrSrpI"
],
"finalize": "https://example.com/acme/order/TOlocE8rfgo/finalize",
"certificate": "https://example.com/acme/cert/mAt3xBGaobw"
}
Tout identifiant de type « dns » dans une requête newOrder PEUT avoir un nom de domaine générique (wildcard) comme valeur. Un nom de domaine générique est composé d'un seul caractère astérisque suivi d'un seul caractère point (« *. ») suivi d'un nom de domaine tel que défini par [RFC5280] pour une utilisation dans l'extension Subject Alternative Name. Les autorisations retournées par le serveur pour un identifiant de nom de domaine générique NE DOIVENT PAS inclure le préfixe astérisque et point (« *. ») dans la valeur de l'identifiant d'autorisation. Les autorisations retournées DOIVENT contenir le champ optionnel « wildcard » avec la valeur true.
Les éléments des tableaux « authorizations » et « identifiers » sont immuables une fois définis. Le serveur NE DOIT PAS modifier le contenu de l'un ou l'autre tableau après la création. Si le client observe une modification du contenu de l'un ou l'autre tableau, il DEVRAIT considérer la commande comme invalide.
Le tableau « authorizations » d'une commande DEVRAIT refléter toutes les autorisations que la CA a prises en compte pour décider de délivrer, même si certaines autorisations ont été accomplies lors de transactions de commande ou de pré-autorisation antérieures. Par exemple, si la CA permet à plusieurs commandes d'être accomplies sur la base d'une seule transaction d'autorisation, elle DEVRAIT refléter cette autorisation dans toutes les commandes.
Notez que le simple fait qu'une URL d'autorisation soit répertoriée dans le tableau « authorizations » d'un objet de commande ne signifie pas que le client doit agir. Il peut y avoir plusieurs raisons pour lesquelles une autorisation référencée est déjà valide :
- Le client a accompli l'autorisation dans le cadre d'une commande précédente
- Le client a pré-autorisé l'identifiant précédemment (voir section 7.4.1)
- Le serveur a accordé au client une autorisation basée sur un compte externe
Le client DEVRAIT vérifier le champ « status » de la commande pour déterminer si une action est nécessaire.
Note : En raison de la longueur du chapitre 7, ce fichier couvre les sections 7.1 à 7.1.3. Les sections 7.1.4 à 7.6 sont dans la Partie 2.
8. Défis de validation d'identifiants
Peu de types d'identifiants dans le monde disposent de mécanismes standardisés pour prouver la possession d'un identifiant donné. Dans pratiquement tous les cas pratiques, les CA s'appuient sur divers moyens pour tester si l'entité demandant un certificat pour un identifiant donné contrôle effectivement cet identifiant.
Les défis fournissent au serveur l'assurance que le titulaire du compte est également l'entité qui contrôle l'identifiant. Pour chaque type de défi, les conditions suivantes doivent être satisfaites : pour qu'une entité accomplisse avec succès le défi, l'entité doit simultanément :
- Détenir la clé privée de la paire de clés de compte utilisée pour répondre au défi, et
- Contrôler l'identifiant en question.
La section 10 documente comment les défis définis dans ce document satisfont ces exigences. Les nouveaux défis doivent documenter comment ils les satisfont.
ACME utilise un cadre extensible de défi/réponse pour la validation des identifiants. Le serveur présente un ensemble de défis (sous forme d'objets dans le tableau « challenges ») dans l'objet d'autorisation envoyé au client, et le client répond en envoyant un objet de réponse dans une requête POST à l'URL du défi.
Cette section décrit un ensemble initial de types de défis. La définition d'un type de défi comprend :
- Le contenu de l'objet de défi
- Le contenu de l'objet de réponse
- Comment le serveur utilise le défi et la réponse pour valider le contrôle de l'identifiant
Les objets de défi contiennent tous les champs de base suivants :
type (requis, chaîne) : Le type de défi encodé dans l'objet.
url (requis, chaîne) : L'URL à laquelle la réponse peut être envoyée en POST.
status (requis, chaîne) : Le statut de ce défi. Les valeurs possibles sont « pending », « processing », « valid » et « invalid » (voir section 7.1.6).
validated (optionnel, chaîne) : L'heure à laquelle le serveur a validé ce défi, encodée au format spécifié dans [RFC3339]. Ce champ est REQUIS si le champ « status » est « valid ».
error (optionnel, objet) : L'erreur survenue lors de la validation du défi par le serveur, le cas échéant, structurée comme un document de problème [RFC7807]. Des sous-problèmes (section 6.7.1) peuvent être utilisés pour indiquer plusieurs erreurs. Le statut d'un objet de défi avec une erreur DOIT être égal à « invalid ».
Tous les autres champs sont spécifiés par le type de défi. Si le serveur définit le « status » d'un défi à « invalid », il DEVRAIT également inclure le champ « error » pour aider le client à diagnostiquer la raison de l'échec du défi.
Différents défis permettent au serveur d'obtenir des preuves de différents aspects du contrôle de l'identifiant. Dans certains défis, comme HTTP et DNS, le client prouve directement sa capacité à effectuer certaines opérations liées à l'identifiant. Le choix des défis à présenter au client dans quelles circonstances relève de la politique du serveur.
Les défis de validation d'identifiants décrits dans cette section concernent tous la validation des noms de domaine. Si ACME est étendu à l'avenir pour prendre en charge d'autres types d'identifiants, de nouveaux types de défis seront nécessaires, et ils devront spécifier à quels types d'identifiants ils s'appliquent.
8.1. Autorisations de clé (Key Authorizations)
Tous les défis définis dans ce document utilisent une chaîne d'autorisation de clé. Une autorisation de clé est une chaîne qui concatène le jeton du défi avec une empreinte de clé, séparés par un caractère « . » :
keyAuthorization = token || '.' || base64url(Thumbprint(accountKey))
L'étape « Thumbprint » représente le calcul spécifié dans [RFC7638], en utilisant le condensat SHA-256 [FIPS180-4]. Comme décrit dans [RFC7518], tout octet de zéro de tête dans les champs d'objet JWK DOIT être supprimé avant d'effectuer le calcul.
Comme spécifié dans chaque défi individuel ci-dessous, le jeton d'un défi est une chaîne composée entièrement de caractères de l'alphabet base64url sécurisé pour les URL. L'opérateur « || » représente la concaténation de chaînes.
8.2. Nouvelles tentatives de défis (Retrying Challenges)
Les défis ACME exigent généralement que le client configure une ressource accessible sur le réseau que le serveur peut interroger pour vérifier que le client contrôle l'identifiant. En pratique, il n'est pas rare que la requête du serveur échoue lors de la configuration de la ressource, par exemple parce que les informations se propagent dans un cluster ou que les règles de pare-feu ne sont pas encore en place.
Les clients NE DEVRAIENT PAS répondre aux défis tant qu'ils ne croient pas que la requête du serveur réussira. Si la requête de validation initiale du serveur échoue, le serveur DEVRAIT réessayer la requête après un certain temps, pour tenir compte des délais de configuration des réponses (tels que les enregistrements DNS ou les ressources HTTP). Le calendrier exact des nouvelles tentatives est laissé à la discrétion du serveur, mais les opérateurs de serveur doivent garder à l'esprit les scénarios opérationnels que le calendrier tente d'accommoder. Étant donné que les nouvelles tentatives visent à résoudre des problèmes tels que les délais de propagation dans la configuration HTTP ou DNS, il ne devrait généralement pas y avoir de raison de réessayer plus d'une fois toutes les 5 ou 10 secondes. Pendant que le serveur tente encore, le statut du défi reste « processing » ; il n'est marqué « invalid » qu'après que le serveur a abandonné.
Le serveur DOIT fournir au client des informations sur son état de nouvelle tentative via le champ « error » dans le défi et le champ d'en-tête HTTP Retry-After dans les réponses aux requêtes de ressource de défi. Le serveur DOIT ajouter une entrée au champ « error » du défi après chaque requête de validation échouée. Le serveur DEVRAIT définir le champ d'en-tête Retry-After à un moment postérieur à la prochaine requête de validation du serveur, car le statut du défi ne changera pas avant ce moment.
Les clients peuvent demander explicitement une nouvelle tentative en renvoyant la réponse au défi dans une nouvelle requête POST (avec un nouveau nonce, etc.). Cela permet aux clients de demander une nouvelle tentative lorsqu'un changement d'état s'est produit (par exemple, après la mise à jour d'une règle de pare-feu). Le serveur DEVRAIT réessayer la requête immédiatement à la réception d'une telle requête POST. Pour éviter les attaques par déni de service via des nouvelles tentatives initiées par le client, le serveur DEVRAIT limiter le débit de telles requêtes.
8.3. Défi HTTP (HTTP Challenge)
Avec la validation HTTP, le client dans une transaction ACME prouve son contrôle sur un nom de domaine en prouvant qu'il peut configurer des ressources HTTP sur un serveur accessible sous ce nom de domaine. Le serveur ACME défie le client de configurer un fichier à un chemin spécifique, avec un contenu spécifique.
Étant donné qu'un nom de domaine peut se résoudre en plusieurs adresses IPv4 et IPv6, le serveur se connectera à sa discrétion à au moins un des hôtes trouvés dans les enregistrements DNS A et AAAA. Étant donné que de nombreux serveurs Web attribuent l'hôte virtuel HTTPS par défaut à des locataires spécifiques à faibles privilèges de manière subtile et non intuitive, le défi doit être accompli via HTTP plutôt que HTTPS.
type (requis, chaîne) : La chaîne « http-01 ».
token (requis, chaîne) : Une valeur aléatoire identifiant de manière unique le défi. Cette valeur DOIT avoir au moins 128 bits d'entropie. Elle NE DOIT PAS contenir de caractères en dehors de l'alphabet base64url, et NE DOIT PAS inclure de caractères de remplissage base64 (« = »). Voir [RFC4086] pour des informations supplémentaires sur les exigences d'aléatoire.
{
"type": "http-01",
"url": "https://example.com/acme/chall/prV_B7yEyA4",
"status": "pending",
"token": "LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0"
}
Le client accomplit ce défi en construisant une autorisation de clé à partir de la valeur « token » fournie dans le défi et de la clé de compte du client. Le client configure ensuite l'autorisation de clé comme ressource sur le serveur HTTP du nom de domaine en question.
Le chemin de la ressource configurée est composé du préfixe fixe « /.well-known/acme-challenge/ » suivi de la valeur « token » du défi. La valeur de la ressource DOIT être la représentation ASCII de l'autorisation de clé.
GET /.well-known/acme-challenge/LoqXcYV8...jxAjEuX0
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/octet-stream
LoqXcYV8...jxAjEuX0.9jg46WB3...fm21mqTI
(Dans l'exemple ci-dessus, « ... » indique que le jeton et l'empreinte JWK dans l'autorisation de clé ont été tronqués pour tenir sur la page.)
Le client répond avec un objet vide ({}) pour confirmer que le serveur peut valider le défi.
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"
}
À la réception de la réponse, le serveur construit et stocke l'autorisation de clé à partir de la valeur « token » du défi et de la clé de compte client actuelle.
Étant donné la paire défi/réponse, le serveur valide le contrôle du client sur le nom de domaine en vérifiant que la ressource est configurée comme prévu.
-
Construire l'URL en remplissant le modèle d'URL [RFC6570]
"http://{domain}/.well-known/acme-challenge/{token}"où :- le champ domain est défini au nom de domaine en cours de validation ; et
- le champ token est défini au jeton dans le défi.
-
Vérifier que l'URL résultante est bien formée.
-
Déréférencer l'URL en utilisant une requête HTTP GET. Cette requête DOIT être envoyée au port TCP 80 du serveur HTTP.
-
Vérifier que le corps de la réponse est une autorisation de clé bien formée. Le serveur DEVRAIT ignorer les espaces blancs à la fin du corps.
-
Vérifier que l'autorisation de clé fournie par le serveur HTTP correspond à l'autorisation de clé stockée par le serveur.
Le serveur DEVRAIT suivre les redirections lors du déréférencement de l'URL. Par exemple, un client peut utiliser des redirections pour que la réponse puisse être servie par un serveur de gestion de certificats centralisé. Voir la section 10.2 pour les considérations de sécurité liées aux redirections.
Si toutes les validations ci-dessus réussissent, la validation est réussie. Si la requête échoue, ou si le corps ne passe pas ces vérifications, la validation échoue.
Le client DEVRAIT déprovisionner la ressource configurée pour ce défi une fois le défi terminé, c'est-à-dire une fois que la valeur du champ « status » du défi est « valid » ou « invalid ».
Notez que, puisque le jeton apparaît à la fois dans la requête envoyée par le serveur ACME et dans l'autorisation de clé dans la réponse, il est possible de construire un client qui copie le jeton de la requête vers la réponse. Les clients devraient éviter ce comportement, car il peut entraîner des vulnérabilités de type cross-site scripting ; au lieu de cela, les clients devraient effectuer une configuration explicite sur la base de chaque défi. Les clients qui copient effectivement le jeton de la requête vers la réponse DOIVENT vérifier que le jeton dans la requête correspond à la syntaxe de jeton ci-dessus (par exemple, qu'il ne contient que des caractères de l'alphabet base64url).
8.4. Défi DNS (DNS Challenge)
Lorsque l'identifiant en cours de validation est un nom de domaine, le client peut prouver son contrôle sur ce nom de domaine en configurant un enregistrement de ressource TXT contenant une valeur spécifiée pour un nom de domaine de validation spécifique.
type (requis, chaîne) : La chaîne « dns-01 ».
token (requis, chaîne) : Une valeur aléatoire identifiant de manière unique le défi. Cette valeur DOIT avoir au moins 128 bits d'entropie. Elle NE DOIT PAS contenir de caractères en dehors de l'alphabet base64url, y compris les caractères de remplissage (« = »). Voir [RFC4086] pour des informations supplémentaires sur les exigences d'aléatoire.
{
"type": "dns-01",
"url": "https://example.com/acme/chall/Rg5dV14Gh1Q",
"status": "pending",
"token": "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA"
}
Le client accomplit ce défi en construisant une autorisation de clé à partir de la valeur « token » fournie dans le défi et de la clé de compte du client. Le client calcule ensuite le condensat SHA-256 [FIPS180-4] de l'autorisation de clé.
L'enregistrement configuré dans le DNS contient l'encodage base64url de ce condensat. Le client construit le nom de domaine de validation en ajoutant l'étiquette « _acme-challenge » au nom de domaine en cours de validation, puis configure un enregistrement TXT avec la valeur du condensat sous ce nom. Par exemple, si le nom de domaine en cours de validation est « www.example.org », le client configurerait l'enregistrement DNS suivant :
_acme-challenge.www.example.org. 300 IN TXT "gfj9Xq...Rg85nM"
Le client répond avec un objet vide ({}) pour confirmer que le serveur peut valider le défi.
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"
}
À la réception de la réponse, le serveur construit et stocke l'autorisation de clé à partir de la valeur « token » du défi et de la clé de compte client actuelle.
Pour valider le défi DNS, le serveur effectue les étapes suivantes :
-
Calculer le condensat SHA-256 [FIPS180-4] de l'autorisation de clé stockée
-
Interroger les enregistrements TXT du nom de domaine de validation
-
Vérifier que le contenu de l'un des enregistrements TXT correspond à la valeur du condensat
Si toutes les validations ci-dessus réussissent, la validation est réussie. Si aucun enregistrement DNS n'est trouvé, ou si les enregistrements DNS et la charge utile de réponse ne passent pas ces vérifications, la validation échoue.
Le client DEVRAIT déprovisionner l'enregistrement de ressource configuré pour ce défi une fois le défi terminé, c'est-à-dire une fois que la valeur du champ « status » du défi est « valid » ou « invalid ».
RFC 8555 — Résumé des chapitres 9 à 12
Note : Ce document fournit un résumé des points clés des chapitres 9 à 12 de la RFC 8555. Pour les détails techniques complets, veuillez consulter le document officiel RFC 8555.
9. Considérations IANA
9.1 Enregistrement de type de média
- application/pem-certificate-chain : Format PEM pour les chaînes de certificats
9.2 URI Well-Known
- /.well-known/acme-challenge : Chemin standard pour le défi HTTP
9.3 Champs d'en-tête HTTP
- Replay-Nonce : Champ d'en-tête nonce anti-relecture
9.4-9.5 Paramètres d'en-tête JWS
- url : Paramètre URL dans JWS
- nonce : Paramètre nonce dans JWS
9.6 Espace de noms URN
- urn:ietf:params:acme : Espace de noms URN pour le protocole ACME
9.7 Nouveaux registres
L'IANA a créé les registres suivants pour ACME :
- Account Object Fields (Champs d'objet de compte)
- Order Object Fields (Champs d'objet de commande)
- Authorization Object Fields (Champs d'objet d'autorisation)
- Error Types (Types d'erreurs)
- Resource Types (Types de ressources)
- Directory Metadata Fields (Champs de métadonnées du répertoire)
- Identifier Types (Types d'identifiants)
- Validation Methods (Méthodes de validation)
10. Considérations de sécurité
10.1 Modèle de menace
Les deux principaux objectifs de sécurité d'ACME :
- Seule l'entité contrôlant un identifiant peut obtenir une autorisation pour cet identifiant
- Après autorisation, l'autorisation d'une clé de compte ne peut pas être utilisée de manière abusive par un autre compte
Canaux de communication :
- Canal ACME : Requêtes HTTPS entre le client et le serveur
- Canal de validation : Canal par lequel le serveur effectue les requêtes de validation
10.2 Intégrité des autorisations
Liaison de clé : Tous les défis lient la clé privée du compte aux requêtes de validation via l'autorisation de clé.
Attaques potentielles :
- Attaque MitM : Les CDN ou proxys inverses peuvent devenir des intermédiaires
- Attaques DNS : Un attaquant peut influencer la validation via le détournement DNS
- Risques des hébergeurs : Les fournisseurs d'hébergement peuvent falsifier la validation
Mesures défensives :
- Utiliser des résolveurs avec validation DNSSEC
- Interroger le DNS depuis plusieurs emplacements réseau
- Appliquer des protections DNS (comme DNS0x20)
10.3 Considérations sur le déni de service
Les CA devraient mettre en œuvre :
- Des limites de débit
- Des quotas de ressources
- Des délais d'expiration pour les requêtes de validation
10.4 Falsification de requête côté serveur (SSRF)
Le défi HTTP-01 peut être utilisé pour des attaques SSRF. Les CA devraient :
- Rejeter les adresses IP privées
- Limiter les redirections
- Définir des délais d'expiration raisonnables
10.5 Considérations de politique des CA
Les CA devraient établir des politiques concernant :
- Le choix des méthodes de validation
- La durée de validité des certificats
- Les conditions de révocation
11. Considérations opérationnelles
11.1 Sélection des clés
Types de clés recommandés :
- ECDSA P-256 ou P-384
- RSA 2048 bits ou plus
11.2 Sécurité DNS
Lors de l'utilisation du défi DNS-01 :
- S'assurer que l'infrastructure DNS est sécurisée
- Envisager l'utilisation de DNSSEC
- Protéger les interfaces de gestion DNS
11.3 Entropie des jetons
Les jetons de défi doivent avoir une entropie suffisante :
- Au moins 128 bits d'entropie
- Utiliser un générateur de nombres aléatoires cryptographiquement sécurisé
11.4 Chaînes de certificats malformées
Les clients devraient :
- Vérifier l'intégrité de la chaîne de certificats téléchargée
- Vérifier la période de validité des certificats
- Valider le chemin de confiance de la chaîne de certificats
12. Références
12.1 Références normatives (liste partielle)
- RFC2119 : Définition des mots-clés (MUST, SHOULD, MAY, etc.)
- RFC5280 : Certificats X.509 et configuration CRL
- RFC7515 : JSON Web Signature (JWS)
- RFC7518 : JSON Web Algorithms (JWA)
- RFC8259 : Format de données JSON
- RFC2818 : HTTPS
- RFC3339 : Format de date et d'heure
- RFC7807 : Détails de problème pour les API HTTP
12.2 Références informatives (liste partielle)
- RFC3552 : Guide des considérations de sécurité pour les protocoles Internet
- RFC6844 : Enregistrement de ressource DNS CAA (Certification Authority Authorization)
- RFC7525 : Recommandations pour l'utilisation sécurisée de TLS et DTLS
Annexes
Remerciements (Acknowledgements)
Le développement de la RFC 8555 a bénéficié des contributions de nombreux membres de la communauté IETF.
Adresses des auteurs (Authors' Addresses)
Auteurs principaux :
- Richard Barnes (Cisco)
- Jacob Hoffman-Andrews (EFF)
- Daniel McCarney (Let's Encrypt)
- James Kasten (University of Michigan)
Ressources connexes
- Document RFC officiel : RFC 8555
- Suivi de données IETF : RFC 8555 DataTracker
- Documentation Let's Encrypt : https://letsencrypt.org/docs/