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