องค์กรของการเข้าถึงผู้ใช้หลายคนในเซิร์ฟเวอร์ GIT

เมื่อติดตั้งและกำหนดค่าเซิร์ฟเวอร์ Git คำถามเกิดขึ้นเกี่ยวกับการจัดระเบียบการเข้าถึงสำหรับผู้ใช้หลายรายไปยังหลายโครงการ ฉันค้นคว้าปัญหานี้และพบวิธีแก้ปัญหาที่ตรงตามความต้องการทั้งหมดของฉัน: เรียบง่าย ปลอดภัย และเชื่อถือได้

ความปรารถนาของฉันคือ:

  • ผู้ใช้แต่ละคนเชื่อมต่อกับบัญชีของตนเอง
  • ผู้ใช้หลายคนสามารถทำงานในโปรเจ็กต์เดียวได้
  • ผู้ใช้คนเดียวกันสามารถทำงานหลายโครงการได้
  • ผู้ใช้แต่ละคนสามารถเข้าถึงเฉพาะโครงการที่เขาทำงานอยู่เท่านั้น
  • ควรเชื่อมต่อผ่านบรรทัดคำสั่งได้ ไม่ใช่แค่ผ่านเว็บอินเตอร์เฟสบางประเภทเท่านั้น

มันจะดีมากเช่นกัน:

  • ให้สิทธิ์แบบอ่านอย่างเดียวแก่ผู้ควบคุม
  • จัดการสิทธิ์การเข้าถึงของผู้ใช้ใน Git อย่างสะดวกสบาย

ภาพรวมของตัวเลือกที่เป็นไปได้สำหรับการเข้าถึงเซิร์ฟเวอร์ GIT

ก่อนอื่น คุณต้องรู้ว่าควรเลือกอะไร ต่อไปนี้เป็นภาพรวมโดยย่อของโปรโตคอล Git

  • ssh - บัญชีผู้ใช้ที่สร้างขึ้นเป็นพิเศษใช้เพื่อเข้าถึงเซิร์ฟเวอร์
    • เป็นเรื่องแปลกที่ Git ไม่ได้แยกคำแนะนำในการใช้บัญชีเดียวเพื่อเข้าถึงที่เก็บข้อมูลทั้งหมด สิ่งนี้ไม่ตรงตามความต้องการของฉันเลย
    • คุณสามารถใช้หลายบัญชีได้ แต่คุณจะจำกัดการเข้าถึงของผู้ใช้เพียงบางไดเรกทอรีได้อย่างไร
      • การปิดโฮมไดเร็กตอรี่ไม่เหมาะสม เนื่องจากเป็นการยากที่จะจัดระเบียบการเข้าถึงการเขียนสำหรับผู้ใช้รายอื่น
      • การใช้ symlink จากโฮมไดเร็กตอรี่ของคุณก็ทำได้ยากเช่นกัน เนื่องจาก Git ไม่ได้ตีความว่าเป็นลิงก์
      • คุณสามารถจำกัดการเข้าถึงล่ามได้ แต่ไม่มีการรับประกันเต็มรูปแบบว่าจะใช้ได้ผลเสมอไป
        • โดยทั่วไปคุณสามารถเชื่อมต่อล่ามคำสั่งของคุณเองสำหรับผู้ใช้ดังกล่าวได้ แต่
          • ประการแรก นี่เป็นการตัดสินใจที่ยากลำบากอยู่แล้ว
          • และประการที่สอง สิ่งนี้สามารถหลีกเลี่ยงได้

    แต่บางทีผู้ใช้จะสามารถรันคำสั่งใด ๆ ก็ไม่ใช่ปัญหาใช่ไหม.. โดยทั่วไปแล้ว วิธีนี้ไม่สามารถตัดออกได้หากคุณทราบวิธีใช้งานอย่างชัดเจน เราจะกลับมาใช้วิธีนี้ในภายหลัง แต่สำหรับตอนนี้เราจะพิจารณาทางเลือกอื่นโดยย่อ อาจมีบางอย่างที่ง่ายกว่านี้

  • สามารถใช้โปรโตคอลท้องถิ่น git ร่วมกับ sshfs ได้ ผู้ใช้หลายคนสามารถใช้ได้ แต่โดยพื้นฐานแล้วจะเหมือนกับกรณีก่อนหน้า
  • http - อ่านอย่างเดียว
  • git เป็นแบบอ่านอย่างเดียว
  • https - ติดตั้งยาก คุณต้องมีซอฟต์แวร์เพิ่มเติม แผงควบคุมบางประเภทเพื่อจัดระเบียบการเข้าถึงของผู้ใช้... ดูเป็นไปได้ แต่อย่างใดทุกอย่างก็ซับซ้อน

