xref: /freebsd/libexec/nuageinit/tests/nuageinit.sh (revision 8a7df6c58d549bd2eaa5cad30b2ef93c3eca3c18)
1#-
2# Copyright (c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org>
3# Copyright (c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org>
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7
8export NUAGE_FAKE_ROOTDIR="$PWD"
9
10atf_test_case args
11atf_test_case nocloud
12atf_test_case nocloud_userdata_script
13atf_test_case nocloud_user_data_script
14atf_test_case nocloud_userdata_cloudconfig_users
15atf_test_case nocloud_network
16atf_test_case config2
17atf_test_case config2_pubkeys
18atf_test_case config2_pubkeys_user_data
19atf_test_case config2_pubkeys_meta_data
20atf_test_case config2_network
21atf_test_case config2_network_static_v4
22atf_test_case config2_network_dns
23atf_test_case config2_ssh_keys
24atf_test_case nocloud_userdata_cloudconfig_ssh_pwauth
25atf_test_case nocloud_userdata_cloudconfig_chpasswd
26atf_test_case nocloud_userdata_cloudconfig_chpasswd_list_string
27atf_test_case nocloud_userdata_cloudconfig_chpasswd_list_list
28atf_test_case config2_userdata_runcmd
29atf_test_case config2_userdata_packages
30atf_test_case config2_userdata_update_packages
31atf_test_case config2_userdata_upgrade_packages
32atf_test_case config2_userdata_shebang
33atf_test_case config2_userdata_ssh_deletekeys
34atf_test_case config2_userdata_disable_root
35atf_test_case config2_userdata_bootcmd
36atf_test_case config2_userdata_manage_etc_hosts
37atf_test_case config2_userdata_mounts
38atf_test_case config2_userdata_resolv_conf
39atf_test_case config2_userdata_keyboard
40atf_test_case config2_userdata_ssh_authkey_fingerprints
41atf_test_case config2_userdata_ntp
42atf_test_case config2_userdata_ca_certs
43atf_test_case config2_userdata_multipart
44atf_test_case config2_userdata_power_state
45atf_test_case config2_userdata_locale
46atf_test_case config2_userdata_fqdn_and_hostname
47atf_test_case config2_userdata_write_files
48atf_test_case config2_userdata_encode_base64
49atf_test_case config2_userdata_final_message
50atf_test_case config2_userdata_phone_home
51
52setup_test_adduser()
53{
54	here=$(pwd)
55	export NUAGE_FAKE_ROOTDIR=$(pwd)
56	mkdir -p etc/ssh
57	cat > etc/master.passwd << EOF
58root:*:0:0::0:0:Charlie &:/root:/bin/csh
59sys:*:1:0::0:0:Sys:/home/sys:/bin/csh
60EOF
61	pwd_mkdb -d etc ${here}/etc/master.passwd
62	cat > etc/group << EOF
63wheel:*:0:root
64users:*:1:
65EOF
66}
67
68args_body()
69{
70	atf_check -s exit:1 -e inline:"Usage: /usr/libexec/nuageinit <cloud-init-directory> (<config-2> | <nocloud>)\n" /usr/libexec/nuageinit
71	atf_check -s exit:1 -e inline:"Usage: /usr/libexec/nuageinit <cloud-init-directory> (<config-2> | <nocloud>)\n" /usr/libexec/nuageinit bla
72	atf_check -s exit:1 -e inline:"Usage: /usr/libexec/nuageinit <cloud-init-directory> (<config-2> | <nocloud>)\n" /usr/libexec/nuageinit bla meh plop
73	atf_check -s exit:1 -e inline:"nuageinit: Unknown cloud init type: meh\n" /usr/libexec/nuageinit bla meh
74}
75
76nocloud_body()
77{
78	mkdir -p media/nuageinit
79	setup_test_adduser
80	atf_check -s exit:1 -e match:"nuageinit: error parsing nocloud.*" /usr/libexec/nuageinit "${PWD}"/media/nuageinit/ nocloud
81	printf "instance-id: iid-local01\nlocal-hostname: cloudimg\n" > "${PWD}"/media/nuageinit/meta-data
82	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
83	atf_check -o inline:"hostname='cloudimg'\n" cat etc/rc.conf.d/hostname
84	cat > media/nuageinit/meta-data << EOF
85instance-id: iid-local01
86hostname: myhost
87EOF
88	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
89	atf_check -o inline:"hostname='myhost'\n" cat etc/rc.conf.d/hostname
90}
91
92nocloud_userdata_script_body()
93{
94	mkdir -p media/nuageinit
95	setup_test_adduser
96	cat > media/nuageinit/meta-data << EOF
97instance-id: iid-local01
98hostname: myhost
99EOF
100	# ensure this is an invalid when parsed with the yaml parser
101	printf "#!/bin/sh\n: ${test:-yes}\necho $test\n" > "${PWD}"/media/nuageinit/user-data
102	chmod 644 "${PWD}"/media/nuageinit/user-data
103	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
104	atf_check test -x var/cache/nuageinit/user_data
105	atf_check -o inline:"#!/bin/sh\n: ${test:-yes}\necho $test\n" cat var/cache/nuageinit/user_data
106	# ensure meta-data is applied, regardless of what is in user-data
107	atf_check -o inline:"hostname='myhost'\n" cat etc/rc.conf.d/hostname
108}
109
110nocloud_user_data_script_body()
111{
112	mkdir -p media/nuageinit
113	setup_test_adduser
114	cat > media/nuageinit/meta-data << EOF
115instance-id: iid-local01
116hostname: myhost
117EOF
118	printf "#!/bin/sh\necho yeah\n" > "${PWD}"/media/nuageinit/user_data
119	chmod 644 "${PWD}"/media/nuageinit/user_data
120	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
121	atf_check test -x var/cache/nuageinit/user_data
122	atf_check -o inline:"#!/bin/sh\necho yeah\n" cat var/cache/nuageinit/user_data
123	# ensure meta-data is applied, regardless of what is in user-data
124	atf_check -o inline:"hostname='myhost'\n" cat etc/rc.conf.d/hostname
125}
126
127nocloud_userdata_cloudconfig_users_head()
128{
129	atf_set "require.user" root
130}
131nocloud_userdata_cloudconfig_users_body()
132{
133	mkdir -p media/nuageinit
134	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
135	mkdir -p etc
136	cat > etc/master.passwd << EOF
137root:*:0:0::0:0:Charlie &:/root:/bin/sh
138sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
139EOF
140	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
141	cat > etc/group << EOF
142wheel:*:0:root
143users:*:1:
144EOF
145	cat > media/nuageinit/user-data << 'EOF'
146#cloud-config
147groups:
148  - admingroup: [root,sys]
149  - cloud-users
150users:
151  - default
152  - name: foobar
153    gecos: Foo B. Bar
154    primary_group: foobar
155    sudo: ALL=(ALL) NOPASSWD:ALL
156    doas: permit persist %u as root
157    groups: users
158    passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
159  - name: bla
160    sudo:
161    - "ALL=(ALL) NOPASSWD:/usr/sbin/pw"
162    - "ALL=(ALL) ALL"
163    doas:
164    - "deny %u as foobar"
165    - "permit persist %u as root cmd whoami"
166EOF
167	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
168	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
169	cat > expectedgroup << EOF
170wheel:*:0:root,freebsd
171users:*:1:foobar
172admingroup:*:1001:root,sys
173cloud-users:*:1002:
174freebsd:*:1003:
175foobar:*:1004:
176bla:*:1005:
177EOF
178	cat > expectedpasswd << 'EOF'
179root:*:0:0::0:0:Charlie &:/root:/bin/sh
180sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
181freebsd:freebsd:1001:1003::0:0:FreeBSD User:/home/freebsd:/bin/sh
182foobar:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/:1002:1004::0:0:Foo B. Bar:/home/foobar:/bin/sh
183bla::1003:1005::0:0:bla User:/home/bla:/bin/sh
184EOF
185	sed -i "" "s/freebsd:.*:1001/freebsd:freebsd:1001/" "${PWD}"/etc/master.passwd
186	atf_check -o file:expectedpasswd cat "${PWD}"/etc/master.passwd
187	atf_check -o file:expectedgroup cat "${PWD}"/etc/group
188	localbase=`sysctl -ni user.localbase 2> /dev/null`
189	if [ -z "${localbase}" ]; then
190		# fallback
191		localbase="/usr/local"
192	fi
193	atf_check -o inline:"foobar ALL=(ALL) NOPASSWD:ALL\nbla ALL=(ALL) NOPASSWD:/usr/sbin/pw\nbla ALL=(ALL) ALL\n" cat "${PWD}/${localbase}/etc/sudoers.d/90-nuageinit-users"
194	atf_check -o inline:"permit persist foobar as root\ndeny bla as foobar\npermit persist bla as root cmd whoami\n" cat "${PWD}/${localbase}/etc/doas.conf"
195}
196
197nocloud_userdata_cloudconfig_users_lock_passwd_head()
198{
199	atf_set "require.user" root
200}
201nocloud_userdata_cloudconfig_users_lock_passwd_body()
202{
203	mkdir -p media/nuageinit
204	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
205	mkdir -p etc
206	cat > etc/master.passwd << EOF
207root:*:0:0::0:0:Charlie &:/root:/bin/sh
208sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
209EOF
210	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
211	cat > etc/group << EOF
212wheel:*:0:root
213users:*:1:
214EOF
215	cat > media/nuageinit/user-data << 'EOF'
216#cloud-config
217users:
218  - name: lockeduser
219    lock_passwd: true
220EOF
221	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
222	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
223	atf_check -o match:'lockeduser:\*LOCKED\*:' cat "${PWD}"/etc/master.passwd
224}
225
226nocloud_network_head()
227{
228	atf_set "require.user" root
229}
230nocloud_network_body()
231{
232	mkdir -p media/nuageinit
233	mkdir -p etc
234	cat > etc/master.passwd << EOF
235root:*:0:0::0:0:Charlie &:/root:/bin/sh
236sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
237EOF
238	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
239	cat > etc/group << EOF
240wheel:*:0:root
241users:*:1:
242EOF
243	mynetworks=$(ifconfig -l ether)
244	if [ -z "$mynetworks" ]; then
245		atf_skip "a network interface is needed"
246	fi
247	set -- $mynetworks
248	myiface=$1
249	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
250	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
251	cat > media/nuageinit/user-data << EOF
252#cloud-config
253network:
254  version: 2
255  ethernets:
256    # opaque ID for physical interfaces, only referred to by other stanzas
257    id0:
258      match:
259        macaddress: "$myaddr"
260      addresses:
261        - 192.0.2.2/24
262        - 2001:db8::2/64
263      gateway4: 192.0.2.1
264      gateway6: 2001:db8::1
265EOF
266	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
267	cat > network << EOF
268ifconfig_${myiface}='inet 192.0.2.2/24'
269ifconfig_${myiface}_ipv6='inet6 2001:db8::2/64'
270ipv6_network_interfaces='${myiface}'
271ipv6_default_interface='${myiface}'
272EOF
273	cat > routing << EOF
274defaultrouter='192.0.2.1'
275ipv6_defaultrouter='2001:db8::1'
276ipv6_route_${myiface}='2001:db8::1 -prefixlen 128 -interface ${myiface}'
277EOF
278	atf_check -o file:network cat "${PWD}"/etc/rc.conf.d/network
279	atf_check -o file:routing cat "${PWD}"/etc/rc.conf.d/routing
280}
281
282config2_body()
283{
284	mkdir -p media/nuageinit
285	setup_test_adduser
286	atf_check -s exit:1 -e match:"nuageinit: error parsing config-2 meta_data.json:.*" /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
287	printf "{}" > media/nuageinit/meta_data.json
288	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
289	cat > media/nuageinit/meta_data.json << EOF
290{
291    "hostname": "cloudimg"
292}
293EOF
294	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
295	atf_check -o inline:"hostname='cloudimg'\n" cat etc/rc.conf.d/hostname
296}
297
298config2_pubkeys_head()
299{
300	atf_set "require.user" root
301}
302config2_pubkeys_body()
303{
304	mkdir -p media/nuageinit
305	touch media/nuageinit/meta_data.json
306	cat > media/nuageinit/user-data << EOF
307#cloud-config
308ssh_authorized_keys:
309  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
310EOF
311	mkdir -p etc
312	mkdir -p root
313	cat > etc/master.passwd << EOF
314root:*:0:0::0:0:Charlie &:/root:/bin/sh
315sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
316EOF
317	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
318	cat > etc/group << EOF
319wheel:*:0:root
320users:*:1:
321EOF
322	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
323	atf_check -o inline:"ssh-rsa AAAAB3NzaC1y...== Generated by Nova\n" cat home/freebsd/.ssh/authorized_keys
324}
325
326config2_pubkeys_user_data_head()
327{
328	atf_set "require.user" root
329}
330config2_pubkeys_user_data_body()
331{
332	mkdir -p media/nuageinit
333	touch media/nuageinit/meta_data.json
334	cat > media/nuageinit/user_data << EOF
335#cloud-config
336ssh_authorized_keys:
337  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
338EOF
339	mkdir -p etc
340	mkdir -p root
341	cat > etc/master.passwd << EOF
342root:*:0:0::0:0:Charlie &:/root:/bin/sh
343sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
344EOF
345	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
346	cat > etc/group << EOF
347wheel:*:0:root
348users:*:1:
349EOF
350	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
351	atf_check -o inline:"ssh-rsa AAAAB3NzaC1y...== Generated by Nova\n" cat home/freebsd/.ssh/authorized_keys
352}
353
354config2_pubkeys_meta_data_body()
355{
356	here=$(pwd)
357	export NUAGE_FAKE_ROOTDIR=$(pwd)
358	if [ $(id -u) -ne 0 ]; then
359		atf_skip "root required"
360	fi
361	mkdir -p media/nuageinit
362	cat > media/nuageinit/meta_data.json << EOF
363{
364    "uuid": "uuid_for_this_instance",
365    "admin_pass": "a_generated_password",
366    "public_keys": {
367        "tdb": "ssh-ed25519 my_key_id tdb@host"
368    },
369    "keys": [
370        {
371            "name": "tdb",
372            "type": "ssh",
373            "data": "ssh-ed25519 my_key_id tdb@host"
374        }
375    ],
376    "hostname": "freebsd-14-test.novalocal",
377    "name": "freebsd-14-test",
378    "launch_index": 0,
379    "availability_zone": "nova",
380    "random_seed": "long_random_seed",
381    "project_id": "my_project_id",
382    "devices": [],
383    "dedicated_cpus": []
384}
385EOF
386	mkdir -p etc
387	mkdir -p root
388	cat > etc/master.passwd << EOF
389root:*:0:0::0:0:Charlie &:/root:/bin/csh
390sys:*:1:0::0:0:Sys:/home/sys:/bin/csh
391EOF
392	pwd_mkdb -d etc ${here}/etc/master.passwd
393	cat > etc/group << EOF
394wheel:*:0:root
395users:*:1:
396EOF
397	atf_check /usr/libexec/nuageinit ${here}/media/nuageinit config-2
398	atf_check -o inline:"ssh-ed25519 my_key_id tdb@host\n" cat home/freebsd/.ssh/authorized_keys
399}
400
401config2_pubkeys_allow_public_ssh_keys_head()
402{
403	atf_set "require.user" root
404}
405config2_pubkeys_allow_public_ssh_keys_body()
406{
407	here=$(pwd)
408	export NUAGE_FAKE_ROOTDIR=$(pwd)
409	if [ $(id -u) -ne 0 ]; then
410		atf_skip "root required"
411	fi
412	mkdir -p media/nuageinit
413	cat > media/nuageinit/meta_data.json << EOF
414{
415    "uuid": "uuid_for_this_instance",
416    "public_keys": {
417        "tdb": "ssh-ed25519 my_key_id tdb@host"
418    }
419}
420EOF
421	cat > media/nuageinit/user_data << EOF
422#cloud-config
423allow_public_ssh_keys: false
424EOF
425	mkdir -p etc
426	mkdir -p root
427	cat > etc/master.passwd << EOF
428root:*:0:0::0:0:Charlie &:/root:/bin/csh
429sys:*:1:0::0:0:Sys:/home/sys:/bin/csh
430EOF
431	pwd_mkdb -d etc ${here}/etc/master.passwd
432	cat > etc/group << EOF
433wheel:*:0:root
434users:*:1:
435EOF
436	atf_check /usr/libexec/nuageinit ${here}/media/nuageinit config-2
437	# no public key should be imported
438	atf_check -s exit:1 test -e home/freebsd/.ssh/authorized_keys
439}
440
441config2_network_body()
442{
443	mkdir -p media/nuageinit
444	setup_test_adduser
445	printf "{}" > media/nuageinit/meta_data.json
446	mynetworks=$(ifconfig -l ether)
447	if [ -z "$mynetworks" ]; then
448		atf_skip "a network interface is needed"
449	fi
450	set -- $mynetworks
451	myiface=$1
452	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
453cat > media/nuageinit/network_data.json << EOF
454{
455    "links": [
456        {
457            "ethernet_mac_address": "$myaddr",
458            "id": "iface0",
459            "mtu": null
460        }
461    ],
462    "networks": [
463        {
464            "id": "network0",
465            "link": "iface0",
466            "type": "ipv4_dhcp"
467        },
468        { // IPv6
469            "id": "private-ipv4",
470            "type": "ipv6",
471            "link": "iface0",
472            // supports condensed IPv6 with CIDR netmask
473            "ip_address": "2001:db8::3257:9652/64",
474            "gateway": "fd00::1",
475            "routes": [
476                {
477                    "network": "::",
478                    "netmask": "::",
479                    "gateway": "fd00::1"
480                },
481                {
482                    "network": "::",
483                    "netmask": "ffff:ffff:ffff::",
484                    "gateway": "fd00::1:1"
485                }
486            ],
487            "network_id": "da5bb487-5193-4a65-a3df-4a0055a8c0d8"
488        }
489    ]
490}
491EOF
492	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
493	cat > network << EOF
494ifconfig_${myiface}='DHCP'
495ifconfig_${myiface}_ipv6='inet6 2001:db8::3257:9652/64'
496ipv6_network_interfaces='${myiface}'
497ipv6_default_interface='${myiface}'
498EOF
499	cat > routing << EOF
500ipv6_defaultrouter='fd00::1'
501ipv6_route_${myiface}='fd00::1 -prefixlen 128 -interface ${myiface}'
502ipv6_static_routes='${myiface}'
503EOF
504	atf_check -o file:network cat "${PWD}"/etc/rc.conf.d/network
505	atf_check -o file:routing cat "${PWD}"/etc/rc.conf.d/routing
506}
507
508config2_network_static_v4_body()
509{
510	mkdir -p media/nuageinit
511	setup_test_adduser
512	printf "{}" > media/nuageinit/meta_data.json
513	mynetworks=$(ifconfig -l ether)
514	if [ -z "$mynetworks" ]; then
515		atf_skip "a network interface is needed"
516	fi
517	set -- $mynetworks
518	myiface=$1
519	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
520cat > media/nuageinit/network_data.json << EOF
521{
522    "links": [
523        {
524            "ethernet_mac_address": "$myaddr",
525            "id": "iface0",
526            "mtu": null
527        }
528    ],
529    "networks": [
530        {
531            "id": "network0",
532            "link": "iface0",
533            "type": "ipv4",
534            "ip_address": "10.184.0.244",
535            "netmask": "255.255.240.0",
536            "routes": [
537                {
538                    "network": "10.0.0.0",
539                    "netmask": "255.0.0.0",
540                    "gateway": "11.0.0.1"
541                },
542                {
543                    "network": "0.0.0.0",
544                    "netmask": "0.0.0.0",
545                    "gateway": "23.253.157.1"
546                }
547            ]
548        }
549    ]
550}
551EOF
552	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
553	cat > network << EOF
554ifconfig_${myiface}='inet 10.184.0.244 netmask 255.255.240.0'
555EOF
556	cat > routing << EOF
557route_cloudinit1_${myiface}='-net 10.0.0.0 11.0.0.1 255.0.0.0'
558defaultrouter='23.253.157.1'
559static_routes='cloudinit1_${myiface}'
560EOF
561	atf_check -o file:network cat "${PWD}"/etc/rc.conf.d/network
562	atf_check -o file:routing cat "${PWD}"/etc/rc.conf.d/routing
563}
564
565config2_network_dns_body()
566{
567	mkdir -p media/nuageinit
568	setup_test_adduser
569	printf "{}" > media/nuageinit/meta_data.json
570	mynetworks=$(ifconfig -l ether)
571	if [ -z "$mynetworks" ]; then
572		atf_skip "a network interface is needed"
573	fi
574	set -- $mynetworks
575	myiface=$1
576	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
577cat > media/nuageinit/network_data.json << EOF
578{
579    "links": [
580        {
581            "ethernet_mac_address": "$myaddr",
582            "id": "iface0",
583            "mtu": null
584        }
585    ],
586    "networks": [
587        {
588            "id": "network0",
589            "link": "iface0",
590            "type": "ipv4_dhcp"
591        }
592    ],
593    "services": [
594        {
595            "type": "dns",
596            "address": "9.9.9.9"
597        },
598        {
599            "type": "dns",
600            "address": "149.112.112.112"
601        }
602    ]
603}
604EOF
605	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
606	atf_check -o inline:"name_servers='9.9.9.9 149.112.112.112'\n" \
607		cat "${PWD}"/etc/resolvconf.conf
608}
609
610config2_ssh_keys_head()
611{
612	atf_set "require.user" root
613}
614config2_ssh_keys_body()
615{
616	here=$(pwd)
617	export NUAGE_FAKE_ROOTDIR=$(pwd)
618	mkdir -p media/nuageinit
619	touch media/nuageinit/meta_data.json
620	cat > media/nuageinit/user-data << EOF
621#cloud-config
622ssh_keys:
623  rsa_private: |
624    -----BEGIN RSA PRIVATE KEY-----
625    MIIBxwIBAAJhAKD0YSHy73nUgysO13XsJmd4fHiFyQ+00R7VVu2iV9Qco
626    ...
627    -----END RSA PRIVATE KEY-----
628  rsa_public: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEAoPRhIfLvedSDKw7Xd ...
629  ed25519_private: |
630    -----BEGIN OPENSSH PRIVATE KEY-----
631    blabla
632    ...
633    -----END OPENSSH PRIVATE KEY-----
634  ed25519_public: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+MH4E8KO32N5CXRvXVqvyZVl0+6ue4DobdhU0FqFd+
635EOF
636	mkdir -p etc/ssh
637	cat > etc/master.passwd << EOF
638root:*:0:0::0:0:Charlie &:/root:/bin/csh
639sys:*:1:0::0:0:Sys:/home/sys:/bin/csh
640EOF
641	pwd_mkdb -d etc ${here}/etc/master.passwd
642	cat > etc/group << EOF
643wheel:*:0:root
644users:*:1:
645EOF
646	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
647	_expected="-----BEGIN RSA PRIVATE KEY-----
648MIIBxwIBAAJhAKD0YSHy73nUgysO13XsJmd4fHiFyQ+00R7VVu2iV9Qco
649...
650-----END RSA PRIVATE KEY-----
651
652"
653	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_rsa_key
654	_expected="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEAoPRhIfLvedSDKw7Xd ...\n"
655	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_rsa_key.pub
656	_expected="-----BEGIN OPENSSH PRIVATE KEY-----
657blabla
658...
659-----END OPENSSH PRIVATE KEY-----
660
661"
662	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_ed25519_key
663	_expected="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+MH4E8KO32N5CXRvXVqvyZVl0+6ue4DobdhU0FqFd+\n"
664	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_ed25519_key.pub
665}
666
667
668nocloud_userdata_cloudconfig_ssh_pwauth_head()
669{
670	atf_set "require.user" root
671}
672nocloud_userdata_cloudconfig_ssh_pwauth_body()
673{
674	mkdir -p etc
675	cat > etc/master.passwd << EOF
676root:*:0:0::0:0:Charlie &:/root:/bin/sh
677sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
678EOF
679	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
680	cat > etc/group << EOF
681wheel:*:0:root
682users:*:1:
683EOF
684	mkdir -p media/nuageinit
685	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
686	cat > media/nuageinit/user-data << 'EOF'
687#cloud-config
688ssh_pwauth: true
689EOF
690	mkdir -p etc/ssh/
691	touch etc/ssh/sshd_config
692
693	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
694	atf_check -o inline:"PasswordAuthentication yes\n" cat etc/ssh/sshd_config
695
696	# Same value we don't touch anything
697	printf "   PasswordAuthentication yes # I want password\n" > etc/ssh/sshd_config
698	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
699	atf_check -o inline:"   PasswordAuthentication yes # I want password\n" cat etc/ssh/sshd_config
700
701	printf "   PasswordAuthentication no # Should change\n" > etc/ssh/sshd_config
702	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
703	atf_check -o inline:"PasswordAuthentication yes\n" cat etc/ssh/sshd_config
704
705	cat > media/nuageinit/user-data << 'EOF'
706#cloud-config
707ssh_pwauth: false
708EOF
709
710	printf "   PasswordAuthentication no # no passwords\n" > etc/ssh/sshd_config
711	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
712	atf_check -o inline:"   PasswordAuthentication no # no passwords\n" cat etc/ssh/sshd_config
713
714	printf "   PasswordAuthentication yes # Should change\n" > etc/ssh/sshd_config
715	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
716	atf_check -o inline:"PasswordAuthentication no\n" cat etc/ssh/sshd_config
717
718	cat > media/nuageinit/user-data << 'EOF'
719#cloud-config
720ssh_pwauth: "no"
721EOF
722
723	printf "   PasswordAuthentication yes # Should change\n" > etc/ssh/sshd_config
724	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
725	atf_check -o inline:"PasswordAuthentication no\n" cat etc/ssh/sshd_config
726
727	cat > media/nuageinit/user-data << 'EOF'
728#cloud-config
729ssh_pwauth: "unchanged"
730EOF
731
732	printf "   PasswordAuthentication yes # keep\n" > etc/ssh/sshd_config
733	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
734	atf_check -o inline:"   PasswordAuthentication yes # keep\n" cat etc/ssh/sshd_config
735}
736
737nocloud_userdata_cloudconfig_chpasswd_head()
738{
739	atf_set "require.user" root
740}
741nocloud_userdata_cloudconfig_chpasswd_body()
742{
743	mkdir -p etc
744	cat > etc/master.passwd << EOF
745root:*:0:0::0:0:Charlie &:/root:/bin/sh
746sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
747user:*:1:0::0:0:Sys:/home/sys:/bin/sh
748EOF
749	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
750	cat > etc/group << EOF
751wheel:*:0:root
752users:*:1:
753EOF
754	mkdir -p media/nuageinit
755	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
756	cat > media/nuageinit/user-data << 'EOF'
757#cloud-config
758chpasswd:
759  expire: true
760  users:
761  - { user: "sys", password: RANDOM }
762EOF
763
764	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
765	atf_check -o empty -e inline:"nuageinit: Invalid entry for chpasswd.users: missing 'name'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
766	# nothing modified
767	atf_check -o inline:"sys:*:1:0::0:0:Sys:/home/sys:/bin/sh\n" pw -R $(pwd) usershow sys
768
769	cat > media/nuageinit/user-data << 'EOF'
770#cloud-config
771chpasswd:
772  expire: true
773  users:
774  - { name: "sys", pwd: RANDOM }
775EOF
776	atf_check -o empty -e inline:"nuageinit: Invalid entry for chpasswd.users: missing 'password'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
777	# nothing modified
778	atf_check -o inline:"sys:*:1:0::0:0:Sys:/home/sys:/bin/sh\n" pw -R $(pwd) usershow sys
779
780	cat > media/nuageinit/user-data << 'EOF'
781#cloud-config
782chpasswd:
783  expire: false
784  users:
785  - { name: "sys", password: RANDOM }
786EOF
787	# not empty because the password is printed to stdout
788	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
789	atf_check -o match:'sys:\$.*:1:0::0:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
790
791	cat > media/nuageinit/user-data << 'EOF'
792#cloud-config
793chpasswd:
794  expire: true
795  users:
796  - { name: "sys", password: RANDOM }
797EOF
798	# not empty because the password is printed to stdout
799	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
800	atf_check -o match:'sys:\$.*:1:0::1:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
801
802	cat > media/nuageinit/user-data << 'EOF'
803#cloud-config
804chpasswd:
805  expire: true
806  users:
807  - { name: "user", password: "$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/" }
808EOF
809	# not empty because the password is printed to stdout
810	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
811	atf_check -o inline:'user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/:1:0::1:0:Sys:/home/sys:/bin/sh\n' pw -R $(pwd) usershow user
812}
813
814
815nocloud_userdata_cloudconfig_chpasswd_list_string_head()
816{
817	atf_set "require.user" root
818}
819nocloud_userdata_cloudconfig_chpasswd_list_string_body()
820{
821	mkdir -p etc
822	cat > etc/master.passwd << EOF
823root:*:0:0::0:0:Charlie &:/root:/bin/sh
824sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
825user:*:1:0::0:0:Sys:/home/sys:/bin/sh
826EOF
827	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
828	cat > etc/group << EOF
829wheel:*:0:root
830users:*:1:
831EOF
832	mkdir -p media/nuageinit
833	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
834	cat > media/nuageinit/user-data << 'EOF'
835#cloud-config
836chpasswd:
837  expire: true
838  list: |
839     sys:RANDOM
840EOF
841
842	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
843	atf_check -o empty -e inline:"nuageinit: chpasswd.list is deprecated consider using chpasswd.users\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
844	atf_check -o match:'sys:\$.*:1:0::1:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
845
846	cat > media/nuageinit/user-data << 'EOF'
847#cloud-config
848chpasswd:
849  expire: false
850  list: |
851     sys:plop
852     user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
853     root:R
854EOF
855
856	atf_check -o empty -e ignore /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
857	atf_check -o match:'sys:\$.*:1:0::0:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
858	atf_check -o inline:'user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/:1:0::0:0:Sys:/home/sys:/bin/sh\n' pw -R $(pwd) usershow user
859	atf_check -o match:'root:\$.*:0:0::0:0:Charlie &:/root:/bin/sh$' pw -R $(pwd) usershow root
860}
861
862nocloud_userdata_cloudconfig_chpasswd_list_list_head()
863{
864	atf_set "require.user" root
865}
866nocloud_userdata_cloudconfig_chpasswd_list_list_body()
867{
868	mkdir -p etc
869	cat > etc/master.passwd << EOF
870root:*:0:0::0:0:Charlie &:/root:/bin/sh
871sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
872user:*:1:0::0:0:Sys:/home/sys:/bin/sh
873EOF
874	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
875	cat > etc/group << EOF
876wheel:*:0:root
877users:*:1:
878EOF
879	mkdir -p media/nuageinit
880	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
881	cat > media/nuageinit/user-data << 'EOF'
882#cloud-config
883chpasswd:
884  expire: true
885  list:
886  - sys:RANDOM
887EOF
888
889	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
890	atf_check -o empty -e inline:"nuageinit: chpasswd.list is deprecated consider using chpasswd.users\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
891	atf_check -o match:'sys:\$.*:1:0::1:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
892
893	cat > media/nuageinit/user-data << 'EOF'
894#cloud-config
895chpasswd:
896  expire: false
897  list:
898  - sys:plop
899  - user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
900  - root:R
901EOF
902
903	atf_check -o empty -e ignore /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
904	atf_check -o match:'sys:\$.*:1:0::0:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
905	atf_check -o inline:'user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/:1:0::0:0:Sys:/home/sys:/bin/sh\n' pw -R $(pwd) usershow user
906	atf_check -o match:'root:\$.*:0:0::0:0:Charlie &:/root:/bin/sh$' pw -R $(pwd) usershow root
907}
908
909config2_userdata_runcmd_head()
910{
911	atf_set "require.user" root
912}
913config2_userdata_runcmd_body()
914{
915	mkdir -p media/nuageinit
916	setup_test_adduser
917	printf "{}" > media/nuageinit/meta_data.json
918	cat > media/nuageinit/user_data << 'EOF'
919#cloud-config
920runcmd:
921EOF
922	chmod 755 "${PWD}"/media/nuageinit/user_data
923	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
924	cat > media/nuageinit/user_data << 'EOF'
925#cloud-config
926runcmd:
927  - plop
928EOF
929	chmod 755 "${PWD}"/media/nuageinit/user_data
930	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
931	test -f var/cache/nuageinit/runcmds || atf_fail "File not created"
932	test -x var/cache/nuageinit/runcmds || atf_fail "Missing execution permission"
933	atf_check -o inline:"#!/bin/sh\nplop\n" cat var/cache/nuageinit/runcmds
934
935	cat > media/nuageinit/user_data << 'EOF'
936#cloud-config
937runcmd:
938  - echo "yeah!"
939  - uname -s
940EOF
941	chmod 755 "${PWD}"/media/nuageinit/user_data
942	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
943	atf_check -o inline:"#!/bin/sh\necho \"yeah!\"\nuname -s\n" cat var/cache/nuageinit/runcmds
944}
945
946config2_userdata_packages_head()
947{
948	atf_set "require.user" root
949}
950
951config2_userdata_packages_body()
952{
953	mkdir -p media/nuageinit
954	setup_test_adduser
955	export NUAGE_RUN_TESTS=1
956	printf "{}" > media/nuageinit/meta_data.json
957	cat > media/nuageinit/user_data << 'EOF'
958#cloud-config
959packages:
960EOF
961	chmod 755 "${PWD}"/media/nuageinit/user_data
962	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
963	cat > media/nuageinit/user_data << 'EOF'
964#cloud-config
965packages:
966  - yeah/plop
967EOF
968	chmod 755 "${PWD}"/media/nuageinit/user_data
969	atf_check -s exit:0 -o inline:"pkg install -y 'yeah/plop'\npkg info -q 'yeah/plop'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
970
971	cat > media/nuageinit/user_data << 'EOF'
972#cloud-config
973packages:
974  - curl
975EOF
976	chmod 755 "${PWD}"/media/nuageinit/user_data
977	atf_check -o inline:"pkg install -y 'curl'\npkg info -q 'curl'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
978
979	cat > media/nuageinit/user_data << 'EOF'
980#cloud-config
981packages:
982  - curl
983  - meh: bla
984EOF
985	chmod 755 "${PWD}"/media/nuageinit/user_data
986	atf_check -o inline:"pkg install -y 'curl'\npkg info -q 'curl'\n" -e inline:"nuageinit: Invalid type: table for packages entry number 2\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
987}
988
989config2_userdata_update_packages_body()
990{
991	mkdir -p media/nuageinit
992	setup_test_adduser
993	export NUAGE_RUN_TESTS=1
994	printf "{}" > media/nuageinit/meta_data.json
995	cat > media/nuageinit/user_data << 'EOF'
996#cloud-config
997package_update: true
998EOF
999	chmod 755 "${PWD}"/media/nuageinit/user_data
1000	atf_check -o inline:"env ASSUME_ALWAYS_YES=yes pkg update\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1001}
1002
1003config2_userdata_upgrade_packages_body()
1004{
1005	mkdir -p media/nuageinit
1006	setup_test_adduser
1007	export NUAGE_RUN_TESTS=1
1008	printf "{}" > media/nuageinit/meta_data.json
1009	cat > media/nuageinit/user_data << 'EOF'
1010#cloud-config
1011package_upgrade: true
1012EOF
1013	chmod 755 "${PWD}"/media/nuageinit/user_data
1014	atf_check -o inline:"env ASSUME_ALWAYS_YES=yes pkg upgrade\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1015}
1016
1017config2_userdata_shebang_body()
1018{
1019	mkdir -p media/nuageinit
1020	setup_test_adduser
1021	printf "{}" > media/nuageinit/meta_data.json
1022	cat > media/nuageinit/user_data <<EOF
1023#!/we/dont/care
1024anything
1025EOF
1026	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1027	test -f var/cache/nuageinit/user_data || atf_fail "File not created"
1028	test -x var/cache/nuageinit/user_data || atf_fail "Missing execution permission"
1029	atf_check -o inline:"#!/we/dont/care\nanything\n" cat var/cache/nuageinit/user_data
1030	cat > media/nuageinit/user_data <<EOF
1031/we/dont/care
1032EOF
1033	rm var/cache/nuageinit/user_data
1034	if [ -f var/cache/nuageinit/user_data ]; then
1035		atf_fail "File should not have been created"
1036	fi
1037}
1038
1039config2_userdata_write_files_body()
1040{
1041	mkdir -p media/nuageinit
1042	setup_test_adduser
1043	printf "{}" > media/nuageinit/meta_data.json
1044	cat > media/nuageinit/user_data <<EOF
1045#cloud-config
1046write_files:
1047- content: "plop"
1048  path: /file1
1049- path: /emptyfile
1050- content: !!binary |
1051    YmxhCg==
1052  path: /file_base64
1053  encoding: b64
1054  permissions: '0755'
1055  owner: nobody
1056- content: "bob"
1057  path: "/foo"
1058  defer: true
1059EOF
1060	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1061	atf_check -o inline:"plop" cat file1
1062	atf_check -o inline:"" cat emptyfile
1063	atf_check -o inline:"bla\n" cat file_base64
1064	test -f foo && atf_fail "foo creation should have been deferred"
1065	atf_check -o match:"^-rwxr-xr-x.*nobody" ls -l file_base64
1066	rm file1 emptyfile file_base64
1067	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1068	test -f file1 -o -f emptyfile -o -f file_base64 && atf_fail "defer not working properly"
1069	atf_check -o inline:"bob" cat foo
1070}
1071
1072config2_userdata_ssh_deletekeys_head()
1073{
1074	atf_set "require.user" root
1075}
1076config2_userdata_ssh_deletekeys_body()
1077{
1078	mkdir -p media/nuageinit
1079	setup_test_adduser
1080	printf "{}" > media/nuageinit/meta_data.json
1081	cat > media/nuageinit/user_data <<EOF
1082#cloud-config
1083ssh_deletekeys: true
1084EOF
1085	mkdir -p etc/ssh
1086	touch etc/ssh/ssh_host_rsa_key
1087	touch etc/ssh/ssh_host_rsa_key.pub
1088	touch etc/ssh/ssh_host_ed25519_key
1089	touch etc/ssh/ssh_host_ed25519_key.pub
1090	touch etc/ssh/ssh_host_ecdsa_key
1091	touch etc/ssh/ssh_host_ecdsa_key.pub
1092	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1093	test -f etc/ssh/ssh_host_rsa_key && atf_fail "ssh_host_rsa_key not deleted"
1094	test -f etc/ssh/ssh_host_rsa_key.pub && atf_fail "ssh_host_rsa_key.pub not deleted"
1095	test -f etc/ssh/ssh_host_ed25519_key && atf_fail "ssh_host_ed25519_key not deleted"
1096	test -f etc/ssh/ssh_host_ed25519_key.pub && atf_fail "ssh_host_ed25519_key.pub not deleted"
1097	test -f etc/ssh/ssh_host_ecdsa_key && atf_fail "ssh_host_ecdsa_key not deleted"
1098	test -f etc/ssh/ssh_host_ecdsa_key.pub && atf_fail "ssh_host_ecdsa_key.pub not deleted"
1099	true
1100}
1101
1102config2_userdata_disable_root_head()
1103{
1104	atf_set "require.user" root
1105}
1106config2_userdata_disable_root_body()
1107{
1108	mkdir -p media/nuageinit
1109	setup_test_adduser
1110	mkdir -p root
1111	printf "{}" > media/nuageinit/meta_data.json
1112	cat > media/nuageinit/user_data <<EOF
1113#cloud-config
1114disable_root: true
1115ssh_authorized_keys:
1116  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
1117EOF
1118	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1119	atf_check -o match:'no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command=.*exit 142" ssh-rsa AAAAB3NzaC1y...== Generated by Nova' cat root/.ssh/authorized_keys
1120	rm -f root/.ssh/authorized_keys
1121	cat > media/nuageinit/user_data <<EOF
1122#cloud-config
1123disable_root: true
1124disable_root_opts: "no-port-forwarding"
1125ssh_authorized_keys:
1126  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
1127EOF
1128	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1129	atf_check -o inline:"no-port-forwarding ssh-rsa AAAAB3NzaC1y...== Generated by Nova\n" cat root/.ssh/authorized_keys
1130	rm -f root/.ssh/authorized_keys
1131	cat > media/nuageinit/user_data <<EOF
1132#cloud-config
1133disable_root: false
1134ssh_authorized_keys:
1135  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
1136EOF
1137	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1138	atf_check -o inline:"ssh-rsa AAAAB3NzaC1y...== Generated by Nova\n" cat root/.ssh/authorized_keys
1139}
1140
1141config2_userdata_bootcmd_head()
1142{
1143	atf_set "require.user" root
1144}
1145config2_userdata_bootcmd_body()
1146{
1147	mkdir -p media/nuageinit
1148	setup_test_adduser
1149	printf "{}" > media/nuageinit/meta_data.json
1150	cat > media/nuageinit/user_data <<EOF
1151#cloud-config
1152bootcmd:
1153  - kldload if_bridge
1154EOF
1155	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1156	test -f var/cache/nuageinit/bootcmds || atf_fail "bootcmds file not created"
1157	atf_check -o inline:"#!/bin/sh\nkldload if_bridge\n" cat var/cache/nuageinit/bootcmds
1158	cat > media/nuageinit/user_data <<EOF
1159#cloud-config
1160bootcmd:
1161  - sysctl net.inet.ip.forwarding=1
1162  - kldload if_bridge
1163EOF
1164	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1165	atf_check -o inline:"#!/bin/sh\nsysctl net.inet.ip.forwarding=1\nkldload if_bridge\n" cat var/cache/nuageinit/bootcmds
1166	# Test 3: empty list (clean up from previous tests first)
1167	rm -f var/cache/nuageinit/bootcmds
1168	cat > media/nuageinit/user_data <<EOF
1169#cloud-config
1170bootcmd: []
1171EOF
1172	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1173	test -f var/cache/nuageinit/bootcmds && atf_fail "bootcmds should not have been created for empty list"
1174	true
1175}
1176
1177config2_userdata_manage_etc_hosts_head()
1178{
1179	atf_set "require.user" root
1180}
1181config2_userdata_manage_etc_hosts_body()
1182{
1183	mkdir -p media/nuageinit
1184	setup_test_adduser
1185	printf "{}" > media/nuageinit/meta_data.json
1186	# Test 1: manage_etc_hosts adds hostname when /etc/hosts does not exist
1187	cat > media/nuageinit/user_data <<EOF
1188#cloud-config
1189hostname: mycloud
1190EOF
1191	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1192	atf_check -o inline:"::1\t\tlocalhost mycloud\n127.0.0.1\t\tlocalhost mycloud\n" cat etc/hosts
1193	# Test 2: manage_etc_hosts appends hostname to existing localhost lines
1194	cat > etc/hosts <<EOF
1195::1		localhost
1196127.0.0.1		localhost
1197EOF
1198	cat > media/nuageinit/user_data <<EOF
1199#cloud-config
1200hostname: myvm
1201EOF
1202	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1203	atf_check -o inline:"::1\t\tlocalhost myvm\n127.0.0.1\t\tlocalhost myvm\n" cat etc/hosts
1204	# Test 3: hostname already present in /etc/hosts, no change
1205	cat > etc/hosts <<EOF
1206::1		localhost myvm
1207127.0.0.1		localhost myvm
1208EOF
1209	cat > media/nuageinit/user_data <<EOF
1210#cloud-config
1211hostname: myvm
1212EOF
1213	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1214	atf_check -o inline:"::1\t\tlocalhost myvm\n127.0.0.1\t\tlocalhost myvm\n" cat etc/hosts
1215	# Test 4: manage_etc_hosts: false disables the behaviour
1216	cat > etc/hosts <<EOF
1217::1		localhost
1218127.0.0.1		localhost
1219EOF
1220	cat > media/nuageinit/user_data <<EOF
1221#cloud-config
1222hostname: nope
1223manage_etc_hosts: false
1224EOF
1225	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1226	atf_check -o inline:"::1\t\tlocalhost\n127.0.0.1\t\tlocalhost\n" cat etc/hosts
1227}
1228
1229config2_userdata_mounts_head()
1230{
1231	atf_set "require.user" root
1232}
1233config2_userdata_mounts_body()
1234{
1235	mkdir -p media/nuageinit
1236	setup_test_adduser
1237	printf "{}" > media/nuageinit/meta_data.json
1238	cat > media/nuageinit/user_data <<EOF
1239#cloud-config
1240mounts:
1241  - [ /dev/ada1p1, /mnt/data, ufs, rw, 0, 2 ]
1242  - device: tmpfs
1243    mountpoint: /mnt/tmp
1244    fstype: tmpfs
1245    options: "size=256M"
1246EOF
1247	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1248	atf_check -o match:"/dev/ada1p1.*/mnt/data.*ufs.*rw.*0.*2" cat etc/fstab
1249	atf_check -o match:"tmpfs.*/mnt/tmp.*tmpfs.*size=256M.*0.*0" cat etc/fstab
1250	test -d mnt/data || atf_fail "/mnt/data directory not created"
1251	test -d mnt/tmp || atf_fail "/mnt/tmp directory not created"
1252	true
1253}
1254
1255config2_userdata_resolv_conf_head()
1256{
1257	atf_set "require.user" root
1258}
1259config2_userdata_resolv_conf_body()
1260{
1261	mkdir -p media/nuageinit
1262	setup_test_adduser
1263	printf "{}" > media/nuageinit/meta_data.json
1264	cat > media/nuageinit/user_data <<EOF
1265#cloud-config
1266resolv_conf:
1267  nameservers:
1268    - 9.9.9.9
1269    - 149.112.112.112
1270  searchdomains:
1271    - example.com
1272    - test.local
1273  domain: mydomain.local
1274  options:
1275    timeout: "1"
1276    attempts: "2"
1277  sortlist:
1278    - 192.168.1.0/255.255.255.0
1279EOF
1280	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1281	atf_check -o match:"domain mydomain.local" cat etc/resolv.conf
1282	atf_check -o match:"search example.com test.local" cat etc/resolv.conf
1283	atf_check -o match:"sortlist 192.168.1.0/255.255.255.0" cat etc/resolv.conf
1284	atf_check -o match:"nameserver 9.9.9.9" cat etc/resolv.conf
1285	atf_check -o match:"nameserver 149.112.112.112" cat etc/resolv.conf
1286	atf_check -o match:"options.*timeout:1" cat etc/resolv.conf
1287	atf_check -o match:"options.*attempts:2" cat etc/resolv.conf
1288	true
1289}
1290
1291config2_userdata_keyboard_head()
1292{
1293	atf_set "require.user" root
1294}
1295config2_userdata_keyboard_body()
1296{
1297	mkdir -p media/nuageinit
1298	setup_test_adduser
1299	printf "{}" > media/nuageinit/meta_data.json
1300	cat > media/nuageinit/user_data <<EOF
1301#cloud-config
1302keyboard:
1303  layout: fr
1304  variant: acc
1305EOF
1306	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1307	atf_check -o inline:"keymap='fr.acc'\n" cat etc/rc.conf.d/keymap
1308	true
1309}
1310
1311config2_userdata_ssh_authkey_fingerprints_head()
1312{
1313	atf_set "require.user" root
1314}
1315config2_userdata_ssh_authkey_fingerprints_body()
1316{
1317	mkdir -p media/nuageinit
1318	setup_test_adduser
1319	printf "{}" > media/nuageinit/meta_data.json
1320	mkdir -p etc/ssh
1321	ssh-keygen -t ed25519 -f etc/ssh/ssh_host_ed25519_key -N "" -q 2>/dev/null
1322	cat > media/nuageinit/user_data <<EOF
1323#cloud-config
1324ssh_authkey_fingerprints: true
1325EOF
1326	atf_check -s exit:0 -e match:"SHA256:" /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1327	true
1328}
1329
1330config2_userdata_ntp_head()
1331{
1332	atf_set "require.user" root
1333}
1334config2_userdata_ntp_body()
1335{
1336	mkdir -p media/nuageinit
1337	setup_test_adduser
1338	printf "{}" > media/nuageinit/meta_data.json
1339	cat > media/nuageinit/user_data <<EOF
1340#cloud-config
1341ntp:
1342  servers:
1343    - 192.168.1.1
1344    - 10.0.0.1
1345  pools:
1346    - 0.pool.ntp.org
1347EOF
1348	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1349	atf_check -o match:"server 192.168.1.1 iburst" cat etc/ntp.conf
1350	atf_check -o match:"server 10.0.0.1 iburst" cat etc/ntp.conf
1351	atf_check -o match:"pool 0.pool.ntp.org iburst" cat etc/ntp.conf
1352	atf_check -o match:"leapfile /var/db/ntpd.leap-seconds.list" cat etc/ntp.conf
1353	true
1354}
1355
1356config2_userdata_ca_certs_head()
1357{
1358	atf_set "require.user" root
1359}
1360config2_userdata_ca_certs_body()
1361{
1362	mkdir -p media/nuageinit
1363	setup_test_adduser
1364	printf "{}" > media/nuageinit/meta_data.json
1365	cat > media/nuageinit/user_data <<'EOF'
1366#cloud-config
1367ca_certs:
1368  trusted:
1369    - |
1370      -----BEGIN CERTIFICATE-----
1371      dGVzdGNlcnQx
1372      -----END CERTIFICATE-----
1373    - |
1374      -----BEGIN CERTIFICATE-----
1375      dGVzdGNlcnQy
1376      -----END CERTIFICATE-----
1377EOF
1378	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1379	atf_check -o match:"dGVzdGNlcnQx" cat usr/share/certs/trusted/nuageinit-1.pem
1380	atf_check -o match:"dGVzdGNlcnQy" cat usr/share/certs/trusted/nuageinit-2.pem
1381	true
1382}
1383
1384config2_userdata_multipart_head()
1385{
1386	atf_set "require.user" root
1387}
1388config2_userdata_multipart_body()
1389{
1390	mkdir -p media/nuageinit
1391	setup_test_adduser
1392	printf "{}" > media/nuageinit/meta_data.json
1393	cat > media/nuageinit/user_data <<'EOF'
1394Content-Type: multipart/mixed; boundary="==BOUNDARY=="
1395
1396--==BOUNDARY==
1397Content-Type: text/cloud-config; charset="us-ascii"
1398
1399#cloud-config
1400hostname: multipart-host
1401
1402--==BOUNDARY==
1403Content-Type: text/x-shellscript
1404
1405#!/bin/sh
1406echo "multipart script executed"
1407
1408--==BOUNDARY==--
1409EOF
1410	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1411	atf_check -o inline:"hostname='multipart-host'\n" cat etc/rc.conf.d/hostname
1412	atf_check -o inline:"#!/bin/sh\necho \"multipart script executed\"\n" cat var/cache/nuageinit/multipart_script
1413	test -x var/cache/nuageinit/multipart_script || atf_fail "multipart_script not executable"
1414	true
1415}
1416
1417config2_userdata_power_state_head()
1418{
1419	atf_set "require.user" root
1420}
1421config2_userdata_power_state_body()
1422{
1423	mkdir -p media/nuageinit
1424	setup_test_adduser
1425	export NUAGE_RUN_TESTS=1
1426	printf "{}" > media/nuageinit/meta_data.json
1427	cat > media/nuageinit/user_data <<EOF
1428#cloud-config
1429power_state:
1430  delay: "+5"
1431  mode: reboot
1432  message: "Rebooting after configuration is complete"
1433  timeout: 30
1434  condition: true
1435EOF
1436	atf_check -o inline:"shutdown -r '+5' 'Rebooting after configuration is complete'\n" \
1437	    /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1438	true
1439}
1440
1441config2_userdata_locale_head()
1442{
1443	atf_set "require.user" root
1444}
1445config2_userdata_locale_body()
1446{
1447	mkdir -p media/nuageinit
1448	setup_test_adduser
1449	printf "{}" > media/nuageinit/meta_data.json
1450	cat > media/nuageinit/user_data <<EOF
1451#cloud-config
1452locale: fr_FR.UTF-8
1453EOF
1454	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1455	atf_check -o inline:"export LANG='fr_FR.UTF-8'\n" cat etc/profile
1456
1457	cat > media/nuageinit/user_data <<EOF
1458#cloud-config
1459locale:
1460  LANG: de_DE.UTF-8
1461  LC_ALL: de_DE.UTF-8
1462EOF
1463	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1464	atf_check -o match:"export LANG='de_DE.UTF-8'" cat etc/profile
1465	atf_check -o match:"export LC_ALL='de_DE.UTF-8'" cat etc/profile
1466	true
1467}
1468
1469config2_userdata_fqdn_and_hostname_body()
1470{
1471	mkdir -p media/nuageinit
1472	setup_test_adduser
1473	printf "{}" > media/nuageinit/meta_data.json
1474	cat > media/nuageinit/user_data <<EOF
1475#cloud-config
1476fqdn: host.domain.tld
1477hostname: host
1478EOF
1479	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1480	atf_check -o inline:"hostname='host.domain.tld'\n" cat ${PWD}/etc/rc.conf.d/hostname
1481	cat > media/nuageinit/user_data <<EOF
1482#cloud-config
1483hostname: host
1484EOF
1485	atf_check -o empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
1486	atf_check -o inline:"hostname='host'\n" cat ${PWD}/etc/rc.conf.d/hostname
1487}
1488
1489config2_userdata_encode_base64_body()
1490{
1491	mkdir -p media/nuageinit
1492	setup_test_adduser
1493	atf_check -o inline:"dGVzdA==\n" \
1494	    /usr/libexec/flua -e "print(require('nuage').encode_base64('test'))"
1495	atf_check -o inline:"dA==\n" \
1496	    /usr/libexec/flua -e "print(require('nuage').encode_base64('t'))"
1497	atf_check -o inline:"dGU=\n" \
1498	    /usr/libexec/flua -e "print(require('nuage').encode_base64('te'))"
1499	# Roundtrip test
1500	atf_check -o inline:"hello world\n" \
1501	    /usr/libexec/flua -e "print(require('nuage').decode_base64(require('nuage').encode_base64('hello world')))"
1502	# Empty input
1503	atf_check -o inline:"\n" \
1504	    /usr/libexec/flua -e "print(require('nuage').encode_base64(''))"
1505}
1506
1507config2_userdata_final_message_body()
1508{
1509	mkdir -p media/nuageinit
1510	setup_test_adduser
1511	export NUAGE_RUN_TESTS=1
1512	printf "{}" > media/nuageinit/meta_data.json
1513	cat > media/nuageinit/user_data << 'EOF'
1514#cloud-config
1515final_message: "System ready after $UPTIME seconds"
1516EOF
1517	atf_check -e match:"System ready after [0-9]+ seconds" \
1518	    /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1519}
1520
1521config2_userdata_phone_home_body()
1522{
1523	mkdir -p media/nuageinit
1524	setup_test_adduser
1525	export NUAGE_RUN_TESTS=1
1526	printf '{"hostname": "myhost", "uuid": "abc-123", "public_keys": ["ssh-rsa AAAAB...", "ssh-ed25519 AAAAC..."]}' > media/nuageinit/meta_data.json
1527	cat > media/nuageinit/user_data << 'EOF'
1528#cloud-config
1529phone_home:
1530  url: "http://example.com/endpoint"
1531  post:
1532    - hostname
1533    - instance_id
1534  tries: 1
1535EOF
1536	atf_check -o match:"fetch -q -o /dev/null --post-data 'hostname=myhost&instance_id=abc-123' 'http://example.com/endpoint'" \
1537	    /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1538
1539	# Test "all" post
1540	printf '{"hostname": "myhost"}' > media/nuageinit/meta_data.json
1541	cat > media/nuageinit/user_data << 'EOF'
1542#cloud-config
1543phone_home:
1544  url: "http://example.com/endpoint"
1545  post: all
1546  tries: 1
1547EOF
1548	atf_check -o match:"fetch -q -o /dev/null --post-data 'hostname=myhost&fqdn=myhost' 'http://example.com/endpoint'" \
1549	    /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet
1550}
1551
1552atf_init_test_cases()
1553{
1554	atf_add_test_case args
1555	atf_add_test_case nocloud
1556	atf_add_test_case nocloud_userdata_script
1557	atf_add_test_case nocloud_user_data_script
1558	atf_add_test_case nocloud_userdata_cloudconfig_users
1559	atf_add_test_case nocloud_userdata_cloudconfig_users_lock_passwd
1560	atf_add_test_case nocloud_network
1561	atf_add_test_case config2
1562	atf_add_test_case config2_pubkeys
1563	atf_add_test_case config2_pubkeys_user_data
1564	atf_add_test_case config2_pubkeys_meta_data
1565	atf_add_test_case config2_pubkeys_allow_public_ssh_keys
1566	atf_add_test_case config2_network
1567	atf_add_test_case config2_network_static_v4
1568	atf_add_test_case config2_network_dns
1569	atf_add_test_case config2_ssh_keys
1570	atf_add_test_case nocloud_userdata_cloudconfig_ssh_pwauth
1571	atf_add_test_case nocloud_userdata_cloudconfig_chpasswd
1572	atf_add_test_case nocloud_userdata_cloudconfig_chpasswd_list_string
1573	atf_add_test_case nocloud_userdata_cloudconfig_chpasswd_list_list
1574	atf_add_test_case config2_userdata_runcmd
1575	atf_add_test_case config2_userdata_packages
1576	atf_add_test_case config2_userdata_update_packages
1577	atf_add_test_case config2_userdata_upgrade_packages
1578	atf_add_test_case config2_userdata_shebang
1579	atf_add_test_case config2_userdata_ssh_deletekeys
1580	atf_add_test_case config2_userdata_disable_root
1581	atf_add_test_case config2_userdata_bootcmd
1582	atf_add_test_case config2_userdata_manage_etc_hosts
1583	atf_add_test_case config2_userdata_mounts
1584	atf_add_test_case config2_userdata_resolv_conf
1585	atf_add_test_case config2_userdata_keyboard
1586	atf_add_test_case config2_userdata_ssh_authkey_fingerprints
1587	atf_add_test_case config2_userdata_ntp
1588	atf_add_test_case config2_userdata_ca_certs
1589	atf_add_test_case config2_userdata_multipart
1590	atf_add_test_case config2_userdata_power_state
1591	atf_add_test_case config2_userdata_locale
1592	atf_add_test_case config2_userdata_fqdn_and_hostname
1593	atf_add_test_case config2_userdata_write_files
1594	atf_add_test_case config2_userdata_encode_base64
1595	atf_add_test_case config2_userdata_final_message
1596	atf_add_test_case config2_userdata_phone_home
1597}
1598