t5563: add tests for basic and anoymous HTTP access

Add a test showing simple anoymous HTTP access to an unprotected repository, that results in no credential helper invocations. Also add a test demonstrating simple basic authentication with simple credential helper support. Leverage a no-parsed headers (NPH) CGI script so that we can directly control the HTTP responses to simulate a multitude of good, bad and ugly remote server implementations around auth. Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Matthew John Cheetham committed Feb 27, 2023 at 17:20 UTC 988aad99b44f3fb3f04f4a75cadf0dbb7ac89ffe
4 files changed +129
t/lib-httpd.sh
+1
@@ -137,6 +137,7 @@ prepare_httpd() {
137 install_script error-smart-http.sh
138 install_script error.sh
139 install_script apply-one-time-perl.sh
140 + install_script nph-custom-auth.sh
141
142 ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
143
t/lib-httpd/apache.conf
+6
@@ -135,6 +135,11 @@ Alias /auth/dumb/ www/auth/dumb/
135 SetEnv GIT_HTTP_EXPORT_ALL
136 SetEnv GIT_PROTOCOL
137 </LocationMatch>
138 +<LocationMatch /custom_auth/>
139 + SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
140 + SetEnv GIT_HTTP_EXPORT_ALL
141 + CGIPassAuth on
142 +</LocationMatch>
143 ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
144 ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
145 ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/
@@ -144,6 +149,7 @@ ScriptAlias /broken_smart/ broken-smart-http.sh/
149 ScriptAlias /error_smart/ error-smart-http.sh/
150 ScriptAlias /error/ error.sh/
151 ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1
152 +ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1
153 <Directory ${GIT_EXEC_PATH}>
154 Options FollowSymlinks
155 </Directory>
t/lib-httpd/nph-custom-auth.sh new
+39
@@ -0,0 +1,39 @@
1 +#!/bin/sh
2 +
3 +VALID_CREDS_FILE=custom-auth.valid
4 +CHALLENGE_FILE=custom-auth.challenge
5 +
6 +#
7 +# If $VALID_CREDS_FILE exists in $HTTPD_ROOT_PATH, consider each line as a valid
8 +# credential for the current request. Each line in the file is considered a
9 +# valid HTTP Authorization header value. For example:
10 +#
11 +# Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
12 +#
13 +# If $CHALLENGE_FILE exists in $HTTPD_ROOT_PATH, output the contents as headers
14 +# in a 401 response if no valid authentication credentials were included in the
15 +# request. For example:
16 +#
17 +# WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
18 +# WWW-Authenticate: Basic realm="example.com"
19 +#
20 +
21 +if test -n "$HTTP_AUTHORIZATION" && \
22 + grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE"
23 +then
24 + # Note that although git-http-backend returns a status line, it
25 + # does so using a CGI 'Status' header. Because this script is an
26 + # No Parsed Headers (NPH) script, we must return a real HTTP
27 + # status line.
28 + # This is only a test script, so we don't bother to check for
29 + # the actual status from git-http-backend and always return 200.
30 + echo 'HTTP/1.1 200 OK'
31 + exec "$GIT_EXEC_PATH"/git-http-backend
32 +fi
33 +
34 +echo 'HTTP/1.1 401 Authorization Required'
35 +if test -f "$CHALLENGE_FILE"
36 +then
37 + cat "$CHALLENGE_FILE"
38 +fi
39 +echo
t/t5563-simple-http-auth.sh new
+83
@@ -0,0 +1,83 @@
1 +#!/bin/sh
2 +
3 +test_description='test http auth header and credential helper interop'
4 +
5 +. ./test-lib.sh
6 +. "$TEST_DIRECTORY"/lib-httpd.sh
7 +
8 +start_httpd
9 +
10 +test_expect_success 'setup_credential_helper' '
11 + mkdir "$TRASH_DIRECTORY/bin" &&
12 + PATH=$PATH:"$TRASH_DIRECTORY/bin" &&
13 + export PATH &&
14 +
15 + CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" &&
16 + write_script "$CREDENTIAL_HELPER" <<-\EOF
17 + cmd=$1
18 + teefile=$cmd-query.cred
19 + catfile=$cmd-reply.cred
20 + sed -n -e "/^$/q" -e "p" >>$teefile
21 + if test "$cmd" = "get"
22 + then
23 + cat $catfile
24 + fi
25 + EOF
26 +'
27 +
28 +set_credential_reply () {
29 + cat >"$TRASH_DIRECTORY/$1-reply.cred"
30 +}
31 +
32 +expect_credential_query () {
33 + cat >"$TRASH_DIRECTORY/$1-expect.cred" &&
34 + test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \
35 + "$TRASH_DIRECTORY/$1-query.cred"
36 +}
37 +
38 +per_test_cleanup () {
39 + rm -f *.cred &&
40 + rm -f "$HTTPD_ROOT_PATH"/custom-auth.valid \
41 + "$HTTPD_ROOT_PATH"/custom-auth.challenge
42 +}
43 +
44 +test_expect_success 'setup repository' '
45 + test_commit foo &&
46 + git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
47 + git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
48 +'
49 +
50 +test_expect_success 'access using basic auth' '
51 + test_when_finished "per_test_cleanup" &&
52 +
53 + set_credential_reply get <<-EOF &&
54 + username=alice
55 + password=secret-passwd
56 + EOF
57 +
58 + # Basic base64(alice:secret-passwd)
59 + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
60 + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
61 + EOF
62 +
63 + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
64 + WWW-Authenticate: Basic realm="example.com"
65 + EOF
66 +
67 + test_config_global credential.helper test-helper &&
68 + git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
69 +
70 + expect_credential_query get <<-EOF &&
71 + protocol=http
72 + host=$HTTPD_DEST
73 + EOF
74 +
75 + expect_credential_query store <<-EOF
76 + protocol=http
77 + host=$HTTPD_DEST
78 + username=alice
79 + password=secret-passwd
80 + EOF
81 +'
82 +
83 +test_done