Der Apache HTTP-Server ist ein „Hochleistungs“-Netzwerk-Server, den Subversion zu seinem Vorteil nutzen kann. Über ein angepasstes Modul macht httpd Subversion-Projektarchive für Clients über das WebDAV/DeltaV-Protokoll verfügbar, welches eine Erweiterung von HTTP 1.1 ist (siehe http://www.webdav.org/ für weitere Informationen). Dieses Protokoll nimmt das allgegenwärtige HTTP-Protokoll, das der Kern des World Wide Web ist, und fügt Schreibfähigkeiten – im Besonderen, versioniertes Schreiben – hinzu. Das Ergebnis ist ein standardisiertes, robustes System, das auf geeignete Weise als Teil der Software Apache 2.0 verteilt wird, die von zahlreichen Betriebssystemen und Drittanbieter-Produkten unterstützt wird und keine Netzwerk-Administratoren benötigt, um einen weiteren speziellen Port zu öffnen. [42] Während ein Apache-Subversion-Server mehr Möglichkeiten bietet als svnserve, ist er allerdings auch etwas schwieriger einzurichten. Flexibilität geht oft mit Komplexität einher.
Viele der folgenden Erläuterungen beziehen sich auf Konfigurationsdirektiven von Apache. Obwohl ein paar Beispiele zur Verwendung dieser Direktiven gegeben werden, würde deren erschöpfende Behandlung dieses Kapitel sprengen. Das Apache-Team verfügt über hervorragende Dokumentation, die auf deren Web-Seite http://httpd.apache.org frei verfügbar ist. So befindet sich beispielsweise eine allgemeine Referenz der Konfigurationsdirektiven unter http://httpd.apache.org/docs-2.0/mod/directives.html.
Falls Sie Änderungen an den Einstellungen von Apache
vornehmen, ist es wahrscheinlich, dass sich irgendwo ein Fehler
einschleicht. Wenn Sie noch nicht mit der Protokollierung von
Apache vertraut sind, sollten sie sich damit vertraut machen. In
der Datei httpd.conf befinden sich
Direktiven, die angeben, wo auf der Platte sich die von Apache
erzeugten Zugriffs- und Fehlerprotokollierungsdateien befinden
(die Direktiven CustomLog bzw.
ErrorLog). Auch
mod_dav_svn von Subversion verwendet die
Protokollierungsschnittstelle von Apache. Sie können jederzeit
den Inhalt dieser Dateien nach Informationen durchforsten, die
eine Problemquelle aufdecken könnten, die sonst nicht
offensichtlich wäre.
Um Ihr Projektarchiv im Netz über HTTP zur Verfügung zu stellen, brauchen Sie grundsätzlich vier Komponenten, die in zwei Paketen verfügbar sind. Sie benötigen Apache httpd 2.0, das dazugelieferte DAV-Modul mod_dav, Subversion und das mitgelieferte Dateisystemmodul mod_dav_svn. Sobald Sie über all diese Komponenten verfügen, ist die Bereitstellung Ihres Projektarchivs über das Netz ganz einfach:
Inbetriebnahme von httpd 2.0 mit dem Modul mod_dav
Installation des mod_dav_svn-Backends zu mod_dav, das die Bibliotheken von Subversions für den Zugriff auf das Projektarchiv verwendet
Konfiguration Ihrer Datei
httpd.conf, um das Projektarchiv zu
exportieren (oder sichtbar zu machen)
Sie können die ersten beiden Punkte bewerkstelligen, indem
Sie entweder httpd und Subversion aus den
Quellen übersetzen oder als vorgefertigte Binärpakete auf
Ihrem System installieren. Die aktuellsten Informationen zur
Übersetzung von Subversion in Verbindung mit dem Apache
HTTP-Server sowie die Übersetzung und Konfigurierung von
Apache zu diesem Zweck finden Sie in der Datei
INSTALL in der obersten Verzeichisebene
des Quelltextes von Subversion.
Sobald alle notwendigen Komponenten auf Ihrem System
installiert sind, bleibt nur noch die Konfiguration von Apache
über seine Datei httpd.conf. Weisen Sie
Apache mit der Direktive LoadModule an,
das Modul mod_dav_svn zu laden. Diese
Direktive muss vor allen Konfigurationseinträgen in Verbindung
mit Subversion stehen. Falls Ihr Apache mit dem vorgegebenen
Aufbau installiert wurde, sollte sich das Modul
mod_dav_svn im Unterverzeichnis
modules des
Apache-Installationsverzeichnisses befinden (oft
/usr/local/apache2). Die Direktive
LoadModule hat eine einfache Syntax, wobei
ein benanntes Modul auf den Ort einer Shared-Library auf
der Platte abgebildet wird:
LoadModule dav_svn_module modules/mod_dav_svn.so
Falls mod_dav als Shared-Objekt
übersetzt wurde (statt statisch direkt in die
httpd-Binärdatei gelinkt worden zu sein),
benötigen Sie hierfür ebenfalls einen ähnlichen
LoadModule-Eintrag. Stellen Sie sicher,
dass er vor der mod_dav_svn-Zeile
steht:
LoadModule dav_module modules/mod_dav.so LoadModule dav_svn_module modules/mod_dav_svn.so
Weiter unten in der Konfigurationsdatei sollten Sie Apache
nun mitteilen, wo Sie Ihr Subversion-Projektarchiv (oder Ihre
Projektarchive) aufbewahren. Die Direktive
Location besitzt eine XML-ähnliche
Notation, beginnend mit einem öffneneden Tag, endend mit einem
schliessenden Tag und verschiedener anderer
Konfigurationsdirektiven dazwischen. Der Zweck der Direktive
Location besteht darin, Apache anzuweisen,
etwas Besonderes zu tun, falls Anfragen bearbeitet werden, die
an einen bestimmten URL oder dessen Kinder gerichtet sind. Im
Fall von Subversion möchten Sie, dass Apache die Unterstützung
für URLs, die auf versionierte Ressourcen zeigen, einfach an
die DAV-Schicht weiterleitet. Sie können Apache anweisen, die
Bearbeitung aller URLs, deren Pfadteile (der Teil des URL, der
nach dem Servernamen und der optionalen Portnummer steht) mit
/repos/ beginnen, an einen DAV-Provider
zu delegieren, dessen Projektarchiv unter
/var/svn/repository liegt, indem Sie die
folgende httpd.conf-Syntax
verwenden:
<Location /repos> DAV svn SVNPath /var/svn/repository </Location>
Falls Sie planen, mehrere Subversion-Projektarchive zu
unterstützen, die sich unterhalb eines gemeinsamen
Elternverzeichnisses auf Ihrer lokalen Platte befinden, können
Sie eine alternative Direktive,
SVNParentPath, verwenden, um auf das
gemeinsame Elternverzeichnis hinzuweisen. Wenn Sie
beispielsweise wissen, dass Sie mehrere
Subversion-Projektarchive in einem Verzeichnis
/var/svn anlegen möchten, auf die über
URLs wie http://my.server.com/svn/repos1,
http://my.server.com/svn/repos2 usw. zugegriffen
werden soll, könnten Sie die Konfigurationssyntax von
httpd.conf aus dem folgenden Beispiel
verwenden:
<Location /svn> DAV svn # any "/svn/foo" URL will map to a repository /var/svn/foo SVNParentPath /var/svn </Location>
Die Verwendung der vorangegangenen Syntax veranlasst
Apache, die Bearbeitung aller URLs, deren Pfadteil mit
/svn/ beginnt, an den
Subversion-DAV-Provider weiterzuleiten, der dann davon
ausgeht, dass alle Objekte in dem durch die
SVNParentPath-Direktive spezifizierten
Verzeichnis tatsächlich Subversion-Projektarchive sind. Dies
ist insofern eine besonders bequeme Syntax, da Sie im
Gegensatz zur Direktive SVNPath Apache
nicht neu starten müssen, wenn Sie neue Projektarchive
erstellen und über das Netz verfügbar machen.
Achten Sie beim Definieren Ihrer neuen
Location darauf, dass sie sich nicht mit
anderen bereits exportierten überschneidet. Wenn
beispielsweise Ihre Haupt-DocumentRoot nach
/www exportiert wird, sollten Sie ein
Subversion-Projektarchiv nicht in <Location
/www/repos> exportieren. Falls eine Anfrage für
den URI /www/repos/foo.c hereinkommt,
weiß Apache nicht, ob die Datei
repos/foo.c in
DocumentRoot gesucht wird oder ob es die
Herausgabe von foo.c aus dem
Projektarchiv an mod_dav_svn delegieren
soll. Das Ergebnis ist oftmals ein Fehler vom Server der Form
301 Moved Permanently.
An dieser Stelle sollten Sie ernsthaft über Berechtigungen nachdenken. Falls Sie Apache schon eine Zeit lang als Ihren regulären Web-Server in Betrieb haben, werden Sie wahrscheinlich bereits eine Ansammlung von Inhalt haben, etwa Webseiten, Skripte usw. Diese Dinge sind bereits mit einer Menge an Berechtigungen versehen, die es ihnen erlauben, mit Apache zusammen zu arbeiten, oder passender, die es Apache erlauben, mit diesen Dateien zu arbeiten. Wenn Apache als Subversion-Server eingesetzt wird, braucht er ebenfalls die richtigen Berechtigungen zum Lesen und Schreiben Ihres Subversion-Projektarchivs.
Sie werden ein Berechtigungssystem festlegen müssen, das
die Anforderungen von Subversion erfüllt, ohne dabei
bestehende Webseiten oder Skriptinstallationen zu
beeinträchtigen. Das kann bedeuten, dass die Berechtigungen
für Ihr Projektarchiv an die anderen Dinge angepasst werden
müssen, die Apache für Sie zur Verfügung stellt, oder dass Sie
die Direktiven User und
Group in httpd.conf
verwenden, um Apache mit denjenigen Benutzer- und
Gruppenkennungen laufen zu lassen, die auch das
Subversion-Projektarchiv besitzt. Es gibt keine einzig
richtige Methode, um die Berechtigungen zu vergeben, und jeder
Administrator wird bestimmte Gründe haben, um es auf eine
bestimmte Art zu tun. Seien Sie sich lediglich bewusst, dass
Probleme im Zusammenhang mit den Berechtigungen am häufigsten
übersehen werden, wenn ein Subversion-Projektarchiv für die
Verwendung mit Apache eingerichtet wird.
Falls Sie httpd.conf dergestalt
konfiguriert haben, so dass sie etwa den folgenden Eintrag
enthält:
<Location /svn> DAV svn SVNParentPath /var/svn </Location>
kann die Welt „anonym“ auf Ihr Projektarchiv
zugreifen. Bis Sie Authentifizierungs- und
Autorisierungsrichtlinien konfiguriert haben, sind die über
die Direktive Location zur Verfügung
gestellten Projektarchive allgemein für jedermann zugreifbar.
Mit anderen Worten:
Jeder kann mit einem Subversion-Client eine Arbeitskopie eines Projektarchiv-URLs (oder irgendeins der Unterverzeichnisse) auschecken.
Jeder kann interaktiv die letzte Revision des Projektarchivs durchstöbern, indem der Projektarchiv-URL einfach mit einem Web-Browser geöffnet wird.
Jeder kann an das Projektarchiv übergeben.
Natürlich kann es sein, dass Sie schon längst ein
pre-commit Hook-Skript bereitgestellt
haben, um Übergaben zu verhindern (siehe „Erstellen von Projektarchiv-Hooks“). Sie werden jedoch
beim Weiterlesen feststellen, dass es möglich ist, die
eingebauten Methoden von Apache zu verwenden, um den Zugriff
auf bestimmte Art und Weise einzuschränken.
Die einfachste Methode, einen Client zu authentifizieren geht über den HTTP-Basic-Authentifizierungsmechanismus, der einfach einen Benutzernamen und ein Passwort verwendet, um sicherzustellen, das ein Benutzer auch derjenige ist, für den er sich ausgibt. Apache stellt ein Dienstprogramm zur Verwaltung der Liste zulässiger Benutzernanen und Passwörter namens htpasswd zur Verfügung. Lassen Sie uns Sally und Harry die Berechtigung zur Übergabe erteilen. Zunächst müssen wir sie der Passwortdatei hinzufügen:
$ ### Beim 1. Mal: -c verwenden, um die Datei anzulegen $ ### -m für die sicherere MD5-Verschlüsselung des Passworts verwenden $ htpasswd -cm /etc/svn-auth-file harry New password: ***** Re-type new password: ***** Adding password for user harry $ htpasswd -m /etc/svn-auth-file sally New password: ******* Re-type new password: ******* Adding password for user sally $
Als nächstes müssen Sie innerhalb Ihres
Location-Blocks ein paar weitere
httpd.conf-Directiven hizufügen, um
Apache zu sagen, was mit Ihrer neuen Passwortdatei zu tun
ist. Die Direktive AuthType spezifiziert
den Typ des zu verwendenden Authentifizierungssystems. In
diesem Fall möchten wir das
Basic-Authentifizierungssystem
spezifizieren. AuthName ist ein
beliebiger Name, den Sie Ihrer Authentifizierungsdomäne
geben. Die meisten Browser zeigen diesen Namen in einem
Dialog an, wenn der Browser den Benutzer nach seinem Namen
und dem Passwort fragt. Verwenden Sie schließlich die
Direktive AuthUserFile, um den Ort der
Passwortdatei zu spezifizieren, die sie mit
htpasswd erstellt haben.
Nachdem Sie diese Direktiven hinzugefügt haben, sollte
Ihr <Location>-Block etwa so
aussehen:
<Location /svn> DAV svn SVNParentPath /var/svn AuthType Basic AuthName "Subversion repository" AuthUserFile /etc/svn-auth-file </Location>
Dieser <Location>-Block ist
noch unvollständig und bewirkt noch nichts sinnvolles. Er
teilt Apache lediglich mit, dass es sich den Benutzernamen
und das Passwort vom Subversion-Client besorgen soll, falls
eine Autorisierung benötigt wird. Was hier jedoch noch
fehlt, sind Direktiven, die Apache sagen,
welche Arten von Client-Anfragen eine
Autorisierung erfordern. Überall dort wo eine Autorisierung
verlangt wird, erwartet Apache auch eine Authentifizierung.
Das Einfachste ist es, alle Anfragen zu schützen. Durch
Hinzufügen von Require valid-user wird
Apache mitgeteilt, dass alle Anfragen einen
authentifizierten Benutzer erfordern:
<Location /svn> DAV svn SVNParentPath /var/svn AuthType Basic AuthName "Subversion repository" AuthUserFile /etc/svn-auth-file Require valid-user </Location>
Stellen Sie sicher, dass Sie für weitere Details zur
Require-Directive und anderen Wegen,
Autorisierungsrichtlinien festzulegen, den nächsten
Abschnitt („Autorisierungsoptionen“)
lesen.
Ein Wort zur Warnung: HTTP-Basic-Auth-Passwörter werden nahezu im Klartext durch das Netz geschickt und sind deshalb in höchstem Maße unsicher.
Eine weitere Option besteht darin, statt der Basic-Authentifizierung die Digest-Authentifizierung zu verwenden. Digest-Authentifizierung erlaubt es dem Server, die Identität des Clients zu bestätigen, ohne das Passwort als Klartext durch das Netz zu schicken. Unter der Voraussetzung, dass sowohl dem Client als auch dem Server das Passwort des Benutzers bekannt ist, können sie verifizieren, dass das Passwort dasselbe ist, indem sie eine Hashfunktion auf ein Einweg-Informationshäppchen anwenden. Der Server sendet eine kleine zufällige Zeichenkette an den Client. Der Client verwendet das Passwort des Benutzers, um die Zeichenkette zu hashen, und der Server prüft dann, ob der gehashte Wert dem erwarteten Ergebnis entspricht.
Es ist auch ziemlich einfach, Apache für die Digest-Authentifizierung zu konfigurieren und lediglich eine kleine Abweichung des vorangegangenen Beispiels. Für weitere Einzelheiten wird die Dokumentation zu Apache empfohlen.
<Location /svn> DAV svn SVNParentPath /var/svn AuthType Digest AuthName "Subversion repository" AuthDigestDomain /svn/ AuthUserFile /etc/svn-auth-file Require valid-user </Location>
Falls Sie maximale Sicherheit anstreben, ist ein
asymmetrisches Kryptosystem das Mittel der Wahl. Am besten
solte eine Art der SSL-Verschlüsselung eingesetzt werden, so
dass Clients sich über https:// statt
http:// authentifizieren; als
Minimallösung können Sie Apache so einstellen, dass ein
selbstsigniertes Server-Zertifikat verwendet wird.
[43]
Wie das bewerkstelligt wird, ist der Dokumentation von
Apache (und OpenSSL) zu entnehmen.
Unternehmen, die ihre Projektarchive für den Zugriff von außerhalb der Firewall freigeben müssen, sollten sich bewusst sein, dass Unbefugte den Netzverkehr „abhören“ könnten. SSL lässt diese Art unerwünschte Aufmerksamkeit weniger anfällig für heikle Datenlecks werden.
Ist ein Subversion-Client für die Verwendung von OpenSSL
übersetzt worden, ist er in der Lage, mit einem
Apache-Server über https://-URLs zu
kommunizieren. Die vom Subversion-Client verwendete
Neon-Bibliothek kann nicht nur Server-Zertifikate
zertifizieren, sondern nach Aufforderung auch
Client-Zertifikate liefern. Wenn der Client und der Server
SSL-Zertifikate ausgetauscht und sich gegenseitig
erfolgreich authentifiziert haben, wird jede weitere
Kommunikation durch einen Sitzungsschlüssel
verschlüsselt.
Es würde den Rahmen dieses Buches sprengen, wenn beschrieben würde, wie Client- und Server-Zertifikate erzeugt werden und wie Apache für ihre Verwendung konfiguriert wird. Viele andere Bücher, darunter Apaches eigene Dokumentation, erläutern diese Aufgabe. Was wir an dieser Stelle jedoch behandeln können, ist die Verwaltung der Client- und Server-Zertifikate durch einen gewöhnlichen Subversion-Client.
Wenn über https:// mit Apache
gesprochen wird, kann ein Subversion-Client zwei
unterschiedliche Arten von Informationen empfangen:
Ein Server-Zertifikat
Eine Anfrage nach einem Client-Zertifikat
Wenn der Client ein Server-Zertifikat empfängt, muss er sicherstellen, dass er dem Zertifikat vertrauen kann: handelt es sich bei dem Server wirklich um denjenigen, fűr den er sich ausgibt? Die OpenSSL-Bibliothek macht das, indem der Unterzeichner des Server-Zertifikats, die sogenannte Certificate Authority (CA), oder Zertifizierungsstelle, untersucht wird. Falls OpenSSL der CA nicht automatisch vertrauen kann, oder falls ein anderes Problem auftaucht (etwa ein abgelaufenes Zertifikat oder ein nicht übereinstimmender Rechnername), fragt Sie der Subversion-Kommandozeilenclient, ob Sie dem Server-Zertifikat dennoch vertrauen möchten:
$ svn list https://host.example.com/repos/project Fehler bei der Validierung des Serverzertifikats für »https://host.example.com:443«: - Das Zertifikat ist nicht von einer vertrauenswürdigen Instanz ausgestellt Überprüfen Sie den Fingerabdruck, um das Zertifikat zu validieren! Zertifikats-Informationen: - Hostname: host.example.com - Gültig: von Jan 30 19:23:56 2004 GMT bis Jan 30 19:23:56 2006 GMT - Aussteller: CA, example.com, Sometown, California, US - Fingerabdruck: 7d:e1:a9:34:33:39:ba:6a:e9:a5:c4:22:98:7b:76:5c:92:a0:9c:7b Ve(r)werfen, (t)emporär akzeptieren oder (p)ermanent akzeptieren?
Dieser Dialog sollte Ihnen bekannt vorkommen; im
Wesentlichen ist es dieselbe Frage, die Sie wahrscheinlich
bei Ihrem Web-Browser gesehen haben (der auch bloß ein
weiterer HTTP-Client ist, so wie Subversion). Falls Sie die
Option (p)ermanent
auswählen, wird das Server-Zertifikat in Ihrem privaten
Laufzeit-auth/-Bereich
zwischengespeichert, ebenso wie Ihr Benutzername und
Passwort (siehe „Zwischenspeicherung der Client-Zugangsdaten“). Falls es
zwischengespeichert ist, wird Subversion diesem Zertifikat
bei künftigen Protokollverhandlungen vertrauen.
Ihre Laufzeit-Datei servers
ermöglicht es Ihrem Client auch, automatisch bestimmten CAs
zu vertrauen, entweder global oder pro Host. Setzen Sie die
Variable ssl-authority-files auf eine
durch Semikolons getrennte Liste PEM-kodierter
CA-Zertifikate:
[global] ssl-authority-files = /path/to/CAcert1.pem;/path/to/CAcert2.pem
Viele OpenSSL-Installationen besitzen auch eine
vordefinierte Menge von „Standard“-CAs, denen
nahezu allgemein vertraut wird. Damit der Subversion-Client
diesen Standard-Zertifizierungsstellen automatisch vertraut,
setzen Sie die Variable
ssl-trust-default-ca auf
true.
Bei der Kommunikation mit Apache kann ein Subversion-Client die Aufforderung erhalten, ein Client-Zertifikat vorzulegen. Apache ersucht den Client, sich zu identifizieren; ist der Client wirklich derjenige, als der er sich ausgibt? Wenn alles richtig funktioniert, schickt der Client ein privates Zertifikat zurück, das von einer CA signiert wurde, der Apache vertraut. Für gewöhnlich wird ein Client-Zertifikat, durch ein lokales Passwort geschützt, verschlüsselt auf Platte gespeichert. Wenn Subversion diese Aufforderung erhält, fragt es Sie nach dem Pfad zum Zertifikat und dem Passwort:
$ svn list https://host.example.com/repos/project Anmeldebereich: https://host.example.com:443 Client Zertifikatsdatei: /path/to/my/cert.p12 Passphrase für »/path/to/my/cert.p12«: ******** …
Beachten Sie, dass das Client-Zertifikat eine „p12“-Datei ist. Um ein Client-Zertifikat mit Subversion verwenden zu können, muss es im PKCS#12-Format sein, was einem portablen Standard entspricht. Die meisten Web-Browser können bereits Zertifikate in diesem Format im- und exportieren. Eine weitere Option ist es, die OpenSSL-Kommandozeilenwerkzeuge zu verwenden, um bestehende Zertifikate in PKCS#12 zu überführen.
Auch hier erlaubt Ihnen die Laufzeitdatei
servers, diese Aufforderung pro Host zu
automatisieren. Diese Informationen lassen sich für sich
oder gemeinsam in Laufzeitvariablen beschreiben:
[groups] examplehost = host.example.com [examplehost] ssl-client-cert-file = /path/to/my/cert.p12 ssl-client-cert-password = somepassword
Sobald die Variablen
ssl-client-cert-file und
ssl-client-cert-password gesetzt sind,
kann der Subversion-Client automatisch auf eine Anforderung
eines Client-Zertifikats antworten, ohne eine Eingabe von
Ihnen zu verlangen.
[44]
An diesem Punkt haben Sie die Authentifizierung eingerichtet, nicht jedoch die Autorisierung. Apache kann Clients auffordern und Identitäten bestätigen, aber es wurde ihm noch nicht gesagt, wie er den Zugriff von Clients mit diesen Identitäten erlauben oder einschränken soll. Dieser Abschnitt beschreibt zwei Strategien, um den Zugriff auf Ihre Projektarchive zu kontrollieren.
Die einfachste Form der Zugriffskontrolle besteht darin, bestimmten Nutzern entweder nur Lesezugriff oder Lese- und Schreibzugriff auf ein Projektarchiv zu gewähren.
Sie lönnen den Zugriff auf alle Operationen im
Projektarchiv einschränken, indem Sie die Direktive
Require valid-user Ihrem
<Location>-Block hinzufügen. Für
unser vorheriges Beispiel würde das bedeuten, dass es nur
Clients, die sich entweder als harry oder
sally ausgeben und das korrekte Passwort
für den entsprechenden Nutzernamen liefern, erlaubt wird,
irgendetwas mit dem Subversion-Projektarchiv zu
machen:
<Location /svn> DAV svn SVNParentPath /var/svn # wie ein Nutzer authentifiziert wird AuthType Basic AuthName "Subversion repository" AuthUserFile /path/to/users/file # nur authentifizierte Nutzer dürfen an das Projektarchiv Require valid-user </Location>
Manchmal müssen Sie gar nicht so ein strenges Regiment
führen. So erlaubt beispielsweise das eigene Projektarchiv
von Subversion unter http://svn.collab.net/repos/svn allen auf der Welt
lesende Operationen (wie etwa das Auschecken von
Arbeitskopien und das Stöbern mit einem Web-Browser),
beschränkt jedoch Schreiboperationen auf authentifiziere
Nutzer. Um diese abgestufte Einschränkung einzurichten,
können Sie die Konfigurationsdirektiven
Limit und LimitExcept
verwenden. Ähnlich der Direktive Location
haben diese Blöcke Start- und End-Tags, die Sie innerhalb
Ihres <Location>-Blocks
unterbringen.
Die für die Ditrektiven Limit und
LimitExcept verfügbaren Parameter sind
HTTP-Anfrage-Typen, die durch diesen Block berührt werden.
Falls Sie beispielsweise alle Zugriffe auf Ihr Projektarchiv
unterbinden möchten, außer die momentan unterstützten
Leseoperationen, so würden Sie die Direktive
LimitExcept mit den Anfrage-Parametern
GET, PROPFIND,
OPTIONS und REPORT
verwenden. Dann wird die eben erwähnte Direktive
Require valid-user im
<LimitExcept>-Block statt innerhalb
des <Location>-Blocks eingefügt.
<Location /svn>
DAV svn
SVNParentPath /var/svn
# wie ein Nutzer authentifiziert wird
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
# nur authentifizierte Nutzer dürfen mehr als die angegebenen Operationen
<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
</LimitExcept>
</Location>
Dies sind nur ein paar einfache Beispiele. Für tiefer
gehende Informationen über Apaches Zugriffskontrolle und die
Direktive Require sollten Sie im
Abschnitt Security der Apache
Lehrbuchsammlung unter http://httpd.apache.org/docs-2.0/misc/tutorials.html
nachlesen.
Es ist möglich, mithilfe eines zweiten Apache http-Moduls – mod_authz_svn – detailliertere Zugriffsrechte einzurichten. Dieses Modul schnappt sich die verschiedenen undurchsichtigen URLs, die vom Client zum Server gereicht werden, fordert mod_dav_svn auf, sie zu dekodieren, und unterbindet dann möglicherweise Anforderungen entsprechend in einer Konfigurationsdatei definierter Zugriffsregeln.
Falls Sie Subversion aus Quellcode gebaut haben, ist
mod_authz_svn automatisch neben
mod_dav_svn gebaut und installiert
worden. Viele binäre Distributionen installieren es
ebenfalls automatisch. Um die korrekte Installation zu
überprüfen, müssen Sie sicherstellen, dass es direkt hinter
der LoadModule-Directive von
mod_dav_svn in
httpd.conf auftaucht:
LoadModule dav_module modules/mod_dav.so LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so
Zur Aktivierung dieses Moduls müssen Sie Ihren
Location-Block mit der Direktive
AuthzSVNAccessFile konfigurieren, die
eine Datei mit Zugriffsrichtlinien für Pfade in Ihren
Projektarchiven bezeichnet. (Gleich werden wir auf das
Format dieser Datei eingehen.)
Da Apache flexibel ist, haben Sie die Wahl, Ihren Block auf eine von drei Arten zu konfigurieren. Fangen Sie mit der Auswahl eines dieser grundlegenden Konfigurationsmuster an. (Die folgenden Beispiele sind sehr einfach gehalten; sehen Sie sich die mitgelieferte Apache-Dokumentation an, um wesentlich mehr Einzelheiten zu den Authentifizierungs- und Autorisierungsoptionen von Apache zu erfahren.)
Der einfachste Block besteht aus einem völlig offenen Zugang. In diesem Szenario schickt Apache niemals Aufforderungen zur Authentifizierung, so dass alle Benutzer als „anonymous“ behandelt werden. (Siehe Beispiel 6.1, „Eine Beispielkonfiguration für anonymen Zugang“.)
Beispiel 6.1. Eine Beispielkonfiguration für anonymen Zugang
<Location /repos>
DAV svn
SVNParentPath /var/svn
# unsere Zugangsrichtlinie
AuthzSVNAccessFile /path/to/access/file
</Location>
Am anderen Ende der Paranoia-Skala können Sie Ihren
Block so konfigurieren, dass sich jedermann authentifizieren
muss. Alle Clients müssen sich ausweisen. Ihr Block verlangt
eine unbedingte Authentifizierung mit der Direktive
Require valid-user; diese Direktive
definiert auch, wie die Authentifizierung erfolgen soll.
(Siehe Beispiel 6.2, „Eine Beispielkonfiguration für authentifizierten Zugang“.)
Beispiel 6.2. Eine Beispielkonfiguration für authentifizierten Zugang
<Location /repos>
DAV svn
SVNParentPath /var/svn
# unsere Zugangsrichtlinie
AuthzSVNAccessFile /path/to/access/file
# nur authentifizierte Benutzer haben Zugriff auf das Projektarchiv
Require valid-user
# wie ein Benutzer zu authentifizieren ist
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
</Location>
Ein drittes sehr verbreitetes Muster ist es, eine
Kombination aus authentifizierten und anonymen Zugriff zu
erlauben. So möchten beispielsweise viele Administratoren
den Lesezugriff auf bestimmte Verzeichnisse des
Projektarchivs für anonyme Benutzer freigeben, während
in heiklen Bereichen nur authentifizierte Benutzer lesen
(oder schreiben) dürfen. Bei dieser Einstellung greifen alle
Benutzer zunächst anonym auf das Projektarchiv zu. Falls
Ihre Zugangsrichtlinien an einer Stelle einen echten
Benutzernamen erfordern sollte, fordert Apache den Client
auf, sich zu authentifizieren. Eingestellt wird dieses
Verhalten mit den gemeinsam verwendeten Direktiven
Satisfy Any sowie Require
valid-user. (Siehe Beispiel 6.3, „Eine Beispielkonfiguration für gemischten
authentifizierten/anonymen Zugang“.)
Beispiel 6.3. Eine Beispielkonfiguration für gemischten authentifizierten/anonymen Zugang
<Location /repos>
DAV svn
SVNParentPath /var/svn
# unsere Zugangsrichtlinie
AuthzSVNAccessFile /path/to/access/file
# erst anonymen Zugang, nach Bedarf
# echte Authentifizierung
Satisfy Any
Require valid-user
# wie ein Benutzer zu authentifizieren ist
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
</Location>
Sobald Sie sich für eine dieser drei grundsätzlichen
httpd.conf-Vorlagen entschieden haben,
müssen Sie Ihre Datei mit den Zugangsregeln für bestimmte
Pfade innerhalb des Projektarchivs erstellen. Wir
beschreiben später in „Path-Based Authorization“ wie das
funktioniert.
Das Modul mod_dav_svn unternimmt
einen hohen Arbeitsaufwand, um sicherzustellen, dass Daten,
die Sie als „nicht lesbar“ markiert haben,
nicht versehentlich nach draußen geraten. Das bedeutet, dass
es aufmerksam alle Pfade überwachen muss, die von Befehlen
wie svn checkout und svn
update zurückgegeben werden. Begegnen diese
Befehle einem Pfad, der aufgrund einer
Autorisierungsrichtlinie nicht lesbar ist, wird dieser Pfad
üblicherweise vollständig unterdrückt. Im Fall der
Historien- oder Umbenennungsverfolgung, z.B. mit einem
Befehl wie svn cat -r OLD foo.c auf
einer Datei, die vor langer Zeit umbenannt wurde, bleibt die
Umbenennungsverfolgung einfach stehen, wenn einer der
früheren Namen des Objektes als lesebeschränkt erkannt
wird.
All diese Pfadüberprüfungen können manchmal sehr teuer
werden, besonders mit svn log. Wenn eine
Liste mit Revisionen erstellt wird, sieht der Server bei
jedem geänderten Pfad in jeder Revision nach, ob er lesbar
ist. Falls ein nicht lesbarer Pfad entdeckt wird, taucht er
in der Liste der geänderten Pfade dieser Revision nicht auf
(normalerweise sichtbar mit der Option
--verbose), und die gesamte
Protokollnachricht wird unterdrückt. Es bedarf wohl keiner
Erwähnung, dass dies bei Revisionen, die eine große Anzahl
an Pfaden betreffen, sehr zeitaufwändig sein kann. Das ist
der Preis für Sicherheit: selbst wenn Sie überhaupt kein
Modul wie mod_authz_svn konfiguriert
haben, fordert das Modul mod_dav_svn
Apache httpd auf,
Autorisierungsüberprüfungen für jeden Pfad vorzunehmen. Das
Modul mod_dav_svn weiß nicht, welche
Autorisierungsmodule installiert wurden, also kann es
lediglich Apache auffordern, all das aufzurufen, was
vorhanden sein könnte.
Auf der anderen Seite gibt es auch eine Art Notausgang,
der es Ihnen erlaubt, Sicherheitsmerkmale gegen
Geschwindigkeit zu tauschen. Falls Sie nicht irgendeine Art
verzeichnisbasierter Auorisierung durchsetzen möchten (d.h.,
mod_authz_svn oder ähnliche Module nicht
verwenden), können Sie die gesamte Pfadüberprüfung
abstellen. Verwenden Sie die Direktive
SVNPathAuthz in Ihrer Datei
httpd.conf wie in Beispiel 6.4, „Abstellen aller Pfadüberprüfungen“
gezeigt.
Beispiel 6.4. Abstellen aller Pfadüberprüfungen
<Location /repos>
DAV svn
SVNParentPath /var/svn
SVNPathAuthz off
</Location>
Standardmäßig steht die Direktive
SVNPathAuthz auf „on“. Auf
„off“ gesetzt, wird die gesamte pfadbasierte
Autorisierungsüberprüfung abgestellt.
mod_dav_svn beendet den Aufruf von
Autorisierungsüberprüfungen für jeden entdeckten
Pfad.
We've covered most of the authentication and authorization options for Apache and mod_dav_svn. But there are a few other nice features that Apache provides.
One of the most useful benefits of an Apache/WebDAV
configuration for your Subversion repository is that the
youngest revisions of your versioned files and directories
are immediately available for viewing via a regular web
browser. Since Subversion uses URLs to identify versioned
resources, those URLs used for HTTP-based repository access
can be typed directly into a web browser. Your browser will
issue an HTTP GET request for that URL;
based on whether that URL represents a versioned directory
or file, mod_dav_svn will respond with a
directory listing or with file contents.
Since the URLs do not contain any information about which version of the resource you wish to see, mod_dav_svn will always answer with the youngest version. This functionality has the wonderful side effect that you can pass around Subversion URLs to your peers as references to documents, and those URLs will always point at the latest manifestation of that document. Of course, you can even use the URLs as hyperlinks from other web sites, too.
When browsing a Subversion repository, the web browser
gets a clue about how to render a file's contents by
looking at the Content-Type: header
returned in Apache's response to the
HTTP GET request. The value of this
header is some sort of MIME type. By default, Apache will
tell the web browsers that all repository files are of
the „default“ MIME type,
typically text/plain. This can be
frustrating, however, if a user wishes repository files to
render as something more meaningful—for example,
it might be nice to have a foo.html file
in the repository actually render as HTML when
browsing.
To make this happen, you need only to make sure that
your files have the
proper svn:mime-type set. We discuss this
in more detail in
„Datei-Inhalts-Typ“,
and you can even configure your client to automatically
attach proper svn:mime-type properties
to files entering the repository for the first time; see
„Automatisches Setzen von Eigenschaften“.
So in our example, if one were to set
the svn:mime-type property
to text/html on
file foo.html, Apache would
properly tell your web browser to render the file as HTML.
One could also attach proper image/*
MIME-type properties to image files and ultimately get an
entire web site to be viewable directly from a repository!
There's generally no problem with this, as long as the web
site doesn't contain any dynamically generated
content.
You generally will get more use out of URLs to
versioned files—after all, that's where the
interesting content tends to lie. But you might have
occasion to browse a Subversion directory listing, where
you'll quickly note that the generated HTML used to
display that listing is very basic, and certainly not
intended to be aesthetically pleasing (or even
interesting). To enable customization of these directory
displays, Subversion provides an XML index feature. A
single SVNIndexXSLT directive in your
repository's Location block of
httpd.conf will
instruct mod_dav_svn to generate XML
output when displaying a directory listing, and to
reference the XSLT stylesheet of your choice:
<Location /svn> DAV svn SVNParentPath /var/svn SVNIndexXSLT "/svnindex.xsl" … </Location>
Using the SVNIndexXSLT directive and
a creative XSLT stylesheet, you can make your directory
listings match the color schemes and imagery used in other
parts of your web site. Or, if you'd prefer, you can use
the sample stylesheets provided in the Subversion source
distribution's tools/xslt/ directory.
Keep in mind that the path provided to the
SVNIndexXSLT directory is actually a URL
path—browsers need to be able to read your
stylesheets to make use of them!
If you're serving a collection of repositories from a
single URL via the SVNParentPath
directive, then it's also possible to have Apache display
all available repositories to a web browser. Just
activate the SVNListParentPath
directive:
<Location /svn> DAV svn SVNParentPath /var/svn SVNListParentPath on … </Location>
If a user now points her web browser to the
URL http://host.example.com/svn/, she'll
see a list of all Subversion repositories sitting
in /var/svn. Obviously, this can
be a security problem, so this feature is turned off by
default.
Because Apache is an HTTP server at heart, it contains
fantastically flexible logging features. It's beyond the
scope of this book to discuss all of the ways logging can be
configured, but we should point out that even the most
generic httpd.conf file will cause
Apache to produce two logs:
error_log
and access_log. These logs may appear
in different places, but are typically created in the
logging area of your Apache installation. (On Unix, they
often live
in /usr/local/apache2/logs/.)
The error_log describes any internal
errors that Apache runs into as it works.
The access_log file records every
incoming HTTP request received by Apache. This makes it
easy to see, for example, which IP addresses Subversion
clients are coming from, how often particular clients use
the server, which users are authenticating properly, and
which requests succeed or fail.
Unfortunately, because HTTP is a stateless protocol,
even the simplest Subversion client operation generates
multiple network requests. It's very difficult to look at
the access_log and deduce what the
client was doing—most operations look like a series
of cryptic PROPPATCH, GET,
PUT, and REPORT
requests. To make things worse, many client operations send
nearly identical series of requests, so it's even harder to
tell them apart.
mod_dav_svn, however, can come to your aid. By activating an „operational logging“ feature, you can ask mod_dav_svn to create a separate log file describing what sort of high-level operations your clients are performing.
To do this, you need to make use of
Apache's CustomLog directive (which is
explained in more detail in Apache's own documentation).
Be sure to invoke this
directive outside your
Subversion Location block:
<Location /svn>
DAV svn
…
</Location>
CustomLog logs/svn_logfile "%t %u %{SVN-ACTION}e" env=SVN-ACTION
In this example, we're asking Apache to create a special
logfile, svn_logfile, in the standard
Apache logs directory.
The %t and %u
variables are replaced by the time and username of the
request, respectively. The really important parts are the
two instances of SVN-ACTION.
When Apache sees that variable, it substitutes the value of
the SVN-ACTION environment variable,
which is automatically set by mod_dav_svn
whenever it detects a high-level client action.
So, instead of having to interpret a
traditional access_log like
this:
[26/Jan/2007:22:25:29 -0600] "PROPFIND /svn/calc/!svn/vcc/default HTTP/1.1" 207 398 [26/Jan/2007:22:25:29 -0600] "PROPFIND /svn/calc/!svn/bln/59 HTTP/1.1" 207 449 [26/Jan/2007:22:25:29 -0600] "PROPFIND /svn/calc HTTP/1.1" 207 647 [26/Jan/2007:22:25:29 -0600] "REPORT /svn/calc/!svn/vcc/default HTTP/1.1" 200 607 [26/Jan/2007:22:25:31 -0600] "OPTIONS /svn/calc HTTP/1.1" 200 188 [26/Jan/2007:22:25:31 -0600] "MKACTIVITY /svn/calc/!svn/act/e6035ef7-5df0-4ac0-b811-4be7c823f998 HTTP/1.1" 201 227 …
you can peruse a much more
intelligible svn_logfile like
this:
[26/Jan/2007:22:24:20 -0600] - get-dir /tags r1729 props [26/Jan/2007:22:24:27 -0600] - update /trunk r1729 depth=infinity send-copyfrom-args [26/Jan/2007:22:25:29 -0600] - status /trunk/foo r1729 depth=infinity [26/Jan/2007:22:25:31 -0600] sally commit r1730
For an exhaustive list of all actions logged, see „Protokollierung auf hoher Ebene“.
One of the nice advantages of using Apache as a Subversion server is that it can be set up for simple replication. For example, suppose that your team is distributed across four offices around the globe. The Subversion repository can exist only in one of those offices, which means the other three offices will not enjoy accessing it—they're likely to experience significantly slower traffic and response times when updating and committing code. A powerful solution is to set up a system consisting of one master Apache server and several slave Apache servers. If you place a slave server in each office, users can check out a working copy from whichever slave is closest to them. All read requests go to their local slave. Write requests get automatically routed to the single master server. When the commit completes, the master then automatically „pushes“ the new revision to each slave server using the svnsync replication tool.
This configuration creates a huge perceptual speed increase for your users, because Subversion client traffic is typically 80–90% read requests. And if those requests are coming from a local server, it's a huge win.
In this section, we'll walk you through a standard setup of this single-master/multiple-slave system. However, keep in mind that your servers must be running at least Apache 2.2.0 (with mod_proxy loaded) and Subversion 1.5 (mod_dav_svn).
First, configure your master server's
httpd.conf file in the usual way.
Make the repository available at a certain URI location,
and configure authentication and authorization however
you'd like. After that's done, configure each of your
„slave“ servers in the exact same way, but
add the special SVNMasterURI directive
to the block:
<Location /svn> DAV svn SVNPath /var/svn/repos SVNMasterURI http://master.example.com/svn … </Location>
This new directive tells a slave server to redirect all write requests to the master. (This is done automatically via Apache's mod_proxy module.) Ordinary read requests, however, are still serviced by the slaves. Be sure that your master and slave servers all have matching authentication and authorization configurations; if they fall out of sync, it can lead to big headaches.
Next, we need to deal with the problem of infinite recursion. With the current configuration, imagine what will happen when a Subversion client performs a commit to the master server. After the commit completes, the server uses svnsync to replicate the new revision to each slave. But because svnsync appears to be just another Subversion client performing a commit, the slave will immediately attempt to proxy the incoming write request back to the master! Hilarity ensues.
The solution to this problem is to have the master
push revisions to a different
<Location> on the slaves. This
location is configured to not proxy
write requests at all, but to accept normal commits from
(and only from) the master's IP address:
<Location /svn-proxy-sync> DAV svn SVNPath /var/svn/repos Order deny,allow Deny from all # Only let the server's IP address access this Location: Allow from 10.20.30.40 … </Location>
Now that you've configured
your Location blocks on master and
slaves, you need to configure the master to replicate to
the slaves. This is done the usual way—
using svnsync. If you're not familiar
with this tool, see
„Projektarchiv Replikation“ for
details.
First, make sure that each slave repository has a
pre-revprop-change hook script which
allows remote revision property changes. (This is
standard procedure for being on the receiving end of
svnsync.) Then log into the master
server and configure each of the slave repository URIs to
receive data from the master repository on the local
disk:
$ svnsync init http://slave1.example.com/svn-proxy-sync file://var/svn/repos Copied properties for revision 0. $ svnsync init http://slave2.example.com/svn-proxy-sync file://var/svn/repos Copied properties for revision 0. $ svnsync init http://slave3.example.com/svn-proxy-sync file://var/svn/repos Copied properties for revision 0. # Perform the initial replication $ svnsync sync http://slave1.example.com/svn-proxy-sync Transmitting file data .... Committed revision 1. Copied properties for revision 1. Transmitting file data ....... Committed revision 2. Copied properties for revision 2. … $ svnsync sync http://slave2.example.com/svn-proxy-sync Transmitting file data .... Committed revision 1. Copied properties for revision 1. Transmitting file data ....... Committed revision 2. Copied properties for revision 2. … $ svnsync sync http://slave3.example.com/svn-proxy-sync Transmitting file data .... Committed revision 1. Copied properties for revision 1. Transmitting file data ....... Committed revision 2. Copied properties for revision 2. …
After this is done, we configure the master server's
post-commit hook script to invoke
svnsync on each slave server:
#!/bin/sh # Post-commit script to replicate newly committed revision to slaves svnsync sync http://slave1.example.com/svn-proxy-sync > /dev/null 2>&1 svnsync sync http://slave2.example.com/svn-proxy-sync > /dev/null 2>&1 svnsync sync http://slave3.example.com/svn-proxy-sync > /dev/null 2>&1
The extra bits on the end of each line aren't
necessary, but they're a sneaky way to allow the sync
commands to run in the background so that the Subversion
client isn't left waiting forever for the commit to
finish. In addition to this
post-commit hook, you'll need a
post-revprop-change hook as well so
that when a user, say, modifies a log message, the slave
servers get that change also:
#!/bin/sh
# Post-revprop-change script to replicate revprop-changes to slaves
REV=${2}
svnsync copy-revprops http://slave1.example.com/svn-proxy-sync ${REV} > /dev/null 2>&1
svnsync copy-revprops http://slave2.example.com/svn-proxy-sync ${REV} > /dev/null 2>&1
svnsync copy-revprops http://slave3.example.com/svn-proxy-sync ${REV} > /dev/null 2>&1
The only thing we've left out here is what to do about
locks. Because locks are strictly enforced by the master
server (the only place where commits happen), we don't
technically need to do anything. Many teams don't use
Subversion's locking features at all, so it may be a
nonissue for you. However, if lock changes aren't
replicated from master to slaves, it means that clients
won't be able to query the status of locks
(e.g., svn status -u will show no
information about repository locks). If this bothers you,
you can write post-lock and
post-unlock hook scripts that run
svn lock and svn
unlock on each slave machine, presumably through
a remote shell method such as SSH. That's left as an
exercise for the reader!
Your master/slave replication system should now be ready to use. A couple of words of warning are in order, however. Remember that this replication isn't entirely robust in the face of computer or network crashes. For example, if one of the automated svnsync commands fails to complete for some reason, the slaves will begin to fall behind. For example, your remote users will see that they've committed revision 100, but then when they run svn update, their local server will tell them that revision 100 doesn't yet exist! Of course, the problem will be automatically fixed the next time another commit happens and the subsequent svnsync is successful—the sync will replicate all waiting revisions. But still, you may want to set up some sort of out-of-band monitoring to notice synchronization failures and force svnsync to run when things go wrong.
Several of the features already provided by Apache in
its role as a robust web server can be leveraged for
increased functionality or security in Subversion as well.
The Subversion client is able to use SSL (the Secure Sockets
Layer, discussed earlier). If your Subversion client is
built to support SSL, it can access your Apache server
using https:// and enjoy a high-quality
encrypted network session.
Equally useful are other features of the Apache and Subversion relationship, such as the ability to specify a custom port (instead of the default HTTP port 80) or a virtual domain name by which the Subversion repository should be accessed, or the ability to access the repository through an HTTP proxy.
Finally, because mod_dav_svn is speaking a subset of the WebDAV/DeltaV protocol, it's possible to access the repository via third-party DAV clients. Most modern operating systems (Win32, OS X, and Linux) have the built-in ability to mount a DAV server as a standard network „shared folder.“ This is a complicated topic, but also wondrous when implemented. For details, read Anhang C, WebDAV und Autoversionierung.
Note that there are a number of other small tweaks one can
make to mod_dav_svn that are too obscure
to mention in this chapter. For a complete list of
all httpd.conf directives
that mod_dav_svn responds to, see
„Anweisungen“.
[42] Die hassen sowas echt.
[43] Obwohl selbstsignierte Server-Zertifikate immer noch verwundbar für einen „Man-in-the-middle“-Angriff sind, ist solch ein Angriff für einen gelegentlichen beobachter ungleich schwieriger durchzuführen als ungeschützte Passwörter abzugreifen.
[44] Sicherheitsbewusstere Leute verzichten
möglicherweise darauf, das Passwort des
Client-Zertifikats in der
servers-Laufzeitdatei
abzulegen.
[45] Back then, it was called ViewCVS.