Skip to content

Commit

Permalink
doc/http-backend: match query-string in apache half-auth example
Browse files Browse the repository at this point in the history
When setting up a "half-auth" repository in which reads can
be done anonymously but writes require authentication, it is
best if the server can require authentication for both the
ref advertisement and the actual receive-pack POSTs. This
alleviates the need for the admin to set http.receivepack in
the repositories, and means that the client is challenged
for credentials immediately, instead of partway through the
push process (and git clients older than v1.7.11.7 had
trouble handling these challenges).

Since detecting a push during the ref advertisement requires
matching the query string, and this is non-trivial to do in
Apache, we have traditionally punted and instructed users to
just protect "/git-receive-pack$".  This patch provides the
mod_rewrite recipe to actually match the ref advertisement,
which is preferred.

While we're at it, let's add the recipe to our test scripts
so that we can be sure that it works, and doesn't get broken
(either by our changes or by changes in Apache).

Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Jakub Narębski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Apr 14, 2013
1 parent 3813a33 commit b080881
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 8 deletions.
32 changes: 24 additions & 8 deletions Documentation/git-http-backend.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,30 @@ ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
----------------------------------------------------------------
+
To enable anonymous read access but authenticated write access,
require authorization with a LocationMatch directive:
require authorization for both the initial ref advertisement (which we
detect as a push via the service parameter in the query string), and the
receive-pack invocation itself:
+
----------------------------------------------------------------
RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
RewriteCond %{REQUEST_URI} /git-receive-pack$
RewriteRule ^/git/ - [E=AUTHREQUIRED:yes]

<LocationMatch "^/git/">
Order Deny,Allow
Deny from env=AUTHREQUIRED

AuthType Basic
AuthName "Git Access"
Require group committers
Satisfy Any
...
</LocationMatch>
----------------------------------------------------------------
+
If you do not have `mod_rewrite` available to match against the query
string, it is sufficient to just protect `git-receive-pack` itself,
like:
+
----------------------------------------------------------------
<LocationMatch "^/git/.*/git-receive-pack$">
Expand Down Expand Up @@ -207,13 +230,6 @@ auth.require = (
# ...and set up auth.backend here
----------------------------------------------------------------
+
Note that unlike the similar setup with Apache, we can easily match the
query string for receive-pack, catching the initial request from the
client. This means that the server administrator does not have to worry
about configuring `http.receivepack` for the repositories (the default
value, which enables it only in the case of authentication, is
sufficient).
+
To require authentication for both reads and writes:
+
----------------------------------------------------------------
Expand Down
18 changes: 18 additions & 0 deletions t/lib-httpd/apache.conf
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ ErrorLog error.log
<IfModule !mod_authz_user.c>
LoadModule authz_user_module modules/mod_authz_user.so
</IfModule>
<IfModule !mod_authz_host.c>
LoadModule authz_host_module modules/mod_authz_host.so
</IfModule>
</IfVersion>

PassEnv GIT_VALGRIND
Expand Down Expand Up @@ -110,6 +113,21 @@ SSLEngine On
Require valid-user
</LocationMatch>

RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
RewriteCond %{REQUEST_URI} /git-receive-pack$
RewriteRule ^/half-auth-complete/ - [E=AUTHREQUIRED:yes]

<Location /half-auth-complete/>
Order Deny,Allow
Deny from env=AUTHREQUIRED

AuthType Basic
AuthName "Git Access"
AuthUserFile passwd
Require valid-user
Satisfy Any
</Location>

<IfDefine DAV>
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
Expand Down
30 changes: 30 additions & 0 deletions t/t5541-http-push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -295,5 +295,35 @@ test_expect_success 'push to auth-only-for-push repo' '
test_cmp expect actual
'

test_expect_success 'create repo without http.receivepack set' '
cd "$ROOT_PATH" &&
git init half-auth &&
(
cd half-auth &&
test_commit one
) &&
git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
'

test_expect_success 'clone via half-auth-complete does not need password' '
cd "$ROOT_PATH" &&
set_askpass wrong &&
git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
half-auth-clone &&
expect_askpass none
'

test_expect_success 'push into half-auth-complete requires password' '
cd "$ROOT_PATH/half-auth-clone" &&
echo two >expect &&
test_commit two &&
set_askpass user@host &&
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
log -1 --format=%s >actual &&
expect_askpass both user@host &&
test_cmp expect actual
'

stop_httpd
test_done

0 comments on commit b080881

Please sign in to comment.