Git
Chapters ▾ 1st Edition

4.7 Git на сервере - Gitosis

Gitosis

Хранение открытых ключей всех пользователей в authorized_keys для предоставления доступа работает хорошо лишь на время. Когда у вас сотни пользователей, это скорее похоже на пытку. Вы должны заходить на сервер каждый раз, и нет никакого разграничения доступа — все перечисленные в файле имеют доступ на чтение и на запись к каждому проекту.

На этой стадии вы можете захотеть обратиться к широко используемому ПО под названием Gitosis. Gitosis — это просто набор сценариев (scripts), который поможет вам управляться с файлом authorized_keys и реализовать простой контроль доступа. Действительно интересно, что добавление людей и настройка доступа для них осуществляется не через веб-интерфейс, а с помощью специального git-репозитория. Вы настраиваете информацию в этом проекте и, когда вы отправляете её в репозиторий, Gitosis, исходя из неё, перенастраивает сервер, что круто.

Установка Gitosis'а — не самая простая задача, хотя и не слишком сложная. Проще всего использовать под него Linux-сервер — в наших примерах используется сервер Ubuntu 8.10 в начальной конфигурации.

Gitosis'у нужны некоторые инструменты для Python'а, так что первым делом вы должны установить для Python'а пакет setuptools, который в Ubuntu называется python-setuptools:

$ apt-get install python-setuptools

Затем вы клонируете и устанавливаете Gitosis с главного сайта проекта:

$ git clone https://github.com/tv42/gitosis.git
$ cd gitosis
$ sudo python setup.py install

Это установит несколько исполняемых файлов, которые Gitosis будет использовать. Затем Gitosis хочет расположить свои репозитории в каталоге /home/git, что неплохо. Но вы уже установили репозитории в /opt/git, так что вместо перенастройки всего на свете вы сделаете символическую ссылку:

$ ln -s /opt/git /home/git/repositories

Gitosis будет управлять ключами за вас, так что вы должны удалить текущий файл, добавить ключи снова позже и предоставить Gitosis'у управлять файлом authorized_keys автоматически. Сейчас просто уберите этот файл с дороги:

$ mv /home/git/.ssh/authorized_keys /home/git/.ssh/ak.bak

Затем вы должны вернуть пользователю git его командную оболочку, если вы меняли её на команду git-shell. Люди всё так же не смогут выполнить вход, но для вас это будет контролировать Gitosis. Итак, давайте поменяем эту строку в файле '/etc/passwd'

git:x:1000:1000::/home/git:/usr/bin/git-shell

обратно на эту:

git:x:1000:1000::/home/git:/bin/sh

Теперь самое время инициализировать Gitosis. Сделаете это, выполнив команду gitosis-init со своим персональным открытым ключом. Если вашего открытого ключа ещё нет на сервере, вам нужно будет скопировать его туда:

$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
Initialized empty Git repository in /opt/git/gitosis-admin.git/
Reinitialized existing Git repository in /opt/git/gitosis-admin.git/

Это позволит пользователю с таким ключом изменять главный Git-репозиторий, который управляет настройками Gitosis'а. Затем вы должны вручную установить бит исполнения на сценарий post-update в новом управляющем репозитории.

$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update

Всё готово. Если вы всё настроили правильно, вы можете попытаться соединиться по SSH с вашим сервером под тем пользователем, для которого вы добавили открытый ключ, чтобы инициализировать Gitosis. Вы должны увидеть что-то вроде этого:

$ ssh git@gitserver
PTY allocation request failed on channel 0
fatal: unrecognized command 'gitosis-serve schacon@quaternion'
  Connection to gitserver closed.

Это означает, что Gitosis узнал вас, но не пустил, потому что вы не пытались выполнить ни одну из команд Git'а. Ну так давайте выполним настоящую команду Git'а — вы склонируете управляющий репозиторий Gitosis:

# на вашем локальном компьютере
$ git clone git@gitserver:gitosis-admin.git

Теперь у вас есть каталог с именем gitosis-admin, в котором есть две главные части:

$ cd gitosis-admin
$ find .
./gitosis.conf
./keydir
./keydir/scott.pub

Файл gitosis.conf — файл настройки, который используется, чтобы указать пользователей, репозитории и права доступа. В каталоге keydir должны храниться открытые ключи всех пользователей, у которых есть какой-либо доступ к вашим репозиториям — по файлу на пользователя. Имя файла в keydir (в предыдущем примере scott.pub) у вас будет отличаться — Gitosis берёт это имя из описания в конце открытого ключа, который был импортирован сценарием gitosis-init.

