]>
Commit | Line | Data |
---|---|---|
30dd9f73 | 1 | #!/usr/bin/env bash |
7b3cec95 | 2 | # SPDX-License-Identifier: LGPL-2.1-or-later |
084575ff FS |
3 | # shellcheck disable=SC2016 |
4 | set -eux | |
30dd9f73 LP |
5 | |
6 | systemd-analyze log-level debug | |
7 | ||
ad2875af FS |
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 regnerate 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 | ||
30dd9f73 LP |
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 \ | |
128db0aa ZJS |
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 | |
30dd9f73 LP |
165 | rm /tmp/ts54-concat |
166 | ||
6d085447 | 167 | # Test that SetCredential= acts as fallback for LoadCredential= |
7a17e41d | 168 | echo piff >/tmp/ts54-fallback |
6d085447 LP |
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 | ||
42a3f23c | 173 | if systemd-detect-virt -q -c ; then |
93a1f57d LP |
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 | ||
8de7de46 LP |
180 | # And that it also works via SMBIOS |
181 | [ "$(systemd-creds --system cat smbioscredential)" = "magicdata" ] | |
182 | [ "$(systemd-creds --system cat binarysmbioscredential)" = "magicbinarydata" ] | |
183 | ||
93a1f57d LP |
184 | # If we aren't run in nspawn, we are run in qemu |
185 | systemd-detect-virt -q -v | |
186 | expected_credential=myqemucredential | |
187 | expected_value=othervalue | |
39f0d1d2 LP |
188 | |
189 | # Verify that writing a sysctl via the kernel cmdline worked | |
190 | [ "$(cat /proc/sys/kernel/domainname)" = "sysctltest" ] | |
3acb6ede LP |
191 | |
192 | # Verify that creating a user via sysusers via the kernel cmdline worked | |
193 | grep -q ^credtestuser: /etc/passwd | |
1d77721f LP |
194 | |
195 | # Verify that writing a file via tmpfiles worked | |
196 | [ "$(cat /tmp/sourcedfromcredential)" = "tmpfilessecret" ] | |
a0f4426d LP |
197 | [ "$(cat /etc/motd.d/50-provision.conf)" = "hello" ] |
198 | [ "$(cat /etc/issue.d/50-provision.conf)" = "welcome" ] | |
93a1f57d LP |
199 | else |
200 | echo "qemu_fw_cfg support missing in kernel. Sniff!" | |
201 | expected_credential="" | |
202 | expected_value="" | |
203 | fi | |
204 | ||
205 | if [ "$expected_credential" != "" ] ; then | |
42a3f23c | 206 | # If this test is run in nspawn a credential should have been passed to us. See test/TEST-54-CREDS/test.sh |
93a1f57d | 207 | [ "$(systemd-creds --system cat "$expected_credential")" = "$expected_value" ] |
42a3f23c LP |
208 | |
209 | # Test that propagation from system credential to service credential works | |
93a1f57d | 210 | [ "$(systemd-run -p LoadCredential="$expected_credential" --pipe --wait systemd-creds cat "$expected_credential")" = "$expected_value" ] |
42a3f23c LP |
211 | |
212 | # Check it also works, if we rename it while propagating it | |
93a1f57d | 213 | [ "$(systemd-run -p LoadCredential=miau:"$expected_credential" --pipe --wait systemd-creds cat miau)" = "$expected_value" ] |
42a3f23c LP |
214 | |
215 | # Combine it with a fallback (which should have no effect, given the cred should be passed down) | |
93a1f57d | 216 | [ "$(systemd-run -p LoadCredential="$expected_credential" -p SetCredential="$expected_credential":zzz --pipe --wait systemd-creds cat "$expected_credential")" = "$expected_value" ] |
4f80cfca LP |
217 | |
218 | # This should succeed | |
219 | systemd-run -p AssertCredential="$expected_credential" -p Type=oneshot true | |
220 | ||
221 | # And this should fail | |
128db0aa | 222 | (! systemd-run -p AssertCredential="undefinedcredential" -p Type=oneshot true) |
42a3f23c LP |
223 | fi |
224 | ||
30dd9f73 | 225 | # Verify that the creds are immutable |
128db0aa ZJS |
226 | (! systemd-run -p LoadCredential=passwd:/etc/passwd \ |
227 | -p DynamicUser=1 \ | |
228 | --unit=test-54-immutable-touch.service \ | |
229 | --wait \ | |
230 | touch '${CREDENTIALS_DIRECTORY}/passwd') | |
231 | (! systemd-run -p LoadCredential=passwd:/etc/passwd \ | |
232 | -p DynamicUser=1 \ | |
233 | --unit=test-54-immutable-rm.service \ | |
234 | --wait \ | |
235 | rm '${CREDENTIALS_DIRECTORY}/passwd') | |
30dd9f73 | 236 | |
3989bdc1 AB |
237 | # Check directory-based loading |
238 | mkdir -p /tmp/ts54-creds/sub | |
239 | echo -n a >/tmp/ts54-creds/foo | |
240 | echo -n b >/tmp/ts54-creds/bar | |
241 | echo -n c >/tmp/ts54-creds/baz | |
242 | echo -n d >/tmp/ts54-creds/sub/qux | |
243 | systemd-run -p LoadCredential=cred:/tmp/ts54-creds \ | |
128db0aa ZJS |
244 | -p DynamicUser=1 \ |
245 | --unit=test-54-dir.service \ | |
246 | --wait \ | |
247 | --pipe \ | |
248 | cat '${CREDENTIALS_DIRECTORY}/cred_foo' \ | |
249 | '${CREDENTIALS_DIRECTORY}/cred_bar' \ | |
250 | '${CREDENTIALS_DIRECTORY}/cred_baz' \ | |
251 | '${CREDENTIALS_DIRECTORY}/cred_sub_qux' >/tmp/ts54-concat | |
97b35c7c | 252 | cmp /tmp/ts54-concat <(echo -n abcd) |
3989bdc1 AB |
253 | rm /tmp/ts54-concat |
254 | rm -rf /tmp/ts54-creds | |
c69620ef | 255 | |
bbfb25f4 DDM |
256 | # Check that globs work as expected |
257 | mkdir -p /run/credstore | |
258 | echo -n a >/run/credstore/test.creds.first | |
259 | echo -n b >/run/credstore/test.creds.second | |
260 | mkdir -p /etc/credstore | |
261 | echo -n c >/etc/credstore/test.creds.third | |
262 | systemd-run -p "ImportCredential=test.creds.*" \ | |
263 | -p DynamicUser=1 \ | |
264 | --wait \ | |
265 | --pipe \ | |
266 | cat '${CREDENTIALS_DIRECTORY}/test.creds.first' \ | |
267 | '${CREDENTIALS_DIRECTORY}/test.creds.second' \ | |
268 | '${CREDENTIALS_DIRECTORY}/test.creds.third' >/tmp/ts54-concat | |
269 | cmp /tmp/ts54-concat <(echo -n abc) | |
270 | ||
3989bdc1 | 271 | # Now test encrypted credentials (only supported when built with OpenSSL though) |
c69620ef LP |
272 | if systemctl --version | grep -q -- +OPENSSL ; then |
273 | echo -n $RANDOM >/tmp/test-54-plaintext | |
274 | systemd-creds encrypt --name=test-54 /tmp/test-54-plaintext /tmp/test-54-ciphertext | |
275 | systemd-creds decrypt --name=test-54 /tmp/test-54-ciphertext | cmp /tmp/test-54-plaintext | |
276 | ||
277 | systemd-run -p LoadCredentialEncrypted=test-54:/tmp/test-54-ciphertext \ | |
128db0aa ZJS |
278 | --wait \ |
279 | --pipe \ | |
280 | cat '${CREDENTIALS_DIRECTORY}/test-54' | cmp /tmp/test-54-plaintext | |
c69620ef LP |
281 | |
282 | echo -n $RANDOM >/tmp/test-54-plaintext | |
283 | systemd-creds encrypt --name=test-54 /tmp/test-54-plaintext /tmp/test-54-ciphertext | |
284 | systemd-creds decrypt --name=test-54 /tmp/test-54-ciphertext | cmp /tmp/test-54-plaintext | |
285 | ||
1c3f490f | 286 | systemd-run -p SetCredentialEncrypted=test-54:"$(cat /tmp/test-54-ciphertext)" \ |
128db0aa ZJS |
287 | --wait \ |
288 | --pipe \ | |
289 | cat '${CREDENTIALS_DIRECTORY}/test-54' | cmp /tmp/test-54-plaintext | |
c69620ef LP |
290 | |
291 | rm /tmp/test-54-plaintext /tmp/test-54-ciphertext | |
292 | fi | |
293 | ||
c9210b74 LB |
294 | # https://github.com/systemd/systemd/issues/27275 |
295 | systemd-run -p DynamicUser=yes -p 'LoadCredential=os:/etc/os-release' \ | |
296 | -p 'ExecStartPre=true' \ | |
297 | -p 'ExecStartPre=systemd-creds cat os' \ | |
574d09ba | 298 | --unit=test-54-exec-start.service \ |
c9210b74 LB |
299 | --wait \ |
300 | --pipe \ | |
301 | true | cmp /etc/os-release | |
302 | ||
30dd9f73 LP |
303 | systemd-analyze log-level info |
304 | ||
0ee99483 | 305 | echo OK >/testok |
30dd9f73 LP |
306 | |
307 | exit 0 |