組織多用戶存取GIT伺服器

安裝和設定 Git 伺服器時,會出現有關組織多個使用者對多個項目的存取的問題。 我研究了這個問題並找到了一個滿足我所有要求的解決方案:簡單、安全、可靠。

我的願望是:

  • 每個用戶都連結自己的帳戶
  • 多個用戶可以處理一個項目
  • 同一用戶可以處理多個項目
  • 每個使用者只能存取他所從事的項目
  • 應該可以透過命令列連接,而不僅僅是透過某種網路介面

這也很棒:

  • 向控制人員授予唯讀權限
  • 方便地管理Git中的使用者存取權限

存取 GIT 伺服器的可能選項概述

首先,您需要知道要選擇什麼,因此這裡是 Git 協定的快速概述。

  • ssh - 專門建立的使用者帳戶用於存取伺服器。
    • 奇怪的是,Git 並沒有將使用一個帳戶存取所有儲存庫的建議排除在外。 這根本不符合我的要求。
    • 您可以使用多個帳戶,但如何限制使用者只能存取某些目錄?
      • 關閉主目錄是不合適的,因為很難為其他使用者組織寫入訪問
      • 使用主目錄中的符號連結也很困難,因為 Git 不會將它們解釋為連結
      • 可以限制對解釋器的訪問,但不能完全保證它始終有效
        • 您通常可以為此類使用者連接自己的命令解釋器,但是
          • 首先,這已經是個艱難的決定,
          • 其次,這是可以規避的。

    但也許用戶能夠執行任何命令都不是問題?.. 一般來說,如果你弄清楚如何使用它,就不能排除這種方法。 我們稍後會回到這個方法,但現在我們將簡要地考慮其他替代方案,也許會有更簡單的方法。

  • git local協定可以和sshfs結合使用,可以使用多個用戶,但本質上和前面的情況是一樣的
  • http - 唯讀
  • git 是唯讀的
  • https - 很難安裝,你需要額外的軟體,某種控制面板來組織用戶訪問......它看起來可行,但不知何故一切都很複雜。

使用ssh協定組織多用戶存取Git伺服器

讓我們回到 ssh 協定。

由於你使用ssh存取git,所以需要確保伺服器資料的安全。 透過 ssh 連線的用戶在 Linux 伺服器上使用自己的登入名,因此他們可以透過 ssh 用戶端連線並存取伺服器的命令列。
沒有針對此類存取的完整保護。

但用戶不應該對 Linux 檔案感興趣。 重要資訊僅儲存在 git 儲存庫中。 因此,可以不透過命令列限制訪問,而是使用Linux工具禁止使用者查看項目,不包括他參與的項目。
顯而易見的選擇是使用 Linux 權限系統。

如同已經提到的,可以只使用一個帳戶進行 ssh 存取。 儘管此配置包含在建議的 git 選項清單中,但對於某些使用者來說是不安全的。

為了實現本文開頭給出的要求,創建了以下目錄結構並分配了權限和所有者:

1)項目目錄

目錄1(項目1:項目1,0770,XNUMX)
目錄2(項目2:項目2,0770,XNUMX)
目錄3(項目3:項目3,0770,XNUMX)
...
哪裡
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權限的基本安全,因此該方案是可靠的。 此外,該計劃非常易於管理。

我們去練習吧。

在 Linux 伺服器上建立 Git 儲存庫

我們檢查。

[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群組(更改developer使用者的主群組沒有幫助,因為那麼你們怎麼能同時進行多個專案呢?)。 在這種情況下,用戶 dev2 將無法更改用戶 dev1 建立的文件,這可能會導致功能崩潰。

Linux chown - 由一般使用者變更檔案的擁有者

文件的所有者無法更改其所有權。 但他可以更改屬於他的文件的群組,然後該文件可以被同一組中的其他使用者修改。 這就是我們所需要的。

使用 Git 掛鉤

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 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 查找中反轉搜尋條件
  • 如何在 Linux shell 中使用單行將多行傳遞到循環中
  • 如何在 bash 中轉義單引號
  • 如何在Windows命令列中刪除目錄及其所有內容
  • 如何使用 bash mv 重命名檔案而不需要再次重寫

感謝您的關注。

來源: www.habr.com

添加評論