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