Сетевые репозитории

Рабочая копия исходных текстов и репозиторий могут быть на разных машинах. Использование CVS таким образом известно как режим клиент/сервер. Вы выполняете CVS-клиент на машине, на которой смонтирован ваш рабочий каталог, и говорите ему общаться с машиной, на которой смонтирован репозиторий, с CVS-сервером. Вообще использование сетевого репозитория похоже на использование локального, только формат имени репозитория таков:

:метод:пользователь@машина:/путь/к/репозиторию

Детали зависят от того, как вы соединяетесь с сервером.

Если метод не указан, а имя репозитория содержит :, то метод по умолчанию — ext или server, в зависимости от платформы; оба метода описаны в разделе “Соединение с помощью rsh”.

Требования к серверу

Простой ответ: требования к серверу умеренны — если дерево каталогов не очень большое, и активность не слишком высока, то подойдет машина с 32Mb памяти или даже меньше.

В реальной жизни, конечно, все сложнее. Оценка пикового использования памяти достаточна, чтобы оценить общие требования. Здесь документированы две такие области максимального потребления памяти; все остальные по сравнению с ними незначительны, чтобы мы обновили документацию.

Первая область большого потребления памяти — извлечения больших рабочих каталогов. Сервер состоит из двух процессов на каждого обслуживаемого клиента. Потребление памяти дочерним процессом должно быть невелико. Родительский процесс же, особенно когда сетевые соединения медленны, может вырасти до размеров, чуть больших размера исходных тестов, или до двух мегабайт, смотря что больше.

Умножая размер каждого CVS-сервера на количество клиентов, которые вы ожидаете одновременно, вы оцените требуемый размер памяти у сервера. По большей части память, потребляемая родительским процессом, будет находиться в файле подкачки, а не в физической памяти.

Вторая область большого потребления памяти — diff при фиксировании изменений в больших файлах. Это требуется даже для бинарных файлов. Можно предусмотреть использование примерно десятикратного размера самого большого файла, который только будет фиксироваться, хотя пятикратный размер будет вполне адекватен. Например, если вы хотите фиксировать файл размером в десять мегабайт, то в машине, на которой выполняется фиксирование (сервер или локальная машина, на которой находится репозиторий), должно быть сто мегабайт. Скорее всего, это будет файл подкачки, а не физическая память. Так как эта память требуется на непродолжительное время, то особенной нужды выделять память под несколько одновременных фиксирований нет.

Потребление ресурсов для клиентской машины еще более умеренны — любая машина, способная выполнять соответствующую операционную систему, будет пригодна.

Информация о требованиях к дисковому пространству находится в разделе “Создание репозитория”.

Соединение с помощью rsh

CVS использует протокол rsh для работы с сетевым репозиторием, поэтому на сетевой машине должен быть создан файл .rhosts, позволяющий доступ данному пользователю.

Например, предположим, что вы пользователь 'mozart' на локальной машине 'toe.example.com', а сервер находится на 'faun.example.com'. На машине 'faun' поместите в файл .rhosts в домашнем каталоге пользователя 'bach' следующее:

toe.example.com mozart

Потом протестируйте, что rsh работает, запустив

rsh -l bach faun.example.org 'echo $PATH'

Затем вам следует убедиться, что rsh найдет сервер. Убедитесь, что путь, напечатанный в результате выполнения этого примера содержит каталог, содержащий исполняемый файл cvs, который является серверной версией CVS. Вы можете установить путь в .bashrc, .cshrc, и т. п., но не в файлах .login или .profile. Можно также установить переменную среды CVS_SERVER на клиентской машине, чтобы указать, какой исполняемый файл вы хотите использовать, например, /usr/local/bin/cvs-1.6.

Не требуется редактировать inetd.conf, чтобы запустить CVS как демона.

