Autorización HTTP de Nginx solo para git push

Autorización HTTP de Nginx solo para git push

Alojo un servidor git privado usando Nginx. Me gustaría que cualquiera clonara mis repositorios (sin autorización), pero necesito autorización si intenta realizar una confirmación.

Mi configuración de Nginx es la siguiente:

server {
  listen 443 ssl;
  server_name git.example.com;
  ssl_certificate /fullchain.pem;
  ssl_certificate_key /privkey.pem;

  location ~ ^.*\.git/(HEAD|info/refs|objects/info/.*|git-(upload|recieve)-pack) {
    root /usr/share/nginx/git;

# --- incorrect solution ---

#    if ($1 = git-upload-pack) {
#        auth_basic "Restricted";
#        auth_basic_user_file /usr/share/nginx/htpasswd;
#    }
    client_max_body_size 0;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
    fastcgi_param GIT_HTTP_EXPORT_ALL "";
    fastcgi_param GIT_PROJECT_ROOT $realpath_root;
    fastcgi_param REMOTE_USER $remote_user;
    fastcgi_param PATH_INFO $uri;
    fastcgi_param unix:/var/fcgiwrap.socket;

  }

Según tengo entendido, una git pushsolicitud envía un git-receive-packa mi servidor. Mi solución simple fue capturar este sufijo $1y usar una declaración if, pero descubrí rápidamente que este no es el uso correcto para ifs (ifisevil).

¿Existe una solución más apropiada para lo que estoy tratando de lograr?

Respuesta1

git podría enviar diferentes solicitudes mediante push (por ejemplo, /path/to/repo.git/path/in/repo/refs?service=git-upload-packo similares), y usted estaba intentando utilizar una comparación equitativa.

Prueba algo como eso:

  # static repo files for faster cloning over https:
  location ~ \.git/objects/(?:[0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+\.(?:pack|idx))$ {
    root /home/git/repositories/;
  }                                                                                                                                               

  # requests that need to go to git-http-backend:
  location ~ \.git/(?:HEAD|info/refs|objects/info/|git-(?:upload|receive)-pack$) {
    root /home/git/repositories;
    # if upload:
    if ( $uri ~* "git-upload-pack$" ) {
       auth_basic ...
    }
    ...
  }

Pero también como escenario de trabajo puedes usar algo como esto:

    # authorize if user name is specified:
    if ( $remote_user != "" ) {
       auth_basic ...
    }

o simplemente una URL (y ubicación) diferente para enviar y reescribirla después de la autorización. Entonces tú puedesconfigurar remotocon diferente URL de inserción (que contiene un nombre de usuario u otra ubicación):

# with user:
git remote set-url --push origin https://[email protected]/repo/...
# with "rw" location (to force authorization):
git remote set-url --push origin https://git.domail.tld/rw/repo/...

Por cierto, la directiva "si" no es más malvada que alguna ubicación de expresiones regulares de nivel superior (especialmente si se aplica solo en cierta ubicación y no molesta directamente en la sección http/servidor).
Pero, de hecho, puedes hacer todo eso también sin "si" (como en el ejemplo siguiente con una ubicación con nombre), pero no es tan sencillo depurar algunos problemas (si no estás familiarizado con nginx):

location ...condGit... {
  root ...;

  location ...condA... {
    ## authorize and supply request to @gitweb:
    auth_basic ...
    try_files "" @gitweb;
  }

  location ...condB... {
    ## authorize and supply request to @gitweb:
    auth_basic ...
    try_files "" @gitweb;
  }

  # send anything else to gitweb if it's not a real file (inside root of gitweb):
  try_files $uri @gitweb;

  location @gitweb {
    # ... single location of fcgi wrapper of git http backend ...
  }
}

información relacionada