При настройката и конфигурирането на 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
