πŸ“œ ⬆️ ⬇️

Organization of multi-user access to the GIT server

When installing and configuring a Git-server, the question arises about the organization of access of several users to several projects. I conducted a research question and found a solution that meets all my requirements: simple, safe, reliable.

My wishes are as follows:


It would also be great:
')

Overview of access options on the GIT server


First of all, you need to know what to choose from, so a quick overview of the Git protocols.


Using ssh for multi-user access to a Git server


Let's go back to the ssh protocol.

Since ssh access is used for git, you need to ensure the security of the server data. A user who connects via ssh uses his own login on the Linux server, so he can connect via the ssh client and access the server command line.
There is no complete protection against such access.

But the user should not be interested in Linux files. Relevant information is stored only in the git repository. Therefore, it is possible not to restrict access via the command line, but using Linux tools to prevent the user from watching projects, excluding those in which he participates.
Obviously use the Linux permissions system.

As already mentioned, it is possible to use only one account for ssh access. This configuration is unsafe for several users, although this method is included in the list of recommended git options.

To implement the requirements listed at the beginning of the article, the following directory structure is created with assignment of rights and owners:

1) project directories

dir1 (proj1: proj1,0770)
dir2 (proj2: proj2,0770)
dir3 (proj3: proj3,0770)
...
Where
dir1, dir2, dir3 - project directories: project 1, project 2, project 3.

proj1: proj1, proj2: proj2, proj3: proj3 are specially created Linux users who are appointed by the owners of the directories of the respective projects.

The rights to all directories are set at 0770 - full access for the owner and his group and total ban for all others.

2) developer accounts

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

The key point is that developers are assigned an additional group of the system user who owns the corresponding project. This is done by the Linux server administrator with a single command.

In this example, Developer 1 is working on project proj1 and proj2, and Developer 2 is working on projects proj2 and proj3.

If any of the Developers connects via ssh via the command line, then its rights will not be enough even to view the contents of the directories of projects in which it does not participate. He cannot change it himself.

Since the basis of this principle is basic security of Linux rights, this scheme is reliable. In addition, the scheme is very easy to administer.

Let's go to practice.

Creating Git repositories on a Linux server


We are checking.

[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 

tired of typing hands ...

 [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 

We are convinced that from the command line it is impossible to access other repositories and even to see their contents.

 [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 collaboration of several developers on one project


One question remains, if one developer enters a new file, the other developers cannot change it, because he himself owns it (for example, dev1), and not the user who owns the project (for example, proj1). Since we have a server repository, first of all, you need to know how the ".git" directory is organized and whether new files are created.

Creating a local Git repository and push to the Git server


Let's go to the client machine.

 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> 

At the same time, new files are generated on the server, and they belong to the user who pushed.

 [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]$ 

When changes are uploaded to the Git server, additional files and directories are created, and they are actually owned by the user who is uploading. But then the group of these files and directories also corresponds to the main group of this user, that is, the group dev1 for the user dev1 and the group dev2 for the user dev2 (changing the main group of the user developer does not help, because then how to work on several projects?). In this case, the user dev2 will not be able to change the files created by the user dev1, and this is fraught with a violation of functionality.

Linux chown - change the owner of the file as a regular user



The owner of the file cannot change its ownership. But he can change the group of the file that belongs to him, and then this file can be available for changing to other users who are in the same group. That's what we need.

Using git hook


The working directory for the hook is the project root directory. A hook is an executable file that runs under the user who pushes. Knowing this, we can carry out our plans.

 [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 

either just

 vi hooks/post-update 

Let's go back to the client machine.

 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 

On the Git server, after the commit, we check the work of the post-update script hook

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

- empty, everything is fine.

Connection of the second developer in Git


Let's simulate the work of the second developer.

On the 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 

And at the same time, on the server ...

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

- again empty, everything works.

Deleting a Git project and loading a project from a Git server


Well, you can once again make sure that all changes are preserved.

 C:\gittest>rd /S /Q .       ,       . 

- to delete a Git project, simply clear the directory completely. Let us put up with the error, since it is impossible to delete the current directory on this command, but we just need this behavior.

 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 access sharing


Now let's make sure that the second developer cannot access the Proj1 project, which he doesn’t work with, through Git.

 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. 

Now allow access

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

and after that everything works.

 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 

additional information


In addition, if there is a problem with the default permissions when creating files and directories, you can use the command in CentOS

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

Also in the article you may stumble upon small useful things:


Thanks for attention.

Source: https://habr.com/ru/post/457056/


All Articles