Идея
Необходимо настроить работу CVS-сервера, который бы обеспечивал:
- Доступ многих удаленных пользователей к одному репозиторию
- Эффективное разделение доступа пользователей к модулям репозитория
- Защиту данных пересылаемых от/к репозиторию
- Защиту конфигурационных файлов CVS от неавторизованных пользователей
- Защиту данных компьютера не имеющих отношение к CVS-репозиторию
Идея для решения подобной задачи была целиком почерпнута из работы "Chrooted SSH CVS server HOW-TO - DRAFT version", которая имеет в качестве своей основы статью "Chrooted tunnelled read-write CVS server", и, если коротко, заключается в следующем:
- Каждому пользователю и группе репозитория выделяется учетная запись в файлах /etc/passwd и /etc/group.
- В качестве командного интерпретатора для пользователей репозитория используется smrsh - командный интерпретатор sendmail'а, который ограничивает круг исполняемых команд только теми, что находятся в специальной директории, указываемой пр компиляции.
- Единственной доступной для пользователя к исполнению командой является одноименная "обертка" для cvs с установленным битом SUID, которая при запуске меняет корневую директорию на директорию для данного репозитория и в новом окружении (chroot-окружение) запускает команду cvs с передачей ей параметров. Таким образом, в директории, куда производится перенос корневого каталога, должна существовать директория bin/ со всеми необходимыми исполняемыми файлами и директория etc/ со всеми файлами необходимыми для авторизации доступа к репозиторию (passwd и group). Причем, все исполняемые файлы должны быть получены путем статической компиляции, поскольку в новом окружении все динамически подгружаемые библиотеки станут недоступными.
- Собственно, устанавливается сам репозиторий.
- Сетевая безопасность обеспечивается путем запрета для всех удаленных клиентов доступа к машине-серверу посредством отличного от SSH протокола (firewall, отсутствие поддержки других протоколов).
К дополнительным бонусам метода можно отнести его автоматическую расширяемость на несколько chrooted-репозиториев. Для этого необходимо проделать необходимое количество раз все манипуляции описанные ниже для каждого проекта, который мы хотим поместить в отдельное chrooted-окружение.
К очевидным минусам данного подхода можно отнести:
- "Засорение" системных файлов /etc/passwd и /etc/group записями пользователей и групп репозиториев.
- Для работы с несколькими репозиториями на одном хосте необходимо иметь для каждого из них по отдельному неперекрывающемуся набору групп и пользователей.
[Up] [Top]
Создание учетных записей (accounts)
Для работы с репозиторием используются следующие группы:
- Группа администраторов cvs-admin, пользователи которой имеют возможность изменять конфигурационные файлы CVS-сервера.
- Группа cvs-devel, пользователи которой имеют право записи в cvs-locks и history. "Обычные" пользователи, которым необходим доступ к файлам репозитория (не защищенным иным образом) хотя бы на чтение, должны быть членами этой группы.
- Остальные группы создаются по мере необходимости, чтобы ограничить доступ к определенным модулям репозитория. Пользователи этих групп также являются членами cvs-devel.
Добавим записи для групп cvs-admin и cvs-devel и пользователя cvs-admin в /etc/passwd и /etc/group.
в passwd:
cvs-admin:x:1000:1000:CVS <poject name> Admin:<base>/home/cvs-admin:<base>/<project>/bin/smrsh
Замечание:Смысл используемых здесь абсолютных путей станет понятен чуть позже.
в group:
cvs-admin:x:1000:
cvs-devel:x:1001:
И домашние директории для них (они необходимы для SSH):
% mkdir -p <base>/home/cvs-devel
% mkdir -p <base>/home/cvs-admin
% chown cvs-devel.cvs-devel <base>/home/cvs-devel
% chown cvs-admin.cvs-admin <base>/home/cvs-admin
Скопируем только что созданные учетные записи из системных passwd и group в соответствующие файлы директории <base>/<project>/chrooted-cvs/etc/. Заменив домашние директории на /tmp. Вот, что получится в passwd:
cvs-admin:x:1000:1000:CVS <poject name> Admin:/tmp:<base>/<project>/bin/smrsh
cvs-devel:x:1001:1001:CVS <poject name> User :/tmp:<base>/<project>/bin/smrsh
Чтобы создать произвольного пользователя репозитория, к примеру foo, поступаем аналогичным путем, не забывая добавить его в группу cvs-devel:
cvs-devel:x:1001:foo
в соответствующих файлах group.
[Up] [Top]
Создаем дерево директорий
Пусть у нас есть два пользователя репозиторием: dev1 и dev2, и парочка проектов: proj1 и proj2, тогда согласно идеи предложенной в "Chrooted SSH CVS server HOW-TO - DRAFT version" надо получить что-то вроде:
.../home/dev1/ домашняя директория разработчика 1
.../home/dev2/ домашняя директория разработчика 2
.../proj1/ домашняя директория проекта 1
.../proj1/bin/ директория для бинарников
.../proj1/smrsh специальный командный интерпретатор
.../proj1/smrsh.bin/ директория для разрешенных команд
.../proj1/smrsh.bin/cvs обертка для CVS
.../proj1/chrooted-cvs/ корневой каталог для подсистемы проекта 1
.../proj1/chrooted-cvs/bin/ допустимые к исполнению команды: только cvs
.../proj1/chrooted-cvs/bin/cvs статически скомпилированный cvs
.../proj1/chrooted-cvs/dev/
.../proj1/chrooted-cvs/dev/null необходимо для нормального функционирования
.../proj1/chrooted-cvs/etc/
.../proj1/chrooted-cvs/etc/passwd часть passwd-файла с юзерами для cvs
.../proj1/chrooted-cvs/etc/group часть group-файла с группами для cvs
.../proj1/chrooted-cvs/cvs/proj1 базовая директория для проекта 1
.../proj1/chrooted-cvs/cvs/proj1/CVSROOT/ настройки CVS проекта 1
.../proj1/chrooted-cvs/cvs/proj1/module1/ модуль 1 для проекта 1
.../proj1/chrooted-cvs/cvs/proj1/module2/ модуль 2 для проекта 1
.../proj1/chrooted-cvs/cvs-locks/ директория для lock-файлов репозитория
.../proj1/chrooted-cvs/tmp/ директория для временных файлов
.../proj2/ домашняя директория проекта 2
... ну и так далее
Это можно сделать, например, с помощью ниже указанного скрипта:
#!/bin/bash
BASE=<base>
PROJECT=<project>
ADMIN=cvs-adm
# create the place where regular home-directories
# of standard CVS users will be (this step will be needed the first time
# only, as all home dirs are in the same place)
mkdir -p ${BASE}/home
chown 0.0 ${BASE}/home
# create the chroot environment for ${PROJECT}
mkdir -p ${BASE}/${PROJECT}/{bin,chrooted-cvs,smrsh.bin}
mkdir -p ${BASE}/${PROJECT}/chrooted-cvs/{bin,cvs,cvs-locks,dev,etc,tmp}
chown 0.0 ${BASE}/${PROJECT}/chrooted-cvs/{bin,dev,etc,home,tmp}
chmod 1777 ${BASE}/${PROJECT}/chrooted-cvs/tmp
# the cvs administrator owns the CVS root
chown ${ADMIN}.${ADMIN} ${BASE}/${PROJECT}/chrooted-cvs/cvs
chmod 770 ${BASE}/${PROJECT}/chrooted-cvs/cvs
chown 0.0 ${BASE}/${PROJECT}/chrooted-cvs/cvs-locks
chmod 666 ${BASE}/${PROJECT}/chrooted-cvs/cvs-locks
# create the /dev/null device under the chroot space
mknod ${BASE}/${PROJECT}/chrooted-cvs/dev/null c 1 3
chown 0.0 ${BASE}/${PROJECT}/chrooted-cvs/dev/null
chmod 666 ${BASE}/${PROJECT}/chrooted-cvs/dev/null
где <base> - директория, в которой будет содержаться описанная выше структура, а <project> - имя директории для отдельного проекта.
[Up] [Top]
Компиляция smrsh
Теперь, что касается smrsh. Его исходники можно скачать с www.sendmail.org в составе пакета sendmail. Далее некие магические действия (такие какими они были в моем случае):
% tar xzf sendmail.8.12.9.tar.gz
% cd sendmail-8.12.9/smrsh
% ./Build
Наблюдаем процесс компиляции каких-то полезных библиотек и нужного нам приложения smrsh. Смотрим в то, что вывелось в терминал, по его завершению и определяем: где собирался smrsh, и при помощи какой команды. Вот, что выяснил я:
<skipped>
Making in ><skipped>sendmail-8.12.9/obj.Linux.2.4.20-8.i686/smrsh
<skipped>
cc -o smrsh smrsh.o <skipped>sendmail-8.12.9/obj.Linux.2.4.20-8.i686/libsm/libsm.a -ldb -lresolv -lcrypt -lnsl -ldl
<skipped>
Далее:
% cd <skipped>sendmail-8.12.9/obj.Linux.2.4.20-8.i686/smrsh
% cc -o -static smrsh smrsh.o <skipped>sendmail-8.12.9/obj.Linux.2.4.20-8.i686/libsm/libsm.a -ldb -lresolv -lcrypt -lnsl -ldl
Получили таким образом статическую версию smrsh. Замечание:На самом деле статическая версия smrsh нам не нужна, поскольку утилита запускается в нормальном окружении. Но мне нравится независимость от внешних библиотек.
Вспомним теперь, что smrsh может запускать команды только из определенной директории, которая указывается при компиляции. Эту директорию можно указать, вставив "#define CMDDIR <путь>" в исходник "smrsh.c", либо скормив Build'у длинную строку соответствующих параметров для последующего скармливания ее make'у:
% ./Build CPPFLAGS+=-DCMDDIR=\"\\\"\\\\\\\"<base>/<project>/smrsh.bin\\\\\\\"\\\"\"
Повторим теперь всю, описанную выше, цепь действий начиная с запуска Build'а с указанием ему пути. (Главное не запутаться в слэшах :-) )
Перенос и настройка репозитория.
В моем случае требовалось перенести существующий репозиторий. Репозиторий "с нуля" создается стандартным образом, и этот процесс здесь не описан. Замечание:Однако, стоит учесть, что если мы создаем с помощью cvs init новый репозиторий, он не будет содержать CVSROOT/val-tags, этот файл необходимо будет создать вручную с помощью команды touch.
% cp -a <путь к старому репозиторию>/* <base>/<project>/chrooted-cvs/cvs
% chowh -R cvs-adm.cvs-adm <base>/<project>/chrooted-cvs/cvs
% chgrp cvs-devel <base>/<project>/chrooted-cvs/cvs/CVSROOT/{history,val-tags}
% chmod 775 <base>/<project>/chrooted-cvs/cvs <base>/<project>/chrooted-cvs/cvs/CVSROOT
% chmod 444 <base>/<project>/chrooted-cvs/cvs/CVSROOT/*
% chmod 775 <base>/<project>/chrooted-cvs/cvs/CVSROOT/Emptydir
% chmod 664 <base>/<project>/chrooted-cvs/cvs/CVSROOT/{history,val-tags}
% chown -R cvs-adm.cvs-devel <base>/<project>/chrooted-cvs/cvs-locks
% chmod -R 770 <base>/<project>/chrooted-cvs/cvs-locks
Поправим в конфигурациях пути к лок-файлам:
% su - cvs-admin
% <base>/<project>/chrooted-cvs/bin/cvs -d <base>/<project>/chrooted-cvs/cvs co CVSROOT
% cd CVSROOT
Дабавляем в файл config строчку LockDir=/cvs-locks. Сохраняем наши изменения в репозитории:
% <base>/<project>/chrooted-cvs/bin/cvs -d <base>/<project>/chrooted-cvs/cvs ci config
Теперь наш репозиторий будет доступен только в окружении chroot.
[Up] [Top]
Сетевая безопасность, доступ клиентов к репозиторию
Сетевая безопасность достигается путем разрешения отдаленного доступа к CVS-серверу только по протоколу SSH.
Чтобы отдаленный клиент мог получить доступ к серверу, ему необходимо установить переменную окружения CVS_RSH=ssh и выполнить команду, например, чтобы получить последнюю версию модуля mymodule, вроде этой:
% cvs -d :ext:anoncvs@cvs.myproject.org:/cvs checkout mymodule
[Up] [Top]