
Organization of multi-user access to the GIT server
When installing and configuring a Git server, the question arises of organizing access for several users to several projects. I conducted a study of the issue and found a solution that satisfies all my requirements: simple, safe, reliable.
My wishes are as follows:
It would also be great:
First of all, you need to know what to choose from, so a brief overview of the Git protocols.
Back to the ssh protocol.
Since ssh access is used for git, you need to secure the server data. A user who connects via ssh uses his own login on the Linux server, so he can connect through the ssh client and gain access to the server command line.
There is no full protection against obtaining such access.
But the user should not be interested in Linux files. Significant information is stored only in the git repository. Therefore, you can not restrict access through the command line, but Linux can prevent the user from watching projects, excluding those in which he participates.
Obviously using 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 given at the beginning of the article, the following directory structure is created with the 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 - specially created Linux users who are appointed owners of the directories of the respective projects.
rights to all directories are set in 0770 - full access for the owner and his group and a complete ban for everyone else.
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 system users who own the corresponding project. This is done by the Linux server administrator as a single command.
In this example, “Developer 1” works on the proj1 and proj2 projects, and “Developer 2” works on the proj2 and proj3 projects.
If any of the Developers connects via ssh via the command line, then his rights will not be enough even to view the contents of project directories in which he is not involved. He himself cannot change this in any way.
Since the basis of this principle is the basic security of Linux rights, this scheme is reliable. In addition, the scheme is very easy to administer.
Let's move on to practice.
We check.
tired of typing with my hands ...
We make sure that it is impossible to access other people's repositories from the command line and even see their contents.
One question remains, if one developer introduces a new file, then the rest of the 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 arranged and whether new files are created.
Let's move on to the client machine.
At the same time, new files are formed on the server, and they belong to the user who carried out push
When the changes are uploaded to the Git server, additional files and directories are created, and at the same time, the user who does the upload is the owner. 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 development user will not help, since then how to work on several projects?). In this case, the user dev2 will not be able to modify the files created by the user dev1, and this is fraught with a violation of functionality.
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 may be available for change to other users who are in the same group. That's what we need.
The working directory for the hook is the root directory of the project. hook is an executable that runs under the user who does push. knowing this, we can fulfill our plan.
either just
Back to the client machine.
On the Git server, we check after the commit the operation of the hook post-update script
- empty, everything is fine.
We will imitate the work of the second developer.
On the client
And at the same time, on the server ...
- empty again, everything works.
Well, you can once again make sure that all changes are preserved.
- To remove a Git project, just clear the directory completely. We will put up with the generated error, since it is impossible to delete the current directory for this command, but we just need this behavior.
Now let’s make sure that even through Git, the second developer cannot get access to the Proj1 project, which he doesn’t work on.
Now allow access
and after that everything works.
In addition, if there is a problem with default permissions when creating files and directories, in CentOS you can use the command
Also in the article you can stumble upon small useful things:
Thanks for attention.
My wishes are as follows:
- each user connects with his own account
- multiple users can work on one project
- the same user can work on several projects
- each user has access only to those projects on which he works
- should be able to connect via the command line, and not just through some kind of web interface
It would also be great:
- grant read-only rights to controlling persons
- conveniently administer user permissions in Git
Overview of options for accessing the GIT server
First of all, you need to know what to choose from, so a brief overview of the Git protocols.
- ssh - a specially created user account is used to access the server.
- it is strange that Git does not exclude from the recommendations the use of a single account to access all repositories. This does not meet my requirements.
- You can use multiple accounts, but how to restrict user access only to certain directories?
- Closing to the home directory is not suitable, because it is difficult to organize there write access for other users
- Using symbolic links from the home directory is also difficult because Git does not interpret them as links
- It’s possible to restrict access to the interpreter, but there is no full guarantee that this will always work
- You can even connect your own command interpreter for such users, but,
- firstly, this is already some kind of difficult decision,
- and in 2, this can be circumvented.
- You can even connect your own command interpreter for such users, but,
But maybe this is not a problem that the user will be able to execute any commands? .. In general, this method cannot be excluded if you come up with how to use it. We will return to this method later, but for now briefly consider the other alternatives, maybe something will be easier there. - The git local protocol can be used in conjunction with sshfs, several users can be used, but in essence, this is the same as the previous case
- http - read only
- git is read only
- https - it’s difficult to install, you need additional software, some kind of control panel for organizing user access ... looks feasible, but somehow it's complicated.
Using the ssh protocol for organizing multi-user access to the Git server
Back to the ssh protocol.
Since ssh access is used for git, you need to secure the server data. A user who connects via ssh uses his own login on the Linux server, so he can connect through the ssh client and gain access to the server command line.
There is no full protection against obtaining such access.
But the user should not be interested in Linux files. Significant information is stored only in the git repository. Therefore, you can not restrict access through the command line, but Linux can prevent the user from watching projects, excluding those in which he participates.
Obviously using 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 given at the beginning of the article, the following directory structure is created with the 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 - specially created Linux users who are appointed owners of the directories of the respective projects.
rights to all directories are set in 0770 - full access for the owner and his group and a complete ban for everyone else.
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 system users who own the corresponding project. This is done by the Linux server administrator as a single command.
In this example, “Developer 1” works on the proj1 and proj2 projects, and “Developer 2” works on the proj2 and proj3 projects.
If any of the Developers connects via ssh via the command line, then his rights will not be enough even to view the contents of project directories in which he is not involved. He himself cannot change this in any way.
Since the basis of this principle is the basic security of Linux rights, this scheme is reliable. In addition, the scheme is very easy to administer.
Let's move on to practice.
Creating Git repositories on a Linux server
We check.
[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 with my 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 make sure that it is impossible to access other people's repositories from the command line and even 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
Collaboration in Git of several developers on one project
One question remains, if one developer introduces a new file, then the rest of the 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 arranged and whether new files are created.
Creating a local Git repository and push to a Git server
Let's move on 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 ..." 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 formed on the server, and they belong to the user who carried out push
[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 the changes are uploaded to the Git server, additional files and directories are created, and at the same time, the user who does the upload is the owner. 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 development user will not help, since then how to work on several projects?). In this case, the user dev2 will not be able to modify the files created by the user dev1, and this is fraught with a violation of functionality.
Linux chown - changing the owner of a file by 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 may be available for change 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 root directory of the project. hook is an executable that runs under the user who does push. knowing this, we can fulfill our plan.
[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
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, we check after the commit the operation of the hook post-update script
[dev1@server proj2]$ find . ! -group proj2
- empty, everything is fine.
Connecting a second developer to Git
We will imitate 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
- empty again, everything works.
Removing a Git Project and Downloading a Project from a Git Server
Well, you can once again make sure that all changes are preserved.
C:\gittest>rd /S /Q .
Процесс не может получить доступ к файлу, так как этот файл занят другим процессом.
- To remove a Git project, just clear the directory completely. We will put up with the generated error, since it is impossible to delete the current directory for this command, but we just need this behavior.
C:\gittest>dir Содержимое папки C:\gittest 21.06.2019 08:43
. 21.06.2019 08:43
.. 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
. 21.06.2019 08:46
.. 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"
Sharing Access in Git
Now let’s make sure that even through Git, the second developer cannot get access to the Proj1 project, which he doesn’t work on.
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 default permissions when creating files and directories, in CentOS you can use the command
setfacl -Rd -m o::5 -m g::7 /var/gitservertest
Also in the article you can stumble upon small useful things:
- how to build a directory tree on Linux
- how to sed to transfer a range of addresses from a certain line to the end of the file, that is, to make a replacement in sed in all lines except the first line
- How on Linux find to invert a search term
- how in linux shell to loop several lines through a single line
- how to escape single quotes in bash
- how to delete the directory with all contents on the windows command line
- How to use bash mv to rename a file without rewriting it again
Thanks for attention.