Zum Stand von Let's Encrypt

Posted by jonas on Friday, October 30, 2015

Derzeit schlagen im Support vermehrt Fragen zum Support von Let’s Encrypt auf, nicht zuletzt seit das Projekt vermelden konnte, nun seine Cross-Root-Signatur von IdenTrust erhalten zu haben, was nicht Wenige damit verwechselt haben, dass es da jetzt produktiv losgeht. Deshalb erstmal die wichtigsten Punkte vorab:

  • Let’s Encrypt ist weiterhin noch nicht allgemein verfügbar; es gibt lediglich eine Closed Beta. Der Verfügbarkeitstermin ist nach deren aktueller Roadmap der 16. November wohl doch erst der 3. Dezember.
  • Let’s Encrypt ist eine Zertifizierungsstelle, aus der letztlich ganz genauso Zertifikate rausfallen wie aus jeder anderen Zertifizierungsstelle - Zertifikate, die wir also ganz genauso wie jedes andere Zertifikat kostenlos bei uns einbinden können - heute schon.
  • User, die das Glück haben, am Beta-Programm von Let’s Encrypt teilnehmen zu können, tun das auch bereits.
  • Ja, wir haben vor, Let’s Encrypt bei uns zu unterstützen, und um diesen Aspekt dreht sich dieser Blogpost.

Wenn davon die Rede ist, dass wir Let’s Encrypt bei uns unterstützen wollen, dann meint das weniger, dass wir deren Zertifikate unterstützen, denn in dieser Hinsicht unterscheidet sich Let’s Encrypt ja nicht von jeder anderen CA. Es bedeutet vielmehr, dass wir deren Validierungsprozess bei uns einbinden möchten, mit dem Ziel, dass User im Prinzip nur noch sowas wie uberspace-letsencrypt (oder sowas in der Richtung) eingeben müssen, und wir kümmern uns darum, ihnen automatisiert einen Account bei Let’s Encrypt zu verschaffen, die Challenges für die Validierung zu erledigen, Key und CSR zu erstellen und das Zertifikat bei uns einzubinden. Soweit der Plan, und wir arbeiten bereits seit einiger Zeit daran, das umzusetzen; ist aber noch nicht fertig. Das macht aber ja nichts, denn Let’s Encrypt selbst ist ja auch noch nicht fertig, d.h. die Zertifikate, die man derzeit von deren Staging-API beziehen kann, tragen ohnehin noch keine Signatur, der Browser vertrauen würden (das ist nur bei den Zertifikaten des Beta-Programms der Fall).

Nun ist das alles nicht so einfach, wie das auf deren Website aussieht, also einfach letsencrypt eingeben und alles ist gut. Tatsächlich ist das fragliche Tool derzeit noch eine Großbaustelle, die zwingend nach root-Rechten verlangt, bei jedem Aufruf erstmal nach neuen Versionen und Abhängigkeiten schaut und in Bezug auf die “Magie”, den ganzen Zertifikatskram irgendwie in den Webserver reinzufuddeln, erstens derzeit noch auf ganz wenige Backends beschränkt ist (konkret Apache und nginx, und da auch speziell auf die Verzeichnisstrukturen von Debian-basierenden Distributionen) und die zweitens auch ziemlich invasiv ist: Invasiv im Sinne von “Wir stoppen den normalen Webserver, starten einen eigenen Webserver auf Port 443, der die Challenge beantwortet, und starten anschließend wieder den normalen Webserver”. Das mag für ein einfach gehaltenes Standalone-System passabel sein; für ein komplexes Shared-Hosting-System, auf dem man als User keine root-Rechte hat, ist die Nutzbarkeit dieses Tools aber eben erstmal ziemlich beschränkt. Überhaupt sind wir nicht die einzigen, denen nicht so ganz wohl dabei ist, dass das letsencrypt-Tool soviel mit sudo hantiert und es Bestrebungen gibt, den Validierungsprozess so auszulagern, dass das nicht nötig ist. Und dann kommt da sowas in der Diskussion, wo wir uns spontan fragten, was die denn wohl im Tee hatten:

The purpose of DVSNI was to ensure that – for CAs that wish to adopt this policy – you can’t get a cert if you can’t more-or-less prove administrative control of the [web]server that the domain is pointed at. That protects against low-privilege users (either shell users or edit-arbitrary-files-in-the-webroot users) on shared systems from getting certs for everything hosted there.

Other CAs may be different, but Let’s Encrypt may well insist on this sort of proof-of-root-access for most classes of domains.

