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:

    • 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.

      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)
    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@"
    C:\gittest>git push origin master
    dev1:dev1@'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://
     * [new branch]      master -> master

    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@'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@"
    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@'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
    21.06.2019  08:43              .
    21.06.2019  08:43              ..
    C:\gittest>git clone ssh://dev2@
    Cloning into 'proj2'...
    dev2@'s password:
    C:\gittest>cd proj2
     Содержимое папки 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@"
    C:\gittest\proj2>git push origin master
    dev2@'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@'s password:
    To ssh://
     * [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.

    Also popular now: