Skip to content

Commit b080881

Browse files
peffgitster
authored andcommitted
doc/http-backend: match query-string in apache half-auth example
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 <[email protected]> Acked-by: Jakub Narębski <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3813a33 commit b080881

File tree

3 files changed

+72
-8
lines changed

3 files changed

+72
-8
lines changed

Documentation/git-http-backend.txt

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,30 @@ ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
8080
----------------------------------------------------------------
8181
+
8282
To enable anonymous read access but authenticated write access,
83-
require authorization with a LocationMatch directive:
83+
require authorization for both the initial ref advertisement (which we
84+
detect as a push via the service parameter in the query string), and the
85+
receive-pack invocation itself:
86+
+
87+
----------------------------------------------------------------
88+
RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
89+
RewriteCond %{REQUEST_URI} /git-receive-pack$
90+
RewriteRule ^/git/ - [E=AUTHREQUIRED:yes]
91+
92+
<LocationMatch "^/git/">
93+
Order Deny,Allow
94+
Deny from env=AUTHREQUIRED
95+
96+
AuthType Basic
97+
AuthName "Git Access"
98+
Require group committers
99+
Satisfy Any
100+
...
101+
</LocationMatch>
102+
----------------------------------------------------------------
103+
+
104+
If you do not have `mod_rewrite` available to match against the query
105+
string, it is sufficient to just protect `git-receive-pack` itself,
106+
like:
84107
+
85108
----------------------------------------------------------------
86109
<LocationMatch "^/git/.*/git-receive-pack$">
@@ -207,13 +230,6 @@ auth.require = (
207230
# ...and set up auth.backend here
208231
----------------------------------------------------------------
209232
+
210-
Note that unlike the similar setup with Apache, we can easily match the
211-
query string for receive-pack, catching the initial request from the
212-
client. This means that the server administrator does not have to worry
213-
about configuring `http.receivepack` for the repositories (the default
214-
value, which enables it only in the case of authentication, is
215-
sufficient).
216-
+
217233
To require authentication for both reads and writes:
218234
+
219235
----------------------------------------------------------------

t/lib-httpd/apache.conf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ ErrorLog error.log
4040
<IfModule !mod_authz_user.c>
4141
LoadModule authz_user_module modules/mod_authz_user.so
4242
</IfModule>
43+
<IfModule !mod_authz_host.c>
44+
LoadModule authz_host_module modules/mod_authz_host.so
45+
</IfModule>
4346
</IfVersion>
4447

4548
PassEnv GIT_VALGRIND
@@ -110,6 +113,21 @@ SSLEngine On
110113
Require valid-user
111114
</LocationMatch>
112115

116+
RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]
117+
RewriteCond %{REQUEST_URI} /git-receive-pack$
118+
RewriteRule ^/half-auth-complete/ - [E=AUTHREQUIRED:yes]
119+
120+
<Location /half-auth-complete/>
121+
Order Deny,Allow
122+
Deny from env=AUTHREQUIRED
123+
124+
AuthType Basic
125+
AuthName "Git Access"
126+
AuthUserFile passwd
127+
Require valid-user
128+
Satisfy Any
129+
</Location>
130+
113131
<IfDefine DAV>
114132
LoadModule dav_module modules/mod_dav.so
115133
LoadModule dav_fs_module modules/mod_dav_fs.so

t/t5541-http-push.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,5 +295,35 @@ test_expect_success 'push to auth-only-for-push repo' '
295295
test_cmp expect actual
296296
'
297297

298+
test_expect_success 'create repo without http.receivepack set' '
299+
cd "$ROOT_PATH" &&
300+
git init half-auth &&
301+
(
302+
cd half-auth &&
303+
test_commit one
304+
) &&
305+
git clone --bare half-auth "$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git"
306+
'
307+
308+
test_expect_success 'clone via half-auth-complete does not need password' '
309+
cd "$ROOT_PATH" &&
310+
set_askpass wrong &&
311+
git clone "$HTTPD_URL"/half-auth-complete/smart/half-auth.git \
312+
half-auth-clone &&
313+
expect_askpass none
314+
'
315+
316+
test_expect_success 'push into half-auth-complete requires password' '
317+
cd "$ROOT_PATH/half-auth-clone" &&
318+
echo two >expect &&
319+
test_commit two &&
320+
set_askpass user@host &&
321+
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
322+
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
323+
log -1 --format=%s >actual &&
324+
expect_askpass both user@host &&
325+
test_cmp expect actual
326+
'
327+
298328
stop_httpd
299329
test_done

0 commit comments

Comments
 (0)