git push auf HTTPS Server mit CAcert/self-signed Zertifikat (don’t do it!)

Gestern hats mal wieder länger gedauert als gedacht, wie das immer so ist, wenn man neue Software enrichtet…

Bis jetzt hatte ich mein Git Repository auf meinem Server über SSH genutzt. Da ich das aber irgendwann teilen will, und wenig Lust auf den Streß mit den Dateiberechtigungen habe, muß eine andere Lösung her.

Auf meinem Apache ist schon WebDAV eingerichtet, ein Subversion Repository gibts auch schon darüber. Es liegt also nahe, Git auch über den Apachen zu machen.

Das geht auch, und es gibt eine sehr gute Anleitung dazu, wie man den Server einrichtet auf kernel.org die ich hier nicht wiederholen werde.

Eine kleine Ergänzung gibts allerdings: Nach dem Anlegen eines neuen bare Repositories wird man mit hoher Wahrscheinlichkeit noch

$ git update-server-info

ausführen müssen.

Wenn man sein Repository nur über HTTPS ansprechen will, gibts auf Client Seite, insbesondere wenn der Client ein MacOS X ist, noch eine Dinge, die man beachten muß, damits dann auch wirklich funktioniert.

Ich hatte einige Mühe, alle Puzzleteile zusammenzusammeln, deswegen hier eine Anleitung für die Nachwelt.

git push verwendet für HTTP(S) libcurl zur Kommunikation.
libcurl muß, um richtig zu funktionieren, die SSL Zertifikatskette verifizieren können.

Ich verwende CAcert für alle meine privaten Zertifikate. Die sind leider immer noch nicht anerkannt bei den großen Browserherstellern, aber das ist trotzdem praktischer als self-signed. Das Vorgehen in diesem Fall mit selbsterstellter CA bleibt aber das gleiche.

Der richtige Platz für CA Zertifikate ist unter MacOS in /System/Library/OpenSSL/certs/.

Der richtige Platz fü CA Zertifikate ist unter MacOS, wenn man MacPorts benutzt (was ich nur jedem ans Herz legen kann) unter /opt/local/etc/openssl/certs (Siehe Update unten)

Unter Debian (& Derivaten) wäre es /etc/ssl/certs/.

Dorthin die CAcert Class 1 und 3 Root Zertifikate kopieren (bzw. die self-signed Zertifikate).

Damit die Zertifikate nun zugeordnet werden können, müssen sie nach ihren Hashes benannt werden – oder besser – Symlinks mit solchen Namen erzeugt werden, die auf die richtige Cert-Datei zeigen.

Unter Debian führt man nun einfach

# c_rehash

aus, welches genau dieses für einen macht. Unter MacOS 10.6.3 bleibt dieser Befehl leider wirkungslos, selbst wenn man den in der Shebang Zeile des Scripts geforderten Symlink #!/usr/bin/perl5 anlegt.

Wegen zwei Dateien werden wir nicht lange herumtun… Wir gehen einfach zu Fuß:

In Zeile 104 von /usr/bin/c_rehash findet sich der Befehl, der benötigt wird:

# openssl x509 -hash -fingerprint -noout -in [filename]

In der ersten Zeile der Ausgabe steht der Hash des Zertifikats. Für das Class 1 Root Zertifikat von CAcert ist das z.B. 5ed36f99.

Dann einen Symlink anlegen mit dem Hash gefolgt von .0:

# ln -s root.crt 5ed36f99.0

Analog mit allen weiteren Zertifikaten.

Jetzt noch git beibringen, libcurl richtig zu parametrieren, am besten gleich systemweit:

# git config --system http.sslcapath /System/Library/OpenSSL/certs/
# git config --system http.sslcapath /opt/local/etc/openssl/certs/

(Siehe git-config Manual auf kernel.org)

Und jetzt sollte ein

$ git push origin master

auch funktionieren…

Update

Ich mußte feststellen, daß MacOS alle angelegten Symlinks in /System/Library/OpenSSL/certs/ beim Systemstart löscht. Daher die Zertifikate besser in der OpenSSL Konfiguration von MacPorts ablegen!

Und noch ein Update

Nach weiterem Gebastel kann ich inzwischen nur jedem abraten, Git über HTTP zu machen… Es ist grauenhaft. Abgesehen von dem Zertifikatsgewetze, wie es hier beschrieben ist, ist der post-update Hook einfach nicht zum laufen zu bekommen (siehe Pro Git) – und ohne den macht der nächste Clone keinen Spaß.

Wenn man ein bißchen mehr Plan von Server Administration hat, kommt man auch gleich drauf, daß man einfach für SSH nur einen Git-User anlegt, den alle benutzen. Dann gibts keine Probleme mit den Dateirechten. Alle anderen (so wie ich) lesen es dann bei Pro Git nach, wie das geht.