Организация на многопотребителски достъп до GIT сървър

При инсталиране и конфигуриране на Git сървър възниква въпросът как да се организира достъпът на множество потребители до няколко проекта. Направих проучване по въпроса и намерих решение, което отговаря на всички мои изисквания: просто, безопасно и надеждно.

Моите желания са следните:

  • всеки потребител да се свързва със собствен акаунт
  • над един проект да могат да работят няколко потребители
  • един и същ потребител да може да работи над множество проекти
  • всеки потребител да има достъп само до тези проекти, по които работи
  • да има възможност за свързване чрез команден ред, а не само през уеб интерфейс

Също така би било чудесно:

  • да се предоставят права само за четене на контролиращите лица
  • удобно администриране на правата на достъп на потребителите в Git

Преглед на възможните опции за достъп до GIT сървър

Преди всичко, трябва да знаем какво да изберем, затова е направен кратък преглед на протоколите Git.

  • ssh — за достъп до сървъра се използва специално създаден акаунт на потребител.
    • странно е, че Git не изключва от препоръките използването на един акаунт за достъп до всички репозитории. Това изобщо не отговаря на моите изисквания.
    • може да се използват множество акаунти, но как да ограничим достъпа на потребителя само до определени директории?
      • Заключването в домашната директория не става, защото е трудно да се организира достъп за запис на други потребители
      • Използването на символични линкове от домашната директория също е сложно, защото Git не ги интерпретира като линкове
      • Ограничаването на достъпа до интерпретатора е възможно, но няма пълна гаранция, че това винаги ще работи
        • Може изобщо да се свърже собствен интерпретатор за такива потребители, но,
          • първо, това вече е някакво сложно решение,
          • а второ, това може да бъде заобиколено.

    Но, може би, не е проблем потребителят да може да изпълнява всякакви команди?.. Общо взето, не бива да изключваме този метод, ако измислим как точно да го използваме. Нека се върнем на този метод по-късно, а засега накратко да разгледаме останалите алтернативи, може би там ще намерим нещо по-просто.

  • Git локалният протокол може да бъде използван в комбинация с sshfs, може да се използват няколко потребители, но по същество това е същото, както в предишния случай.
  • HTTP — само за четене.
  • Git — само за четене.
  • HTTPS — трудно за настройка, нужно е допълнително софтуерно осигуряване, нещо. управляваща панел За организиране на достъпа на потребителите… изглежда реализируемо, но всичко е малко сложно.

Използването на SSH протокол за организиране на многопотребителски достъп до Git сървър.

Нека се върнем към SSH протокола.

Тъй като се използва достъп по SSH за Git, трябва да осигурим сигурност на данните на сървъра. Потребителят, който се свързва по SSH, използва собствено име на потребител на сървър Linux, затова може да се свърже чрез SSH клиент и да получи достъп до командния ред на сървъра.
Няма пълна защита от получаване на такъв достъп.

Но за потребителя не трябва да бъдат интересни файловете на Linux. Значимата информация се съхранява само в Git репозитория. Затова може да не ограничавате достъпа чрез командния ред, но чрез средствата на Linux да забраните на потребителя да вижда проектите, с изключение на тези, в които участва.
Очевидно е, че трябва да се използва системата за права на достъп на Linux.

Както вече беше споменато, е възможно да се използва само един акаунт за SSH достъп. Тази конфигурация е небезопасна за няколко потребители, въпреки че този начин е включен в списъка с препоръчителни Git варианти.

За изпълнението на изискванията, посочени в началото на статията, се създава следната структура на директории с назначаване на права и собственици:

1) директории на проектите.

dir1(proj1:proj1,0770)
dir2(proj2:proj2,0770)
dir3(proj3:proj3,0770)
…
където
dir1, dir2, dir3 — директории на проектите: проект 1, проект 2, проект 3.

proj1:proj1, proj2:proj2, proj3:proj3 — специално създадени Linux потребители, които са назначени за собственици на директориите на съответните проекти.

Права на всички директории се задават на 0770 — пълен достъп за собственика и неговата група и пълен забранен достъп за всички останали.

2) акаунти на разработчиците.

Разработчик 1: dev1:dev1,proj1,proj2.
Разработчик 2: dev2:dev2,proj2,proj3.

Ключовият момент е, че на разработчиците се назначава допълнителна група на системния потребител-собственик на съответния проект. Това се прави от администратора на Linux сървъра с една команда.

В този пример, „Разработчик 1“ работи по проектите proj1 и proj2, а „Разработчик 2“ работи по проектите proj2 и proj3.

Ако някой от разработчиците се свърже по ssh чрез командния ред, правата му няма да са достатъчни дори за преглед на съдържанието на директорийте на проектите, в които не участва. Той не може да промени това сам.

Тъй като основата на този принцип е базовата безопасност на правата в Linux, тази схема е надеждна. Освен това, схемата е много лесна за администриране.

