Merge branch 'ar/submodule-add-config'
[git/debian.git] / t / t5534-push-signed.sh
blobbba768f5ded1fc9b74a6920db74436335d254559
1 #!/bin/sh
3 test_description='signed push'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/lib-gpg.sh
11 prepare_dst () {
12 rm -fr dst &&
13 test_create_repo dst &&
15 git push dst main:noop main:ff main:noff
18 test_expect_success setup '
19 # main, ff and noff branches pointing at the same commit
20 test_tick &&
21 git commit --allow-empty -m initial &&
23 git checkout -b noop &&
24 git checkout -b ff &&
25 git checkout -b noff &&
27 # noop stays the same, ff advances, noff rewrites
28 test_tick &&
29 git commit --allow-empty --amend -m rewritten &&
30 git checkout ff &&
32 test_tick &&
33 git commit --allow-empty -m second
36 test_expect_success 'unsigned push does not send push certificate' '
37 prepare_dst &&
38 mkdir -p dst/.git/hooks &&
39 write_script dst/.git/hooks/post-receive <<-\EOF &&
40 # discard the update list
41 cat >/dev/null
42 # record the push certificate
43 if test -n "${GIT_PUSH_CERT-}"
44 then
45 git cat-file blob $GIT_PUSH_CERT >../push-cert
47 EOF
49 git push dst noop ff +noff &&
50 ! test -f dst/push-cert
53 test_expect_success 'talking with a receiver without push certificate support' '
54 prepare_dst &&
55 mkdir -p dst/.git/hooks &&
56 write_script dst/.git/hooks/post-receive <<-\EOF &&
57 # discard the update list
58 cat >/dev/null
59 # record the push certificate
60 if test -n "${GIT_PUSH_CERT-}"
61 then
62 git cat-file blob $GIT_PUSH_CERT >../push-cert
64 EOF
66 git push dst noop ff +noff &&
67 ! test -f dst/push-cert
70 test_expect_success 'push --signed fails with a receiver without push certificate support' '
71 prepare_dst &&
72 mkdir -p dst/.git/hooks &&
73 test_must_fail git push --signed dst noop ff +noff 2>err &&
74 test_i18ngrep "the receiving end does not support" err
77 test_expect_success 'push --signed=1 is accepted' '
78 prepare_dst &&
79 mkdir -p dst/.git/hooks &&
80 test_must_fail git push --signed=1 dst noop ff +noff 2>err &&
81 test_i18ngrep "the receiving end does not support" err
84 test_expect_success GPG 'no certificate for a signed push with no update' '
85 prepare_dst &&
86 mkdir -p dst/.git/hooks &&
87 write_script dst/.git/hooks/post-receive <<-\EOF &&
88 if test -n "${GIT_PUSH_CERT-}"
89 then
90 git cat-file blob $GIT_PUSH_CERT >../push-cert
92 EOF
93 git push dst noop &&
94 ! test -f dst/push-cert
97 test_expect_success GPG 'signed push sends push certificate' '
98 prepare_dst &&
99 mkdir -p dst/.git/hooks &&
100 git -C dst config receive.certnonceseed sekrit &&
101 write_script dst/.git/hooks/post-receive <<-\EOF &&
102 # discard the update list
103 cat >/dev/null
104 # record the push certificate
105 if test -n "${GIT_PUSH_CERT-}"
106 then
107 git cat-file blob $GIT_PUSH_CERT >../push-cert
108 fi &&
110 cat >../push-cert-status <<E_O_F
111 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
112 KEY=${GIT_PUSH_CERT_KEY-nokey}
113 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
114 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
115 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
116 E_O_F
120 git push --signed dst noop ff +noff &&
123 cat <<-\EOF &&
124 SIGNER=C O Mitter <committer@example.com>
125 KEY=13B6F51ECDDE430D
126 STATUS=G
127 NONCE_STATUS=OK
129 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
130 ) >expect &&
132 noop=$(git rev-parse noop) &&
133 ff=$(git rev-parse ff) &&
134 noff=$(git rev-parse noff) &&
135 grep "$noop $ff refs/heads/ff" dst/push-cert &&
136 grep "$noop $noff refs/heads/noff" dst/push-cert &&
137 test_cmp expect dst/push-cert-status
140 test_expect_success GPG 'inconsistent push options in signed push not allowed' '
141 # First, invoke receive-pack with dummy input to obtain its preamble.
142 prepare_dst &&
143 git -C dst config receive.certnonceseed sekrit &&
144 git -C dst config receive.advertisepushoptions 1 &&
145 printf xxxx | test_might_fail git receive-pack dst >preamble &&
147 # Then, invoke push. Simulate a receive-pack that sends the preamble we
148 # obtained, followed by a dummy packet.
149 write_script myscript <<-\EOF &&
150 cat preamble &&
151 printf xxxx &&
152 cat >push
154 test_might_fail git push --push-option="foo" --push-option="bar" \
155 --receive-pack="\"$(pwd)/myscript\"" --signed dst --delete ff &&
157 # Replay the push output on a fresh dst, checking that ff is truly
158 # deleted.
159 prepare_dst &&
160 git -C dst config receive.certnonceseed sekrit &&
161 git -C dst config receive.advertisepushoptions 1 &&
162 git receive-pack dst <push &&
163 test_must_fail git -C dst rev-parse ff &&
165 # Tweak the push output to make the push option outside the cert
166 # different, then replay it on a fresh dst, checking that ff is not
167 # deleted.
168 perl -pe "s/([^ ])bar/\$1baz/" push >push.tweak &&
169 prepare_dst &&
170 git -C dst config receive.certnonceseed sekrit &&
171 git -C dst config receive.advertisepushoptions 1 &&
172 git receive-pack dst <push.tweak >out &&
173 git -C dst rev-parse ff &&
174 grep "inconsistent push options" out
177 test_expect_success GPG 'fail without key and heed user.signingkey' '
178 prepare_dst &&
179 mkdir -p dst/.git/hooks &&
180 git -C dst config receive.certnonceseed sekrit &&
181 write_script dst/.git/hooks/post-receive <<-\EOF &&
182 # discard the update list
183 cat >/dev/null
184 # record the push certificate
185 if test -n "${GIT_PUSH_CERT-}"
186 then
187 git cat-file blob $GIT_PUSH_CERT >../push-cert
188 fi &&
190 cat >../push-cert-status <<E_O_F
191 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
192 KEY=${GIT_PUSH_CERT_KEY-nokey}
193 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
194 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
195 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
196 E_O_F
200 test_config user.email hasnokey@nowhere.com &&
202 sane_unset GIT_COMMITTER_EMAIL &&
203 test_must_fail git push --signed dst noop ff +noff
204 ) &&
205 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
206 git push --signed dst noop ff +noff &&
209 cat <<-\EOF &&
210 SIGNER=C O Mitter <committer@example.com>
211 KEY=13B6F51ECDDE430D
212 STATUS=G
213 NONCE_STATUS=OK
215 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
216 ) >expect &&
218 noop=$(git rev-parse noop) &&
219 ff=$(git rev-parse ff) &&
220 noff=$(git rev-parse noff) &&
221 grep "$noop $ff refs/heads/ff" dst/push-cert &&
222 grep "$noop $noff refs/heads/noff" dst/push-cert &&
223 test_cmp expect dst/push-cert-status
226 test_expect_success GPGSM 'fail without key and heed user.signingkey x509' '
227 test_config gpg.format x509 &&
228 prepare_dst &&
229 mkdir -p dst/.git/hooks &&
230 git -C dst config receive.certnonceseed sekrit &&
231 write_script dst/.git/hooks/post-receive <<-\EOF &&
232 # discard the update list
233 cat >/dev/null
234 # record the push certificate
235 if test -n "${GIT_PUSH_CERT-}"
236 then
237 git cat-file blob $GIT_PUSH_CERT >../push-cert
238 fi &&
240 cat >../push-cert-status <<E_O_F
241 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
242 KEY=${GIT_PUSH_CERT_KEY-nokey}
243 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
244 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
245 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
246 E_O_F
250 test_config user.email hasnokey@nowhere.com &&
251 test_config user.signingkey "" &&
253 sane_unset GIT_COMMITTER_EMAIL &&
254 test_must_fail git push --signed dst noop ff +noff
255 ) &&
256 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
257 git push --signed dst noop ff +noff &&
260 cat <<-\EOF &&
261 SIGNER=/CN=C O Mitter/O=Example/SN=C O/GN=Mitter
262 KEY=
263 STATUS=G
264 NONCE_STATUS=OK
266 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
267 ) >expect.in &&
268 key=$(cat "${GNUPGHOME}/trustlist.txt" | cut -d" " -f1 | tr -d ":") &&
269 sed -e "s/^KEY=/KEY=${key}/" expect.in >expect &&
271 noop=$(git rev-parse noop) &&
272 ff=$(git rev-parse ff) &&
273 noff=$(git rev-parse noff) &&
274 grep "$noop $ff refs/heads/ff" dst/push-cert &&
275 grep "$noop $noff refs/heads/noff" dst/push-cert &&
276 test_cmp expect dst/push-cert-status
279 test_expect_success GPG 'failed atomic push does not execute GPG' '
280 prepare_dst &&
281 git -C dst config receive.certnonceseed sekrit &&
282 write_script gpg <<-EOF &&
283 # should check atomic push locally before running GPG.
284 exit 1
286 test_must_fail env PATH="$TRASH_DIRECTORY:$PATH" git push \
287 --signed --atomic --porcelain \
288 dst noop ff noff >out 2>err &&
290 test_i18ngrep ! "gpg failed to sign" err &&
291 cat >expect <<-EOF &&
292 To dst
293 = refs/heads/noop:refs/heads/noop [up to date]
294 ! refs/heads/ff:refs/heads/ff [rejected] (atomic push failed)
295 ! refs/heads/noff:refs/heads/noff [rejected] (non-fast-forward)
296 Done
298 test_cmp expect out
301 test_done