Gentoo и системы контроля версий.

Gentoo и Subversion.

HOWTO Subversion сервер при помощи Apache2 и WebDav

Ссылка на оригинал: http://ru.gentoo-wiki.com/HOWTO Subversion сервер при помощи Apache2 и WebDav

C версии: 1.5

О чем эта статья

Данное HOWTO является вольным переводом оригинальной английской статьи. Также в статью добавленно некоторое количество отсебятины по поводу и без (надеюсь автор оригинала не знает русского и не увидит как я испохабил его несчастную статью).

Данная статья посвещена настройке сервера Subversion под Apache с применением WebDav и только ей. Информацию по клиенту и настройке автономного сервера можно найти по ссылке en:HOWTO Subversion

Предупреждение: Данная статья предусматривает, что читатель - разумный человек и не будет вешать репозиторий не на ssl хост, и вообще заботится о безопасности.

FIXME: Хорошо бы описать в чем плюсы WebDav подхода и в чем минусы

Настройка WebDav глобально, безотносительно в virtual-хостам

Apache. Компиляция без Worker MPM

Существует известная проблема при больших коммитах (commit, оффициальный перевод - "фиксация изменений", на мой взгляд длинновато) связанная с использованием апачевого (от Apache) "worker" MPM. Рекомендуется просто отключить этот MPM и скомпилировать Apache с "prefork" MPM. Для этого просто добавьте новую (или поменяйте существующую, если таковая уже есть) строчку в package.use (в случае использования Gentoo, естественно):

Файл: /etc/portage/package.use

www-servers/apache -mpm-worker mpm-prefork

После чего перекомпилируйте Апач: emerge -aDNtuv apache

Более того, пожалуйста убедитесь, что subversion скомпилированна с (use flag) apache2 и без nowebdav юзами (от use flags).

Включение SVN и WebDav модулей в Apache

Для использования WebDav и Subversion модулей их, как ни странно, необходимо включить. Делается это при помощи передачи соответсвующих опций (далее - дефайнов, от Define) Апачу при загрузке. Также, для аутентификации, вам возможно понадобится SSL (если вам так не кажется, советую подумать еще раз). Добавте следующую строчку после уже существующей APACHE2_OPTS строчки. (-D SVN_AUTHZ необходимо для использования авторизации, см. ниже)

Файл: /etc/conf.d/apache2

        APACHE2_OPTS="$APACHE2_OPTS -D SVN -D SVN_AUTHZ -D DAV -D SSL"

Создание репозиториев применительно к данной конфигурации

Необходимо, чтобы Апач имел права на запись на папку репозитория(иев), с которым(и) он должен работать. Это можно сделать двумя способами:

Лично я, переводчик, рекомендую воспользоваться комбинацией этих способов, из соображений, что права на запись могут понадобится не только Апачу, а включать страждущего пользователя в группу apache тоже как-то нехорошо, т.к. это даст доступ не только к репозиториям. Для упрощения этой задачи мною был написан следующий скрипт:

Файл: create_repository.sh

#!/bin/sh

DIR_MODE=770
FILE_MODE=660
SVN_ROOT="/var/svn"

SVN_USER="apache"
SVN_GROUP="svn"

NAME=${1:?"Usage: create_repository.sh <repository name>"}

REPO_DIR="${SVN_ROOT}/${NAME}"

svnadmin create "${REPO_DIR}"
chown "${SVN_USER}:${SVN_GROUP}" -R "${REPO_DIR}"
find "${REPO_DIR}" -type d -exec chmod ${DIR_MODE} {} +
find "${REPO_DIR}" -type f -exec chmod ${FILE_MODE} {} +

# vim: nobackup

Базовая настройка

Вместе с subversion устанавливается файл /etc/apache2/modules.d/47_mod_dav_svn.conf (в случае включенного юза apache2), в котором и содержится практически работающий конфиг (от config - настройка).

Инструкция

<Location /svn>
        DAV svn

сообщает Апачу о том, что все запросы, чей путь начинается с /svn необходимо обрабатывать при помощи WebDav модуля (Dav svn директива).

        SVNPath /путь/к/репозиторию
        SVNParentPath /путь/к/папке/с/репозиториями

В этом случае все подпапки папки, указанной в SVNParentPath директиве, будут рассматриватся как репозитории Subversion (Даже если они таковыми не являются).

Также существует возможность заставить Апач формировать список репозиториев/содержимого в них, в случае захода с обычного брузера. Для этого существует магическая опция SVNListParentPath (Правда данная опция доступна только с subversion версии 1.3, но для настоящего гентушника это все равно уже антиквариат), которую необходимо установить в on:

        SVNListParentPath on