Да преминем към практиката.

Създаване на Git репозитории на Linux сървър

Проверяваме.

[root@server ~]# cd /var/
[root@server var]# useradd gitowner
[root@server var]# mkdir gitservertest
[root@server var]# chown gitowner:gitowner gitservertest
[root@server var]# adduser proj1
[root@server var]# adduser proj2
[root@server var]# adduser proj3
[root@server var]# adduser dev1
[root@server var]# adduser dev2
[root@server var]# passwd dev1
[root@server var]# passwd dev2

омръзна ми да въвеждам ръчно…

[root@server gitservertest]# sed "s/ /n/g" <<< "proj1 proj2 proj3" | while read u; do mkdir $u; chown $u:$u $u; chmod 0770 $u; done

[root@server gitservertest]# usermod -aG proj1 dev1
[root@server gitservertest]# usermod -aG proj2 dev1
[root@server gitservertest]# usermod -aG proj2 dev2
[root@server gitservertest]# usermod -aG proj3 dev2

Убеждаваме се, че от командния ред не може да се получи достъп до чужди репозитории и дори да се види съдържанието им.

[dev1@server ~]$ cd /var/gitservertest/proj3
-bash: cd: /var/gitservertest/proj3: Permission denied
[dev1@server ~]$ ls /var/gitservertest/proj3
ls: cannot open directory /var/gitservertest/proj3: Permission denied

Съвместна работа в Git на няколко разработчици по един проект

Остава един въпрос, ако един разработчик създаде нов файл, останалите разработчици не могат да го променят, защото той самият е собственик на файла (например, dev1), а не потребител-собственик на проекта (например, proj1). Тъй като имаме сървърен репозиторий, на първо място е нужно да знаем как е структурирана директория „.git“ и дали се създават нови файлове.

Създаване на локален Git репозиторий и push на Git сървър

Да преминем на клиентската машина.

Microsoft Windows [Version 6.1.7601]
(c) Microsoft Corporation, 2009. Всички права запазени.

C:gittest>git init .
Инициализирана празна Git репозитория в C: \/gittest\/ .git\/ 

C:gittest>echo "test dev1 to proj2" > test1.txt

C:gittest>git add .

C:gittest>git status
На клон master
Все още няма комити
Промени, които трябва да бъдат ангажирани:
  (използвайте "git rm --cached <file>..." за да премахнете от етапа)
        нов файл:   test1.txt

C:gittest>git commit -am "нов тестов файл добавен"
[master (root-commit) a7ac614] нов тестов файл добавен
 1 файл променен, 1 вставка(+)
 създаден режим 100644 test1.txt
 
C:gittest>git remote add origin "ssh:\/\/dev1@10.1.1.11\/var\/gitservertest\/proj2"

C:gittest>git push origin master
dev1:dev1@10.1.1.11's парола:
Броене на обекти: 3, готово.
Записване на обекти: 100% (3\/3), 243 байта | 243.00 KiB\/s, готово.
Общо 3 (делта 0), повторно използвани 0 (делта 0)
До ssh:\/\/10.1.1.11\/var\/gitservertest\/proj2
 * [нов клон]      master -> master

C:gittest>

В същото време на сървъра се създават нови файлове, и те принадлежат на потребителя, който е направил push.

[dev1@server proj2]$ tree
.
├── 1.txt
├── branches
├── config
├── description
├── HEAD
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── prepare-commit-msg.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── 75
│   │   └── dcd269e04852ce2f683b9eb41ecd6030c8c841
│   ├── a7
│   │   └── ac6148611e69b9a074f59a80f356e1e0c8be67
│   ├── f0
│   │   └── 82ea1186a491cd063925d0c2c4f1c056e32ac3
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

12 директории, 18 файлове
[dev1@server proj2]$ ls -l objects\/75\/dcd269e04852ce2f683b9eb41ecd6030c8c841
-r--r--r--. 1 dev1 dev1 54 Jun 20 14:34 objects\/75\/dcd269e04852ce2f683b9eb41ecd6030c8c841
[dev1@server proj2]$

При качване на промени на сървъра Git се създават допълнителни файлове и директории, и техният собственик наистина е този потребител, който качва. Но тогава и групата на тези файлове и директории също съответства на основната група на този потребител, тоест, групата dev1 за потребителя dev1 и групата dev2 за потребителя dev2 (смяната на основната група на разработчика няма да помогне, тъй като как тогава да работим по няколко проекта?). В такъв случай, потребителят dev2 не може да променя файлове, създадени от потребителя dev1, и това е свързано с нарушаване на функционалността.

Linux chown — промяна на собствеността на файла от обикновен потребител.

Собственикът на файла не може да променя неговата принадлежност. Но той може да промени групата на файла, който му принадлежи, и тогава този файл може да бъде достъпен за промяна от други потребители, които са в същата група. Това е, което ни трябва.

