]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5534-push-signed.sh
Merge branch 'jc/unleak-core-excludesfile'
[thirdparty/git.git] / t / t5534-push-signed.sh
CommitLineData
a85b377d
JH
1#!/bin/sh
2
3test_description='signed push'
4
3ac8f630 5GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
334afbc7
JS
6export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
a85b377d
JH
8. ./test-lib.sh
9. "$TEST_DIRECTORY"/lib-gpg.sh
10
11prepare_dst () {
12 rm -fr dst &&
13 test_create_repo dst &&
14
3ac8f630 15 git push dst main:noop main:ff main:noff
a85b377d
JH
16}
17
18test_expect_success setup '
3ac8f630 19 # main, ff and noff branches pointing at the same commit
a85b377d
JH
20 test_tick &&
21 git commit --allow-empty -m initial &&
22
23 git checkout -b noop &&
24 git checkout -b ff &&
25 git checkout -b noff &&
26
27 # noop stays the same, ff advances, noff rewrites
28 test_tick &&
29 git commit --allow-empty --amend -m rewritten &&
30 git checkout ff &&
31
32 test_tick &&
33 git commit --allow-empty -m second
34'
35
36test_expect_success 'unsigned push does not send push certificate' '
37 prepare_dst &&
bef805b7 38 test_hook -C dst post-receive <<-\EOF &&
a85b377d
JH
39 # discard the update list
40 cat >/dev/null
41 # record the push certificate
42 if test -n "${GIT_PUSH_CERT-}"
43 then
44 git cat-file blob $GIT_PUSH_CERT >../push-cert
45 fi
46 EOF
47
48 git push dst noop ff +noff &&
49 ! test -f dst/push-cert
50'
51
52test_expect_success 'talking with a receiver without push certificate support' '
53 prepare_dst &&
bef805b7 54 test_hook -C dst post-receive <<-\EOF &&
a85b377d
JH
55 # discard the update list
56 cat >/dev/null
57 # record the push certificate
58 if test -n "${GIT_PUSH_CERT-}"
59 then
60 git cat-file blob $GIT_PUSH_CERT >../push-cert
61 fi
62 EOF
63
64 git push dst noop ff +noff &&
65 ! test -f dst/push-cert
66'
67
68test_expect_success 'push --signed fails with a receiver without push certificate support' '
69 prepare_dst &&
a85b377d 70 test_must_fail git push --signed dst noop ff +noff 2>err &&
6789275d 71 test_grep "the receiving end does not support" err
a85b377d
JH
72'
73
46667418 74test_expect_success 'push --signed=1 is accepted' '
c4b71a77 75 prepare_dst &&
c4b71a77 76 test_must_fail git push --signed=1 dst noop ff +noff 2>err &&
6789275d 77 test_grep "the receiving end does not support" err
c4b71a77
78'
79
20a7558f
JH
80test_expect_success GPG 'no certificate for a signed push with no update' '
81 prepare_dst &&
bef805b7 82 test_hook -C dst post-receive <<-\EOF &&
20a7558f
JH
83 if test -n "${GIT_PUSH_CERT-}"
84 then
85 git cat-file blob $GIT_PUSH_CERT >../push-cert
86 fi
87 EOF
88 git push dst noop &&
89 ! test -f dst/push-cert
90'
91
a85b377d
JH
92test_expect_success GPG 'signed push sends push certificate' '
93 prepare_dst &&
b89363e4 94 git -C dst config receive.certnonceseed sekrit &&
bef805b7 95 test_hook -C dst post-receive <<-\EOF &&
a85b377d
JH
96 # discard the update list
97 cat >/dev/null
98 # record the push certificate
99 if test -n "${GIT_PUSH_CERT-}"
100 then
101 git cat-file blob $GIT_PUSH_CERT >../push-cert
d05b9618
JH
102 fi &&
103
104 cat >../push-cert-status <<E_O_F
105 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
106 KEY=${GIT_PUSH_CERT_KEY-nokey}
107 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
b89363e4
JH
108 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
109 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
d05b9618
JH
110 E_O_F
111
112 EOF
113
a85b377d 114 git push --signed dst noop ff +noff &&
b89363e4
JH
115
116 (
117 cat <<-\EOF &&
118 SIGNER=C O Mitter <committer@example.com>
119 KEY=13B6F51ECDDE430D
120 STATUS=G
121 NONCE_STATUS=OK
122 EOF
123 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
124 ) >expect &&
125
8722947e
JS
126 noop=$(git rev-parse noop) &&
127 ff=$(git rev-parse ff) &&
128 noff=$(git rev-parse noff) &&
129 grep "$noop $ff refs/heads/ff" dst/push-cert &&
130 grep "$noop $noff refs/heads/noff" dst/push-cert &&
d05b9618 131 test_cmp expect dst/push-cert-status
a85b377d
JH
132'
133
f265f2d6
FS
134test_expect_success GPGSSH 'ssh signed push sends push certificate' '
135 prepare_dst &&
f265f2d6
FS
136 git -C dst config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
137 git -C dst config receive.certnonceseed sekrit &&
bef805b7 138 test_hook -C dst post-receive <<-\EOF &&
f265f2d6
FS
139 # discard the update list
140 cat >/dev/null
141 # record the push certificate
142 if test -n "${GIT_PUSH_CERT-}"
143 then
144 git cat-file blob $GIT_PUSH_CERT >../push-cert
145 fi &&
146
147 cat >../push-cert-status <<E_O_F
148 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
149 KEY=${GIT_PUSH_CERT_KEY-nokey}
150 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
151 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
152 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
153 E_O_F
154
155 EOF
156
157 test_config gpg.format ssh &&
158 test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
159 FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
160 git push --signed dst noop ff +noff &&
161
162 (
163 cat <<-\EOF &&
164 SIGNER=principal with number 1
165 KEY=FINGERPRINT
166 STATUS=G
167 NONCE_STATUS=OK
168 EOF
169 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
170 ) | sed -e "s|FINGERPRINT|$FINGERPRINT|" >expect &&
171
172 noop=$(git rev-parse noop) &&
173 ff=$(git rev-parse ff) &&
174 noff=$(git rev-parse noff) &&
175 grep "$noop $ff refs/heads/ff" dst/push-cert &&
176 grep "$noop $noff refs/heads/noff" dst/push-cert &&
177 test_cmp expect dst/push-cert-status
178'
179
cbaf82cc
JT
180test_expect_success GPG 'inconsistent push options in signed push not allowed' '
181 # First, invoke receive-pack with dummy input to obtain its preamble.
182 prepare_dst &&
183 git -C dst config receive.certnonceseed sekrit &&
184 git -C dst config receive.advertisepushoptions 1 &&
185 printf xxxx | test_might_fail git receive-pack dst >preamble &&
186
187 # Then, invoke push. Simulate a receive-pack that sends the preamble we
188 # obtained, followed by a dummy packet.
189 write_script myscript <<-\EOF &&
190 cat preamble &&
191 printf xxxx &&
192 cat >push
193 EOF
194 test_might_fail git push --push-option="foo" --push-option="bar" \
195 --receive-pack="\"$(pwd)/myscript\"" --signed dst --delete ff &&
196
197 # Replay the push output on a fresh dst, checking that ff is truly
198 # deleted.
199 prepare_dst &&
200 git -C dst config receive.certnonceseed sekrit &&
201 git -C dst config receive.advertisepushoptions 1 &&
202 git receive-pack dst <push &&
203 test_must_fail git -C dst rev-parse ff &&
204
205 # Tweak the push output to make the push option outside the cert
206 # different, then replay it on a fresh dst, checking that ff is not
207 # deleted.
208 perl -pe "s/([^ ])bar/\$1baz/" push >push.tweak &&
209 prepare_dst &&
210 git -C dst config receive.certnonceseed sekrit &&
211 git -C dst config receive.advertisepushoptions 1 &&
212 git receive-pack dst <push.tweak >out &&
213 git -C dst rev-parse ff &&
214 grep "inconsistent push options" out
215'
216
b9459019
MG
217test_expect_success GPG 'fail without key and heed user.signingkey' '
218 prepare_dst &&
b9459019 219 git -C dst config receive.certnonceseed sekrit &&
bef805b7 220 test_hook -C dst post-receive <<-\EOF &&
b9459019
MG
221 # discard the update list
222 cat >/dev/null
223 # record the push certificate
224 if test -n "${GIT_PUSH_CERT-}"
225 then
226 git cat-file blob $GIT_PUSH_CERT >../push-cert
227 fi &&
228
229 cat >../push-cert-status <<E_O_F
230 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
231 KEY=${GIT_PUSH_CERT_KEY-nokey}
232 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
233 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
234 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
235 E_O_F
236
237 EOF
238
53fc9993
HS
239 test_config user.email hasnokey@nowhere.com &&
240 (
241 sane_unset GIT_COMMITTER_EMAIL &&
242 test_must_fail git push --signed dst noop ff +noff
243 ) &&
244 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
b9459019
MG
245 git push --signed dst noop ff +noff &&
246
247 (
248 cat <<-\EOF &&
249 SIGNER=C O Mitter <committer@example.com>
250 KEY=13B6F51ECDDE430D
251 STATUS=G
252 NONCE_STATUS=OK
253 EOF
254 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
255 ) >expect &&
256
8722947e
JS
257 noop=$(git rev-parse noop) &&
258 ff=$(git rev-parse ff) &&
259 noff=$(git rev-parse noff) &&
260 grep "$noop $ff refs/heads/ff" dst/push-cert &&
261 grep "$noop $noff refs/heads/noff" dst/push-cert &&
b9459019
MG
262 test_cmp expect dst/push-cert-status
263'
264
53fc9993
HS
265test_expect_success GPGSM 'fail without key and heed user.signingkey x509' '
266 test_config gpg.format x509 &&
267 prepare_dst &&
53fc9993 268 git -C dst config receive.certnonceseed sekrit &&
bef805b7 269 test_hook -C dst post-receive <<-\EOF &&
53fc9993
HS
270 # discard the update list
271 cat >/dev/null
272 # record the push certificate
273 if test -n "${GIT_PUSH_CERT-}"
274 then
275 git cat-file blob $GIT_PUSH_CERT >../push-cert
276 fi &&
277
278 cat >../push-cert-status <<E_O_F
279 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
280 KEY=${GIT_PUSH_CERT_KEY-nokey}
281 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
282 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
283 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
284 E_O_F
285
286 EOF
287
288 test_config user.email hasnokey@nowhere.com &&
289 test_config user.signingkey "" &&
290 (
291 sane_unset GIT_COMMITTER_EMAIL &&
292 test_must_fail git push --signed dst noop ff +noff
293 ) &&
294 test_config user.signingkey $GIT_COMMITTER_EMAIL &&
295 git push --signed dst noop ff +noff &&
296
297 (
298 cat <<-\EOF &&
299 SIGNER=/CN=C O Mitter/O=Example/SN=C O/GN=Mitter
300 KEY=
301 STATUS=G
302 NONCE_STATUS=OK
303 EOF
304 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
305 ) >expect.in &&
f636d25d 306 key=$(cut -d" " -f1 <"${GNUPGHOME}/trustlist.txt" | tr -d ":") &&
53fc9993
HS
307 sed -e "s/^KEY=/KEY=${key}/" expect.in >expect &&
308
309 noop=$(git rev-parse noop) &&
310 ff=$(git rev-parse ff) &&
311 noff=$(git rev-parse noff) &&
312 grep "$noop $ff refs/heads/ff" dst/push-cert &&
313 grep "$noop $noff refs/heads/noff" dst/push-cert &&
314 test_cmp expect dst/push-cert-status
315'
316
f265f2d6
FS
317test_expect_success GPGSSH 'fail without key and heed user.signingkey ssh' '
318 test_config gpg.format ssh &&
319 prepare_dst &&
f265f2d6
FS
320 git -C dst config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
321 git -C dst config receive.certnonceseed sekrit &&
bef805b7 322 test_hook -C dst post-receive <<-\EOF &&
f265f2d6
FS
323 # discard the update list
324 cat >/dev/null
325 # record the push certificate
326 if test -n "${GIT_PUSH_CERT-}"
327 then
328 git cat-file blob $GIT_PUSH_CERT >../push-cert
329 fi &&
330
331 cat >../push-cert-status <<E_O_F
332 SIGNER=${GIT_PUSH_CERT_SIGNER-nobody}
333 KEY=${GIT_PUSH_CERT_KEY-nokey}
334 STATUS=${GIT_PUSH_CERT_STATUS-nostatus}
335 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
336 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
337 E_O_F
338
339 EOF
340
341 test_config user.email hasnokey@nowhere.com &&
342 test_config gpg.format ssh &&
343 test_config user.signingkey "" &&
344 (
345 sane_unset GIT_COMMITTER_EMAIL &&
346 test_must_fail git push --signed dst noop ff +noff
347 ) &&
348 test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
349 FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") &&
350 git push --signed dst noop ff +noff &&
351
352 (
353 cat <<-\EOF &&
354 SIGNER=principal with number 1
355 KEY=FINGERPRINT
356 STATUS=G
357 NONCE_STATUS=OK
358 EOF
359 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
360 ) | sed -e "s|FINGERPRINT|$FINGERPRINT|" >expect &&
361
362 noop=$(git rev-parse noop) &&
363 ff=$(git rev-parse ff) &&
364 noff=$(git rev-parse noff) &&
365 grep "$noop $ff refs/heads/ff" dst/push-cert &&
366 grep "$noop $noff refs/heads/noff" dst/push-cert &&
367 test_cmp expect dst/push-cert-status
368'
369
a4f324a4
HX
370test_expect_success GPG 'failed atomic push does not execute GPG' '
371 prepare_dst &&
372 git -C dst config receive.certnonceseed sekrit &&
373 write_script gpg <<-EOF &&
374 # should check atomic push locally before running GPG.
375 exit 1
376 EOF
377 test_must_fail env PATH="$TRASH_DIRECTORY:$PATH" git push \
378 --signed --atomic --porcelain \
2cd6e1d5 379 dst noop ff noff >out 2>err &&
a4f324a4 380
6789275d 381 test_grep ! "gpg failed to sign" err &&
a4f324a4
HX
382 cat >expect <<-EOF &&
383 To dst
384 = refs/heads/noop:refs/heads/noop [up to date]
385 ! refs/heads/ff:refs/heads/ff [rejected] (atomic push failed)
386 ! refs/heads/noff:refs/heads/noff [rejected] (non-fast-forward)
387 Done
388 EOF
2cd6e1d5 389 test_cmp expect out
a4f324a4
HX
390'
391
a85b377d 392test_done