Wir schreiben ein Plugin, um Wildcard-Zertifikate von Let's Encrypt zu erhalten

Hallo nochmal, lieber Leser. Das zweite Kapitel über Let's Encrypt-Abenteuer im ISPmanager-Bereich wird für geöffnet erklärt. In einem früheren Artikel haben wir das Plugin für ACME v01 besprochen. In diesem Artikel werden wir über seine Entwicklung unter dem Gesichtspunkt der Logik der Zusammenarbeit mit dem Benutzer und natürlich über das ACME v02-Protokoll mit Unterstützung für Platzhalterzertifikate sprechen.



Übermäßige Pflege


Wenn Sie versuchen, den Benutzer sorgfältig zu umgeben, können Sie weit gehen. Bisher wird er überhaupt nicht mit Funktionalität arbeiten können. Und der erste Teil unserer Geschichte handelt genau davon.

Während der Entwicklung des Moduls wollten wir den Client vor einer langen Vorbereitung auf das Zertifikat bewahren. Hierfür wurden zwei Einschränkungen eingeführt: Sie durften SSL nur für im Panel registrierte Webdomains und nur für die dem Panel bekannten Domain-Aliase bestellen.

Beide Einschränkungen schienen logisch. Die erste erlaubte es nicht, Zertifikate für nicht existierende Domänen zu bestellen und "tote" Entitäten zu produzieren - Zertifikate, die nicht ausgestellt würden, da es keinen Ort gibt, an dem die Token der Überprüfung abgelegt werden können. Die zweite beseitigte auch unnötige Entitäten und erlaubte immer noch nicht, Zertifikate für "*" - Aliase - zu bestellen, während LE solche Zertifikate einfach nicht unterstützte.

Alles war in Ordnung, bis eines Tages in LE eine Funktion zum Überprüfen einer Domain über DNS-Einträge und zum Bestellen eines Zertifikats für eine Mail-Domain erschien. Bei der Bestellung einer Mail-Domain haben wir uns dann entschlossen, den Aliasen Folgendes hinzuzufügen: "mail", "pop", "smtp" - schließlich sind meistens Zertifikate mit ihnen verbunden. Am Ende stellte sich heraus, dass es Benutzer gab, die ihre Mailserver ursprünglich auf völlig andere Aliase konfiguriert hatten. Aufgrund unserer Bestellbeschränkungen konnten die erforderlichen Namen nicht hinzugefügt werden.

Glücklicherweise haben wir den Fehler schnell erkannt und behoben, sodass Benutzer bei der Bestellung eines Zertifikats die erforderlichen Daten angeben können. Trotzdem gibt es manchmal zu viele Sorgen :).

Platzhalter


Lassen Sie uns nun über den Wechsel zu ACME v02 sprechen , da nur in dieser Version des LE- Protokolls die Unterstützung für Platzhalterzertifikate angezeigt wurde. Beginnen wir mit einem neuen oder besser gesagt einem geänderten Verzeichnis:

curl -o- 'https://acme-v02.api.letsencrypt.org/directory' { "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change", "mIU2Y2m2FsA": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "meta": { "caaIdentities": [ "letsencrypt.org" ], "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf", "website": "https://letsencrypt.org" }, "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct", "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce", "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order", "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert" } 

Der erste und offensichtlichste Unterschied ist, dass die Tasten unterschiedlich sind :). Meiner Meinung nach sind sie viel intuitiver geworden. Der zweite Unterschied ist eine separate URL zum Abrufen von Replay-Nonce. Dies geschieht jetzt folgendermaßen:

 curl -LD - 'https://acme-v02.api.letsencrypt.org/acme/new-nonce' HTTP/1.1 204 No Content Server: nginx Replay-Nonce: QQgdAERh1MLQ6LHC0SVmB9OJXBcEWnwGB53CP0V4JlQ X-Frame-Options: DENY Strict-Transport-Security: max-age=604800 Expires: Sat, 02 Jun 2018 09:49:47 GMT Cache-Control: max-age=0, no-cache, no-store Pragma: no-cache Date: Sat, 02 Jun 2018 09:49:47 GMT Connection: keep-alive 

Nonce wird uns natürlich mehr als einmal nützlich sein.

Lassen Sie uns nun über die nicht offensichtlichen Änderungen sprechen, die der Übergang zu ACME v02 mit sich bringt.

