Organização do acesso multiusuário ao servidor GIT

Ao instalar e configurar um servidor Git, surge a questão de organizar o acesso de vários usuários a vários projetos. Pesquisei o problema e encontrei uma solução que atendeu a todos os meus requisitos: simples, segura e confiável.

Meus desejos são:

  • cada usuário se conecta com sua própria conta
  • Vários usuários podem trabalhar em um projeto
  • o mesmo usuário pode trabalhar em vários projetos
  • cada usuário tem acesso apenas aos projetos em que trabalha
  • Deveria ser possível conectar-se através da linha de comando, e não apenas através de algum tipo de interface web

Também seria ótimo:

  • conceder permissões somente leitura para pessoas controladoras
  • Gerencie convenientemente os direitos de acesso do usuário no Git

Visão geral das opções possíveis para acessar o servidor GIT

Primeiro de tudo, você precisa saber o que escolher, então aqui está uma rápida visão geral dos protocolos Git.

  • ssh - uma conta de usuário especialmente criada é usada para acessar o servidor.
    • É estranho que o Git não exclua de suas recomendações o uso de uma conta para acessar todos os repositórios. Isso não atende aos meus requisitos.
    • Você pode usar várias contas, mas como limitar o acesso do usuário apenas a determinados diretórios?
      • Fechar o diretório inicial não é adequado porque é difícil organizar o acesso de gravação para outros usuários
      • Usar links simbólicos do seu diretório pessoal também é difícil porque o Git não os interpreta como links
      • É possível restringir o acesso ao intérprete, mas não há garantia total de que sempre funcionará
        • Geralmente você pode conectar seu próprio interpretador de comandos para esses usuários, mas
          • em primeiro lugar, esta já é uma decisão difícil,
          • e em segundo lugar, isto pode ser contornado.

    Mas talvez não seja um problema que o usuário consiga executar algum comando?.. Em geral, esse método não pode ser descartado se você descobrir exatamente como usá-lo. Voltaremos a este método mais tarde, mas por enquanto consideraremos brevemente as outras alternativas, talvez haja algo mais simples.

  • O protocolo local git pode ser usado em combinação com sshfs, vários usuários podem ser usados, mas essencialmente igual ao caso anterior
  • http - somente leitura
  • git é somente leitura
  • https - difícil de instalar, você precisa de software adicional, algum tipo de painel de controle para organizar o acesso do usuário... parece viável, mas de alguma forma tudo é complicado.

Usando o protocolo ssh para organizar o acesso multiusuário ao servidor Git

Voltemos ao protocolo ssh.

Como você usa acesso ssh para git, você precisa garantir a segurança dos dados do servidor. O usuário que se conecta via ssh utiliza seu próprio login no servidor Linux, para poder se conectar via cliente ssh e acessar a linha de comando do servidor.
Não há proteção completa contra esse acesso.

Mas o usuário não deve estar interessado em arquivos Linux. Informações significativas são armazenadas apenas no repositório git. Portanto, é possível não restringir o acesso via linha de comando, mas sim utilizar ferramentas do Linux para proibir o usuário de visualizar projetos, excluindo aqueles dos quais ele participa.
A escolha óbvia é usar o sistema de permissões Linux.

Como já mencionado, é possível utilizar apenas uma conta para acesso ssh. Esta configuração não é segura para vários usuários, embora esteja incluída na lista de opções recomendadas do git.

Para implementar os requisitos indicados no início do artigo, é criada a seguinte estrutura de diretórios com atribuição de direitos e proprietários:

1) diretórios de projetos

dir1(proj1:proj1,0770)
dir2(proj2:proj2,0770)
dir3(proj3:proj3,0770)
...
onde
dir1, dir2, dir3 - diretórios do projeto: projeto 1, projeto 2, projeto 3.

proj1:proj1, proj2:proj2, proj3:proj3 são usuários Linux especialmente criados e atribuídos como proprietários dos diretórios de projeto correspondentes.

as permissões para todos os diretórios são definidas como 0770 - acesso total para o proprietário e seu grupo e banimento total para todos os outros.

2) contas de desenvolvedor

Разработчик 1: dev1:dev1,proj1,proj2
Разработчик 2: dev2:dev2,proj2,proj3

O ponto principal é que os desenvolvedores recebem um grupo adicional do usuário do sistema proprietário do projeto correspondente. Isso é feito pelo administrador do servidor Linux com um comando.

Neste exemplo, o "Desenvolvedor 1" está trabalhando nos projetos proj1 e proj2, e o "Desenvolvedor 2" está trabalhando nos projetos proj2 e proj3.

