安装和配置 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 重命名文件而不需要再次重写
感谢您的关注。
来源: habr.com