Андрей Шетухин, Ольга Никулина
Прогресс в области разработки систем контроля версий не стоит на месте.
Представляем вам Subversion современную замену устаревшей системы CVS.
Что такое Subversion?
Если коротко, Subversion это свободно распространяемая система контроля
версий, призванная заменить собой устаревшую систему CVS. Subversion
используется такими программистскими коллективами, как команда разработчиков
компиляторов GNU, KDE Development Team, разработчиками СУБД Ingres, Apache
Software Foundation, Samba и многими, многими другими. Далеко не полный список
проектов, исходные коды которых хранятся в Subversion, доступен поссылке:
http://subversion.tigris.org/testimonials.htm.
CVS vs Subversion
Поскольку Subversion разрабатывалась как продвинутая замена
CVS, изначально ставилась задача: сохранить всю привычную функциональность
придобавлении новых возможностей. Поэтому большинство широкоиспользуемых
команд Subversion имеют такой же синтаксис, какиCVS. Переход на
Subversion несложен и не требует долгого привыкания.
n Атомарное принятие изменений. Поддержка
атомарных коммитов позволяет либо принимать весь измененный код, либо не
принимать изменения вовсе, если транзакция по каким-либо причинам (например,
из-за падения канала) не была завершена. Subversion поддерживает такой режим
работы и гарантирует, что репозиторий небудет содержать в себе
несовместимых данных либо репозиторий останется неизмененным, либо
обновление будет полным.
n Переименование, перенос и копирование файлов
икаталогов безпотери версионирования иистории изменений.
В отличие отCVS, которая требует вмешательства администратора сервера и
ручного копирования файлов, Subversion изначально обладает такой возможностью,
а при установке модуля SVN::Mirror, разработанного Chia-Ling Kao, Subversion
также обучается клонировать данные из текущего в произвольный удаленный
репозиторий.
n Права доступа к репозиторию.
Выможете назначать пользователям права доступа к различным частям
репозитория, простым редактированием текстового конфигурационного файла.
n Комментарии к каждому измененному объекту.
Теперь вы можете оставлять комментарий в журнале коммита к любому измененному
вами файлу.
n Простота развертывания системы. Для
построения полноценной работоспособной системы Subversion вбольшинстве
случаев необходим только веб-сервер Apache2 и интерпретатор PHP, а минимальный
набор утилит Subversion, позволяющий работать по протоколам SVN и SVN + SSH,
вообще не требует установки стороннегоПО.
n Простота интеграции в существующую
инфраструктуру сети. Доступ крепозиторию Subversion может
осуществляться по протоколам HTTP, HTTPS, SVN, SVN+SSH, изнабора которых
вы сможете легко выбрать наиболее подходящий для заданной конфигурации сети.
n Разнообразные веб-интерфейсы для доступа
крепозиторию.Натекущий момент доступно около десятка
программ для работы с репозиторием SVN: ViewCVS, SVN::Web, WebSVN, ViewSVN,
mod_svn_view, Chora, Trac, SVN::RaWeb::Ligh, SVN Browser, Insurrection и т. д.
Вданной статье мы рассмотрим настройку WebSVN как наиболее простого
ивто же время функционального инструмента.
n Кроме утилит командной строки, доступны
также графические интерфейсы: кроссплатформенный RapidSVN, TortoiseSVN
плагин для MS Windows Explorer, а также Jsvn, написанный на Java и
доступный везде, гдеесть Java-машина.
n Ну и, наконец, лицензия. Subversion
программное обеспечение с открытым кодом и распространяется полицензии
Apache/BSD-style.
Что входит в состав пакета
Subversion
n svn клиент Subversion. Представляет
собой утилиту командной строки, осуществляющую доступ к репозиторию Subversion.
n svnversion программа, показывающая
состояние компонент текущего репозитория.
n svnlook утилита для контроля
репозитария Subversion.
n svnadmin утилита для создания,
управления и восстановления репозитария Subversion.
n svndumpfilter программа фильтрации
дампов репозитория Subversion.
n mod_dav_svn модуль для веб-сервера
Apache2, предоставляющий доступ в репозиторий Subversion по протоколам HTTP и
HTTPS.
n svnserve программа-сервер,
запускающаяся как одиночный демон или из inetd и предоставляющая доступ к
репозиторию Subversion по протоколу SVN илиSSH.
План установки Subversion
n Установка необходимого ПО. В этом
разделе будут описаны установка и запуск FreeBSD Jail, установка веб-сервера
Apache 2.X, Subversion, PHP4 и WebSVN.
n Создание сертификатов и конфигурация серверного
ПО. Здесь мы рассмотрим создание собственного самоподписанного сертификата
(Certificate Authority, CA), создание сертификата сервера и создание клиентских
сертификатов.
n Настройка клиентов SVN на *nix и Windows.
Этот раздел посвящен работе с Subversion на платформе *nix
(Linux/FreeBSD/Solaris ), а также установке на Windows-машину клиента
TortoiseSVN.
Создаем и устанавливаем Jail
Jail необходим для того, чтобы система контроля версий жила в собственном
мире и никак не пересекалась состальными приложениями. Кроме того,
используя jail, выповышаете общий уровень защищенности системы: если
обнаружится уязвимость в пакетах Subversion, Apache илиPHP, основная
система не пострадает. Jail будет также полезен в том случае, если на основной
системе установлен Apache 1.3.X.
Если для Subversion используется выделенный
сервер, этот пункт можно смело пропустить.
Собираем jail. Обратите внимание, что на FreeBSD
5.3 команда make world DESTDIR=$D из jail(8) не работает. Вместо нее следует
воспользоваться командами:
make buildworld
make installworld DESTDIR=$D
Итак, в нашем случае сборка jail будет выглядеть
так:
# cd /usr/src
# mkdir -p
/usr/home/jails/svn
# make buildworld
# make installworld
DESTDIR=/usr/home/jails/svn
# cd etc
# make distribution
DESTDIR=/usr/home/jails/svn
В файл /etc/rc.conf добавляем следующие строчки:
jail_enable="YES" #
Включаем загрузку jail
jail_list="svn" #
Список всех jail, которые есть в системе
jail_set_hostname_allow="NO" #
Запрещаем изменение hostname из jail
jail_socket_unixiproute_only="YES" #
Разрешаем для jail обмен только по TCP/IP
jail_sysvipc_allow="NO" #
Запрещаем SystemV IPC внутри jail
# Для jail с именем
"svn"
jail_svn_rootdir="/usr/home/jails/svn" #
Каталог jail
jail_svn_hostname="svn.reki.ru" #
Имя хоста jail
jail_svn_ip="XX.YY.XX.TT" #
IP адрес
jail_svn_exec="/bin/sh
/etc/rc" # Скрипт инициализации
jail_svn_devfs_enable="YES" #
Монтировать devfs в jail
Добавляем пользователя, под которым мы будем
заходить в jail. Для этого можно воспользоваться командой:
# vipw -d
/usr/home/jails/svn/etc
либо:
# pw -V /usr/home/jails/svn/etc
useradd admin -g 0 -d /usr/home/jails/svn/usr/home/admin -s /bin/csh -h 0 -m
Для удобства работы присваиваем пользователю
группу 0 (wheel) и разрешаем в jail запуск sshd. В файл
/usr/home/jails/svn/etc/rc.conf добавляем строчку sshd_enable=YES изапускаем
jail командой /etc/rc.d/jail start. Если все сделано правильно, команда jls(8)
выведет примерно следующее:
# jls
JID IP
Address Hostname Path
1
XX.YY.XX.TT svn.reki.ru /usr/home/jails/svn
Заходим в jail по ssh, получаем права
суперпользователя, выкачиваем и разворачиваем архив дерева портов:
# ssh XX.YY.XX.TT -l admin
# su - root
# cd /usr
# fetch
ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz
# tar -xzf ports.tar.gz
Начиная с этого момента jail представляет собой
полноценную виртуальную машину, доступную для администрирования по ssh.
Устанавливаем веб-сервер
Apache2
Для повышения общего уровня безопасности, будем авторизовывать клиента через
подписанный нами сертификат; поэтому нам следует воспользоваться опцией
FakeBasicAuth. При входе клиента с выданным нами сертификатом на сервер Apache
произведет псевдоавторизацию, основываясь на данных сертификата.
Надо отметить, что при подобной авторизации имя
пользователя выглядит как строка свойств сертификата. Соответственно при
коммите через HTTPS имя пользователя будет не stellar, а
/C=RU/ST=-/L=Moscow/O=Reki.ru/OU=SVN/CN=stellar/emailAddress=stellar@reki.ru.
Понятно, что наличие в двух ипостасях одного и того же пользователя никого
устроить не может и хорошим решением было бы взять в качестве логина часть
строки данных сертификата. Дляэтого в Apache предусмотрена директива
SSLUserName и... увы иах, мир несовершенен: без исправлений кода mod_ssl
опции FakeBasicAuth и SSLUserName вместе не работают.
К счастью, по URL http://reki.ru/products/subversion/patch-server-ssl_engine_kernel.c,
теперь доступен патч, исправляющий это недоразумение.
Для сборки Apache с поддержкой FakeBasicAuth +
SSLUserName надо скачать патч и положить его в каталог
/usr/ports/www/apache2/files. Если предполагается, чторепозиторий
Subversion будет храниться в BerkeleyDB, намтакже будет необходимо
включить поддержку BerkeleyDB дляApache.
Итак, устанавливаем необходимые переменные
окружения и запускаем установку Apache.
# cd /usr/ports/www/apache2
# setenv WITH_BERKELEYDB db42
# cd files
# fetch
http://reki.ru/products/subversion/patch-server-ssl_engine_kernel.c
# cd ../
# make install clean
Устанавливаем систему контроля
версий Subversion
Поскольку предполагается, что доступ к SVN будет осуществляться по протоколу
HTTPS, нам следует установить модуль mod_dav_svn. По умолчанию репозиторий SVN
создается в каталоге /home/svn/repos.
# cd /usr/ports/devel/subversion
# setenv WITH_MOD_DAV_SVN yes
# setenv WITH_APACHE2_APR yes
# make install clean
Если требуется подсветка синтаксиса исходных
файлов, устанавливаем программу enscript. В этом случае в файле конфигурации
WebSVN следует включить поддежку enscript.
# cd
/usr/ports/print/enscript-a4
# make install clean
Устанавливаем PHP4
PHP4 нам понадобится для WebSVN веб-фронтэнда репозитория. Для работы
WebSVN необходимо установить расширения PHP для поддержки zlib и pcre.
# cd /usr/ports/lang/php4
# make install clean
# cd
/usr/ports/lang/php4-extensions
# make install clean
Устанавливаем и настраиваем
WebSVN
По умолчанию WebSVN устанавливается в /usr/local/www/data/WebSVN. Для наших
целей придется скопировать его содержимое в каталог /usr/home/www/svn/svn.reki.ru/www.
# cd /usr/ports/devel/websvn
# make install clean
# mkdir -p
/usr/home/www/svn/svn.reki.ru/www
# mkdir -p
/var/log/apache/www/svn.reki.ru
# cp -r
/usr/local/www/data/WebSVN /usr/home/www/svn/svn.reki.ru/www
// Правим файл конфигурации
фронтэнда
# vi
/usr/home/www/svn/svn.reki.ru/www/include/config.inc
Примерный вид файла конфигурации следующий:
// Указываем пути к
программам svn, diff, sed, tar и gzip
$config->setSVNCommandPath("/usr/local/bin");
$config->setDiffPath("/usr/bin");
$config->setSedPath("/usr/bin");
$config->setTarPath("/usr/bin");
$config->setGZipPath("/usr/bin");
// Перечисляем все те
репозитории, которые должны быть доступны через фронтэнд
$config->addRepository("Example
Repository #1", "/usr/home/svn/example");
$config->addRepository(Example
Repository #2", "/usr/home/svn/example2");
// Язык веб-интерфейса
include("languages/russian.inc");
// Кодировки веб-интерфейса
$config->setInputEncoding("windows-1251");
$config->setOutputEncoding("windows-1251");
// Включить кэширование
данных для фронтэнда
$config->setCachingOn();
// Разрешить скачивание
проекта в виде tar.gz-архива
$config->allowDownload();
// Включить подсветку
синтаксиса программой enscript
$config->setEnscriptPath("/usr/local/bin");
$config->useEnscript();
Создаем сертификаты и
конфигурируем серверное ПО
Создаем собственный самоподписанный сертификат (Certificate Authority, CA).
Используя этот сертификат, мыбудем подписывать сертификат сервера и все
клиентские сертификаты.
# openssl req -new -newkey
rsa:1024 -x509 -days 3650 -nodes -out ca.crt -keyout ca.key -subj
/C=RU/ST=-/L=Moscow/O=Reki.ru/OU=Certificate_Issuer/CN=reki.ru/emailAddress=admin@reki.ru
Перечислим список команд:
n req запрос на создание нового сертификата.
n -new cоздание запроса на сертификат
(Certificate Signing Request, CSR).
n -newkey rsa:1024 длина RSA ключа сертификата.
n -x509 создание самоподписанного сертификата
вместо создания CSR.
n -days 3650 срок действия сертификата (10
лет). Этозначение должно быть больше срока действия создаваемого
сертификата сервера и клиентских сертификатов.
n -nodes флаг, указывающий не шифровать ключ.
n -out ca.crt сертификат.
n -keyout ca.key закрытый ключ сертификата.
n -subj данные сертификата.
Строка subj имеет следующие поля:
n С код страны (Country). Двухбуквенная
аббревиатура.
n ST название республики, региона или округа
(State Name).
n L название города/деревни (Locality Name).
n O организация (Organization Name).
n OU отдел организации (Organization Unit).
n CN имя. Для сервера ServerName; для
клиентского сертификата что угодно.
n emailAddress почтовый адрес администратора
сервера.
Для создания серверного и клиентских сертификатов
вам понадобится либо воспользоваться стандартным файлом конфигурации
openssl.cnf, который, как правило, находится в каталоге /etc/ssl, либо вручную
создать собственный файл конфигурации (название файла ca.config):
[ca]
default_ca =
CA_CLIENT
[CA_CLIENT]
dir =
./db # Рабочий каталог для базы данных клиентских ключей
certs = $dir/certs #
Каталог для новых сертификатов
new_certs_dir =
$dir/newcerts # Каталог, куда будут складываться выписанные сертификаты
database =
$dir/index.txt # Индекс базы данных выписанных ключей
serial =
$dir/serial # Номер текущего ключа
certificate =
./ca.crt # Собственный самоподписанный сертификат CA
private_key =
./ca.key # Закрытый ключ сертификата CA
default_days = 365 #
Время, на которое выписывается клиентский сертификат
default_crl_days = 7 #
Срок действия CRL
default_md = md5 #
Алгоритм подписи
policy =
policy_anything # Название секции политики
[policy_anything]
countryName =
optional # Разрешаем не указывать код страны
stateOrProvinceName =
optional # ------ // ------- название штата или округа
localityName = optional #
------ // ------- название города/деревни
organizationName =
optional # ------ // ------- название организации
organizationalUnitName =
optional # ------ // ------- название отдела
commonName =
supplied # Обязательно указать имя.
emailAddress =
optional # Почтовый адрес можно не указывать
Создаем структуру каталогов, описанную в секции
[CA_CLIENT]
# mkdir -p /usr/local/etc/crt
# cd /usr/local/etc/crt
// Создаем и редактируем файл
конфигурации
# vi ca.config
# mkdir ./db
# mkdir ./db/certs
# mkdir ./db/newcerts
# touch ./db/index.txt
# echo "01" >
./db/serial
Создаем сертификат сервера:
# openssl req -new -newkey
rsa:1024 -nodes -keyout server.key -out server.csr -subj
/C=RU/ST=-/L=Moscow/O=Reki.ru/OU=SVN/CN=svn.reki.ru/emailAddress=svn@svn.reki.ru
Для сертификата сервера тег CN должен содержать
егоServerName. В данном случае это svn.reki.ru.
Подписываем сертификат собственным CA:
# openssl ca -config
ca.config -in server.csr -out server.crt -batch
Устанавливаем сертификаты:
# cp server.crt
/usr/local/etc/apache2/ssl.crt/server.crt
# cp server.key
/usr/local/etc/apache2/ssl.key/server.key
# cp ca.crt
/usr/local/etc/apache2/ssl.crt/ca.crt
Конфигурируем веб-сервер. Создаем необходимую
структуру каталогов:
# mkdir -p
/var/log/apache/www/svn.reki.ru
# mkdir -p
/usr/home/www/svn/svn.reki.ru/www
В файл /usr/local/etc/apache2/ssl.conf
прописываем конфигурацию виртуального веб-сервера:
<VirtualHost *:443>
DocumentRoot
/usr/home/www/svn/svn.reki.ru/www
ServerName svn.reki.ru:443
ServerAdmin
admin@svn.reki.ru
ErrorLog
/var/log/apache/www/svn.reki.ru/error_log
CustomLog
/var/log/apache/www/svn.reki.ru/access_log "%t %h %{SSL_PROTOCOL}x
%{SSL_CIPHER}x \"%r\" %b"
SSLEngine on
SSLCipherSuite
ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile
/usr/local/etc/apache2/ssl.crt/server.crt
SSLCertificateKeyFile
/usr/local/etc/apache2/ssl.key/server.key
SSLCACertificateFile
/usr/local/etc/apache2/ssl.crt/ca.crt
SSLVerifyClient require
# Пускаем
только тех пользователей, которые имеют подписанные нами сертификаты
SSLVerifyDepth 1
<Location
/>
SSLVerifyClient
require
# Для
совместной работы этих опций
SSLOptions
+FakeBasicAuth
SSLUserName
SSL_CLIENT_S_DN_CN # необходим патч
AuthName
"SVN"
AuthType
Basic
AuthUserFile
/usr/home/www/svn/svn.reki.ru/.htpasswd_ssl
require
valid-user
</Location>
<Location
/svn>
DAV svn #
Обработчик DAV - svn
# общий
каталог для репизиториев
SVNParentPath
/usr/home/svn
AuthzSVNAccessFile
/usr/home/www/svn/svn.reki.ru/.htauth_svn
require
valid-user
</Location>
SetEnvIf User-Agent
.*MSIE.* nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
</VirtualHost>
Строчки, выделенные красным, указывает серверу, чтопринимать
соединение необходимо только для тех клиентов, которые имеют правильный, то
есть выданный нами сертификат. В строках, выделенных зеленым, мы имитируем
авторизацию по паролю. Это необходимо для того, чтобы разрешить доступ к
репозиторию SVN только тем пользователям, которым выдан личный сертификат SSL.
Для этого мы указываем файл паролей, находящийся по адресу:
/usr/home/www/svn/svn.reki.ru/.htpasswd_ssl. Его содержимое состоит из строки
CN (commonName), которую мызадавали при создании пользовательского ключа,
и магического заклинания xxj31ZMTZzkVA, являющегося DES-хэшем слова
password.
stellar:xxj31ZMTZzkVA
oniks:xxj31ZMTZzkVA
Заметим, что поскольку это не настоящая
авторизация (по-настоящему мы авторизуемся через сертификат), увсех пользователей
один и тот же пароль: xxj31ZMTZzkVA: password.
Синие строки указывают, какой путь будет
использоваться для https-доступа к SVN. Для нашего случая это
https://svn.reki.ru/svn. Ввиду того, что мы планируем использовать Subversion
для нескольких разных проектов одновременно, нам потребуется при помощи
директивы SVNParentPath указать общий родительский каталог для всех
репозиториев. Все репозитории из каталога /usr/home/svn будут доступны как
https://svn.reki.ru/svn/имя_репозитория.
Теперь нам остается только раздать пользователям
права доступа к проектам. Для этого используется директива AuthzSVNAccessFile,
указывающая файл с описанием прав доступа к тому или иному репозиторию.
Формат файла следующий:
# имя репозитория:/путь
[example:/]
# Имена пользователей = права
доступа
stellar = rw
oniks = rw
[example2:/]
stellar = rw
oniks = r
Пользователь stellar имеет полный доступ к
репозиториям example и example1, а пользователь oniks полный доступ к example
и право на чтение из example2.
Создаем репозитории
Поскольку мы условились, что будем использовать Subversion для двух проектов
с именами example и example2, создаем два репозитория в каталоге /usr/home/svn:
# svnadmin create
/usr/home/svn/example
# svnadmin create
/usr/home/svn/example2
# chown -R www:www
/usr/home/svn/
Структура проекта может быть произвольной, но
общепринято создавать три основных каталога: branches для веток, tags для
тегов проекта и trunk непосредственную рабочую область для коммитов. Чтобы
каждый раз неделать одну и ту же работу, создаем шаблон проекта с
основными каталогами и импортируем его в созданные репозитории:
# svnadmin create
/usr/home/svn/example
# mkdir -p
/usr/local/share/svn/skel
// Каталог с шаблоном
репозитория
# cd
/usr/local/share/svn/skel
# mkdir branches tags trunk
# svn import
/usr/local/share/svn/skel/tree file:///usr/home/svn/example -m "initial
import"
В дальнейшем можно создавать каталоги внутри
проекта посредством команды svn add, удалять их командой svn delete.
Права на каталоги репозиториев должны принадлежать пользователю, от которого запущен
Apache.
В файл /etc/rc.conf добавляем строчки:
apache2_enable="YES"
apache2ssl_enable="YES"
и запускаем Apache:
#
/usr/local/etc/rc.d/apache2.sh start
Если все сделано правильно, команда ps(1) покажет
нечто похожее на это:
# ps axw | grep
httpdvv
33928 ??
SsJ 0:03.31 /usr/local/sbin/httpd -k start -DSSL
81260 ??
IJ 0:00.01 /usr/local/sbin/httpd -k start -DSSL
81261 ??
IJ 0:00.00 /usr/local/sbin/httpd -k start -DSSL
81262 ??
IJ 0:00.00 /usr/local/sbin/httpd -k start -DSSL
81263 ??
IJ 0:00.00 /usr/local/sbin/httpd -k start -DSSL
81264 ??
IJ 0:00.00 /usr/local/sbin/httpd -k start -DSSL