Organizarea accesului multi-utilizator pe serverul GIT

Atunci când instalezi și configurezi un server Git, apare întrebarea despre organizarea accesului mai multor utilizatori la mai multe proiecte. Am efectuat o cercetare asupra subiectului și am găsit o soluție care îndeplinește toate cerințele mele: simplă, sigură și fiabilă.

Dorințele mele sunt următoarele:

  • fiecare utilizator se conectează cu contul său propriu
  • mai mulți utilizatori pot lucra la același proiect
  • același utilizator poate lucra la mai multe proiecte
  • fiecare utilizator are acces doar la proiectele în care lucrează
  • trebuie să existe posibilitatea de conectare prin linia de comandă, nu doar printr-o interfață web

De asemenea, ar fi grozav:

  • să se ofere drepturi doar pentru citire pentru persoanele de control
  • să fie ușor de administrat drepturile de acces ale utilizatorilor în Git

O prezentare a opțiunilor posibile de acces pe serverul GIT

În primul rând, trebuie să știi din ce să alegi, așa că iată o scurtă prezentare a protocoalelor Git.

  • ssh - pentru accesul la server se utilizează un cont de utilizator creat special.
    • Este ciudat că Git nu exclude din recomandări utilizarea unui singur cont pentru accesul la toate repozitoarele. Aceasta nu corespunde cerințelor mele.
    • se pot folosi mai multe conturi, dar cum putem restricționa accesul utilizatorului doar la anumite directoare?
      • Restricționarea în directorul home nu este potrivită, deoarece este dificil să organizezi accesul pentru scriere pentru alți utilizatori
      • Utilizarea link-urilor simbolice din directorul home este și ea complicată, deoarece Git nu le interpretează ca legături
      • Restricționarea accesului la interpretator, bine, se poate, dar nu există garanția că va funcționa întotdeauna
        • Se poate conecta un interpret de comenzi pentru acești utilizatori, dar,
          • în primul rând, acesta este deja o soluție complicată,
          • iar în al doilea rând, acest lucru poate fi ocolit.

    Dar poate că nu este o problemă ca utilizatorul să poată executa orice comenzi?... În general, nu trebuie exclusă această metodă, dacă putem găsi o modalitate de a o utiliza. Revenim la acest subiect mai târziu, dar între timp să aruncăm o privire asupra celorlalte alternative, poate că acolo este ceva mai simplu.

  • Protocolul git local poate fi utilizat împreună cu sshfs, fiind posibil să folosești mai mulți utilizatori, dar esențial este același lucru ca în cazul anterior.
  • http — doar pentru citire
  • git — doar pentru citire
  • https — dificil de instalat, necesită software suplimentar, ceva panoul de control pentru organizarea accesului utilizatorilor… pare realizabil, dar totul este complicat.

Utilizarea protocolului ssh pentru a organiza accesul multiutilizator la serverul Git

Să ne întoarcem la protocolul ssh.

Deoarece se folosește accesul prin ssh pentru git, trebuie să asigurăm securitatea datelor serverului. Utilizatorul care se conectează prin ssh folosește propriul login pe server Linux, astfel că se poate conecta prin client ssh și obține acces la linia de comandă a serverului.
Nu există o protecție completă împotriva obținerii unui astfel de acces.

Dar pentru utilizator nu ar trebui să conteze fișierele Linux. Informațiile semnificative sunt stocate doar în depozitul git. De aceea, nu este necesar să limităm accesul prin linia de comandă, dar prin intermediul Linux, să interzicem utilizatorului să vizualizeze proiectele, excluzându-le pe cele în care este implicat.
Este evident că se poate folosi sistemul de permisiuni Linux.

Așa cum s-a menționat, este posibil să se folosească un singur cont pentru accesul ssh. Această configurație este nesigură pentru mai mulți utilizatori, deși acest mod este inclus în lista variantelor recomandate git.

Pentru a implementa cerințele menționate la începutul articolului, se creează următoarea structură de directoare cu drepturi și proprietari:

1) directoarele proiectelor