ВАЖНО: При использовании SVNListParentPath может так случится, что вы получите 403 Forbidden, а не список репозиториев (Более подробно данный природный феномен описан здесь). Как вариант избавления, вы можете добавить в описание блока Location заключительный слэш.

        <Location /svn/>

В таком случае, вам наверняка также захочется, чтобы Апач также отлавливал и просто путь /svn . Для этого можно воспользоватся магической опцией RedirectMatch (добавив ее куда-нибудь вовне блока Location), как показанно в нижеприведенном заклинании.

        RedirectMatch ^(/svn)$ $1/

Дабы избежать ппроблем, вроде описанной тут: Resource cannot be created at the destination..., будет полезно добавить в конфиг директиву:

        SVNAutoVersioning On

Аутентификация

Стандартная

На данный момент мы, чисто теоретически, имеем работающий Апач с подключенным Сабвершеном (от Subversion). Однако любая подозрительная личность может сделать с нашим репозиторием что захочет, что естественно не входит в наши планы.

Добавление следующих строчек в /etc/apache2/modules.d/47_mod_dav_svn.conf включит базовую аутентификацию Апача

Файл: /etc/apache2/modules.d/47_mod_dav_svn.conf

        AuthType Basic
        AuthName "Subversion repository"
        AuthUserFile /var/svn/conf/svnusers
        Require valid-user
        # Тип встроенной аутентификации "Basic" посылает пароли открытым текстом, что есть небезопасно. Чтобы избежать  ситуации кражи пароля необходимо добавить следующую директиву, которая будет требовать подключения с ssl
        SSLRequireSSL

Примечание: Как несложно догадатся, для того чтобы можно было требовать ssl, его неплохо было бы включить. Как это сделать было описано выше.

Дополнение: Однако намного более завлекательным вариантом является принудительный редирект на ssl хост, т.к. не вводит среднестатистического пользователя в ступор при виде непонятной ошибки на иноземном языке

Начало общефилософского лирического отступления

Также положительным побочным действием предложенного решения является то, что если у вас стандартный ssl порт уже занят, то таким образом можно ликвидировать проблему с запоминанием номера порта, просто заходя на http, а Апач вас уже перешлет на правильный порт (при условии, что вы ему скажите это делать, естественно - болезненной самостоятельностью юниксовые сервера, по счастью, не обладают (хотя периодически и кажется, что они проявляют признаки очень вредного интеллекта, подкидывая все новые и новые гадости)))

Конец лирическому отступлению

Файл: /etc/apache2/modules.d/47_mod_dav_svn.conf

<Location /svn>
        [...]
 
        RewriteEngine On
        RewriteCond %{HTTPS} !on
        RewriteRule ^/(.*) https://%{SERVER_NAME}%{REQUEST_URI} [R]


Возможность: Чтобы ограничить доступ только по ssl, недостаточно директивы SSLRequireSSL в 47_mod_dav_svn.conf. Для этого необходимо перенести все директивы из 47_mod_dav_svn.conf в файл с дефолтным (от default - по умолчанию) виртуальным хостом для ssl - XX_mod_ssl_default-vhost.conf. Также необходимо так поменять номер этого виртуального хоста так чтобы он грузился после mod_dav (все файлы в папке /etc/apache2/conf/modules.d загружаются в алфавитном порядке). Впрочем это необходимо только тем у кого настолько древний Апач (или настолько новый, кто знает - постоянно туда-сюда эти хосты путешествуют. По моему мнению, их вообще выкинуть можно), что дефолтный хост лежит все еще в modules.d - их уже месяцов пять как переместили в vhosts.d. Остальным беспокоится не зачем - vhosts.d загружаются после modules.d