การใช้โปรโตคอล ssh เพื่อจัดระเบียบการเข้าถึงเซิร์ฟเวอร์ Git ของผู้ใช้หลายคน

กลับไปที่โปรโตคอล ssh กัน

เนื่องจากคุณใช้การเข้าถึง ssh สำหรับ git คุณจึงต้องมั่นใจในความปลอดภัยของข้อมูลเซิร์ฟเวอร์ ผู้ใช้ที่เชื่อมต่อผ่าน ssh จะใช้การเข้าสู่ระบบของตนเองบนเซิร์ฟเวอร์ Linux เพื่อให้สามารถเชื่อมต่อผ่านไคลเอ็นต์ ssh และเข้าถึงบรรทัดคำสั่งของเซิร์ฟเวอร์ได้
ไม่มีการป้องกันการเข้าถึงดังกล่าวอย่างสมบูรณ์

แต่ผู้ใช้ไม่ควรสนใจไฟล์ Linux ข้อมูลสำคัญจะถูกเก็บไว้ในที่เก็บ git เท่านั้น ดังนั้นจึงเป็นไปไม่ได้ที่จะจำกัดการเข้าถึงผ่านทางบรรทัดคำสั่ง แต่ใช้เครื่องมือ Linux เพื่อห้ามไม่ให้ผู้ใช้ดูโครงการ ยกเว้นโครงการที่เขาเข้าร่วม
ตัวเลือกที่ชัดเจนคือการใช้ระบบการอนุญาต Linux

ดังที่ได้กล่าวไปแล้ว คุณสามารถใช้เพียงบัญชีเดียวในการเข้าถึง ssh การกำหนดค่านี้ไม่ปลอดภัยสำหรับผู้ใช้หลายคน แม้ว่าจะรวมอยู่ในรายการตัวเลือกคอมไพล์ที่แนะนำก็ตาม

เพื่อดำเนินการตามข้อกำหนดที่ให้ไว้ตอนต้นของบทความ โครงสร้างไดเร็กทอรีต่อไปนี้จะถูกสร้างขึ้นพร้อมกับการกำหนดสิทธิ์และเจ้าของ:

1) ไดเรกทอรีโครงการ

dir1(โปรเจ1:โปรเจ1,0770)
dir2(โปรเจ2:โปรเจ2,0770)
dir3(โปรเจ3:โปรเจ3,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 ด้วยคำสั่งเดียว

ในตัวอย่างนี้ "Developer 1" กำลังทำงานในโปรเจ็กต์ proj1 และ proj2 และ "Developer 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 ในเครื่องและพุชไปยังเซิร์ฟเวอร์ 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>

ในเวลาเดียวกัน ไฟล์ใหม่จะถูกสร้างขึ้นบนเซิร์ฟเวอร์ และเป็นของผู้ใช้ที่ทำการพุช

[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 เป็นไฟล์ปฏิบัติการที่ทำงานภายใต้ผู้ใช้ที่ทำการพุช เมื่อรู้สิ่งนี้แล้ว เราก็สามารถดำเนินการตามแผนของเราได้

[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 หลังจากการคอมมิต

[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
  • วิธีหลีกเลี่ยงเครื่องหมายคำพูดเดี่ยวใน bash
  • วิธีลบไดเร็กทอรีที่มีเนื้อหาทั้งหมดในบรรทัดคำสั่งของ windows
  • วิธีใช้ bash mv เพื่อเปลี่ยนชื่อไฟล์โดยไม่ต้องเขียนใหม่อีกครั้ง

ขอบคุณสำหรับความสนใจของคุณ

ที่มา: will.com

เพิ่มความคิดเห็น