Арганізацыя шматкарыстальніцкага доступу на сервер GIT

Пры ўсталёўцы і канфігураванні Git-сервера ўстае пытанне аб арганізацыі доступу некалькіх карыстачоў да некалькіх праектаў. Я правёў даследаванне пытання і знайшоў рашэнне, якое адпавядае ўсім маім патрабаванням: простае, бяспечнае, надзейнае.

Мае пажаданні такія:

  • кожны карыстач падлучаецца са сваім уласным акаўнтам
  • над адным праектам можа працаваць некалькі карыстальнікаў
  • адзін і той жа карыстач можа працаваць над некалькімі праектамі
  • кожны карыстач мае доступ толькі ў тыя праекты, над якімі ён працуе
  • павінна быць магчымасць падключэння праз камандны радок, а не толькі праз нейкі вэб-інтэрфейс

Таксама было б выдатна:

  • прадастаўляць правы толькі для чытання для кантралюючых асоб
  • зручна адміністраваць правы доступу карыстальнікаў у Git

Агляд магчымых варыянтаў доступу на GIT сервер

Перш за ўсё трэба ведаць, з чаго выбіраць, таму кароткі агляд пратаколаў Git.

  • ssh - для доступу да сервера выкарыстоўваецца спецыяльна заведзены рахунак карыстальніка.
    • дзіўна, што Git не выключае з рэкамендацый выкарыстанне аднаго акаўнта для доступу да ўсіх рэпазітароў. Гэта ніяк не адпавядае маім патрабаванням.
    • можна выкарыстоўваць некалькі акаўнтаў, але як абмежаваць доступ карыстальніка толькі пэўнымі дырэкторыямі?
      • Закрыццё ў хатнюю дырэкторыю не падыходзіць, таму што складана арганізаваць туды доступ на запіс для іншых карыстальнікаў.
      • Выкарыстанне сімвалічных спасылак з хатняй дырэкторыі таксама складана з-за таго, што Git не інтэрпрэтуе іх як спасылкі.
      • Абмежаваць доступ да інтэрпрэтатара, ну можна, але няма поўнай гарантыі, што гэта будзе працаваць заўсёды
        • Можна наогул падлучыць для такіх карыстачоў свой інтэрпрэтатар каманд, але,
          • па-першае, гэта ўжо нейкае складанае рашэнне,
          • а ў 2-х, гэта можна абыйсці.

    Але, можа быць, гэта не з'яўляецца праблемай, што карыстач зможа выконваць любыя каманды?.. Увогуле, нельга выключаць гэты метад, калі прыдумаць, як менавіта яго выкарыстоўваць. Вернемся да гэтага спосабу пазней, а пакуль коратка разгледзім астатнія альтэрнатывы, можа быць там будзе нешта прасцейшае.

  • git local пратакол можа быць выкарыстаны ў спалучэнні з 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 Corp.), 2009. Все права защищены.

C:gittest>git init .
Initialized empty Git repository in C:/gittest/.git/

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

C:gittest>git add .

C:gittest>git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   test1.txt

C:gittest>git commit -am "new test file added"
[master (root-commit) a7ac614] new test file added
 1 file changed, 1 insertion(+)
 create mode 100644 test1.txt
 
C:gittest>git remote add origin "ssh://[email protected]/var/gitservertest/proj2"

C:gittest>git push origin master
dev1:[email protected]'s password:
Counting objects: 3, done.
Writing objects: 100% (3/3), 243 bytes | 243.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://10.1.1.11/var/gitservertest/proj2
 * [new branch]      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 directories, 18 files
[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 <<< 'find . -group $(whoami) -exec chgrp proj2 '"'"'{}'"'"' ;' >> 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:[email protected]'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://[email protected]/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
[email protected]'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    <DIR>          .
21.06.2019  08:43    <DIR>          ..

C:gittest>git clone ssh://[email protected]/var/gitservertest/proj2
Cloning into 'proj2'...
[email protected]'s password:

C:gittest>cd proj2

C:gittestproj2>dir
 Содержимое папки C:gittestproj2

21.06.2019  08:46    <DIR>          .
21.06.2019  08:46    <DIR>          ..
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://[email protected]/var/gitservertest/proj1"

C:gittestproj2>git push origin master
[email protected]'s password:
fatal: '/var/gitservertest/proj1' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Цяпер дазваляем доступ

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

і пасля гэтага ўсё працуе.

C:gittestproj2>git push origin master
[email protected]'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

Дадаць каментар