Если вы посмотрите в файл gitosis.conf, там должна быть указана только информация о проекте gitosis-admin, который вы только что склонировали:

$ cat gitosis.conf 
[gitosis]

[group gitosis-admin]
writable = gitosis-admin
members = scott

Это показывает, что пользователь 'scott' — пользователь, чьим открытым ключом вы инициализировали Gitosis — единственный, кто имеет доступ к проекту gitosis-admin.

А теперь давайте добавим новый проект. Добавьте новую секцию с названием mobile и перечислите в ней всех разработчиков из команды, занимающейся мобильными устройствами, а также проекты, к которым этим разработчикам нужно иметь доступ. Поскольку scott — пока что единственный пользователь в системе, добавьте его как единственного члена и создайте новый проект под названием iphone_project, чтобы ему было с чем начать работать:

[group mobile]
writable = iphone_project
members = scott

Когда вы вносите изменения в проект gitosis-admin, вы должны зафиксировать изменения и отправить их на сервер, чтобы они возымели эффект:

$ git commit -am 'add iphone_project and mobile group'
[master]: created 8962da8: "changed name"
 1 files changed, 4 insertions(+), 0 deletions(-)
$ git push
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 272 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@gitserver:/opt/git/gitosis-admin.git
   fb27aec..8962da8  master -> master

Вы можете сделать свой первый push в новый проект iphone_project, добавив свой сервер в качестве удалённого (remote) в локальную версию проекта и выполнив git push. Вам больше не нужно вручную создавать голые репозитории на сервере для новых проектов — Gitosis создаёт их сам автоматически, когда видит первый push:

$ git remote add origin git@gitserver:iphone_project.git
$ git push origin master
Initialized empty Git repository in /opt/git/iphone_project.git/
Counting objects: 3, done.
Writing objects: 100% (3/3), 230 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:iphone_project.git
 * [new branch]      master -> master

Заметьте, что вам не нужно указывать путь (фактически, если вы это сделаете, то оно не сработает), только двоеточие и имя проекта — Gitosis найдёт его за вас.

Вы хотите работать над проектом с вашими друзьями, так что вам нужно снова добавить их открытые ключи. Но вместо того, чтобы вручную добавлять их к файлу ~/.ssh/authorized_keys на вашем сервере, добавьте их, один файл на ключ, в каталог keydir. То, как вы назовёте ключи, определит, как вы будете ссылаться на пользователей в gitosis.conf. Давайте по-новому добавим открытые ключи для Джона, Джози и Джессики:

$ cp /tmp/id_rsa.john.pub keydir/john.pub
$ cp /tmp/id_rsa.josie.pub keydir/josie.pub
$ cp /tmp/id_rsa.jessica.pub keydir/jessica.pub

Теперь вы можете добавить их всех в вашу 'мобильную' команду, чтобы они имели доступ на чтение и запись в iphone_project:

[group mobile]
writable = iphone_project
members = scott john josie jessica

После того, как вы зафиксируете и отправите изменения, все четыре пользователя будут иметь возможность читать и писать в проект.

В Gitosis'е также есть простой контроль доступа. Если вы хотите, чтобы Джон имел только доступ на чтение к этому проекту, вы можете вместо этого сделать:

[group mobile]
writable = iphone_project
members = scott josie jessica

[group mobile_ro]
readonly = iphone_project
members = john

Теперь Джон может клонировать проект и получать обновления, но Gitosis не позволит ему отправлять изменения обратно в проект. Вы можете создать таких групп сколько хотите, каждую содержащую разные проекты и пользователей. Вы также можете указать другую группу в качестве одного из пользователей (используя @ как префикс), чтобы автоматически добавить всех её членов:

[group mobile_committers]
members = scott josie jessica

[group mobile]
writable  = iphone_project
members   = @mobile_committers

[group mobile_2]
writable  = another_iphone_project
members   = @mobile_committers john

Если у вас возникли какие-то проблемы, полезным может быть добавить loglevel=DEBUG в секции [gitosis]. Если вы потеряли доступ к отправке, отправив неверную конфигурацию, вы можете вручную поправить файл /home/git/.gitosis.conf на сервере — файл, из которого Gitosis читает свою информацию. Отправка в проект берёт файл gitosis.conf, который вы только что отправили, и помещает его туда. Если вы отредактируете этот файл вручную, он останется таким до следующей успешной отправки в проект gitosis-admin.