dir1(proj1:proj1,0770)
dir2(proj2:proj2,0770)
dir3(proj3:proj3,0770)
…
unde
dir1, dir2, dir3 — directoare de proiecte: proiectul 1, proiectul 2, proiectul 3.

proj1:proj1, proj2:proj2, proj3:proj3 — utilizatori Linux creați special, care sunt desemnați ca proprietari ai directoarelor proiectelor corespunzătoare.

drepturile pentru toate directoarele sunt setate la 0770 — acces complet pentru proprietar și grupul său și interzicere completă pentru toți ceilalți.

2) conturile dezvoltatorilor

Dezvoltator 1: dev1:dev1,proj1,proj2
Dezvoltator 2: dev2:dev2,proj2,proj3

Cheia constă în faptul că dezvoltatorilor li se atribuie un grup suplimentar al utilizatorului de sistem-proprietar al proiectului corespunzător. Acest lucru se face de către administratorul serverului Linux cu o singură comandă.

În acest exemplu, „Dezvoltatorul 1” lucrează la proiectele proj1 și proj2, iar „Dezvoltatorul 2” lucrează la proiectele proj2 și proj3.

Dacă orice Dezvoltator se conectează prin ssh prin linia de comandă, drepturile sale nu vor fi suficiente nici măcar pentru a vizualiza conținutul directoarelor proiectelor în care nu participă. Nu poate schimba nici el acest lucru.

Având în vedere că baza acestui principiu este securitatea de bază a drepturilor Linux, acest sistem este fiabil. În plus, schema este foarte ușor de administrat.

Să trecem la practică.

Crearea de repozitorii Git pe un server Linux

Verificăm.

