Organizacja dostępu wielu użytkowników do serwera GIT

Podczas instalacji i konfiguracji serwera Git pojawia się pytanie o zorganizowanie dostępu kilku użytkowników do kilku projektów. Zbadałem problem i znalazłem rozwiązanie, które spełniło wszystkie moje wymagania: proste, bezpieczne, niezawodne.

Moje życzenia to:

  • każdy użytkownik łączy się ze swoim kontem
  • 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
  • Powinno być możliwe połączenie za pomocą wiersza poleceń, a nie tylko poprzez jakiś interfejs sieciowy

Byłoby też świetnie:

  • przyznaj uprawnienia tylko do odczytu osobom kontrolującym
  • Wygodnie zarządzaj prawami dostępu użytkowników w Git

Przegląd możliwych opcji dostępu do serwera GIT

Przede wszystkim musisz wiedzieć, z czego wybierać, dlatego oto krótki przegląd protokołów Git.

  • ssh - do uzyskania dostępu do serwera wykorzystywane jest specjalnie utworzone konto użytkownika.
    • Dziwne, że Git nie wyklucza ze swoich rekomendacji używania jednego konta w celu uzyskania dostępu do wszystkich repozytoriów. To zupełnie nie spełnia moich wymagań.
    • Możesz korzystać z wielu kont, ale jak ograniczyć dostęp użytkowników tylko do wybranych katalogów?
      • Zamykanie katalogu domowego nie jest wskazane, ponieważ trudno jest zorganizować tam dostęp do zapisu dla innych użytkowników
      • Używanie dowiązań symbolicznych z katalogu domowego jest również trudne, ponieważ Git nie interpretuje ich jako dowiązań
      • Można ograniczyć dostęp do tłumacza, jednak nie ma pełnej gwarancji, że zawsze będzie to działać
        • Ogólnie rzecz biorąc, możesz podłączyć własny interpreter poleceń dla takich użytkowników, ale
          • po pierwsze, jest to już dość trudna decyzja,
          • po drugie, można to obejść.

    Ale może to nie problem, że użytkownik będzie mógł wykonać dowolne polecenia?.. W sumie nie można wykluczyć tej metody, jeśli dokładnie się domyślimy, jak jej używać. Do tej metody wrócimy później, ale na razie pokrótce rozważymy inne alternatywy, może będzie coś prostszego.

  • Lokalnego protokołu git można używać w połączeniu z sshfs, można używać wielu użytkowników, ale zasadniczo tak samo jak w poprzednim przypadku
  • http – tylko do odczytu
  • git jest tylko do odczytu
  • https - trudny w instalacji, potrzebne jest dodatkowe oprogramowanie, jakiś panel kontrolny do organizacji dostępu użytkowników... wygląda to na wykonalne, ale jakoś wszystko jest skomplikowane.

Używanie protokołu ssh do organizowania dostępu wielu użytkowników do serwera Git

Wróćmy do protokołu ssh.

Ponieważ używasz dostępu ssh dla git, musisz zadbać o bezpieczeństwo danych serwera. Użytkownik łączący się przez ssh używa własnego loginu na serwerze Linux, dzięki czemu może połączyć się za pośrednictwem klienta ssh i uzyskać dostęp do wiersza poleceń serwera.
Nie ma pełnej ochrony przed takim dostępem.

Ale użytkownik nie powinien być zainteresowany plikami Linuksa. Istotne informacje przechowywane są wyłącznie w repozytorium git. Można zatem nie ograniczać dostępu poprzez linię poleceń, lecz za pomocą narzędzi linuksowych uniemożliwić użytkownikowi przeglądanie projektów, z wyłączeniem tych, w których uczestniczy.
Oczywistym wyborem jest użycie systemu uprawnień Linux.

Jak już wspomniano, możliwe jest użycie tylko jednego konta do dostępu ssh. Ta konfiguracja jest niebezpieczna dla kilku użytkowników, chociaż znajduje się na liście zalecanych opcji git.

Aby zrealizować wymagania podane na początku artykułu, tworzona jest następująca struktura katalogów z przypisaniem praw i właścicieli:

1) katalogi projektów

katalog1(proj1:proj1,0770)
katalog2(proj2:proj2,0770)
katalog3(proj3:proj3,0770)
...
gdzie
dir1, dir2, dir3 - katalogi projektów: projekt 1, projekt 2, projekt 3.

proj1:proj1, proj2:proj2, proj3:proj3 to specjalnie stworzeni użytkownicy Linuksa, którzy są przypisani jako właściciele odpowiednich katalogów projektu.

uprawnienia do wszystkich katalogów są ustawione na 0770 - pełny dostęp dla właściciela i jego grupy oraz całkowity zakaz dla wszystkich innych.

2) konta deweloperskie

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

Kluczową kwestią jest to, że programistom przydzielana jest dodatkowa grupa użytkowników systemu, właścicieli odpowiedniego projektu. Dokonuje tego administrator serwera Linux za pomocą jednego polecenia.