Also … “shell users” … “on shared systems” … mit anderen Worten: Ubernauten, zum Beispiel. Die sollen keine Zertifikate von Let’s Encrypt kriegen. WTF?

Was Let’s Encrypt bereitstellt, ist eine API und dazu ein Kommandozeilentool, das mit dieser API spricht und Open Source ist. Es gibt exakt keinen Grund, warum dieses Kommandozeilentool zwingend root-Rechte verlangen müsste; im Allgemeinen könnten Admins ja auch durchaus ein Interesse daran haben, den Prozess der Zertifikatsanforderung bewusst auf einem anderen Rechner abwickeln zu wollen als dem Webserver und die Challenge auf anderem Wege erfüllen zu wollen. Einen “proof-of-root-access” verlangen zu wollen, ist da nicht nur völlig unsinnig, sondern auch technisch gar nicht forcierbar, denn wenn’s eine API ist, die per HTTPS angesprochen werden kann, und die Forcierung von root-Rechten nur durch den Client erfolgt … naja, dann nimmt man eben einen anderen Client, der das nicht tut. Aber dieses Verständnis scheint da auch bei anderen Diskussionsteilnehmern nicht vorzuliegen:

Absolutely, I agree that proving root access on your domain’s server should be required.

Nun gut. Zum Glück ist die Situation schlicht nicht so, wie die Diskutierenden es offenbar alle gerne hätten. Es gibt andere Clients, und die brauchen keine root-Rechte. Für uns sehen hier derzeit die Libraries letsencrypt_simpleclient (Python 3) sowie Acme::Client (Ruby) am Vielversprechendsten aus, und wir werden unsere Anbindung wohl auf einer davon basieren lassen.

Wenn wir insbesondere die Erfüllung der Challenge automatisieren wollen, stellt sich aber natürlich die Frage nach dem Wie. Die Challenge sieht hier so aus, dass die API meldet, dass sie unter dem URL-Pfad /.well-known/acme-challenge/... auf dem zu zertifizierenden Hostnamen eine Jose-Datei mit vorgegebenem Content erwartet. Und da fängt’s schon an, denn auch wenn der häufigste Fall sein dürfte, dass User einfach in /var/www/virtual/$USER/html irgendwas für’s Web ablegen, so gibt es dennoch Ausnahmen:

  • User, die dort nur noch eine .htaccess-Datei reinwerfen, die eine Proxy-RewriteRule enthält, die die Requests z.B. auf eine node.js-Applikation umleitet
  • User, die in /var/www/virtual/$USER ein separates Verzeichnis für einen Hostnamen angelegt haben
  • User, die ein eigenes Backend durch unseren Support direkt an Pound haben anbinden lassen, bei denen der Request gar nicht durch den Apache läuft

Die naheliegendste Variante wäre, sämtliche HTTPS-Requests mit /.well-known/acme-challenge/... im URL-Pfad direkt in Pound abzufangen und auf ein festes Backend zu schicken, was sich dann um die Erfüllung der Challenges kümmert. Das wäre vermutlich sogar trivial und schick, aber: Es nimmt Usern, die aus irgendwelchen Gründen die Challenge selbst erfüllen wollen (z.B. weil sie ihr Let’s-Encrypt-Zertifikat lieber selbst generieren wollen, oder weil sie schlicht nichts von der Integration bei uns mitkriegen) die Möglichkeit, diesen Request selbst zu beantworten, und es dürfte reichlich irritierend sein, wenn man da brav in seinem DocumentRoot etwas ablegt und Let’s Encrypt sagt, so, validier mal, und der Request dann aber “irgendwie nicht bei einem ankommt” (weil wir den in diesem Szenario abfangen würden). Umgekehrt könnte es aber auch für User mit eigenem Pound-Backend ggf. schwierig sein, die Challenge aus ihrer eigenen Applikation heraus beantworten zu können, und es wäre ihnen eigentlich lieber, wenn wir das automatisch für sie abfackeln könnten. Hm.

Die Angelegenheit bleibt also noch ein bisschen tricky, wenn wir etwas hinkriegen wollen, was für das Gros der User automatisiert funktionieren soll und dabei aber gleichzeitig nicht so stark eingreift, dass es Usern, die den Automatismus nicht wollen, die Möglichkeit nimmt, die Angelegenheit selbst zu regeln. Für irgendeine Variante werden wir uns aber letztlich entscheiden müssen. Das ist aber noch offen.

So oder so: Wir sind dran, und das wollten wir euch angesichts der vielen Fragen einfach wissen lassen. Stay tuned! :-)