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