Organización del acceso multiusuario al servidor GIT

Al instalar y configurar un servidor Git, surge la cuestión de organizar el acceso de varios usuarios a varios proyectos. Investigué un poco sobre el tema y encontré una solución que cumple con todos mis requisitos: simple, segura y confiable.

Mis deseos son:

  • cada usuario se conecta con su propia cuenta
  • Varios usuarios pueden trabajar en el mismo proyecto
  • el mismo usuario puede trabajar en varios proyectos
  • cada usuario tiene acceso solo a aquellos proyectos en los que trabaja
  • debería ser posible conectarse a través de la línea de comando, y no solo a través de algún tipo de interfaz web

También sería genial:

  • otorgar derechos de solo lectura a las personas controladoras
  • administrar convenientemente los permisos de usuario en Git

Descripción general de las posibles opciones para acceder al servidor GIT

En primer lugar, debe saber qué elegir, así que una breve descripción general de los protocolos de Git.

  • ssh: se utiliza una cuenta de usuario especialmente creada para acceder al servidor.
    • es extraño que Git no recomiende usar una cuenta para acceder a todos los repositorios. Esto no cumple mis requisitos en absoluto.
    • Puede usar varias cuentas, pero ¿cómo puede limitar el acceso de un usuario solo a ciertos directorios?
      • Cerrar el directorio de inicio no es adecuado, porque es difícil organizar el acceso de escritura para otros usuarios allí.
      • El uso de enlaces simbólicos desde el directorio de inicio también es complicado porque Git no los interpreta como enlaces.
      • Restrinja el acceso al intérprete, bueno, puede, pero no hay garantía total de que esto funcione siempre.
        • Por lo general, puede conectar su propio intérprete de comandos para dichos usuarios, pero,
          • en primer lugar, esto ya es una especie de decisión difícil,
          • y 2, se puede omitir.

    ¿Pero tal vez no sea un problema que el usuario pueda ejecutar cualquier comando? ... En general, este método no se puede descartar si descubre exactamente cómo usarlo. Volveremos a este método más adelante, pero por ahora consideraremos brevemente las alternativas restantes, tal vez haya algo más simple.

  • El protocolo local git se puede usar en combinación con sshfs, se pueden usar múltiples usuarios, pero es esencialmente lo mismo que en el caso anterior
  • http - solo lectura
  • git es de solo lectura
  • https es difícil de instalar, necesita un software adicional, algún tipo de panel de control para organizar el acceso de los usuarios ... parece factible, pero de alguna manera todo es complicado.

Uso del protocolo ssh para organizar el acceso multiusuario al servidor Git

Volvamos al protocolo ssh.

Dado que el acceso ssh se usa para git, los datos del servidor deben estar seguros. El usuario que se conecta a través de ssh utiliza su propio inicio de sesión en el servidor Linux, por lo que puede conectarse a través del cliente ssh y acceder a la línea de comandos del servidor.
No existe una protección completa contra la obtención de dicho acceso.

Pero el usuario no debería estar interesado en los archivos de Linux. La información significativa se almacena solo en el repositorio de git. Por tanto, no se puede restringir el acceso a través de la línea de comandos, pero mediante Linux, prohibir al usuario la visualización de proyectos, excluyendo aquellos en los que participa.
Es obvio usar el sistema de permisos de Linux.

Como ya se mencionó, es posible usar solo una cuenta para el acceso ssh. Esta configuración no es segura para varios usuarios, aunque está incluida en la lista de opciones recomendadas de git.

Para implementar los requisitos dados al comienzo del artículo, se crea la siguiente estructura de directorio con la asignación de derechos y propietarios:

1) directorios de proyectos

dir1(proyecto1:proyecto1,0770)
dir2(proyecto2:proyecto2,0770)
dir3(proyecto3:proyecto3,0770)
...
donde
dir1, dir2, dir3 - directorios de proyectos: proyecto 1, proyecto 2, proyecto 3.

proj1:proj1, proj2:proj2, proj3:proj3 son usuarios de Linux especialmente creados que se asignan como propietarios de los respectivos directorios de proyectos.

los derechos de todos los directorios se establecen en 0770: acceso completo para el propietario y su grupo, y una prohibición total para todos los demás.

2) cuentas de desarrollador

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

El punto clave es que a los desarrolladores se les asigna un grupo adicional del usuario del sistema que posee el proyecto correspondiente. Esto lo hace el administrador del servidor Linux con un comando.

En este ejemplo, el Desarrollador 1 está trabajando en los proyectos proj1 y proj2, y el Desarrollador 2 está trabajando en los proyectos proj2 y proj3.

Si alguno de los Desarrolladores se conecta a través de ssh a través de la línea de comando, sus derechos no serán suficientes ni siquiera para ver los contenidos de los directorios de proyectos en los que no participa. Él mismo no puede cambiarlo.

Dado que la base de este principio es la seguridad básica de los derechos de Linux, este esquema es confiable. Además, el esquema es muy fácil de administrar.

Pasemos a la práctica.

Creación de repositorios Git en un servidor Linux

Comprobación.

[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

cansado de escribir...

[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 es imposible acceder a los repositorios de otras personas desde la línea de comandos e incluso ver su contenido.

[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

Colaboración en Git de varios desarrolladores en un proyecto

Queda una pregunta, si un desarrollador introduce un nuevo archivo, entonces otros desarrolladores no pueden cambiarlo, porque él mismo es su propietario (por ejemplo, dev1) y no el usuario propietario del proyecto (por ejemplo, proj1). Dado que tenemos un repositorio de servidor, en primer lugar, necesitamos saber cómo está organizado el directorio ".git" y si se crean nuevos archivos.

Cree un repositorio Git local y envíelo a un servidor Git

Pasemos a la 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>

Al mismo tiempo, se generan nuevos archivos en el servidor y pertenecen al usuario que realizó el envío.

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

Cuando los cambios se cargan en el servidor de Git, se crean archivos y directorios adicionales y en realidad son propiedad de la persona que los subió. Pero entonces el grupo de estos archivos y directorios también corresponde al grupo principal de este usuario, es decir, el grupo dev1 para el usuario dev1 y el grupo dev2 para el usuario dev2 (cambiar el grupo principal del usuario desarrollador no ayudará, porque entonces ¿Cómo trabajar en múltiples proyectos?). En este caso, el usuario dev2 no podrá modificar los archivos creados por el usuario dev1, y esto está plagado de una violación de la funcionalidad.

Chown de Linux: cambiar el propietario de un archivo por un usuario normal

El propietario de un archivo no puede cambiar su propiedad. Pero puede cambiar el grupo de un archivo que le pertenece, y luego este archivo puede ser cambiado por otros usuarios que están en el mismo grupo. Eso es lo que necesitamos.

Usando el Git Hook

El directorio de trabajo para hook es el directorio raíz del proyecto. hook es un ejecutable que se ejecuta bajo el usuario que está haciendo el push. sabiendo esto, podemos llevar a cabo nuestros planes.

[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

o solo

vi hooks/post-update

Volvamos a la 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

En el servidor Git, verifique el trabajo del script posterior a la actualización del enlace después de la confirmación

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

- vacío, todo está bien.

Conexión de un segundo desarrollador a Git

Simulemos el trabajo del segundo desarrollador.

en el 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

Y al mismo tiempo, en el servidor...

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

- de nuevo vacío, todo funciona.

Eliminación de un proyecto Git y carga de un proyecto desde un servidor Git

Bueno, una vez más puede asegurarse de que todos los cambios se hayan guardado.

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

- para eliminar un proyecto de Git, simplemente borre el directorio por completo. Aceptemos el error dado, ya que es imposible eliminar el directorio actual con este comando, pero este es exactamente el comportamiento que necesitamos.

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"

Compartir acceso en Git

Ahora asegurémonos de que el segundo desarrollador no pueda acceder al proyecto Proj1 a través de Git, en el que no está trabajando.

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.

Ahora permitir el acceso

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

y despues de eso todo 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 obtener más información,

Además, si hay un problema con los permisos predeterminados al crear archivos y directorios, en CentOS puede usar el comando

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

También en el artículo puedes tropezar con pequeñas cosas útiles:

  • Cómo construir un árbol de directorios en Linux
  • como pasar un rango de direcciones desde cierta linea hasta el final del archivo en sed, es decir, hacer un reemplazo en sed en todas las lineas menos en la primera linea
  • Cómo invertir la condición de búsqueda en Linux find
  • cómo pasar varias líneas a través de una sola línea en un shell de Linux
  • cómo escapar comillas simples en bash
  • cómo eliminar un directorio con todo el contenido en la línea de comando de Windows
  • Cómo cambiar el nombre de un archivo usando bash mv sin reescribirlo

Gracias por su atención.

Fuente: habr.com

Añadir un comentario