Für alle Fälle möchte ich Sie daran erinnern, wie unsere alte POST-Anfrage für die Kommunikation mit der ersten Version von ACME aussah:

 { "header": jws, // JSON Web Signature "protected": Base64Url(jws + Replay-Nonce), // Nonce —    "payload": Base64Url(payload), //  "signature": Base64Url(sign(protected.payload, private.pem)) //  } 

Jetzt wird die allgemeine Datenstruktur anders sein:

 { "protected": Base64Url(protected), "payload": Base64Url(payload), // "signature": Base64Url(sign(protected.payload, private.pem)) } 

Wie Sie sehen können, wurde das Header-Feld abgebrochen. Die Vorbereitungsphase hat sich zur großen Freude von „Kryptografieliebhabern“ wie mir überhaupt nicht geändert: Wir werden alle gleichen RSA-Schlüssel, JWK und JWS, benötigen (mehr dazu im ersten Teil ).

Registrierung


Um einen Benutzer zu registrieren, müssen Sie nur die Benutzervereinbarung akzeptieren und eine Anforderung für "newAccount" aus dem Verzeichnis senden.

 payload = {"termsOfServiceAgreed": true} 

Und kompilieren Sie den richtigen geschützten:

 { "alg" : "RS256", "jwk" : jwk, \\ JSON Web Key “url” : url, \\       “nonce” : Replay-Nonce \\    } 

Wir bilden den Hauptteil der Anfrage, senden sie und ... nehmen uns Zeit! Verarbeiten Sie die Antwortheader von ACME sorgfältig und sorgfältig. Wir finden einen Header namens Location und speichern dessen Inhalt. Dies ist das sogenannte KID - der Identifikationsschlüssel des neu registrierten Benutzers. Alle nachfolgenden Anforderungen müssen diesen Wert in protected anstelle von JWK enthalten . Seien Sie vorsichtig : Wenn Sie weiterhin Anfragen nach dem alten Schema senden, werden nur Fehlermeldungen beantwortet.

Hier ist unser späterer Schutz:

 { "alg" : "RS256", "kid" : kid, \\    “url” : url, \\        “nonce” : Replay-Nonce \\    } 

Zertifikatsbestellung


Wir bereiten uns darauf vor, eine Anfrage an das Verzeichnis ["newOrder"] zu senden. Wir fügen der Nutzlast alle Aliase unserer Webdomain hinzu, für die wir ein Zertifikat ausstellen werden:

 payload ={ "identifiers":[ { "type":"dns", "value":"name1" }, ... { "type":"dns", "value":"nameN" } ] } 

Beachten Sie, dass die Namen, wenn Sie ein Platzhalterzertifikat ausstellen möchten, nur den Hauptnamen und "*." - einen Alias ​​- enthalten sollten. Das Vorhandensein anderer Namen führt zu einem Release-Fehler.

In der Antwort erhalten wir einen JSON, der Methoden zum Bestätigen des Eigentums an der Domain und die URL enthält, die zum Abschließen der Ausstellung des Zertifikats verwendet wird.

 { "status":"pending", "expires":"2018-06-08T08:05:49.437251947Z", "identifiers":[ { "type":"dns", "value":"name1" }, { "type":"dns", "value":"www.name1" } ], "authorizations":[ //    "https://acme-v02.api.letsencrypt.org/acme/authz/Xp0a_...", "https://acme-v02.api.letsencrypt.org/acme/authz/o3Bvy..." ], "finalize":"https://acme-v02.api.letsencrypt.org/acme/finalize/..." //   } 

Weiterhin erhalten wir detaillierte Anweisungen zu Schecks:

 curl -o- 'https://acme-v02.api.letsencrypt.org/acme/authz/Xp0a_...' { "identifier":{ "type":"dns", "value":"name1" }, "status":"pending", "expires":"2018-06-08T08:05:49Z", "challenges":[ { "type":"http-01", "status":"pending", "url":"https://acme-v02.api.letsencrypt.org/acme/challenge/Xp0a_.../4906756205", "token":"Me_cKM2Stu3iyCJQWEssho8Kj2nvRKuSJvIPF5tRyko" }, { "type":"dns-01", "status":"pending", "url":"https://acme-v02.api.letsencrypt.org/acme/challenge/Xp0a_.../4906756206", "token":"p-0xyySPQClTXVlgTxwJUvVOQtdHmNPpFht95bWrq8s" } ] } 

Der Bestätigungsprozess unterscheidet sich nicht von dem, was für ACME v01 implementiert wurde . Bitte beachten Sie: Für ein Platzhalterzertifikat müssen Sie die Bestätigung „dns-01“ auswählen.

Ein Zertifikat erhalten


Nach dem Bestätigungsvorgang muss die Finalize- URL noch aufgerufen werden. Es sind geringfügige Verzögerungen möglich. Daher sollte eine GET-Anforderung an diese Adresse erfolgen, bis in der Antwort Folgendes angezeigt wird:

 { "status": "valid", ///<    "expires": "2018-06-11T10:39:24Z", "identifiers": [ { "type": "dns", "value": "name1" }, { "type": "dns", "value": "name2" } ], "authorizations": [ "https://acme-v02.api.letsencrypt.org/acme/authz/Xp0a_...", "https://acme-v02.api.letsencrypt.org/acme/authz/o3Bvy..." ], "finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/...", "certificate": "https://acme-v02.api.letsencrypt.org/acme/cert/..." ///<  } 

Das Zertifikat enthält bereits eine Kette, sodass es vollständig einsatzbereit ist.

Im Vergleich zur ersten ist die zweite Version von ACME wesentlich praktischer und verständlicher geworden. Die Integration des Schreibens ist noch einfacher geworden, da sich die "Kryptographie" selbst nicht geändert hat. Ich werde die Entwicklung dieses erstaunlichen Werkzeugs mit Interesse beobachten und mit neuen Informationen hierher zurückkehren, wenn wichtige und nützliche Änderungen eintreten.

Source: https://habr.com/ru/post/de413429/


All Articles