]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/units/testsuite-54.sh
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / test / units / testsuite-54.sh
1 #!/usr/bin/env bash
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # shellcheck disable=SC2016
4 set -eux
5
6 systemd-analyze log-level debug
7
8 run_with_cred_compare() {
9 local cred="${1:?}"
10 local exp="${2?}"
11 shift 2
12
13 diff <(systemd-run -p SetCredential="$cred" --wait --pipe -- systemd-creds "$@") <(echo -ne "$exp")
14 }
15
16 # Sanity checks
17 #
18 # Create a dummy "full" disk (similar to /dev/full) to check out-of-space
19 # scenarios
20 mkdir /tmp/full
21 mount -t tmpfs -o size=1,nr_inodes=1 tmpfs /tmp/full
22
23 # verb: setup
24 # Run this first, otherwise any encrypted credentials wouldn't be decryptable
25 # as we regenerate the host key
26 rm -fv /var/lib/systemd/credential.secret
27 systemd-creds setup
28 test -e /var/lib/systemd/credential.secret
29 rm -fv /var/lib/systemd/credential.secret
30
31 # Prepare a couple of dummy credentials for the cat/list verbs
32 CRED_DIR="$(mktemp -d)"
33 ENC_CRED_DIR="$(mktemp -d)"
34 echo foo >"$CRED_DIR/secure-or-weak"
35 echo foo >"$CRED_DIR/insecure"
36 echo foo | systemd-creds --name="encrypted" encrypt - - | base64 -d >"$ENC_CRED_DIR/encrypted"
37 echo foo | systemd-creds encrypt - - | base64 -d >"$ENC_CRED_DIR/encrypted-unnamed"
38 chmod -R 0400 "$CRED_DIR" "$ENC_CRED_DIR"
39 chmod -R 0444 "$CRED_DIR/insecure"
40 mkdir /tmp/empty/
41
42 systemd-creds --system
43 systemd-creds --no-pager --help
44 systemd-creds --version
45 systemd-creds has-tpm2 || :
46 systemd-creds has-tpm2 -q || :
47
48 # verb: list
49 systemd-creds list --system
50 ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --no-legend
51 ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=pretty | jq
52 ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=short | jq
53 ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=off
54 ENCRYPTED_CREDENTIALS_DIRECTORY="/tmp/empty/" CREDENTIALS_DIRECTORY="/tmp/empty/" systemd-creds list
55
56 # verb: cat
57 for cred in secure-or-weak insecure encrypted encrypted-unnamed; do
58 ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds cat "$cred"
59 done
60 run_with_cred_compare "mycred:" "" cat mycred
61 run_with_cred_compare "mycred:\n" "\n" cat mycred
62 run_with_cred_compare "mycred:foo" "foo" cat mycred
63 run_with_cred_compare "mycred:foo" "foofoofoo" cat mycred mycred mycred
64 # Note: --newline= does nothing when stdout is not a tty, which is the case here
65 run_with_cred_compare "mycred:foo" "foo" --newline=yes cat mycred
66 run_with_cred_compare "mycred:foo" "foo" --newline=no cat mycred
67 run_with_cred_compare "mycred:foo" "foo" --newline=auto cat mycred
68 run_with_cred_compare "mycred:foo" "foo" --transcode=no cat mycred
69 run_with_cred_compare "mycred:foo" "foo" --transcode=0 cat mycred
70 run_with_cred_compare "mycred:foo" "foo" --transcode=false cat mycred
71 run_with_cred_compare "mycred:foo" "Zm9v" --transcode=base64 cat mycred
72 run_with_cred_compare "mycred:Zm9v" "foo" --transcode=unbase64 cat mycred
73 run_with_cred_compare "mycred:Zm9v" "foofoofoo" --transcode=unbase64 cat mycred mycred mycred
74 run_with_cred_compare "mycred:Zm9vCg==" "foo\n" --transcode=unbase64 cat mycred
75 run_with_cred_compare "mycred:hello world" "68656c6c6f20776f726c64" --transcode=hex cat mycred
76 run_with_cred_compare "mycred:68656c6c6f20776f726c64" "hello world" --transcode=unhex cat mycred
77 run_with_cred_compare "mycred:68656c6c6f20776f726c64" "hello worldhello world" --transcode=unhex cat mycred mycred
78 run_with_cred_compare "mycred:68656c6c6f0a776f726c64" "hello\nworld" --transcode=unhex cat mycred
79 run_with_cred_compare 'mycred:{ "foo" : "bar", "baz" : [ 3, 4 ] }' '{"foo":"bar","baz":[3,4]}\n' --json=short cat mycred
80 systemd-run -p SetCredential='mycred:{ "foo" : "bar", "baz" : [ 3, 4 ] }' --wait --pipe -- systemd-creds --json=pretty cat mycred | jq
81
82 # verb: encrypt/decrypt
83 echo "According to all known laws of aviation..." >/tmp/cred.orig
84 systemd-creds --with-key=host encrypt /tmp/cred.orig /tmp/cred.enc
85 systemd-creds decrypt /tmp/cred.enc /tmp/cred.dec
86 diff /tmp/cred.orig /tmp/cred.dec
87 rm -f /tmp/cred.{enc,dec}
88 # --pretty
89 cred_name="fo'''o''bar"
90 cred_option="$(systemd-creds --pretty --name="$cred_name" encrypt /tmp/cred.orig -)"
91 mkdir -p /run/systemd/system
92 cat >/run/systemd/system/test-54-pretty-cred.service <<EOF
93 [Service]
94 Type=oneshot
95 ${cred_option:?}
96 ExecStart=bash -c "diff <(systemd-creds cat \"$cred_name\") /tmp/cred.orig"
97 EOF
98 systemctl daemon-reload
99 systemctl start test-54-pretty-cred
100 rm /run/systemd/system/test-54-pretty-cred.service
101 # Credential validation: name
102 systemd-creds --name="foo" -H encrypt /tmp/cred.orig /tmp/cred.enc
103 (! systemd-creds decrypt /tmp/cred.enc /tmp/cred.dec)
104 (! systemd-creds --name="bar" decrypt /tmp/cred.enc /tmp/cred.dec)
105 systemd-creds --name="" decrypt /tmp/cred.enc /tmp/cred.dec
106 diff /tmp/cred.orig /tmp/cred.dec
107 rm -f /tmp/cred.dec
108 systemd-creds --name="foo" decrypt /tmp/cred.enc /tmp/cred.dec
109 diff /tmp/cred.orig /tmp/cred.dec
110 rm -f /tmp/cred.{enc,dec}
111 # Credential validation: time
112 systemd-creds --not-after="+1d" encrypt /tmp/cred.orig /tmp/cred.enc
113 (! systemd-creds --timestamp="+2d" decrypt /tmp/cred.enc /tmp/cred.dec)
114 systemd-creds decrypt /tmp/cred.enc /tmp/cred.dec
115 diff /tmp/cred.orig /tmp/cred.dec
116 rm -f /tmp/cred.{enc,dec}
117
118 (! unshare -m bash -exc "mount -t tmpfs tmpfs /run/credentials && systemd-creds list")
119 (! unshare -m bash -exc "mount -t tmpfs tmpfs /run/credentials && systemd-creds --system list")
120 (! CREDENTIALS_DIRECTORY="" systemd-creds list)
121 (! systemd-creds --system --foo)
122 (! systemd-creds --system -@)
123 (! systemd-creds --system --json=)
124 (! systemd-creds --system --json="")
125 (! systemd-creds --system --json=foo)
126 (! systemd-creds --system cat)
127 (! systemd-creds --system cat "")
128 (! systemd-creds --system cat this-should-not-exist)
129 (! systemd-run -p SetCredential=mycred:foo --wait --pipe -- systemd-creds --transcode= cat mycred)
130 (! systemd-run -p SetCredential=mycred:foo --wait --pipe -- systemd-creds --transcode="" cat mycred)
131 (! systemd-run -p SetCredential=mycred:foo --wait --pipe -- systemd-creds --transcode=foo cat mycred)
132 (! systemd-run -p SetCredential=mycred:foo --wait --pipe -- systemd-creds --newline=foo cat mycred)
133 (! systemd-run -p SetCredential=mycred:notbase64 --wait --pipe -- systemd-creds --transcode=unbase64 cat mycred)
134 (! systemd-run -p SetCredential=mycred:nothex --wait --pipe -- systemd-creds --transcode=unhex cat mycred)
135 (! systemd-run -p SetCredential=mycred:a --wait --pipe -- systemd-creds --transcode=unhex cat mycred)
136 (! systemd-run -p SetCredential=mycred:notjson --wait --pipe -- systemd-creds --json=short cat mycred)
137 (! systemd-run -p SetCredential=mycred:notjson --wait --pipe -- systemd-creds --json=pretty cat mycred)
138 (! systemd-creds encrypt /foo/bar/baz -)
139 (! systemd-creds decrypt /foo/bar/baz -)
140 (! systemd-creds decrypt / -)
141 (! systemd-creds encrypt / -)
142 (! echo foo | systemd-creds --with-key=foo encrypt - -)
143 (! echo {0..20} | systemd-creds decrypt - -)
144 (! systemd-creds --not-after= encrypt /tmp/cred.orig /tmp/cred.enc)
145 (! systemd-creds --not-after="" encrypt /tmp/cred.orig /tmp/cred.enc)
146 (! systemd-creds --not-after="-1d" encrypt /tmp/cred.orig /tmp/cred.enc)
147 (! systemd-creds --timestamp= encrypt /tmp/cred.orig /tmp/cred.enc)
148 (! systemd-creds --timestamp="" encrypt /tmp/cred.orig /tmp/cred.enc)
149 (! dd if=/dev/zero count=2M | systemd-creds --with-key=tpm2-absent encrypt - /dev/null)
150 (! dd if=/dev/zero count=2M | systemd-creds --with-key=tpm2-absent decrypt - /dev/null)
151 (! echo foo | systemd-creds encrypt - /tmp/full/foo)
152 (! echo foo | systemd-creds encrypt - - | systemd-creds decrypt - /tmp/full/foo)
153
154 # Verify that the creds are properly loaded and we can read them from the service's unpriv user
155 systemd-run -p LoadCredential=passwd:/etc/passwd \
156 -p LoadCredential=shadow:/etc/shadow \
157 -p SetCredential=dog:wuff \
158 -p DynamicUser=1 \
159 --unit=test-54-unpriv.service \
160 --wait \
161 --pipe \
162 cat '${CREDENTIALS_DIRECTORY}/passwd' '${CREDENTIALS_DIRECTORY}/shadow' '${CREDENTIALS_DIRECTORY}/dog' \
163 >/tmp/ts54-concat
164 (cat /etc/passwd /etc/shadow && echo -n wuff) | cmp /tmp/ts54-concat
165 rm /tmp/ts54-concat
166
167 # Test that SetCredential= acts as fallback for LoadCredential=
168 echo piff >/tmp/ts54-fallback
169 [ "$(systemd-run -p LoadCredential=paff:/tmp/ts54-fallback -p SetCredential=paff:poff --pipe --wait systemd-creds cat paff)" = "piff" ]
170 rm /tmp/ts54-fallback
171 [ "$(systemd-run -p LoadCredential=paff:/tmp/ts54-fallback -p SetCredential=paff:poff --pipe --wait systemd-creds cat paff)" = "poff" ]
172
173 if systemd-detect-virt -q -c ; then
174 expected_credential=mynspawncredential
175 expected_value=strangevalue
176 elif [ -d /sys/firmware/qemu_fw_cfg/by_name ]; then
177 # Verify that passing creds through kernel cmdline works
178 [ "$(systemd-creds --system cat kernelcmdlinecred)" = "uff" ]
179 [ "$(systemd-creds --system cat waldi)" = "woooofffwufffwuff" ]
180
181 # And that it also works via SMBIOS
182 [ "$(systemd-creds --system cat smbioscredential)" = "magicdata" ]
183 [ "$(systemd-creds --system cat binarysmbioscredential)" = "magicbinarydata" ]
184
185 # If we aren't run in nspawn, we are run in qemu
186 systemd-detect-virt -q -v
187 expected_credential=myqemucredential
188 expected_value=othervalue
189
190 # Verify that writing a sysctl via the kernel cmdline worked
191 [ "$(cat /proc/sys/kernel/domainname)" = "sysctltest" ]
192
193 # Verify that creating a user via sysusers via the kernel cmdline worked
194 grep -q ^credtestuser: /etc/passwd
195
196 # Verify that writing a file via tmpfiles worked
197 [ "$(cat /tmp/sourcedfromcredential)" = "tmpfilessecret" ]
198 [ "$(cat /etc/motd.d/50-provision.conf)" = "hello" ]
199 [ "$(cat /etc/issue.d/50-provision.conf)" = "welcome" ]
200 else
201 echo "qemu_fw_cfg support missing in kernel. Sniff!"
202 expected_credential=""
203 expected_value=""
204 fi
205
206 if [ "$expected_credential" != "" ] ; then
207 # If this test is run in nspawn a credential should have been passed to us. See test/TEST-54-CREDS/test.sh
208 [ "$(systemd-creds --system cat "$expected_credential")" = "$expected_value" ]
209
210 # Test that propagation from system credential to service credential works
211 [ "$(systemd-run -p LoadCredential="$expected_credential" --pipe --wait systemd-creds cat "$expected_credential")" = "$expected_value" ]
212
213 # Check it also works, if we rename it while propagating it
214 [ "$(systemd-run -p LoadCredential=miau:"$expected_credential" --pipe --wait systemd-creds cat miau)" = "$expected_value" ]
215
216 # Combine it with a fallback (which should have no effect, given the cred should be passed down)
217 [ "$(systemd-run -p LoadCredential="$expected_credential" -p SetCredential="$expected_credential":zzz --pipe --wait systemd-creds cat "$expected_credential")" = "$expected_value" ]
218
219 # This should succeed
220 systemd-run -p AssertCredential="$expected_credential" -p Type=oneshot true
221
222 # And this should fail
223 (! systemd-run -p AssertCredential="undefinedcredential" -p Type=oneshot true)
224 fi
225
226 # Verify that the creds are immutable
227 (! systemd-run -p LoadCredential=passwd:/etc/passwd \
228 -p DynamicUser=1 \
229 --unit=test-54-immutable-touch.service \
230 --wait \
231 touch '${CREDENTIALS_DIRECTORY}/passwd')
232 (! systemd-run -p LoadCredential=passwd:/etc/passwd \
233 -p DynamicUser=1 \
234 --unit=test-54-immutable-rm.service \
235 --wait \
236 rm '${CREDENTIALS_DIRECTORY}/passwd')
237
238 # Check directory-based loading
239 mkdir -p /tmp/ts54-creds/sub
240 echo -n a >/tmp/ts54-creds/foo
241 echo -n b >/tmp/ts54-creds/bar
242 echo -n c >/tmp/ts54-creds/baz
243 echo -n d >/tmp/ts54-creds/sub/qux
244 systemd-run -p LoadCredential=cred:/tmp/ts54-creds \
245 -p DynamicUser=1 \
246 --unit=test-54-dir.service \
247 --wait \
248 --pipe \
249 cat '${CREDENTIALS_DIRECTORY}/cred_foo' \
250 '${CREDENTIALS_DIRECTORY}/cred_bar' \
251 '${CREDENTIALS_DIRECTORY}/cred_baz' \
252 '${CREDENTIALS_DIRECTORY}/cred_sub_qux' >/tmp/ts54-concat
253 cmp /tmp/ts54-concat <(echo -n abcd)
254 rm /tmp/ts54-concat
255 rm -rf /tmp/ts54-creds
256
257 # Check that globs work as expected
258 mkdir -p /run/credstore
259 echo -n a >/run/credstore/test.creds.first
260 echo -n b >/run/credstore/test.creds.second
261 mkdir -p /etc/credstore
262 echo -n c >/etc/credstore/test.creds.third
263 systemd-run -p "ImportCredential=test.creds.*" \
264 --unit=test-54-ImportCredential.service \
265 -p DynamicUser=1 \
266 --wait \
267 --pipe \
268 cat '${CREDENTIALS_DIRECTORY}/test.creds.first' \
269 '${CREDENTIALS_DIRECTORY}/test.creds.second' \
270 '${CREDENTIALS_DIRECTORY}/test.creds.third' >/tmp/ts54-concat
271 cmp /tmp/ts54-concat <(echo -n abc)
272
273 # Now test encrypted credentials (only supported when built with OpenSSL though)
274 if systemctl --version | grep -q -- +OPENSSL ; then
275 echo -n $RANDOM >/tmp/test-54-plaintext
276 systemd-creds encrypt --name=test-54 /tmp/test-54-plaintext /tmp/test-54-ciphertext
277 systemd-creds decrypt --name=test-54 /tmp/test-54-ciphertext | cmp /tmp/test-54-plaintext
278
279 systemd-run -p LoadCredentialEncrypted=test-54:/tmp/test-54-ciphertext \
280 --wait \
281 --pipe \
282 cat '${CREDENTIALS_DIRECTORY}/test-54' | cmp /tmp/test-54-plaintext
283
284 echo -n $RANDOM >/tmp/test-54-plaintext
285 systemd-creds encrypt --name=test-54 /tmp/test-54-plaintext /tmp/test-54-ciphertext
286 systemd-creds decrypt --name=test-54 /tmp/test-54-ciphertext | cmp /tmp/test-54-plaintext
287
288 systemd-run -p SetCredentialEncrypted=test-54:"$(cat /tmp/test-54-ciphertext)" \
289 --wait \
290 --pipe \
291 cat '${CREDENTIALS_DIRECTORY}/test-54' | cmp /tmp/test-54-plaintext
292
293 rm /tmp/test-54-plaintext /tmp/test-54-ciphertext
294 fi
295
296 # https://github.com/systemd/systemd/issues/27275
297 systemd-run -p DynamicUser=yes -p 'LoadCredential=os:/etc/os-release' \
298 -p 'ExecStartPre=true' \
299 -p 'ExecStartPre=systemd-creds cat os' \
300 --unit=test-54-exec-start.service \
301 --wait \
302 --pipe \
303 true | cmp /etc/os-release
304
305 if ! systemd-detect-virt -q -c ; then
306 # Validate that the credential we inserted via the initrd logic arrived
307 test "$(systemd-creds cat --system myinitrdcred)" = "guatemala"
308
309 # Check that the fstab credential logic worked
310 test -d /injected
311 grep -q /injected /proc/self/mountinfo
312
313 # Make sure the getty generator processed the credentials properly
314 systemctl -P Wants show getty.target | grep -q container-getty@idontexist.service
315 fi
316
317 # Decrypt/encrypt via varlink
318
319 echo -n '{"data":"Zm9vYmFyCg=="}' > /tmp/vlcredsdata
320
321 varlinkctl call /run/systemd/io.systemd.Credentials io.systemd.Credentials.Encrypt "$(cat /tmp/vlcredsdata)" | \
322 varlinkctl call /run/systemd/io.systemd.Credentials io.systemd.Credentials.Decrypt > /tmp/vlcredsdata2
323
324 cmp /tmp/vlcredsdata /tmp/vlcredsdata2
325 rm /tmp/vlcredsdata /tmp/vlcredsdata2
326
327 systemd-analyze log-level info
328
329 touch /testok