Let’s Encrypt und Puppet

lets-encrypt-logoIch habe früher fast alle meine Zertifikate von CAcert bezogen. Ich habe sie regelmäßig aktualisiert und für das deployen habe ich ein Puppet Modul, dass die Zertifikate verteilt.

Nach und nach bin ich auf Let’s Encrypt Zertifikate umgestiegen. Da ein hoher Grad an Automatisierung bei Let’s Encrypt immer wieder propagiert wird dachte ich mir, dass sollte auch mit Puppet dann kein zu großes Problem sein. Hier die Lösung, die bei mir nun in Betrieb ist:

Als erstes habe ich das Puppet Modul bzed/letsencrypt installiert. Das Modul benötigt eine PuppetDB. Über exported resources  transportiert es die CSRs auf den puppetmaster, macht dort die gesamte Abwicklung und transferiert dann die Ergebnisse wieder zurück auf den Node. Das funktioniert auch sehr gut.

Auf dem Puppetmaster habe ich die Klasse eingebunden und einige wenige Einstellungen gesetzt (hiera). Bei dem Hook handelt sich m übrigen um einen letsencrypt.sh Hook:

---
classes:
  - letsencrypt

letsencrypt::challengetype: 'http-01'
letsencrypt::hook_source: 'puppet:///modules/helper/%{::fqdn}/le_hook.sh'

Auf den Nodes habe ich die Klasse eingebunden und die Domains definiert für die ein Zertifikat bezogen werden soll:

---
classes:
- letsencrypt

letsencrypt::domains:
- 'foo.example.net'
- 'bar.example.net'
- 'baz.example.net'

PL_logo_vertical_RGB_lgIn meinem recht simplen Szenario ist es so, dass ich einen Gate-Server habe, hinter dem sich alle anderen Maschinen „verstecken“. Dort läuft ein Apache Server als Proxy, der Anfragen über HTTP nach hinten weiterreicht. Die Konfiguration von Apache erfolgt ebenfalls über Puppet. Eine Authentifizierung über DNS für ACME klappt bei mir leider nicht, weswegen ich HTTP nehmen muss. Das habe ich so gelöst, dass ich für die Apache vhosts einfach über ProxyPassMatch den .well-known/acme-challenge/ auf einen Apache Vhost auf dem Puppetmaster weiterreiche. Auf dem Gate-Server sieht das für einen Vhost wie folgt aus:

apache::vhost:
  'proxy-foo.example.net':
    servername: 'foo.example.net'
    serveradmin: 'webmaster@example.net'
    port: '80'
    docroot: '/var/www/empty'
    proxy_dest: 'http://10.20.30.1'
    proxy_pass_match:
      -
        path: '^/.well-known/acme-challenge/(.*)$'
        url: 'http://10.20.30.2/$1'
        params:
          retry: '0'
    headers:
      - 'unset X-Powered-By'
    proxy_preserve_host: true

Auf dem Puppetmaster wiederum läuft ein Vhost, der einfach alle Domains als ServerAlias eingetragen hat.

Nun kommt noch der Hook für letsencrypt.sh ins Spiel den ich oben bereits erwähnt habe. Das Skript schreibt die ACME-Challenge in eine Textdatei in den DocRoot und löscht sie nach dem Erfolg wieder:

#!/bin/bash
 
#
# http-01 hook
#
 
CHALLENGEDIR="/var/www/example.net/letsencrypt"
 
done="no"
if [[ "$1" = "deploy_challenge" ]]; then
    echo "${4}" > "${CHALLENGEDIR}/${3}"
    chmod 644 "${CHALLENGEDIR}/${3}"
    done="yes"
fi
 
if [[ "$1" = "clean_challenge" ]]; then
    rm "${CHALLENGEDIR}/${3}"
    done="yes"
fi
 
if [[ "${1}" = "deploy_cert" ]]; then
    # do nothing for now
    done="yes"
fi
 
if [[ ! "${done}" = "yes" ]]; then
    echo Unkown hook "${1}"
    exit 1
fi
 
exit 0

Voila! Es braucht ein paar Durchläufe bis alles über die Puppetdb jeweils transportiert wurde, aber alles läuft vollautomatisch ab. Sehr cool!

Kostenlose HTTPS-Zertifikate von WoSign / China

Da Let’s encrypt noch nicht so weit ist, ich aber trotzdem immer mal wieder HTTPS Zertifikate haben möchte die von den bekannten Webbrowsern ohne Rückfrage akzeptiert werden hab ich mir schon mal das ein oder andere günstige gekauft. Den Großteil verwalte ich aber noch mit CAcert.

Für die Zertifikate zu bezahlen war mir aber schon immer ein Dorn im Auge. Schon früh hatte ich mir StartSSL angeschaut aber das war mir alles deutlich zu umständlich. Über Twitter wurde ich dann auf einen neuen chinesischen Anbieter hingewiesen:

https://twitter.com/hanno/status/566193681594855424

Lange Rede kurzer Sinn. Das ganze ist sehr simpel und funktioniert super:

  • Key + CSR erzeugen:
    openssl req -new -nodes -newkey rsa:4096 -sha256 -keyout host.example.net.key -out host.example.net.csr
  • URL öffnen: https://buy.wosign.com/free/
  • Formular ausfüllen, Domain bestätigen, Zertifikat beantragen, auf Email warten
  • Nach Erhalt der ZIP Datei mit Zertifikat und Intermediates die Bundle-Datei öffnen und den letzten Eintrag entfernen
  • Im Webserver einbinden und SSL Server Test machen um zu prüfen ob alles korrekt ist

SSL: Zertifikate auf sha2 Umstellen…

Key und CSR neu erzeugen. Das -sha256 ist das entscheidende:

openssl req -new -nodes -newkey rsa:2048 -sha256 -keyout sub.example.org.sha2.key -out sub.example.org.sha2.csr

Wenn das Zertifikat im Apache eingebunden ist auch gleich prüfen ob SSLProtocol und SSLCipherSuite aktuell ist. Aktuelle Empfehlung von BetterCrypto.org lautet:

SSLProtocol All -SSLv2 -SSLv3
 
SSLCipherSuite 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:
	EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:
	+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:
	!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA'

Ob alles gut ist, vor allem auch mit der Chain kann man dann sehr gut beim Qualys SSL Labs Server Test sehen.

An dieser Stelle möchte ich auch einmal auf den sehr guten Service von domaindiscount24 hinweisen. Ich habe meine Zertifikate (sofern nicht von CAcert) dort gekauft. Im Backend gab es bei Zertifikaten die vor der Heartbleed-Lücke gekauft wurden dann eine neue Spalte, in der man diese kostenlos erneuern konnte. Bei SHA1 vs. SHA2 ist nun das gleiche, man kann bei den Zertifikaten kostenlos dazwischen hin und her wechseln. Klasse!

dd24-Zertifikate