Вы можете использовать в CVSROOT два метода доступа для rsh. :server: задает использование внутреннего клиента rsh, который поддерживается только в некоторых портах CVS. :ext: указывает внешнюю программу rsh. По умолчанию это rsh, но вы можете установить переменную среды CVS_RSH, чтобы выполнять другую программу, которая может соединиться с сервером (например, remsh на HP-UX 9, потому что rsh немного отличается. Эта программа должна уметь пересылать данные с сервера и на сервер, не изменяя их; например, rsh из Windows NT не подходит, потому что он транслирует CR-LF в LF. Порт CVS для OS/2 содержит хэк, который передает rsh параметр -b, чтобы обойти это, но поскольку это может привести к проблемам с программами, не являющимися стандартным rsh, это может быть изменено в будущем. Если вы устанавливаете CVS_RSH в ssh или какую-нибудь другую замену rsh, то инструкции по настройке .rhosts, скорее всего, неприменимы, поэтому обратитесь к документации по соответствующей программе.

Продолжая наш пример, предположив, что вы хотите обратиться к модулю foo в репозитории /usr/local/cvsroot на машине 'faun.example.org', вы набираете:

cvs -d :ext:bach@faun.example.org:/usr/local/cvsroot checkout foo

(Можно не писать 'bach@', если имена пользователей совпадают на локальной и сетевой машинах.)

Прямое соединение с парольной аутентификацией

Клиент CVS также может соединяться с сервером, используя протокол с паролем. Это особенно полезно, когда использование rsh неосуществимо, (например, если сервер находится за файерволлом), и kerberos также недоступен.

Чтобы использовать этот метод, необходима некоторая настройка как сервера, так и клиентов.

Настройка сервера для парольной аутентификации

Во-первых, вы, вероятно, хотите усилить права доступа к каталогам $CVSROOT и $CVSROOT/CVSROOT. См. раздел “Прямое соединение с парольной аутентификацией”.

На стороне сервера следует редактировать файл /etc/inetd.conf, чтобы inetd знал, что следует выполнять команду cvs pserver, когда кто-либо пытается соединиться с соответствующим портом. По умолчанию номер порта равен 2401; это значение можно изменить, если перед компиляцией установить параметр CVS_AUTH_PORT в другое значение.

Если ваш inetd позволяет использование номеров портов в /etc/inetd.conf, то можно использовать такую строку (строка отформатирована, чтобы влезла на страницу):

2401 stream tcp nowait root /usr/local/bin/cvs cvs -f 
--allow-root=/usr/cvsroot pserver

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

Ключ командной строки --allow-root задает разрешенный каталог CVSROOT. Клиенты, пытающиеся использовать другой каталог, не смогут соединиться. Если вы хотите разрешить доступ к нескольким каталогам CVSROOT, повторите эту опцию.

Если ваш inetd требует текстовых имен сервисов вместо номеров портов, поместите эту строчку в /etc/services:

cvspserver 2401/tcp

и напишите cvspserver вместо 2401 в файле /etc/inetd.conf.

После всего этого перезапустите inetd или заставьте его перечитать файлы конфигурации.

Так как клиент хранит и пересылает пароли практически открытым тестом (см. раздел “Прямое соединение с парольной аутентификацией”), то может использоваться отдельный файл паролей для CVS, чтобы пользователи не раскрывали своих обычных паролей при доступе к репозиторию. Этот файл — $CVSROOT/CVSROOT/passwd. В этом файле используется обычный формат строк, разделенных двоеточиями, типа того, что используется в файле /etc/passwd в Unix-системах. В этом файле несколько полей: имя пользователя CVS, необязательный пароль и необязательное имя системного пользователя, на правах которого будет работать CVS после успешной аутентификации. Вот пример файла passwd, в котором находится пять строк:

anonymous:
bach:ULtgRLXo7NRxs
spwang:1sOp854gDF3DY
melissa:tGX1fS8sun6rY:pubcvs
qproj:XR4EZcEs0szik:pubcvs

(Пароли шифруются стандартной функцией UNIX crypt(), поэтому можно просто перенести пароль из обычного файла /etc/passwd.

Первая строка в этом примере предоставляет доступ любому CVS-клиенту, пытающемуся аутентифицироваться с именем anonymous и любым паролем, включая пустой пароль. (Это обычное решение для машин, предоставляющих анонимный доступ только для чтения; информация о предоставлении доступа только для чтения находится в разделе “Доступ к репозиторию только для чтения”.

Вторая и третья строки предоставляют доступ пользователям bach и spwang, если они знают соответствующий пароль.

Четвертая строка предоставляет доступ пользователю melissa, если она знает правильный пароль. При этом сама серверная программа CVS на самом деле выполняется на правах системного пользователя pubcvs. Таким образом, в системе не требуется заводить пользователя melissa, но обязательно должен быть пользователь pubcvs.

Пятая строка демонстрирует, что системные пользователи могут использоваться совместно: любой клиент, который успешно аутентифицируется как qproj, будет работать на правах системного пользователя pubcvs, так же, как и melissa. Таким образом, вы можете создать единственного общего системного пользователя для каждого проекта в вашем репозитории, и предоставить каждому разработчику свою собственную строку в файле $CVSROOT/CVSROOT/passwd. Имя CVS-пользователя в каждой строке будет разным, но имя системного пользователя будет одним и тем же. Причина, по которой нужно иметь разные имена пользователей CVS в том, что все действия CVS будут журналироваться под этими именами: когда melissa фиксирует изменения в проекте, эта фиксация записывается в историю проекта под именем melissa, а не pubcvs. Причина, по которой следует иметь одиночного системного пользователя в том, что вы сможете задать права доступа к соответствующим каталогам репозитория так, что только этот системный пользователь будет иметь права на запись.

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

Пароль и имя системного пользователя могут отсутствовать (при отсутствии последнего не следует писать двоеточие, которое служит разделителем полей). Например, файл $CVSROOT/CVSROOT/passwd может выглядеть так:

anonymous::pubcvs
fish:rKa5jzULzmhOo:kfogel
sussman:1sOp854gDF3DY

Когда пароль пропущен или пустой, то аутентификация произойдет успешно с любым паролем, включая пустую строку. Однако, двоеточие после имени пользователя CVS всегда обязательно, даже если пароль пуст.

CVS также может использовать стандартную системную аутентификацию. При парольной аутентификации сервер сначала проверяет наличие пользователя в файле $CVSROOT/CVSROOT/passwd. Если пользователь обнаружен в этом файле, то соответствующая строка будет использована для аутентификации, как описано выше. Если же пользователь не найден, или файле passwd не существует, то сервер пытается аутентифицировать пользователя с помощью системных процедур (это "резервное" поведение может быть запрещено, установив SystemAuth=no в файле config. Помните, однако, что использование системной аутентификации может увеличить риск нарушения безопасности: операции CVS будут аутентифицироваться его обычным паролем, который будет передаваться по сети в текстовом виде. См. раздел “Вопросы безопасности при парольной аутентификации”, где описаны детали.

В настоящее время единственный способ поместить пароль в CVSROOT/passwd — это вырезать его откуда-нибудь еще. Когда-нибудь появится команда cvs passwd.

В отличие от большинства файлов в $CVSROOT/CVSROOT, обычно практикуется редактирование файла passwd прямо в репозитории, без использования CVS. Это из-за риска безопасности, связанного с извлечением этого файла в чью-нибудь рабочую копию. Если вы хотите, чтобы файл passwd извлекался вместе с остальными файлами в $CVSROOT/CVSROOT, см. раздел “Как в каталоге CVSROOT хранятся файлы”.

Использование клиента с парольной аутентификацией

Для того, чтобы выполнить команду CVS в сетевом репозитории с помощью сервера парольной аутентификации, нужно задать протокол pserver, имя пользователя, машину, на которой находится репозиторий, и путь к репозиторию. Например:

cvs -d :pserver:bach@faun.example.org:/usr/local/cvsroot checkout someproj

или

CVSROOT=:pserver:bach@faun.example.org:/usr/local/cvsroot
cvs checkout someproj

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

cvs -d :pserver:bach@faun.example.org:/usr/local/cvsroot login
CVS password: _

После того, как вы ввели пароль, CVS проверяет этот пароль на сервере. Если результат положителен, то комбинация имени пользователя, машины, пути к репозиторию и пароля сохраняются в специальном файле, чтобы при дальнейшей работе с этим репозиторием от вас не требовалось запускать cvs login. (Если результат проверки отрицателен, CVS пожалуется, что пароль неверен, и, естественно, он не будет сохранен.)

Пароли обычно хранятся в файле $HOME/.cvspass. Этот файл можно прочитать глазами, и, до какой-то степени, можно отредактировать руками. Заметьте, впрочем, что пароли не хранятся в совсем открытом виде: они тривиально закодированы, чтобы защититься от нечаянного подсматривания (например, системным администратором или кем-либо другим, не настроенным враждебно).

Изменить место расположения этого файла можно, установив переменную окружения CVS_PASSFILE. При использовании этой переменной не забудьте установить её перед использованием cvs login. Если вы этого не сделаете, то последующие команды CVS не смогут найти паролей для отправки на сервер.

После того, как вы вошли в систему, все команды CVS, использующие этот сетевой репозиторий и имя пользователя, смогут аутентифицироваться, используя этот сохраненный пароль. Поэтому, например:

cvs -d :pserver:bach@faun.example.org:/usr/local/cvsroot checkout foo

будет работать без дополнительных вопросов (если только пароль не изменится на сервере, в этому случае вам нужно ещё раз выполнить cvs login).

Заметьте, что если забыть про :pserver: в имени репозитория, то CVS будет считать, что вы собираетесь использовать rsh (см. раздел “Соединение с помощью rsh”).

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

Пароль к определенному сетевому репозиторию можно удалить из файла паролей с помощью команды cvs logout.

Вопросы безопасности при парольной аутентификации

Пароли хранятся на стороне клиента тривиально зашифрованным открытым текстом и передаются точно так же. Такое шифрование используется только для предотвращения нечаянного подсматривания пароля (например, системный администратор, случайно заглянувший в файл) и не предотвращает даже самые тривиальные атаки.

Отдельный файл паролей CVS (см. раздел “Настройка сервера для парольной аутентификации”) позволяет использовать для доступа к репозиторию пароль, отличающийся от пароля для доступа к машине. С другой стороны, если пользователь получил доступ к репозиторию для чтения и записи, он может различными способами выполнять программы на сервере. Таким образом, доступ к репозиторию означает также довольно широкий диапазон другого доступа к системе. Можно было бы модифицировать CVS, чтобы предотвратить это, но до сих пор никто этого не сделал. Более того, могут быть другие способы, которыми люди, имеющие доступ к репозиторию, получат доступ к системе; никто не производил тщательного аудита.

Заметьте, что из-за того, что каталог $CVSROOT/CVSROOT содержит passwd и прочие файлы, использующиеся в целях безопасности, нужно следить за правами доступа к этому каталогу так же хорошо, как из правами доступа к /etc. То же самое применимо к самому каталогу $CVSROOT и любому каталогу, находящему в нем. Кто угодно, получив доступ для записи в этот каталог, сможет стать любым пользователем в системе. Заметьте, что эти права доступа обычно строже при использовании pserver.

Вообще, любой, кто получает пароль, получает доступ к репозиторию, и, до некоторой степени, доступ к самой системе. Пароль доступен всем, кто может перехватить сетевые пакеты или прочитать защищенный (принадлежащий пользователю) файл. Если вы хотите настоящей безопасности, используйте Kerberos.

Прямое соединение с использованием GSSAPI

GSSAPI — это общий интерфейс к системам сетевой безопасности, таким как Kerberos 5.

Если у вас есть рабочая библиотека GSSAPI, то ваш CVS может совершать TCP-соединения с сервером, аутентифицируясь с помощью GSSAPI. Для этого CVS нужно скомпилировать с поддержкой GSSAPI; при конфигурировании CVS пытается определить, наличествуют ли в системе библиотеки GSSAPI, использующие Kerberos версии 5. Вы также можете дать configure флаг --with-gssapi.

Соединение аутентифицируется, используя GSSAPI, но сам поток данных не аутентифицируется по умолчанию. Вы должны использовать глобальный ключ командной строки -a, чтобы запросить аутентификацию потока.

Передаваемые данные по умолчанию не шифруются. Как сервер, так и клиент могут быть скомпилированы с поддержкой шифрования; используйте ключ командной строки configure --enable-encrypt. Для включения шифрования используйте ключ командной строки -x.

Соединения GSSAPI обрабатываются на стороне сервера тем же сервером, что производит парольную аутентификацию; смотри раздел “Настройка сервера для парольной аутентификации”. Если вы используете, например, Kerberos, обеспечивающий хорошую аутентификацию, вы, вероятно, захотите также устранить возможность аутентифицироваться с использованием паролей открытым текстом. Для этого создайте пустой файл CVSROOT/passwd и поместите SystemAuth=no в файл конфигурации config.

Сервер GSSAPI использует principal name cvs/имя-машины, где имя-машины — это каноническое имя сервера. Вам потребуется настроить ваш механизм GSSAPI.

Для соединения с использованием GSSAPI, используйте :gserver:. Например,

cvs -d :gserver:faun.example.org:/usr/local/cvsroot checkout foo

Прямое соединение с помощью Kerberos

Самый простой способ использования Kerberos — это kerberos rsh, что описано в разделе “Соединение с помощью rsh”. Основной недостаток использования rsh — тот, что все данные должны проходить сквозь дополнительные программы, что замедляет работу. Поэтому если у вас установлен Kerberos, вам следует использовать прямые TCP-соединения, аутентифицируясь с помощью Kerberos.

Эта глава относится к системе Kerberos версии 4. Kerberos версии 5 поддерживается посредством общего интерфейса сетевой безопасности GSSAPI, как описано в предыдущей главе.

CVS должен быть скомпилирован с поддержкой kerberos; при конфигурировании CVS пытается определить, какая версия Kerberos присутствует на машине. Вы можете также использовать ключ командной строки configure --with-krb4.

Пересылаемые данные по умолчанию не шифруются. Как клиент, так и сервер должны быть скомпилированы с использованием шифрования; используйте ключ командной строки configure --enable-encryption. Для включения шифрования используйте глобальный ключ командной строки -x.

На сервере требуется отредактировать /etc/inetd.conf, чтобы запустить cvs kserver. Клиент по умолчанию использует порт 1999; если вы хотите использовать другой порт, задайте его на клиентской машине в переменной окружения CVS_CLIENT_PORT.

Когда вы захотите использовать CVS, сначала, как обычно, получите билет (kinit); этот билет должен позволять вам зарегистрироваться на сервере. Затем выполните

cvs -d :kserver:faun.example.org:/usr/local/cvsroot checkout foo

Предыдущие версии CVS могли в случае неудачи использовать соединение с помощью rsh; текущие версии так не делают.

Использование параллельного cvs server для соединения

Этот метод доступа позволяет вам соединяться с репозиторием, находящимся на локальном диске, используя сетевой протокол. Другими словами, он делает то же самое, что и :local:, но при этом с особенностями и ошибками, существующими у сетевого, а нее локального CVS.

Для каждодневных операций вы, скорее всего, предпочтете :local: или :fork:, в зависимости от ваших предпочтений. Конечно, :fork: особенно полезен при тестировании и отладке cvs и сетевого протокола. Точнее, мы избавляемся от необходимости настройки сети, таймаутов, проблем с аутентификацией, свойственных сетевому доступа, но при этом пользуемся собственно сетевым протоколом.

Чтобы соединиться, используя метод доступа :fork:, добавьте его к имени локального репозитория, например:

cvs -d :fork:/usr/local/cvsroot checkout foo

Как и при использовании :ext:, сервер по умолчанию называется cvs. Если установлена переменная окружения CVS_SERVER, используется ее значение.