Podczas instalacji i konfiguracji serwera Git pojawia się pytanie o organizację dostępu wielu użytkowników do różnych projektów. Przeprowadziłem badania w tej kwestii i znalazłem rozwiązanie spełniające wszystkie moje wymagania: proste, bezpieczne, niezawodne.
Moje życzenia są następujące:
- każdy użytkownik łączy się na swoim własnym koncie
- nad jednym projektem może pracować kilku użytkowników
- ten sam użytkownik może pracować nad wieloma projektami
- każdy użytkownik ma dostęp tylko do tych projektów, nad którymi pracuje
- powinna być możliwość połączenia przez wiersz poleceń, a nie tylko przez jakiś interfejs webowy
Również byłoby świetnie:
- przyznawać prawa tylko do odczytu dla osób kontrolujących
- łatwo zarządzać uprawnieniami użytkowników w Git
Przegląd możliwych opcji dostępu do serwera GIT
Przede wszystkim trzeba wiedzieć, z czego wybierać, więc krótki przegląd protokołów Git.
- ssh - do dostępu do serwera wykorzystywane jest specjalnie założone konto użytkownika.
- dziwne, że Git nie wyklucza z rekomendacji użycia jednego konta do dostępu do wszystkich repozytoriów. To w żaden sposób nie spełnia moich wymagań.
- można używać kilku kont, ale jak ograniczyć dostęp użytkownika tylko do określonych katalogów?
- Zamknięcie w katalogu domowym nie jest odpowiednie, ponieważ trudno zorganizować tam dostęp do zapisu dla innych użytkowników
- Użycie linków symbolicznych z katalogu domowego również jest trudne, ponieważ Git nie interpretuje ich jako linków
- Ograniczenie dostępu do interpretera, no można, ale nie ma pełnej gwarancji, że to będzie działać zawsze
- Można w ogóle podłączyć dla takich użytkowników własny interpreter poleceń, ale,
- po 1-sze, to już jakieś skomplikowane rozwiązanie,
- a po 2-gie, można to obejść.
- Można w ogóle podłączyć dla takich użytkowników własny interpreter poleceń, ale,
Ale może to nie jest problem, że użytkownik będzie mógł wykonywać dowolne polecenia?.. W każdym razie, nie można wykluczyć tej metody, jeśli wymyślić, jak dokładnie jej używać. Do tego sposobu wrócimy później, a teraz krótko rozważmy inne alternatywy, może tam będzie coś prostszego.
- Protokół git local może być używany w połączeniu z sshfs, można używać kilku użytkowników, ale w zasadzie jest to to samo, co poprzedni przypadek
- http — tylko do odczytu
- git — tylko do odczytu
- https — trudny do zainstalowania, potrzebne jest dodatkowe oprogramowanie, coś panelu administracyjnego do organizacji dostępu użytkowników… wygląda na wykonalne, ale jest jakoś skomplikowane.
Użycie protokołu ssh do organizacji wieloużytkownikowego dostępu do serwera Git
Wróćmy do protokołu ssh.
Ponieważ używany jest dostęp przez ssh do git, należy zapewnić bezpieczeństwo danych na serwerze. Użytkownik, który łączy się przez ssh, korzysta z własnego loginu na serwerze Linux, dzięki czemu może połączyć się za pomocą klienta ssh i uzyskać dostęp do wiersza poleceń serwera.
Nie ma pełnej ochrony przed uzyskaniem takiego dostępu.
Jednak dla użytkownika pliki Linux nie powinny być interesujące. Znaczące informacje przechowywane są tylko w repozytorium git. Dlatego nie ma potrzeby ograniczania dostępu do wiersza poleceń, ale za pomocą Linuxa można zabronić użytkownikowi przeglądania projektów, z wyjątkiem tych, w których bierze udział.
Oczywiste jest użycie systemu uprawnień Linuxa.
Jak już wspomniano, możliwe jest użycie tylko jednego konta do dostępu ssh. Taka konfiguracja nie jest bezpieczna dla wielu użytkowników, chociaż metoda ta jest wymieniana wśród rekomendowanych opcji git.
Aby zrealizować wymagania przedstawione na początku artykułu, tworzy się następującą strukturę katalogów z przypisaniem uprawnień i właścicieli:
1) katalogi projektów
dir1(proj1:proj1,0770)
dir2(proj2:proj2,0770)
dir3(proj3:proj3,0770)
…
gdzie
dir1, dir2, dir3 — katalogi projektów: projekt 1, projekt 2, projekt 3.
proj1:proj1, proj2:proj2, proj3:proj3 — specjalnie utworzeni użytkownicy Linuxa, którzy zostają przypisani jako właściciele odpowiednich katalogów projektów.
uprawnienia do wszystkich katalogów są ustawiane na 0770 — pełny dostęp dla właściciela i jego grupy oraz całkowity zakaz dla wszystkich innych.
2) konta programistów
Programista 1: dev1:dev1,proj1,proj2
Programista 2: dev2:dev2,proj2,proj3
Kluczowym punktem jest to, że programistom przypisywana jest dodatkowa grupa systemowego użytkownika-właściciela odpowiedniego projektu. Robi to administrator serwera Linux jedną komendą.
W tym przykładzie, „Programista 1” pracuje nad projektami proj1 i proj2, a „Programista 2” nad projektami proj2 i proj3.
Jeśli którykolwiek z Programistów połączy się przez ssh za pomocą wiersza poleceń, jego uprawnienia będą niewystarczające nawet do przeglądania zawartości katalogów projektów, w których nie uczestniczy. Nie może tego sam zmienić.
Ponieważ podstawą tej zasady jest podstawowe bezpieczeństwo praw Linux, ten schemat jest niezawodny. Poza tym schemat jest bardzo łatwy do zarządzania.
Przejdźmy do praktyki.
Tworzenie repozytoriów Git na serwerze Linux
Sprawdzamy.
[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
mam dość ręcznego wprowadzania…
[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 dev2Upewnij się, że z wiersza poleceń nie można uzyskać dostępu do cudzych repozytoriów ani nawet przeglądać ich zawartości.
[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 deniedWspółpraca kilku programistów w Git nad jednym projektem
Pozostaje jedno pytanie, jeśli jeden programista wprowadza nowy plik, inni programiści nie mogą go zmieniać, ponieważ sam jest jego właścicielem (na przykład, dev1), a nie użytkownikiem będącym właścicielem projektu (na przykład, proj1). Ponieważ mamy repozytorium serwerowe, przede wszystkim trzeba wiedzieć, jak zorganizowany jest katalog „.git” i czy tworzone są nowe pliki.
Tworzenie lokalnego repozytorium Git i push na serwer Git
Przejdźmy na komputer kliencki.
Microsoft Windows [Version 6.1.7601]
(c) Microsoft Corporation, 2009. Wszelkie prawa zastrzeżone.
C:gittest>git init .
Zainicjowano pustą repozytorium Git w C:\/gittest\/git\.
C:gittest>echo "test dev1 do proj2" > test1.txt
C:gittest>git add .
C:gittest>git status
Na gałęzi master
Brak commitów
Zmiany do zatwierdzenia:
(użyj "git rm --cached <plik>..." aby odznaczyć)
nowy plik: test1.txt
C:gittest>git commit -am "dodano nowy plik testowy"
[master (root-commit) a7ac614] dodano nowy plik testowy
1 plik zmieniony, 1 dodanie(+)
utworzono tryb 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 password:
Liczenie obiektów: 3, zrobione.
Pisanie obiektów: 100% (3\/3), 243 bajty | 243.00 KiB\/s, zrobione.
Razem 3 (delta 0), powtórzono 0 (delta 0)
Do ssh:\/\/10.1.1.11\/var\/gitservertest\/proj2
* [nowa gałąź] master -> master
C:gittest>W tym samym czasie na serwerze tworzone są nowe pliki, a ich właścicielem jest użytkownik, który wykonał 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 katalogów, 18 plików
[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]$Podczas przesyłania zmian na serwer Git tworzy dodatkowe pliki i katalogi, a ich właścicielem jest rzeczywiście ten użytkownik, który dokonuje przesyłania. Ale w takim przypadku grupa tych plików i katalogów również odpowiada głównej grupie tego użytkownika, to znaczy, grupa dev1 dla użytkownika dev1 i grupa dev2 dla użytkownika dev2 (zmiana głównej grupy użytkownika-dewelopera nie pomoże, ponieważ w przeciwnym razie trudno będzie pracować nad wieloma projektami?). W takim przypadku użytkownik dev2 nie będzie mógł zmieniać plików stworzonych przez użytkownika dev1, co może prowadzić do problemów z funkcjonalnością.
Linux chown — zmiana właściciela pliku przez zwykłego użytkownika.
Właściciel pliku nie może zmieniać jego przynależności. Może jednak zmienić grupę pliku, do której należy, co pozwoli innym użytkownikom w tej samej grupie na modyfikację tego pliku. To właśnie jest to, czego potrzebujemy.
Używanie Git hook
Katalogiem roboczym dla hooka jest katalog główny projektu. Hook to plik wykonywalny, który uruchamiany jest przez użytkownika, który wykonuje push. Wiedząc to, możemy zrealizować nasze zamierzenia.
[dev1@server proj2]$ mv hooks/post-update{.sample,}
[dev1@server proj2]$ sed -i '2,$ s/^/#/' hooks/post-update
[dev1@server proj2]$ cat <> hooks/post-updatelub po prostu
vi hooks/post-updateWrócimy na maszynę kliencką.
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 zmieniony, 1 dodanie(+)
C:gittest>git push origin master
dev1:dev1@10.1.1.11's password:
d22c66e..b045e22 master -> masterNa serwerze Git sprawdzamy działanie skryptu hook post-update po commicie.
[dev1@server proj2]$ find . ! -group proj2
— pusto, wszystko w porządku.
Dodanie drugiego dewelopera do Git
Symulujemy pracę drugiego dewelopera.
Na kliencie
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 pliki zmienione, 2 dodania(+)
nowy tryb 100644 test2.txt
C:gittest>git push origin master
dev2@10.1.1.11's password:
b045e22..55d49a6 master -> master
A w tym samym czasie, na serwerze…
[dev1@server proj2]$ find . ! -group proj2
— znów pusto, wszystko działa.
Usunięcie projektu Git i pobranie projektu z serwera Git
Możemy jeszcze raz upewnić się, że wszystkie zmiany zostały zapisane.
C:gittest>rd /S /Q .
Proces nie może uzyskać dostępu do pliku, ponieważ ten plik jest używany przez inny proces.— aby usunąć projekt Git, po prostu całkowicie opróżniamy katalog. Pogodzimy się z generowanym błędem, ponieważ nie można usunąć bieżącego katalogu przy tym poleceniu, ale takie zachowanie jest dokładnie tym, czego potrzebujemy.
C:gittest>dir
Zawartość folderu 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
Klonowanie do 'proj2'...
dev2@10.1.1.11's password:
C:gittest>cd proj2
C:gittestproj2>dir
Zawartość folderu 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 do proj2"
"dev1 dodał coś więcej"
"dev1 3-ci wiersz"
"!!! dev2 dodał to"
C:gittestproj2>type test2.txt
"!!! dev2 napisał"Podział dostępu w Git
Teraz upewnijmy się, że również przez Git drugi deweloper nie może uzyskać dostępu do projektu Proj1, nad którym nie pracuje.
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' nie wydaje się być repozytorium git
fatal: Nie można odczytać z zdalnego repozytorium.
Upewnij się, że masz odpowiednie uprawnienia dostępu
oraz że repozytorium istnieje.Teraz zezwalamy na dostęp
[root@server ~]# usermod -aG proj1 dev2i po tym wszystkim wszystko działa.
C:gittestproj2>git push origin master
dev2@10.1.1.11's password:
Do ssh://10.1.1.11/var/gitservertest/proj1
* [nowa gałąź] master -> masterDodatkowe informacje
Dodatkowo, jeśli występuje problem z domyślnymi prawami przy tworzeniu plików i katalogów, w CentOS można skorzystać z polecenia
setfacl -Rd -m o::5 -m g::7 /var/gitservertestW artykule możesz również natknąć się na drobne przydatne rzeczy:
- jak w systemie Linux zbudować drzewo katalogów
- jak w sed przekazać zakres adresów od określonej linii do końca pliku, czyli jak w sed wykonać zamianę we wszystkich liniach z wyjątkiem pierwszej linii
- Jak w systemie Linux zainvertować warunek wyszukiwania przy użyciu find
- jak w powłoce Linux przekazać do pętli kilka linii przez jednoliniowe polecenie
- jak w bashu uciekać od pojedynczych cudzysłowów
- jak w wierszu poleceń Windows usunąć katalog ze wszystkimi jego zawartościami
- Jak za pomocą bash mv zmienić nazwę pliku, nie zapisując go ponownie
Dziękujemy za uwagę.
Źródło: habr.com