W tym przykładzie „Programista 1” pracuje nad projektami proj1 i proj2, a „Programista 2” pracuje nad projektami proj2 i proj3.

Jeśli którykolwiek z Deweloperów połączy się przez ssh z linii poleceń, wówczas jego uprawnienia nie będą wystarczające nawet do przeglądania zawartości katalogów projektu, w którym nie uczestniczą. Sam nie jest w stanie tego zmienić.

Ponieważ podstawą tej zasady jest podstawowe bezpieczeństwo praw Linuksa, schemat ten jest niezawodny. Ponadto schemat jest bardzo łatwy w administrowaniu.

Przejdźmy do praktyki.

Tworzenie repozytoriów Git na serwerze Linux

Sprawdźmy.

[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 już dość ręcznego pisania...

[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

Jesteśmy przekonani, że nie da się uzyskać dostępu do repozytoriów innych osób z wiersza poleceń, a nawet przeglądać ich zawartość.

[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

Współpracuj z wieloma programistami nad tym samym projektem w Git

Pozostaje pytanie, jeśli jeden programista wprowadzi nowy plik, to inni programiści nie będą mogli go zmienić, ponieważ on sam jest jego właścicielem (na przykład dev1), a nie właścicielem użytkownika projektu (na przykład proj1). Ponieważ mamy repozytorium po stronie serwera, przede wszystkim musimy wiedzieć, jak zbudowany jest katalog „.git” i czy tworzone są nowe pliki.

Tworzenie lokalnego repozytorium Git i wypychanie na serwer Git

Przejdźmy do komputera klienckiego.

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>

Jednocześnie na serwerze powstają nowe pliki, które należą do użytkownika, 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 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]$

Kiedy przesyłasz zmiany na serwer Git, tworzone są dodatkowe pliki i katalogi, a ich właścicielem jest w rzeczywistości użytkownik, który przesyła zmiany. Ale wtedy grupa tych plików i katalogów odpowiada również głównej grupie tego użytkownika, czyli grupie dev1 dla użytkownika dev1 i grupie dev2 dla użytkownika dev2 (zmiana głównej grupy użytkownika dewelopera nie pomoże, bo w takim razie jak można pracować nad wieloma projektami?). W takim przypadku użytkownik dev2 nie będzie mógł zmieniać plików utworzonych przez użytkownika dev1, co może prowadzić do awarii funkcjonalności.

Chown Linux - zmiana właściciela pliku przez zwykłego użytkownika

Właściciel pliku nie może zmienić jego własności. Może jednak zmienić grupę pliku, który do niego należy, a wtedy plik ten będzie mógł być modyfikowany przez innych użytkowników znajdujących się w tej samej grupie. Właśnie tego potrzebujemy.

Korzystanie z haka Git

Katalog roboczy haka jest katalogiem głównym projektu. hook to plik wykonywalny, który działa pod użytkownikiem wykonującym operację push. Wiedząc to, możemy realizować nasze plany.

[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

Lub tylko

vi hooks/post-update

Wróćmy do komputera klienckiego.

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

Na serwerze Git sprawdzamy działanie skryptu po aktualizacji haka po zatwierdzeniu

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

- pusty, wszystko w porządku.

Podłączenie drugiego programisty w Git

Zasymulujmy pracę drugiego programisty.

Na kliencie

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

A jednocześnie na serwerze...

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

— znowu pusty, wszystko działa.

Usuwanie projektu Git i pobieranie projektu z serwera Git

Cóż, możesz jeszcze raz upewnić się, że wszystkie zmiany zostały zapisane.

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

— aby usunąć projekt Git, po prostu całkowicie wyczyść katalog. Pogódźmy się z generowanym błędem, ponieważ za pomocą tego polecenia nie można usunąć bieżącego katalogu, ale właśnie takiego zachowania potrzebujemy.

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"

Udostępnianie dostępu w Git

Teraz upewnijmy się, że nawet poprzez Git drugi programista nie będzie miał dostępu do projektu Proj1, nad którym nie pracuje.

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.

Teraz umożliwiamy dostęp

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

i potem wszystko działa.

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

Aby uzyskać więcej informacji,

Dodatkowo, jeśli przy tworzeniu plików i katalogów wystąpi problem z domyślnymi uprawnieniami, w CentOS można skorzystać z polecenia

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

Również w artykule możesz natknąć się na małe przydatne rzeczy:

  • jak zbudować drzewo katalogów w systemie Linux
  • jak przekazać zakres adresów w sed z określonej linii na koniec pliku, czyli dokonać zamiany w sed we wszystkich liniach z wyjątkiem pierwszej linii
  • Jak odwrócić warunek wyszukiwania w systemie Linux find
  • Jak przekazać wiele linii do pętli za pomocą jednej linijki w powłoce systemu Linux
  • Jak uniknąć pojedynczych cudzysłowów w bash
  • jak usunąć katalog wraz z całą jego zawartością w wierszu poleceń systemu Windows
  • Jak używać bash mv do zmiany nazwy pliku bez ponownego zapisywania go

Dziękuję za uwagę.

Źródło: www.habr.com

Dodaj komentarz