2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # shellcheck disable=SC2016
6 systemd-analyze log-level debug
8 run_with_cred_compare
() {
13 diff <(systemd-run
-p SetCredential
="$cred" --wait --pipe -- systemd-creds
"$@") <(echo -ne "$exp")
18 # Create a dummy "full" disk (similar to /dev/full) to check out-of-space
21 mount
-t tmpfs
-o size
=1,nr_inodes
=1 tmpfs
/tmp
/full
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
28 test -e /var
/lib
/systemd
/credential.secret
29 rm -fv /var
/lib
/systemd
/credential.secret
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"
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 ||
:
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
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"
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
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
}
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
96 ExecStart=bash -c "diff <(systemd-creds cat \"$cred_name\") /tmp/cred.orig"
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
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
}
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
)
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 \
159 --unit=test-54-unpriv.service \
162 cat '${CREDENTIALS_DIRECTORY}/passwd' '${CREDENTIALS_DIRECTORY}/shadow' '${CREDENTIALS_DIRECTORY}/dog' \
164 (cat /etc
/passwd
/etc
/shadow
&& echo -n wuff
) |
cmp /tmp
/ts54-concat
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" ]
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" ]
180 # And that it also works via SMBIOS
181 [ "$(systemd-creds --system cat smbioscredential)" = "magicdata" ]
182 [ "$(systemd-creds --system cat binarysmbioscredential)" = "magicbinarydata" ]
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
189 # Verify that writing a sysctl via the kernel cmdline worked
190 [ "$(cat /proc/sys/kernel/domainname)" = "sysctltest" ]
192 # Verify that creating a user via sysusers via the kernel cmdline worked
193 grep -q ^credtestuser
: /etc
/passwd
195 # Verify that writing a file via tmpfiles worked
196 [ "$(cat /tmp/sourcedfromcredential)" = "tmpfilessecret" ]
197 [ "$(cat /etc/motd.d/50-provision.conf)" = "hello" ]
198 [ "$(cat /etc/issue.d/50-provision.conf)" = "welcome" ]
200 echo "qemu_fw_cfg support missing in kernel. Sniff!"
201 expected_credential
=""
205 if [ "$expected_credential" != "" ] ; then
206 # If this test is run in nspawn a credential should have been passed to us. See test/TEST-54-CREDS/test.sh
207 [ "$(systemd-creds --system cat "$expected_credential")" = "$expected_value" ]
209 # Test that propagation from system credential to service credential works
210 [ "$(systemd-run -p LoadCredential="$expected_credential" --pipe --wait systemd-creds cat "$expected_credential")" = "$expected_value" ]
212 # Check it also works, if we rename it while propagating it
213 [ "$(systemd-run -p LoadCredential=miau:"$expected_credential" --pipe --wait systemd-creds cat miau)" = "$expected_value" ]
215 # Combine it with a fallback (which should have no effect, given the cred should be passed down)
216 [ "$(systemd-run -p LoadCredential="$expected_credential" -p SetCredential="$expected_credential":zzz --pipe --wait systemd-creds cat "$expected_credential")" = "$expected_value" ]
218 # This should succeed
219 systemd-run
-p AssertCredential
="$expected_credential" -p Type
=oneshot true
221 # And this should fail
222 (! systemd-run
-p AssertCredential
="undefinedcredential" -p Type
=oneshot true
)
225 # Verify that the creds are immutable
226 (! systemd-run
-p LoadCredential
=passwd
:/etc
/passwd \
228 --unit=test-54-immutable-touch.service \
230 touch '${CREDENTIALS_DIRECTORY}/passwd')
231 (! systemd-run
-p LoadCredential
=passwd
:/etc
/passwd \
233 --unit=test-54-immutable-rm.service \
235 rm '${CREDENTIALS_DIRECTORY}/passwd')
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 \
245 --unit=test-54-dir.service \
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
252 cmp /tmp
/ts54-concat
<(echo -n abcd
)
254 rm -rf /tmp
/ts54-creds
256 # Now test encrypted credentials (only supported when built with OpenSSL though)
257 if systemctl
--version |
grep -q -- +OPENSSL
; then
258 echo -n $RANDOM >/tmp
/test-54-plaintext
259 systemd-creds encrypt
--name=test-54
/tmp
/test-54-plaintext
/tmp
/test-54-ciphertext
260 systemd-creds decrypt
--name=test-54
/tmp
/test-54-ciphertext |
cmp /tmp
/test-54-plaintext
262 systemd-run
-p LoadCredentialEncrypted
=test-54
:/tmp
/test-54-ciphertext \
265 cat '${CREDENTIALS_DIRECTORY}/test-54' |
cmp /tmp
/test-54-plaintext
267 echo -n $RANDOM >/tmp
/test-54-plaintext
268 systemd-creds encrypt
--name=test-54
/tmp
/test-54-plaintext
/tmp
/test-54-ciphertext
269 systemd-creds decrypt
--name=test-54
/tmp
/test-54-ciphertext |
cmp /tmp
/test-54-plaintext
271 systemd-run
-p SetCredentialEncrypted
=test-54
:"$(cat /tmp/test-54-ciphertext)" \
274 cat '${CREDENTIALS_DIRECTORY}/test-54' |
cmp /tmp
/test-54-plaintext
276 rm /tmp
/test-54-plaintext
/tmp
/test-54-ciphertext
279 # https://github.com/systemd/systemd/issues/27275
280 systemd-run
-p DynamicUser
=yes -p 'LoadCredential=os:/etc/os-release' \
281 -p 'ExecStartPre=true' \
282 -p 'ExecStartPre=systemd-creds cat os' \
283 --unit=test-54-exec-start.service \
286 true |
cmp /etc
/os-release
288 systemd-analyze log-level info