Използване на Git hook

Рабочата директория за hook е коренната директория на проекта. hook е изпълним файл, който се изпълнява под потребителя, който прави push. Знаейки това, можем да реализираме замисъла.

[dev1@server proj2]$ mv hooks/post-update{.sample,}
[dev1@server proj2]$ sed -i '2,$ s/^/#/' hooks/post-update
[dev1@server proj2]$ cat <<> hooks/post-update

или просто

vi hooks/post-update

Да се върнем на клиентския компютър.

C:gittest>echo "dev1 3rd line" >> test1.txt

C:gittest>git commit -am "3rd from dev1, testing server hook"
[master b045e22] 3rd from dev1, testing server hook
 1 file changed, 1 insertion(+)

C:gittest>git push origin master
dev1:dev1@10.1.1.11's password:
   d22c66e..b045e22  master -> master

На Git сървъра проверяваме след commit работата на скрипта post-update hook.

[dev1@server proj2]$ find . ! -group proj2

— празно, всичко е наред.

Свързване на втория разработчик в Git

Нека симулираме работата на втория разработчик.

На клиента

C:gittest>git remote remove origin

C:gittest>git remote add origin "ssh://dev2@10.1.1.11/var/gitservertest/proj2"

C:gittest>echo "!!! dev2 added this" >> test1.txt

C:gittest>echo "!!! dev2 wrote" > test2.txt

C:gittest>git add test2.txt

C:gittest>git commit -am "dev2 added to test1 and created test2"
[master 55d49a6] dev2 added to test1 and created test2
 2 files changed, 2 insertions(+)
 create mode 100644 test2.txt

C:gittest>git push origin master
dev2@10.1.1.11's password:
   b045e22..55d49a6  master -> master

А по същото време, на сървъра…

[dev1@server proj2]$ find . ! -group proj2

— отново празно, всичко работи.

Изтриване на проекта Git и качване на проекта от Git сървъра

Можем още веднъж да се уверим, че всичките промени са запазени.

C:gittest>rd /S /Q .
Процесът не може да получи достъп до файла, тъй като файлът е зает от друг процес.

— за изтриване на Git проекта просто изчистваме директорията напълно. Ще приемем генерираната грешка, тъй като не можем да изтрием текущата директория с тази команда, но такова поведение точно ни трябва.

C:gittest>dir
 Съдържание на папката C:gittest

21.06.2019  08:43              .
21.06.2019  08:43              ..

C:gittest>git clone ssh://dev2@10.1.1.11/var/gitservertest/proj2
Cloning into 'proj2'...
dev2@10.1.1.11's password:

C:gittest>cd proj2

C:gittestproj2>dir
 Съдържание на папката C:gittestproj2

21.06.2019  08:46              .
21.06.2019  08:46              ..
21.06.2019  08:46               114 test1.txt
21.06.2019  08:46                19 test2.txt
C:gittestproj2>type test1.txt
"test dev1 to proj2"
"dev1 added some omre"
"dev1 3rd line"
"!!! dev2 added this"

C:gittestproj2>type test2.txt
"!!! dev2 wrote"

Разделяне на достъпа в Git

Сега да видим, че и през Git вторият разработчик не може да получи достъп до проекта Proj1, за който не работи.

C:gittestproj2>git remote remove origin

C:gittestproj2>git remote add origin "ssh://dev2@10.1.1.11/var/gitservertest/proj1"

C:gittestproj2>git push origin master
dev2@10.1.1.11's password:
fatal: '/var/gitservertest/proj1' не кажется git репозиторием
fatal: Не удалось прочитать из удаленного репозитория.

Пожалуйста, убедитесь, что у вас есть правильные права доступа
и что репозиторий существует.

Сега разрешаваме достъп

[root@server ~]# usermod -aG proj1 dev2

и след това всичко работи.

C:gittestproj2>git push origin master
dev2@10.1.1.11's password:
To ssh://10.1.1.11/var/gitservertest/proj1
 * [new branch]      master -> master

Допълнителна информация

В допълнение, ако има проблем с правата по подразбиране при създаване на файлове и директории, в CentOS може да се използва командата

setfacl -Rd -m o::5 -m g::7 /var/gitservertest

Също така в статията може да се натъкнете на малки полезни неща:

  • как в Linux да се построи дърво от каталози
  • как в sed да се предаде диапазон адреси от определена линия до края на файла, тоест, да се направи замяна в sed във всички линии, освен в първата
  • Как в Linux find да се инвертира условието за търсене
  • как в Linux shell да се предадат в цикъл няколко реда чрез едноредовка
  • как в bash да се екранират единични кавички
  • как в командния ред на Windows да се изтрие директория с всичкото съдържание
  • Как с помощта на bash mv да се преименува файл, без да се записва отново

Благодаря за вниманието.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster