Autorização HTTP Nginx apenas para git push

Autorização HTTP Nginx apenas para git push

Eu hospedo um servidor git privado usando Nginx. Gostaria que alguém clonasse em meus repositórios (sem autorização), mas exigisse autorização se tentar enviar um commit.

Minha configuração do Nginx é a seguinte:

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;

  }

Pelo que entendi, uma git pushsolicitação envia um git-receive-packpara o meu servidor. Minha solução simples foi capturar esse sufixo $1e usar uma instrução if, mas descobri rapidamente que esse não é o uso correto para ifs (ifisevil).

Existe uma solução mais apropriada para o que estou tentando realizar?

Responder1

O git poderia enviar solicitações diferentes por push (por exemplo, /path/to/repo.git/path/in/repo/refs?service=git-upload-packou similar), e você estava tentando usar comparação igual.

Tente algo assim:

  # 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 ...
    }
    ...
  }

Mas também como cenário de trabalho você pode usar algo assim:

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

ou simplesmente URL (e local) diferente para push que o reescreve após autorização. Então você podeconfigurar remotocom push-url diferente (contendo um nome de usuário ou outro local):

# 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/...

A propósito, a diretiva "if" não é mais maligna do que algum local regex de nível superior (especialmente se for aplicada apenas em determinado local e não se preocupar diretamente na seção http/servidor).
Mas você pode fazer tudo isso também sem "if" (como no exemplo abaixo com localização nomeada), mas não é tão simples depurar alguns problemas (se você não estiver familiarizado com o 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 ...
  }
}

informação relacionada