]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5534-push-signed.sh
Merge branch 'jk/complete-branch-force-delete'
[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 &&
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
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 &&
55 mkdir -p dst/.git/hooks &&
a85b377d
JH
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
63 fi
64 EOF
65
66 git push dst noop ff +noff &&
67 ! test -f dst/push-cert
68'
69
70test_expect_success 'push --signed fails with a receiver without push certificate support' '
71 prepare_dst &&
72 mkdir -p dst/.git/hooks &&
a85b377d
JH
73 test_must_fail git push --signed dst noop ff +noff 2>err &&
74 test_i18ngrep "the receiving end does not support" err
75'
76
46667418 77test_expect_success 'push --signed=1 is accepted' '
c4b71a77
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
82'
83
20a7558f
JH
84test_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
91 fi
92 EOF
93 git push dst noop &&
94 ! test -f dst/push-cert
95'
96
a85b377d
JH
97test_expect_success GPG 'signed push sends push certificate' '
98 prepare_dst &&
99 mkdir -p dst/.git/hooks &&
b89363e4 100 git -C dst config receive.certnonceseed sekrit &&
a85b377d
JH
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
d05b9618
JH
108 fi &&
109
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}
b89363e4
JH
114 NONCE_STATUS=${GIT_PUSH_CERT_NONCE_STATUS-nononcestatus}
115 NONCE=${GIT_PUSH_CERT_NONCE-nononce}
d05b9618
JH
116 E_O_F
117
118 EOF
119
a85b377d 120 git push --signed dst noop ff +noff &&
b89363e4
JH
121
122 (
123 cat <<-\EOF &&
124 SIGNER=C O Mitter <committer@example.com>
125 KEY=13B6F51ECDDE430D
126 STATUS=G
127 NONCE_STATUS=OK
128 EOF
129 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
130 ) >expect &&
131
8722947e
JS
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 &&
d05b9618 137 test_cmp expect dst/push-cert-status
a85b377d
JH
138'
139
cbaf82cc
JT
140test_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 &&
146
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
153 EOF
154 test_might_fail git push --push-option="foo" --push-option="bar" \
155 --receive-pack="\"$(pwd)/myscript\"" --signed dst --delete ff &&
156
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 &&
164
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
175'
176
b9459019
MG
177test_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 &&
189
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
197
198 EOF
199
53fc9993
HS
200 test_config user.email hasnokey@nowhere.com &&
201 (
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 &&
b9459019
MG
206 git push --signed dst noop ff +noff &&
207
208 (
209 cat <<-\EOF &&
210 SIGNER=C O Mitter <committer@example.com>
211 KEY=13B6F51ECDDE430D
212 STATUS=G
213 NONCE_STATUS=OK
214 EOF
215 sed -n -e "s/^nonce /NONCE=/p" -e "/^$/q" dst/push-cert
216 ) >expect &&
217
8722947e
JS
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 &&
b9459019
MG
223 test_cmp expect dst/push-cert-status
224'
225
53fc9993
HS
226test_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 &&
239
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
247
248 EOF
249
250 test_config user.email hasnokey@nowhere.com &&
251 test_config user.signingkey "" &&
252 (
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 &&
258
259 (
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
265 EOF
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 &&
270
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
277'
278
a4f324a4
HX
279test_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
285 EOF
286 test_must_fail env PATH="$TRASH_DIRECTORY:$PATH" git push \
287 --signed --atomic --porcelain \
2cd6e1d5 288 dst noop ff noff >out 2>err &&
a4f324a4 289
2cd6e1d5 290 test_i18ngrep ! "gpg failed to sign" err &&
a4f324a4
HX
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
297 EOF
2cd6e1d5 298 test_cmp expect out
a4f324a4
HX
299'
300
a85b377d 301test_done