Organização de acesso multiusuário no servidor GIT

Ao instalar e configurar um servidor Git, surge a questão de como organizar o acesso de vários usuários a vários projetos. Eu fiz uma pesquisa sobre o assunto e encontrei uma solução que atende a todos os meus requisitos: simples, segura e confiável.

Meus desejos são os seguintes:

  • cada usuário se conecta com sua própria conta
  • vários usuários podem trabalhar em um mesmo projeto
  • o mesmo usuário pode trabalhar em vários projetos
  • cada usuário tem acesso apenas aos projetos em que está trabalhando
  • deve haver a possibilidade de conexão via linha de comando, e não apenas por alguma interface web

Além disso, seria ótimo:

  • oferecer direitos apenas de leitura para pessoas de controle
  • administrar os direitos de acesso dos usuários no Git de forma conveniente

Visão geral das opções de acesso ao servidor GIT

Antes de mais nada, é preciso saber o que escolher, portanto, uma breve visão geral dos protocolos Git.

  • ssh - para acessar o servidor, é usada uma conta de usuário especificamente criada.
    • é estranho que o Git não exclua das recomendações o uso de uma única conta para acessar todos os repositórios. Isso não atende aos meus requisitos.
    • é possível usar várias contas, mas como restringir o acesso do usuário a apenas diretórios específicos?
      • Fechar no diretório home não funciona, pois é difícil organizar o acesso de gravação para outros usuários
      • Usar links simbólicos do diretório home também é complicado, pois o Git não os interpreta como links
      • Restringir o acesso ao interpretador é possível, mas não há garantia total de que isso sempre funcionará
        • É possível conectar um interpretador de comandos específico para esses usuários, mas,
          • em primeiro lugar, essa já é uma solução complexa,
          • e em segundo lugar, isso pode ser contornado.

    Mas, talvez, não seja um problema que o usuário consiga executar quaisquer comandos?.. De qualquer forma, não podemos descartar esse método, se conseguirmos descobrir como usá-lo. Voltaremos a essa abordagem mais tarde, mas agora vamos dar uma olhada nas outras alternativas, pode ser que haja algo mais simples.

  • O protocolo git local pode ser utilizado em conjunto com sshfs, permitindo o uso de vários usuários, mas essencialmente, é a mesma coisa que o caso anterior.
  • http — somente leitura.
  • git — somente leitura.
  • https — difícil de configurar, requer software adicional, algum tipo de. painel de controle para organizar o acesso de usuários... parece viável, mas é um pouco complicado.

Uso do protocolo ssh para organizar acesso multiusuário ao servidor Git.

Vamos voltar ao protocolo ssh.

Como o acesso via ssh é utilizado para o git, é necessário garantir a segurança dos dados do servidor. O usuário que se conecta via ssh usa seu próprio login no. servidor Linux, portanto, pode se conectar através do cliente ssh e acessar a linha de comando do servidor.
Não há proteção completa contra tal acesso.

Mas os arquivos do Linux não devem interessar ao usuário. Informações significativas estão armazenadas apenas no repositório git. Portanto, é possível não restringir o acesso através da linha de comando, mas proibir o usuário de visualizar projetos por meio de recursos do Linux, exceto aqueles em que ele participa.
É evidente usar um sistema de permissões do Linux.

Como já foi mencionado, é possível usar apenas uma conta para acesso ssh. Essa configuração é insegura para vários usuários, embora esse método esteja na lista de opções recomendadas do git.

Para implementar os requisitos apresentados no início do artigo, cria-se a seguinte estrutura de diretórios com a designação de permissões e proprietários:

1) diretórios dos projetos.

dir1(proj1:proj1,0770)
dir2(proj2:proj2,0770)
dir3(proj3:proj3,0770)
…
onde
dir1, dir2, dir3 — diretórios dos projetos: projeto 1, projeto 2, projeto 3.