[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

s-a săturat să introducă manual…

[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

Ne asigurăm că, din linia de comandă, nu este posibil să se acceseze repozitoriile altor persoane sau chiar să se vizualizeze conținutul acestora.

[dev1@server ~]$ cd /var/gitservertest/proj3
-bash: cd: /var/gitservertest/proj3: Permisiune refuzată
[dev1@server ~]$ ls /var/gitservertest/proj3
ls: nu se poate deschide directorul /var/gitservertest/proj3: Permisiune refuzată

Colaborarea în Git a mai multor dezvoltatori la un singur proiect

Rămâne o întrebare, dacă un dezvoltator introduce un fișier nou, ceilalți dezvoltatori nu pot să-l schimbe, deoarece el este singurul proprietar (de exemplu, dev1) și nu utilizatorul-proprietar al proiectului (de exemplu, proj1). Deoarece avem un repozitoriu server, mai întâi trebuie să știm cum este structurat directorul „.git” și dacă se creează fișiere noi.

Crearea unui repozitoriu Git local și push pe serverul Git

Să ne mutăm pe mașina client.

Microsoft Windows [Version 6.1.7601]
(c) Corporația Microsoft (Microsoft Corp.), 2009. Toate drepturile rezervate.

C:gittest>git init .
Repository Git gol inițializat în C: /gittest / .git/

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

C:gittest>git add .

C:gittest>git status
Pe ramura master
Nu există încă comenzi
Modificări de adus în comitere:
  (folosește "git rm --cached <file>..." pentru a elimina din stagiu)
        fișier nou:   test1.txt

C:gittest>git commit -am "fișier de test nou adăugat"
[master (root-commit) a7ac614] fișier de test nou adăugat
 1 fișier modificat, 1 inserție(+)
 create mode 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:
Contorizând obiectele: 3, complet.
Scrierea obiectelor: 100% (3/3), 243 bytes | 243.00 KiB/s, complet.
Total 3 (delta 0), reutilizat 0 (delta 0)
Către ssh://10.1.1.11/var/gitservertest/proj2
 * [ramură nouă]      master -> master

C:gittest>

În aceeași perioadă, pe server apar fișiere noi, iar acestea aparțin utilizatorului care a realizat 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 directoare, 18 fișiere
[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]$

Când s-au încărcat modificările pe server, se creează fișiere și directoare suplimentare în Git, iar proprietar este într-adevăr utilizatorul care face încărcarea. Dar atunci, grupul acestor fișiere și directoare este, de asemenea, corespunzător grupului principal al acestui utilizator, adică grupul dev1 pentru utilizatorul dev1 și grupul dev2 pentru utilizatorul dev2 (schimbarea grupului principal al utilizatorului-dezvoltator nu va ajuta, deoarece cum ar putea lucra asupra mai multor proiecte?). În acest caz, utilizatorul dev2 nu va putea modifica fișierele create de utilizatorul dev1, ceea ce poate duce la probleme în funcționalitate.

Linux chown — schimbarea proprietarului fișierului de către un utilizator obișnuit.

Proprietarul fișierului nu poate schimba apartenența acestuia. Dar poate schimba grupul fișierului care îi aparține, iar astfel acest fișier poate fi accesibil pentru modificare altor utilizatori care se află în același grup. Asta este ceea ce ne trebuie.

Utilizarea Git hook

Directorul de lucru pentru hook este directorul principal al proiectului. Hook este un fișier executabil care rulează sub utilizatorul care efectuează push. Având în vedere acest lucru, putem realiza ceea ce ne-am propus.

[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

sau pur și simplu

vi hooks/post-update

Să ne întoarcem la mașina clientului.

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:dev1@10.1.1.11's password:
   d22c66e..b045e22  master -> master

Pe serverul Git, verificăm funcționarea scriptului hook post-update după commit.

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

— gol, totul este în regulă.

Conectarea celui de-al doilea dezvoltator în Git

Să simulăm activitatea celui de-al doilea dezvoltator.

Pe client

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 files changed, 2 insertions(+)
 create mode 100644 test2.txt

C:gittest>git push origin master
dev2@10.1.1.11's password:
   b045e22..55d49a6  master -> master

Și în același timp, pe server...

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

— din nou gol, totul funcționează.

Ștergerea proiectului Git și încărcarea proiectului de pe serverul Git

Putem verifica din nou dacă toate modificările s-au păstrat.

C:gittest>rd /S /Q .
Procesul nu poate accesa fișierul deoarece acesta este folosit de un alt proces.

— pentru a șterge proiectul Git, pur și simplu curățăm complet directorul. Să acceptăm mesajul de eroare generat, deoarece nu putem elimina directorul curent prin această comandă, dar acesta este comportamentul pe care ne-l dorim.

C:gittest>dir
 Conținutul folderului 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
Clonare în 'proj2'...
dev2@10.1.1.11's password:

C:gittest>cd proj2

C:gittestproj2>dir
 Conținutul folderului 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 to proj2"
"dev1 added some omre"
"dev1 3rd line"
"!!! dev2 added this"

C:gittestproj2>type test2.txt
"!!! dev2 wrote"

Separarea accesului în Git

Acum să ne asigurăm că și prin Git, al doilea dezvoltator nu poate accesa proiectul Proj1, la care nu lucrează.

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' nu pare să fie un depozit git
fatal: Nu s-a putut citi din depozitul remote.

Asigurați-vă că aveți drepturile de acces corecte
și că depozitul există.

Acum permitem accesul

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

și după aceasta totul funcționează.

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

Informații suplimentare

În plus, dacă există o problemă cu permisiunile implicite la crearea fișierelor și directorilor, în CentOS se poate folosi comanda

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

De asemenea, în articol puteți găsi lucruri utile mici:

  • cum se construiește un arbore de directoare în Linux
  • cum se transmite în sed un interval de adrese de la o anumită linie până la sfârșitul fișierului, adică, cum se face o înlocuire în sed în toate liniile, cu excepția primei linii
  • Cum se inversează condiția de căutare în Linux find
  • cum se transmit în shell-ul Linux mai multe linii într-un ciclu printr-o linie unică
  • cum se scapă apostrofuri în bash
  • cum se șterge un director cu tot conținutul său din linia de comandă Windows
  • Cum se redenumește un fișier cu bash mv fără a-l suprascrie

Vă mulțumesc pentru atenție.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster