Wir möchten den Zugriff auf unseren Entwicklungsserver auf Benutzer beschränken, die über ein gültiges SSL-Client-Zertifikat verfügen. Wir verwenden Apache 2.2.16 unter Debian 6.
Für einige Abschnitte (hauptsächlich git-http, Setup mit gitolite aufhttps://my.server/git/) wir brauchen eine Ausnahme, da viele Git-Clients keine SSL-Client-Zertifikate unterstützen.
Es ist mir gelungen, eine Client-Zertifikatauthentifizierung für den Server zu verlangen und Ausnahmen für einige Standorte hinzuzufügen. Bei Git scheint das jedoch nicht zu funktionieren.
Die aktuelle Konfiguration ist wie folgt:
SSLCACertificateFile ssl-certs/client-ca-certs.crt
<Location />
SSLVerifyClient require
SSLVerifyDepth 2
</Location>
# this works
<Location /foo>
SSLVerifyClient none
</Location>
# this does not
<Location /git>
SSLVerifyClient none
</Location>
Ich habe auch eine alternative Lösung ausprobiert, mit dem gleichen Ergebnis:
# require authentication everywhere except /git and /foo
<LocationMatch "^/(?!git|foo)">
SSLVerifyClient require
SSLVerifyDepth 2
</LocationMatch>
In beiden Fällen kann ein Benutzer ohne Client-Zertifikat problemlos auf my.server/foo/ zugreifen, aber nicht auf my.server/git/ (der Zugriff wird verweigert, da kein gültiges Client-Zertifikat vorliegt). Wenn ich die SSL-Client-Zertifikat-Authentifizierung vollständig deaktiviere, funktioniert my.server/git/ einwandfrei.
Das ScriptAlias-Problem
Gitolite wird mit der ScriptAlias-Direktive eingerichtet. Ich habe festgestellt, dass das Problem bei jedem ähnlichen ScriptAlias auftritt:
# Gitolite
ScriptAlias /git/ /path/to/gitolite-shell/
ScriptAlias /gitmob/ /path/to/gitolite-shell/
# My test
ScriptAlias /test/ /path/to/test/script/
Beachten Sie, dass /path/to/test/script eine Datei und kein Verzeichnis ist. Dasselbe gilt für /path/to/gitolite-shell/.
Mein Testskript druckt einfach die Umgebung aus, ganz einfach:
#!/usr/bin/perl
print "Content-type:text/plain\n\n";
print "TEST\n";
@keys = sort(keys %ENV);
foreach (@keys) {
print "$_ => $ENV{$_}\n";
}
Es scheint, dass wenn ich gehe zuhttps://my.server/test/irgendeinStandort, dass alle SSLVerifyClient-Direktiven angewendet werden, die sich in Location-Blöcken befinden, die mit /test/someLocation übereinstimmen.oder einfach /irgendeinStandort.
Wenn ich die folgende Konfiguration habe:
<LocationMatch "^/f">
SSLVerifyClient require
SSLVerifyDepth 2
</LocationMatch>
Dann erfordert die folgende URL ein Client-Zertifikat:https://my.server/test/foo. Bei der folgenden URL ist dies jedoch nicht der Fall:https://my.server/test/etwasAnderes/foo
Beachten Sie, dass dies anscheinend nur für die SSL-Konfiguration gilt. Folgendes hat keinerlei Auswirkungen aufhttps://my.server/test/foo:
<LocationMatch "^/f">
Order allow,deny
Deny from all
</LocationMatch>
Allerdings blockiert es den Zugang zuhttps://my.server/foo.
Dies stellt ein großes Problem dar, wenn ich ein Projekt gleichzeitig laufen habehttps://mein.server/projekt(wofür eine SSL-Client-Zertifikatautorisierung erforderlich sein muss),UndEs gibt ein Git-Repository für dieses Projekt unterhttps://my.server/git/projectdie kein SSL-Client-Zertifikat erfordern kann. Da die URL /git/project auch mit /project- Location
Blöcken abgeglichen wird, erscheint eine solche Konfiguration nach meinen derzeitigen Erkenntnissen unmöglich.
Frage: Warum passiert das und wie löse ich mein Problem?
Letztendlich möchte ich eine SSL-Client-Zertifikatautorisierung für den gesamten Server außer /git und /someLocation verlangen, und zwar mit möglichst minimaler Konfiguration (damit ich die Konfiguration nicht jedes Mal ändern muss, wenn etwas Neues bereitgestellt oder ein neues Git-Repository hinzugefügt wird).
AktualisierenWeitere Informationen: Beachten Sie, dass in einigen Fällenhttps://mein.server/projektwird tatsächlich per Reverse-Proxy verwendet, so dass eine <Directory /path/to/project>
Direktive unmöglich ist. Wenn ich diese Anwendung mit einem SSL-Client-Zertifikat schützen möchte, muss dies zwangsläufig mit einem <Location /project>
(oder allgemeineren <Location />
) Block erfolgen.
Aktualisierung 2Ich habe dies gerade in Apache 2.4.3 getestet, mit demselben Ergebnis. Wenn dies auf einen Fehler zurückzuführen ist, ist er zumindest in zwei Versionen vorhanden.
Hinweis: Ich habe meine Frage umgeschrieben (anstatt einfach unten weitere Aktualisierungen hinzuzufügen), um meine neuen Erkenntnisse zu berücksichtigen und dies hoffentlich klarer zu machen.
Antwort1
Nach der aktuellenApache-DokumentationDies könnte ein Problem sein:
Im Serverkontext gilt es für den Client-Authentifizierungsprozess, der im Standard-SSL-Handshake verwendet wird, wenn eine Verbindung hergestellt wird. Im Verzeichniskontext erzwingt es eine SSL-Neuverhandlung mit der neu konfigurierten Client-Verifizierungsebene, nachdem die HTTP-Anforderung gelesen wurde, aber bevor die HTTP-Antwort gesendet wird.
Wie wäre es, den Kontext <Directory> anstelle von <Location> zu verwenden? Ein Eintrag für die Stammebene und der andere für den Script-Alias-Pfad: /path/to/gitolite-shell/
Aktualisieren:
Ich habe einige Ratschläge zu diesem Fall gefunden ->Frage/Antwort bei Stackoverflow