proj1:proj1, proj2:proj2, proj3:proj3 — usuários Linux criados especificamente que são designados como proprietários dos diretórios dos respectivos projetos.

As permissões de todos os diretórios são definidas como 0770 — acesso completo ao proprietário e seu grupo, e proibição total para todos os outros.

2) contas dos desenvolvedores.

Desenvolvedor 1: dev1:dev1,proj1,proj2.
Desenvolvedor 2: dev2:dev2,proj2,proj3.

O ponto-chave é que os desenvolvedores são atribuídos a um grupo adicional do usuário proprietário do sistema correspondente ao projeto. Isso é feito pelo administrador do servidor Linux com um único comando.

Neste exemplo, "Desenvolvedor 1" está trabalhando no projeto proj1 e proj2, enquanto "Desenvolvedor 2" trabalha nos projetos proj2 e proj3.

Se qualquer um dos desenvolvedores se conectar via ssh através da linha de comando, seus direitos serão insuficientes até mesmo para visualizar o conteúdo dos diretórios dos projetos nos quais não participa. Ele não pode mudar isso por conta própria.

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

Vamos para a prática.

Criando repositórios Git em um servidor Linux

Verificando.

[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

já estou cansado de digitar manualmente…

[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

Certificamo-nos de que, a partir da linha de comando, não é possível acessar repositórios de outros usuários nem mesmo visualizar seu conteúdo.

[dev1@server ~]$ cd /var/gitservertest/proj3
-bash: cd: /var/gitservertest/proj3: Permissão negada
[dev1@server ~]$ ls /var/gitservertest/proj3
ls: impossível abrir o diretório /var/gitservertest/proj3: Permissão negada

Colaboração em Git de vários desenvolvedores em um único projeto

Resta uma pergunta: se um desenvolvedor cria um novo arquivo, os outros desenvolvedores não podem alterá-lo, pois ele mesmo é o proprietário (por exemplo, dev1), e não o usuário proprietário do projeto (por exemplo, proj1). Como temos um repositório servidor, é fundamental entender como o diretório " .git" é estruturado e como novos arquivos são criados.

Criando um repositório Git local e realizando push para o servidor Git

Vamos para a máquina cliente.

Microsoft Windows [Version 6.1.7601]
(c) Microsoft Corp., 2009. Todos os direitos reservados.

C:gittest>git init .
Repositório Git vazio inicializado em C:/gittest/.git/

C:gittest>echo "test dev1 to proj2" > test1.txt

C:gittest>git add .

C:gittest>git status
No ramo master
Nenhum commit ainda
Alterações a serem confirmadas:
  (use "git rm --cached <arquivo>..." para desmarcar)
        novo arquivo:   test1.txt

C:gittest>git commit -am "novo arquivo de teste adicionado"
[master (root-commit) a7ac614] novo arquivo de teste adicionado
 1 arquivo alterado, 1 inserção(+)
 modo de criação 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:
Contando objetos: 3, feito.
Escrevendo objetos: 100% (3/3), 243 bytes | 243.00 KiB/s, feito.
Total 3 (delta 0), reutilizados 0 (delta 0)
Para ssh://10.1.1.11/var/gitservertest/proj2
 * [novo ramo]      master -> master

C:gittest>

Ao mesmo tempo, novos arquivos estão sendo criados no servidor, e eles pertencem ao usuário que fez 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 diretórios, 18 arquivos
[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]$

Ao fazer upload de alterações no servidor Git, arquivos e diretórios adicionais são criados, e seu proprietário é realmente o usuário que faz o upload. Porém, o grupo desses arquivos e diretórios também corresponde ao grupo principal desse usuário, ou seja, grupo dev1 para o usuário dev1 e grupo dev2 para o usuário dev2 (mudar o grupo principal do usuário desenvolvedor não ajudará, pois como trabalhar em vários projetos?). Nesse caso, o usuário dev2 não poderá modificar arquivos criados pelo usuário dev1, e isso pode comprometer a funcionalidade.

Linux chown — mudança de proprietário de arquivo por um usuário comum.

O proprietário do arquivo não pode alterar sua propriedade. Mas ele pode mudar o grupo do arquivo que pertence a ele, permitindo que esse arquivo seja acessado para modificações por outros usuários que estão no mesmo grupo. Isso é o que precisamos.

Uso de Git hook

O diretório de trabalho para o hook é o diretório raiz do projeto. O hook é um arquivo executável que é executado sob o usuário que faz o push. Sabendo isso, podemos realizar o planejado.

[dev1@server proj2]$ mv hooks/post-update{.sample,}
[dev1@server proj2]$ sed -i '2,$ s/^/#/' hooks/post-update
[dev1@server proj2]$ cat <<> hooks/post-update

ou apenas

vi hooks/post-update

Vamos voltar à máquina do 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:dev1@10.1.1.11's password:
   d22c66e..b045e22  master -> master

No servidor Git, verificamos após o commit se o script hook post-update está funcionando

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

— vazio, tudo normal.

Conexão do segundo desenvolvedor no Git

Simularemos o trabalho do segundo desenvolvedor.

No cliente

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

E ao mesmo tempo, no servidor...

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

— novamente vazio, tudo está funcionando.

Removendo o projeto Git e carregando o projeto do servidor Git

Bem, podemos conferir mais uma vez se todas as alterações foram salvas.

C:gittest>rd /S /Q .
O processo não pode acessar o arquivo porque ele está sendo usado por outro processo.

— para remover o projeto Git, apenas limpamos completamente o diretório. Aceitamos o erro mostrado, pois não é possível remover o diretório atual com este comando, mas é esse o comportamento que precisamos.

C:gittest>dir
 Conteúdo da pasta 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
Clonando para 'proj2'...
dev2@10.1.1.11's password:

C:gittest>cd proj2

C:gittestproj2>dir
 Conteúdo da pasta C:gittestproj2

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:gittestproj2>type test1.txt
"test dev1 to proj2"
"dev1 added some more"
"dev1 3rd line"
"!!! dev2 added this"

C:gittestproj2>type test2.txt
"!!! dev2 wrote"

Divisão de acesso no Git

Agora vamos garantir que mesmo pelo Git, o segundo desenvolvedor não pode acessar o projeto Proj1, do qual ele não está trabalhando.

C:gittestproj2>git remote remove origin

C:gittestproj2>git remote add origin "ssh://dev2@10.1.1.11/var/gitservertest/proj1"

C:gittestproj2>git push origin master
dev2@10.1.1.11's password:
fatal: '/var/gitservertest/proj1' não parece ser um repositório git
fatal: Não foi possível ler do repositório remoto.

Por favor, verifique se você tem os direitos de acesso corretos
e se o repositório existe.

Agora, concedemos acesso

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

e depois disso tudo funciona.

C:gittestproj2>git push origin master
dev2@10.1.1.11's password:
Para ssh://10.1.1.11/var/gitservertest/proj1
 * [novo branch]      master -> master

Informações adicionais

Além disso, se houver um problema com os direitos padrão ao criar arquivos e diretórios, no CentOS pode-se usar o comando

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

Você também pode encontrar algumas coisas úteis no artigo:

  • como construir uma árvore de diretórios no Linux
  • como passar um intervalo de endereços no sed a partir de uma linha específica até o final do arquivo, ou seja, fazer uma substituição no sed em todas as linhas, exceto na primeira
  • Como inverter a condição de pesquisa no find do Linux
  • como passar várias linhas para um loop no shell do Linux através de uma linha única
  • como escapar aspas simples no bash
  • como excluir um diretório com todo o conteúdo na linha de comando do Windows
  • Como renomear um arquivo usando mv no bash, sem sobrescrevê-lo novamente

Obrigado pela atenção.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster