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. Llevé a cabo un estudio del problema y encontré una solución que satisface todos mis requisitos: simple, seguro y confiable.

Mis deseos son los siguientes:

  • cada usuario se conecta con su propia cuenta
  • múltiples usuarios pueden trabajar en un proyecto
  • el mismo usuario puede trabajar en varios proyectos
  • cada usuario tiene acceso solo a aquellos proyectos en los que trabaja
  • debería poder 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:

  • conceder derechos de solo lectura a las personas controladoras
  • Administra convenientemente los permisos de usuario en Git

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


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

  • ssh: se utiliza una cuenta de usuario especialmente creada para acceder al servidor.
    • Es extraño que Git no excluya de las recomendaciones el uso de una sola cuenta para acceder a todos los repositorios. Esto no cumple con mis requisitos.
    • Puede usar varias cuentas, pero ¿cómo restringir el acceso de los usuarios solo a ciertos directorios?

      • Cerrar el directorio de inicio no es adecuado, porque es difícil organizar allí el acceso de escritura para otros usuarios
      • Usar enlaces simbólicos desde su directorio de inicio también es difícil porque Git no los interpreta como enlaces
      • Es posible restringir el acceso al intérprete, pero no hay garantía total de que esto siempre funcione

        • Incluso puede conectar su propio intérprete de comandos para dichos usuarios, pero,

          • en primer lugar, esto ya es una decisión difícil,
          • y en 2, esto se puede evitar.

    Pero tal vez esto no sea un problema de que el usuario pueda ejecutar cualquier comando ... En general, este método no puede excluirse si se le ocurre cómo usarlo. Volveremos a este método más tarde, pero por ahora considere brevemente las otras alternativas, tal vez algo sea más fácil allí.
  • El protocolo local de git se puede usar junto con sshfs, se pueden usar varios usuarios, pero en esencia, esto es lo mismo que el caso anterior
  • http - solo lectura
  • git es de solo lectura
  • https: es difícil de instalar, necesita software adicional, algún tipo de panel de control para organizar el acceso de los usuarios ... parece factible, pero de alguna manera es complicado.

Usando el protocolo ssh para organizar el acceso multiusuario al servidor Git


De vuelta al protocolo ssh.

Dado que el acceso ssh se usa para git, debe proteger los datos del servidor. El usuario que se conecta a través de ssh usa 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 hay protección total 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 lo tanto, no puede restringir el acceso a través de la línea de comandos, pero Linux puede evitar que el usuario vea proyectos, excluyendo aquellos en los que participa.
Obviamente usando el sistema de permisos de Linux.

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

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

1) directorios de proyectos

dir1 (proj1: proj1,0770)
dir2 (proj2: proj2,0770)
dir3 (proj3: proj3,0770)
...
donde
dir1, dir2, dir3 - directorios del proyecto: proyecto 1, proyecto 2, proyecto 3.

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

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

2) cuentas de desarrollador

Desarrollador 1: dev1: dev1, proj1, proj2
Desarrollador 2: dev2: dev2, proj2, proj3

El punto clave es que a los desarrolladores se les asigna un grupo adicional de usuarios del sistema que poseen el proyecto correspondiente. Esto lo realiza el administrador del servidor Linux como un solo comando.

En este ejemplo, "Developer 1" funciona en los proyectos proj1 y proj2, y "Developer 2" funciona 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, entonces sus derechos no serán suficientes ni siquiera para ver el contenido de los directorios del proyecto en los que no está involucrado. Él mismo no puede cambiar esto de ninguna manera.

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

Crear repositorios Git en un servidor Linux


Lo comprobamos

[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 con mis manos

 [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 

Nos aseguramos de que sea 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 el resto de los desarrolladores no pueden cambiarlo, porque él mismo lo posee (por ejemplo, dev1), y no el usuario propietario del proyecto (por ejemplo, proj1). Dado que tenemos un repositorio de servidores, en primer lugar, debe saber cómo está organizado el directorio ".git" y si se crean nuevos archivos.

Creación de un repositorio Git local y envío a un servidor Git


Pasemos a la máquina del 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://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> 

Al mismo tiempo, se forman nuevos archivos en el servidor y pertenecen al usuario que realizó la inserción.

 [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 Git, se crean archivos y directorios adicionales y, al mismo tiempo, el usuario que realiza la carga es el propietario. 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 de desarrollo no ayudará, desde entonces, ¿cómo trabajar en varios proyectos?). En este caso, el usuario dev2 no podrá modificar archivos creados por el usuario dev1, y esto está plagado de una violación de la funcionalidad.

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



El propietario del archivo no puede cambiar su propiedad. Pero puede cambiar el grupo del archivo que le pertenece, y luego este archivo puede estar disponible para cambiarlo a otros usuarios que están en el mismo grupo. Esto es lo que necesitamos.

Usando git hook


El directorio de trabajo para el gancho es el directorio raíz del proyecto. hook es un ejecutable que se ejecuta bajo el usuario que empuja. sabiendo esto, podemos cumplir nuestro 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 

ya sea solo

 vi hooks/post-update 

De vuelta a la máquina del 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 

En el servidor Git, verificamos después de confirmar la operación del script de post actualización de hook

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

- Vacío, todo está bien.

Conectando un segundo desarrollador a Git


Imitaremos el trabajo del segundo desarrollador.

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

Y al mismo tiempo, en el servidor ...

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

- vacío de nuevo, todo funciona.

Eliminar un proyecto Git y descargar un proyecto desde un servidor Git


Bueno, una vez más puedes asegurarte de que se conservan todos los cambios.

 C:\gittest>rd /S /Q .       ,       . 

- Para eliminar un proyecto Git, simplemente borre el directorio por completo. Vamos a soportar el error generado, ya que es imposible eliminar el directorio actual para este comando, pero solo necesitamos este comportamiento.

 C:\gittest>dir   C:\gittest 21.06.2019 08:43 <DIR> . 21.06.2019 08:43 <DIR> .. 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 <DIR> . 21.06.2019 08:46 <DIR> .. 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" 

Compartir acceso en Git


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

 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. 

Ahora permitir acceso

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

y después de eso todo funciona.

 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 

Información adicional


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

 setfacl -Rd -mo::5 -mg::7 /var/gitservertest 

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

  • Cómo construir un árbol de directorios en Linux
  • cómo sed para transferir un rango de direcciones desde una determinada línea hasta el final del archivo, es decir, hacer un reemplazo en sed en todas las líneas excepto la primera línea
  • Cómo en Linux encontrar para invertir un término de búsqueda
  • cómo en Linux Shell para recorrer varias líneas a través de una sola línea
  • cómo escapar de comillas simples en bash
  • Cómo eliminar el directorio con todo el contenido en la línea de comando de Windows
  • Cómo usar bash mv para cambiar el nombre de un archivo sin volver a escribirlo

Gracias por su atencion

Source: https://habr.com/ru/post/457056/


All Articles