组织对GIT服务器的多用户访问

在安装和配置Git服务器时,出现了组织多个用户对多个项目进行访问的问题。 我对该问题进行了研究,发现了一个可以满足我所有要求的解决方案:简单,安全,可靠。

我的愿望如下:

  • 每个用户都使用自己的帐户进行连接
  • 多个用户可以从事一个项目
  • 同一用户可以从事多个项目
  • 每个用户只能访问他所从事的那些项目
  • 应该能够通过命令行进行连接,而不仅仅是通过某种Web界面进行连接

这也很棒:

  • 向控制人授予只读权限
  • 在Git中方便地管理用户权限

访问GIT服务器的选项概述


首先,您需要知道从中选择什么,因此简要概述了Git协议。

  • ssh-专门创建的用户帐户用于访问服务器。
    • 奇怪的是,Git没有从建议中排除使用单个帐户访问所有存储库的建议。 这不符合我的要求。
    • 您可以使用多个帐户,但是如何限制用户仅访问某些目录?

      • 不适合关闭主目录,因为在此难以组织其他用户的写访问权限
      • 使用主目录中的符号链接也很困难,因为Git不会将它们解释为链接
      • 可以限制对口译员的访问,但不能完全保证这将始终有效

        • 您甚至可以为此类用户连接自己的命令解释器,但是,

          • 首先,这已经是某种困难的决定,
          • 而在2中,可以避免这种情况。

    但是,也许这不是用户将能够执行任何命令的问题吗?..通常,如果您想出如何使用该方法,则不能排除该方法。 稍后我们将返回此方法,但现在暂时简要考虑其他替代方法,可能会更容易一些。
  • git local协议可以与sshfs结合使用,可以使用多个用户,但从本质上讲,这与前面的情况相同
  • http-只读
  • git是只读的
  • https-安装困难,您需要其他软件,以及用于组织用户访问权限的某种控制面板...看起来可行,但是有点复杂。

使用ssh协议来组织对Git服务器的多用户访问


返回ssh协议。

由于ssh访问用于git,因此您需要保护服务器数据。 通过ssh连接的用户在Linux服务器上使用自己的登录名,因此他可以通过ssh客户端连接并访问服务器命令行。
没有全面的保护措施来防止获得这种访问权限。

但是用户不应对Linux文件感兴趣。 重要信息仅存储在git存储库中。 因此,您不能限制通过命令行的访问,但是Linux可以阻止用户观看项目,但不包括参与的项目。
显然使用Linux权限系统。

如前所述,可以仅使用一个帐户进行ssh访问。 尽管此方法包含在推荐的git选项列表中,但此配置对多个用户而言是不安全的。

为了实现本文开头给出的要求,将创建以下目录结构并分配权限和所有者:

1)项目目录

dir1(proj1:proj1,0770)
dir2(proj2:proj2,0770)
dir3(proj3:proj3,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服务器管理员作为单个命令完成的。

在此示例中,“开发人员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://dev1@10.1.1.11/var/gitservertest/proj2" C:\gittest>git push origin master dev1:dev1@10.1.1.11'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是在执行推送的用户下运行的可执行文件。 知道这一点,我们就可以实现我们的计划。

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

在Git服务器上,我们在提交后检查钩子更新后脚本的操作

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

-空的,一切都很好。

将第二个开发人员连接到Git


我们将模仿第二个开发人员的工作。

在客户端上

 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 

同时,在服务器上

 [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://dev2@10.1.1.11/var/gitservertest/proj2 Cloning into 'proj2'... dev2@10.1.1.11's password: C:\gittest>cd proj2 C:\gittest\proj2>dir   C:\gittest\proj2 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:\gittest\proj2>type test1.txt "test dev1 to proj2" "dev1 added some omre" "dev1 3rd line" "!!! dev2 added this" C:\gittest\proj2>type test2.txt "!!! dev2 wrote" 

在Git中共享访问


现在,请确保即使通过Git,第二位开发人员也无法访问他不从事的Proj1项目。

 C:\gittest\proj2>git remote remove origin C:\gittest\proj2>git remote add origin "ssh://dev2@10.1.1.11/var/gitservertest/proj1" C:\gittest\proj2>git push origin master dev2@10.1.1.11'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:\gittest\proj2>git push origin master dev2@10.1.1.11's password: To ssh://10.1.1.11/var/gitservertest/proj1 * [new branch] master -> master 

附加信息


另外,如果在创建文件和目录时默认权限存在问题,在CentOS中,您可以使用以下命令

 setfacl -Rd -mo::5 -mg::7 /var/gitservertest 

同样在本文中,您可以偶然发现一些有用的东西:

  • 如何在Linux上建立目录树
  • sed如何将某一范围的地址从某一行传输到文件的末尾,即在第一行以外的所有行中对sed进行替换
  • 在Linux上如何找到反转搜索词的方法
  • 如何在linux shell中通过单行循环几行
  • 如何在bash中转义单引号
  • 如何删除Windows命令行上所有内容的目录
  • 如何使用bash mv重命名文件而无需再次重写

谢谢您的关注。

Source: https://habr.com/ru/post/zh-CN457056/


All Articles