Организация на многопотребителския достъп до сървър 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 [Версия 6.1.7601]
(c) Корпорация Майкрософт (Microsoft Corp.), 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 ..." за да отнемете от инсталирането)
        нов файл:   test1.txt

C:gittest>git commit -am "нов тестов файл добавен"
[master (корен-комит) 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 от dev1, тестване на server hook"
[master b045e22] 3rd от dev1, тестване на server hook
 1 файл променен, 1 добавяне(+)

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

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

[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 добави това" >> test1.txt

C:gittest>echo "!!! dev2 написа" > test2.txt

C:gittest>git add test2.txt

C:gittest>git commit -am "dev2 добави в test1 и създаде test2"
[master 55d49a6] dev2 добави в test1 и създаде test2
 2 файла променени, 2 добавяния(+)
 създаден режим 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
Клониране в '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 на proj2"
"dev1 добави нещо ново"
"dev1 3rd line"
"!!! dev2 добави това"

C:gittestproj2>type test2.txt
"!!! dev2 написа"

Разделяне на достъпа в 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:
Към ssh://10.1.1.11/var/gitservertest/proj1
 * [нов клон]      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