Небольшая оптимизация: Однако вместо того чтобы перемещать директивы из файла 47_mod_dav_svn.conf внутрь виртуального ssl-хоста, можно попросту проинклюдить (от include - включать (в себя)) туда целиком файл, предварительно поменяв ему расширение на что-нибуть отличное от .conf, либо вынеся вовне {{filename|modules.d}, дабы самостоятельно Апач его не разыскал. Делается это при помощи магической директивы Include с указанием абсолютного пути до желаемого файла

Начало лирического отступления о культурных особенностях индейцев Вообще-то можно указать и относительный, но стоит учитывать, что Апач - индеец и имеет несколько свои представления о том что такое "относительный путь". Для него это путь относительно истинного пути - путь ServerRoot'а - т.е. по умолчанию откуда-то от /usr/lib/apache2

Конец лирическому отступлению

Оптимизация побольше и по-глобальнее: По-умолчанию Апач грузит все конфиги в папке {{filename|modules.d} по маске {{filename|modules.d/*.conf}, так что можно немного переписать систему инклюдов, дабы разделить конфиги на обычные и продвинутые-ssl-ные. Для этого достаточно переименовать полюбившийся конфиг, в нашем случае - 47_mod_dav_svn.conf, в что-нибудь с расширением отличным от .conf (либо, как уже было предложено выше, создав отдельную папку для подобных продвинутых конфигов), к примеру в 47_mod_dav_svn.ssl-conf. Тогда достаточно будет указать в httpd.conf (или любом другом глобальном конфиге - к примеру в modules.d/40_mod_ssl.conf), внутри соответствующего блока <IfModule ssl_module>/<IfDefine SSL> следующие строчки:

        # Загрузить модули зависщие от ssl
        Include /etc/apache2/modules.d/*.ssl-conf # либо /etc/apache2/modules.ssl.d/*.conf

Анонимный доступ: Хорошо, мы добились того, что теперь при каждом запросе к subversion будет спрашиваться пароль, однако вам может захотеться, чтобы анонимные пользователи могли читать ваш труд, а то зачем все это надо? В таком случае директиву Require valid-user стоит поместить в блок <LimitExcept ...> указав в качестве параметра список операций, которые, по вашему мнению, всякие подозрительные личности без особой опасности могут производить на вашем репозитории:

        [...]
        AuthType Basic
        [...]
        # Для любых операций, кроме нижеперечисленных, спрашивать пароль.
        <LimitExcept GET PROPFIND OPTIONS REPORT>
                Require valid-user
        </LimitExcept>

В любом случае, для правильной работы subversion клиента с ssl в дефолтный ssl-хост XX_mod_ssl_default-vhost.conf, либо в 40_mod_ssl.conf, необходимо добавить следующую строчку ( подробности - тут )

        BrowserMatch "SVN" redirect-carefully

Упомянутый выше файл /var/svn/conf/svnusers и содержит имена и зашифрованные пароли пользователей.

Чтобы создать этот файл/добавить в него новую запись воспользуйтесь коммандой htpasswd2.

Для создания файла с первым пользователем:

htpasswd2 -c /var/svn/conf/svnusers <имя первого пользователя>

и для добавления последующих:

htpasswd2 /var/svn/conf/svnusers <имя последующего пользователя>



Основанная на PAM

Если управление аж двумя различными файлами с паролями (системного и Апачевого) для вас слишком утомительно, то специально для вас был придуман модуль mod_auth_pam, который использует PAM для аутентификации пользователей. Если у вас нет еще этого модуля - emerge mod_auth_pam

Предупреждение: Да будет вам известно, что mod_auth_pam представляет из себя потенциальную уязвимость: системный пользователь 'apache' (или тот под которым запущен ваш сервер) получит доступ на чтение к /etc/shadow. Это означает, что в случае взлома Апача, злоумышленник получит доступ к файлу /etc/shadow, и сможет натравить на него программу по взлому паролей (дальнейшая судьба системы будет зависить от того, заметите ли вы взлом и примите меры раньше, чем злоумышленник получит пароль рута).

После сборки mod_auth_pam необходимо внести несколько изменений (суперпользователем) в ваши конфигурационные файлы. Для начала надо выдать пользователю 'apache' доступ на чтение /etc/shadow:

  1. groupadd shadow

  2. gpasswd -a apache shadow

  3. chgrp shadow /etc/shadow

  4. chmod g+r /etc/shadow

Предупреждение: Если у вас есть веб-сервер на котором работают посторонние люди, и он работает под тем же пользователем 'apache', то эти самые посторонние люди без всякого взлома смогут прочесть ваш /etc/shadow, и это уже действительно опасно!.

После чего внесите следующие изменения в /etc/apache2/modules.d/47_mod_dav_svn.conf: Вовнутрь блока <Location /svn> впишите:

Файл: /etc/apache2/modules.d/47_mod_dav_svn.conf

<IfModule mod_auth_sys_group.c>
        AuthPAM_Enabled on
        AuthType Basic
        AuthName "Subversion Repository"
        SSLRequireSSL
        Require group subversion
</IfModule>

ВАЖНО: В отличие от стандартной ('basic') аутентификации, описанной выше, убедитесь что вы не указали директивы

AuthUserFile /var/svn/conf/svnusers

Впрочем существует возможность оставить стандартную аутентификацию как запасную на случай если PAM модуль по каким-то причинам не сработает. Для этого обратите внимание на файл /etc/apache2/modules.d/10_mod_auth_pam.conf

ВАЖНО: Как уже упоминалось выше базовый тип встроенной аутентификации (AuthType Basic) передает пароли открытым текстом и для обеспечения минимальной безопасности необходимо ограничить аутентификацию только по ссл, при помощи директивы SSLRequireSSL

Ну а для того, чтобы все, в пределах этого параграфа, проделанное имело смысл, необходимо включить mod_auth_pam, добавив -D AUTH_PAM в APACHE2_OPTS в /etc/conf.d/apache2

Active Directory/LDAP

Для того, чтобы настроить авторизацию в SVN через LDAP или Active Directory, следуйте следующим инструкциям.

В /etc/conf.d/apache2 добавляем -D LDAP и -D AUTH_LDAP

APACHE2_OPTS="-D SSL -D PHP4 -D DAV -D DAV_FS -D SVN -D DAV_SVN -D LDAP -D AUTH_LDAP"

вот пример моей рабочей конфигурации Apache для авторизации через Active Directory: (нужно изменить путь к ldap на тот, что вы хотите использовать)

<IfDefine SVN>
<Location /svn/repo>
DAV svn
SVNPath /var/svn/repo
AuthType Basic
Options Indexes FollowSymLinks
AllowOverride None
order allow,deny
allow from all
AuthName "Authorize Me"
AuthLDAPURL
ldap://domain.com:389/OU=IT,OU=MainOffice,OU=Locations,OU=Corporate,DC=domainname,DC=com?samAccountName?sub?(objectCategory=person)
AuthLDAPBindDN "CN=webuser,OU=Resources,OU=Corporate,OU=AOM,DC=domain,DC=com"
AuthLDAPBindPassword xxxxxxxxxxx
Require valid-user
</Location>
</IfDefine>


Для того, чтобы разрешить доступ только ограниченному списку пользователей:

<Location "/useraccess">
AuthName "user permissions"
require user larry bill sam
</Location>


Для того, чтобы разрешить доступ только ограниченному списку групп:

<Location "/group">
AuthName "group permissions"
require group cn=Group,cn=Users,dc=domainname,dc=com
</Location>

В случае возникновения проблем с запросами к LDAP, запустите следующую команду на вашем Windows-сервере:

ldifde -f mydomain.ldif -s 127.0.0.1

Она сбросит все содержимое LDAP в указанный файл.

Авторизация

Если обычной авторизации недостаточно, можно расширить ее списками доступа. Имеется в виду что базовая аутентификация уже настроена и мы будем раздавать или запрещать доступ отдельным пользователям. Управлять списком можно через специальный файл, SVNAccessFile:

Файл: SVNAccessFile

AuthzSVNAccessFile /var/svn/conf/svnpolicy

Директива, указанная выше включает возможность создания списков доступа (ACL) для работы с репозиториями subversion через apache.

Правила авторизации для определенного репозитория задаются примерно так:

Файл: SVNAccessFile

[test:/trunk]
testuser1 = rw
testuser2 = 
* = r

Описанное выше правило разрешает производить пользователю testuser1 запись (commit, copy и т.д.) в репозиторий test (папка /trunk). Пользователь же testuser2 не имеет доступа к репозиторию. Остальные пользователи (маска *) имеют доступ только для чтения (могут производить checkout).

Для того, чтобы apache был в курсе наших опытов, нам нужно подредактировать /etc/conf.d/apache2:

Файл: /etc/conf.d/apache2

APACHE2_OPTS="... -D SVN_AUTHZ"


И напоследок, несколько замечаний по работе с правилами доступа: будьте осторожны с пробелами - внутри скобок не должно быть ни одного; при использовании только одного репозитория, его название можно не указывать, достаточно указать только папку.

Наводим марафет

В последней ревизии репозитория можно полазать в любимом браузере. Удовольствия это много недоставит - выглядит все это дело не очень красиво. Чтобы это исправить, добавьте директиву

SVNIndexXSLT /svnindex.xsl

внутри тега <Location /svn> и укажите свой xsl-файл. Если же с xml вы знакомы недостаточно хорошо, попробуйте xsl и css -файлы, входящие в стандартный пакет subversion в папке /usr/share/doc/subversion-<версия_пакета>.

Некоторые браузеры (например, Opera), вместо нормального отображения XSL-файла, могут показывать пустую страницу. Чтобы этого избежать, можно пропустить XSL через xsltproc, чтобы он преобразовал это дело в обычный html. Для этого необходимо установить пакет xsltproc:

emerge libxslt

И добавить следующее в файл настроек apache:

BrowserMatch "Opera" xsltfilter 

ExtFilterDefine xslt mode=output enableenv=xsltfilter \ 
        intype=text/xml outtype=text/html \ 
        cmd="/usr/bin/xsltproc /var/www/svnindex.xsl -" 

И добавить следующее внутрь тега <Location /svn>:

SetOutputFilter xslt 
AddDefaultCharset utf-8

Полезные ссылки