Se algum dos Desenvolvedores se conectar via ssh através da linha de comando, então seus direitos não serão suficientes nem mesmo para visualizar o conteúdo dos diretórios do projeto dos quais não participa. Ele não pode mudar isso sozinho.

Como a base deste princípio é a segurança básica dos direitos do Linux, este esquema é confiável. Além disso, o esquema é muito fácil de administrar.

Vamos seguir em frente para praticar.

Criando repositórios Git em um servidor Linux

Vamos checar.

[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

Estou cansado de digitar à mão...

[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

Estamos convencidos de que é impossível acessar os repositórios de outras pessoas a partir da linha de comando e até mesmo visualizar seu conteúdo.

[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

Colabore com vários desenvolvedores no mesmo projeto no Git

Uma questão permanece: se um desenvolvedor inserir um novo arquivo, outros desenvolvedores não poderão alterá-lo, porque ele próprio é o proprietário (por exemplo, dev1), e não o usuário proprietário do projeto (por exemplo, proj1). Como temos um repositório do lado do servidor, antes de mais nada, precisamos saber como está estruturado o diretório “.git” e se novos arquivos são criados.

Criando um repositório Git local e enviando para o servidor Git

Vamos passar para a máquina cliente.

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>

Ao mesmo tempo, novos arquivos são criados no servidor e pertencem ao usuário que realizou o 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]$

Quando você carrega alterações no servidor Git, arquivos e diretórios adicionais são criados e seu proprietário é, na verdade, o usuário que faz o upload. Mas então o grupo desses arquivos e diretórios também corresponde ao grupo principal deste usuário, ou seja, o grupo dev1 para o usuário dev1 e o grupo dev2 para o usuário dev2 (alterar o grupo principal do usuário desenvolvedor não vai ajudar, porque então como você pode trabalhar em vários projetos?). Neste caso, o usuário dev2 não poderá alterar os arquivos criados pelo usuário dev1, o que pode levar a uma falha na funcionalidade.

Linux chown - alterando o proprietário de um arquivo por um usuário normal

O proprietário de um arquivo não pode alterar sua propriedade. Mas ele pode alterar o grupo de um arquivo que pertence a ele, e então esse arquivo pode ser modificado por outros usuários que estejam no mesmo grupo. É disso que precisamos.

Usando o gancho Git

O diretório de trabalho do hook é o diretório raiz do projeto. hook é um executável executado pelo usuário que faz o push. Sabendo disso, podemos implementar nossos planos.

[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

ou apenas

vi hooks/post-update

Voltemos à máquina cliente.

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

No servidor Git, verificamos o funcionamento do script pós-atualização do gancho após o commit

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

- vazio, está tudo bem.

Conectando um segundo desenvolvedor no Git

Vamos simular o trabalho do segundo desenvolvedor.

No cliente

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

E ao mesmo tempo, no servidor...

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

— vazio novamente, tudo funciona.

Excluindo um projeto Git e baixando o projeto do servidor Git

Bem, você pode mais uma vez ter certeza de que todas as alterações foram salvas.

C:gittest>rd /S /Q .
Процесс не может получить доступ к файлу, так как этот файл занят другим процессом.

— para excluir um projeto Git, simplesmente limpe o diretório completamente. Vamos aguentar o erro que se gera, pois é impossível deletar o diretório atual com este comando, mas é exatamente esse comportamento que precisamos.

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"

Compartilhando acesso no Git

Agora vamos garantir que mesmo através do Git o segundo desenvolvedor não consiga acessar o projeto Proj1, no qual ele não está trabalhando.

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.

Agora permitimos acesso

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

e depois disso tudo funciona.

C:gittestproj2>git push origin master
[email protected]'s password:
To ssh://10.1.1.11/var/gitservertest/proj1
 * [new branch]      master -> master

Para mais informações,

Além disso, se houver um problema com as permissões padrão ao criar arquivos e diretórios, no CentOS você poderá usar o comando

setfacl -Rd -m o::5 -m g::7 /var/gitservertest

Também no artigo você pode encontrar pequenas coisas úteis:

  • como construir uma árvore de diretórios no Linux
  • como passar um intervalo de endereços no sed de uma determinada linha até o final do arquivo, ou seja, fazer uma substituição no sed em todas as linhas exceto a primeira linha
  • Como inverter uma condição de pesquisa no Linux find
  • Como passar múltiplas linhas em um loop usando uma linha no shell do Linux
  • Como escapar de aspas simples no bash
  • como deletar um diretório com todo o seu conteúdo na linha de comando do Windows
  • Como usar o bash mv para renomear um arquivo sem reescrevê-lo novamente

Obrigado por sua atenção.

Fonte: habr.com

Adicionar um comentário