xref: /freebsd/libexec/nuageinit/tests/nuageinit.sh (revision 2e47f35be5dc61945afdbd1a70e8fd505c032c94)
1#-
2# Copyright (c) 2022 Baptiste Daroussin <bapt@FreeBSD.org>
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6
7export NUAGE_FAKE_ROOTDIR="$PWD"
8
9atf_test_case args
10atf_test_case nocloud
11atf_test_case nocloud_userdata_script
12atf_test_case nocloud_user_data_script
13atf_test_case nocloud_userdata_cloudconfig_users
14atf_test_case nocloud_network
15atf_test_case config2
16atf_test_case config2_pubkeys
17atf_test_case config2_pubkeys_user_data
18atf_test_case config2_pubkeys_meta_data
19atf_test_case config2_network
20atf_test_case config2_network_static_v4
21atf_test_case config2_ssh_keys
22atf_test_case nocloud_userdata_cloudconfig_ssh_pwauth
23
24args_body()
25{
26	atf_check -s exit:1 -e inline:"Usage: /usr/libexec/nuageinit <cloud-init-directory> (<config-2> | <nocloud>)\n" /usr/libexec/nuageinit
27	atf_check -s exit:1 -e inline:"Usage: /usr/libexec/nuageinit <cloud-init-directory> (<config-2> | <nocloud>)\n" /usr/libexec/nuageinit bla
28	atf_check -s exit:1 -e inline:"Usage: /usr/libexec/nuageinit <cloud-init-directory> (<config-2> | <nocloud>)\n" /usr/libexec/nuageinit bla meh plop
29	atf_check -s exit:1 -e inline:"nuageinit: Unknown cloud init type: meh\n" /usr/libexec/nuageinit bla meh
30}
31
32nocloud_body()
33{
34	mkdir -p media/nuageinit
35	atf_check -s exit:1 -e match:"nuageinit: error parsing nocloud.*" /usr/libexec/nuageinit "${PWD}"/media/nuageinit/ nocloud
36	printf "instance-id: iid-local01\nlocal-hostname: cloudimg\n" > "${PWD}"/media/nuageinit/meta-data
37	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
38	atf_check -o inline:"hostname=\"cloudimg\"\n" cat etc/rc.conf.d/hostname
39	cat > media/nuageinit/meta-data << EOF
40instance-id: iid-local01
41hostname: myhost
42EOF
43	atf_check -s exit:0 /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
44	atf_check -o inline:"hostname=\"myhost\"\n" cat etc/rc.conf.d/hostname
45}
46
47nocloud_userdata_script_body()
48{
49	mkdir -p media/nuageinit
50	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
51	printf "#!/bin/sh\necho yeah\n" > "${PWD}"/media/nuageinit/user-data
52	chmod 755 "${PWD}"/media/nuageinit/user-data
53	atf_check -s exit:0 -o inline:"yeah\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
54}
55
56nocloud_user_data_script_body()
57{
58	mkdir -p media/nuageinit
59	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
60	printf "#!/bin/sh\necho yeah\n" > "${PWD}"/media/nuageinit/user_data
61	chmod 755 "${PWD}"/media/nuageinit/user_data
62	atf_check -s exit:0 -o inline:"yeah\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
63}
64
65nocloud_userdata_cloudconfig_users_head()
66{
67	atf_set "require.user" root
68}
69nocloud_userdata_cloudconfig_users_body()
70{
71	mkdir -p media/nuageinit
72	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
73	mkdir -p etc
74	cat > etc/master.passwd << EOF
75root:*:0:0::0:0:Charlie &:/root:/bin/sh
76sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
77EOF
78	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
79	cat > etc/group << EOF
80wheel:*:0:root
81users:*:1:
82EOF
83	cat > media/nuageinit/user-data << 'EOF'
84#cloud-config
85groups:
86  - admingroup: [root,sys]
87  - cloud-users
88users:
89  - default
90  - name: foobar
91    gecos: Foo B. Bar
92    primary_group: foobar
93    groups: users
94    passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
95EOF
96	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
97	cat > expectedgroup << EOF
98wheel:*:0:root,freebsd
99users:*:1:foobar
100admingroup:*:1001:root,sys
101cloud-users:*:1002:
102freebsd:*:1003:
103foobar:*:1004:
104EOF
105	cat > expectedpasswd << 'EOF'
106root:*:0:0::0:0:Charlie &:/root:/bin/sh
107sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
108freebsd:freebsd:1001:1003::0:0:FreeBSD User:/home/freebsd:/bin/sh
109foobar:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/:1002:1004::0:0:Foo B. Bar:/home/foobar:/bin/sh
110EOF
111	sed -i "" "s/freebsd:.*:1001/freebsd:freebsd:1001/" "${PWD}"/etc/master.passwd
112	atf_check -o file:expectedpasswd cat "${PWD}"/etc/master.passwd
113	atf_check -o file:expectedgroup cat "${PWD}"/etc/group
114}
115
116nocloud_network_head()
117{
118	atf_set "require.user" root
119}
120nocloud_network_body()
121{
122	mkdir -p media/nuageinit
123	mkdir -p etc
124	cat > etc/master.passwd << EOF
125root:*:0:0::0:0:Charlie &:/root:/bin/sh
126sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
127EOF
128	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
129	cat > etc/group << EOF
130wheel:*:0:root
131users:*:1:
132EOF
133	mynetworks=$(ifconfig -l ether)
134	if [ -z "$mynetworks" ]; then
135		atf_skip "a network interface is needed"
136	fi
137	set -- $mynetworks
138	myiface=$1
139	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
140	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
141	cat > media/nuageinit/user-data << EOF
142#cloud-config
143network:
144  version: 2
145  ethernets:
146    # opaque ID for physical interfaces, only referred to by other stanzas
147    id0:
148      match:
149        macaddress: "$myaddr"
150      addresses:
151        - 192.0.2.2/24
152        - 2001:db8::2/64
153      gateway4: 192.0.2.1
154      gateway6: 2001:db8::1
155EOF
156	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
157	cat > network << EOF
158ifconfig_${myiface}="inet 192.0.2.2/24"
159ifconfig_${myiface}_ipv6="inet6 2001:db8::2/64"
160ipv6_network_interfaces="${myiface}"
161ipv6_default_interface="${myiface}"
162EOF
163	cat > routing << EOF
164defaultrouter="192.0.2.1"
165ipv6_defaultrouter="2001:db8::1"
166ipv6_route_${myiface}="2001:db8::1 -prefixlen 128 -interface ${myiface}"
167EOF
168	atf_check -o file:network cat "${PWD}"/etc/rc.conf.d/network
169	atf_check -o file:routing cat "${PWD}"/etc/rc.conf.d/routing
170}
171
172config2_body()
173{
174	mkdir -p media/nuageinit
175	atf_check -s exit:1 -e match:"nuageinit: error parsing config-2 meta_data.json:.*" /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
176	printf "{}" > media/nuageinit/meta_data.json
177	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
178	cat > media/nuageinit/meta_data.json << EOF
179{
180    "hostname": "cloudimg"
181}
182EOF
183	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
184	atf_check -o inline:"hostname=\"cloudimg\"\n" cat etc/rc.conf.d/hostname
185}
186
187config2_pubkeys_head()
188{
189	atf_set "require.user" root
190}
191config2_pubkeys_body()
192{
193	mkdir -p media/nuageinit
194	touch media/nuageinit/meta_data.json
195	cat > media/nuageinit/user-data << EOF
196#cloud-config
197ssh_authorized_keys:
198  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
199EOF
200	mkdir -p etc
201	cat > etc/master.passwd << EOF
202root:*:0:0::0:0:Charlie &:/root:/bin/sh
203sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
204EOF
205	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
206	cat > etc/group << EOF
207wheel:*:0:root
208users:*:1:
209EOF
210	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
211	atf_check -o inline:"ssh-rsa AAAAB3NzaC1y...== Generated by Nova\n" cat home/freebsd/.ssh/authorized_keys
212}
213
214config2_pubkeys_user_data_head()
215{
216	atf_set "require.user" root
217}
218config2_pubkeys_user_data_body()
219{
220	mkdir -p media/nuageinit
221	touch media/nuageinit/meta_data.json
222	cat > media/nuageinit/user_data << EOF
223#cloud-config
224ssh_authorized_keys:
225  - "ssh-rsa AAAAB3NzaC1y...== Generated by Nova"
226EOF
227	mkdir -p etc
228	cat > etc/master.passwd << EOF
229root:*:0:0::0:0:Charlie &:/root:/bin/sh
230sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
231EOF
232	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
233	cat > etc/group << EOF
234wheel:*:0:root
235users:*:1:
236EOF
237	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
238	atf_check -o inline:"ssh-rsa AAAAB3NzaC1y...== Generated by Nova\n" cat home/freebsd/.ssh/authorized_keys
239}
240
241config2_pubkeys_meta_data_body()
242{
243	here=$(pwd)
244	export NUAGE_FAKE_ROOTDIR=$(pwd)
245	if [ $(id -u) -ne 0 ]; then
246		atf_skip "root required"
247	fi
248	mkdir -p media/nuageinit
249	cat > media/nuageinit/meta_data.json << EOF
250{
251    "uuid": "uuid_for_this_instance",
252    "admin_pass": "a_generated_password",
253    "public_keys": {
254        "tdb": "ssh-ed25519 my_key_id tdb@host"
255    },
256    "keys": [
257        {
258            "name": "tdb",
259            "type": "ssh",
260            "data": "ssh-ed25519 my_key_id tdb@host"
261        }
262    ],
263    "hostname": "freebsd-14-test.novalocal",
264    "name": "freebsd-14-test",
265    "launch_index": 0,
266    "availability_zone": "nova",
267    "random_seed": "long_random_seed",
268    "project_id": "my_project_id",
269    "devices": [],
270    "dedicated_cpus": []
271}
272EOF
273	mkdir -p etc
274	cat > etc/master.passwd << EOF
275root:*:0:0::0:0:Charlie &:/root:/bin/csh
276sys:*:1:0::0:0:Sys:/home/sys:/bin/csh
277EOF
278	pwd_mkdb -d etc ${here}/etc/master.passwd
279	cat > etc/group << EOF
280wheel:*:0:root
281users:*:1:
282EOF
283	atf_check /usr/libexec/nuageinit ${here}/media/nuageinit config-2
284	atf_check -o inline:"ssh-ed25519 my_key_id tdb@host\n" cat home/freebsd/.ssh/authorized_keys
285}
286
287config2_network_body()
288{
289	mkdir -p media/nuageinit
290	printf "{}" > media/nuageinit/meta_data.json
291	mynetworks=$(ifconfig -l ether)
292	if [ -z "$mynetworks" ]; then
293		atf_skip "a network interface is needed"
294	fi
295	set -- $mynetworks
296	myiface=$1
297	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
298cat > media/nuageinit/network_data.json << EOF
299{
300    "links": [
301        {
302            "ethernet_mac_address": "$myaddr",
303            "id": "iface0",
304            "mtu": null
305        }
306    ],
307    "networks": [
308        {
309            "id": "network0",
310            "link": "iface0",
311            "type": "ipv4_dhcp"
312        },
313        { // IPv6
314            "id": "private-ipv4",
315            "type": "ipv6",
316            "link": "iface0",
317            // supports condensed IPv6 with CIDR netmask
318            "ip_address": "2001:db8::3257:9652/64",
319            "gateway": "fd00::1",
320            "routes": [
321                {
322                    "network": "::",
323                    "netmask": "::",
324                    "gateway": "fd00::1"
325                },
326                {
327                    "network": "::",
328                    "netmask": "ffff:ffff:ffff::",
329                    "gateway": "fd00::1:1"
330                }
331            ],
332            "network_id": "da5bb487-5193-4a65-a3df-4a0055a8c0d8"
333        }
334    ]
335}
336EOF
337	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
338	cat > network << EOF
339ifconfig_${myiface}="DHCP"
340ifconfig_${myiface}_ipv6="inet6 2001:db8::3257:9652/64"
341ipv6_network_interfaces="${myiface}"
342ipv6_default_interface="${myiface}"
343EOF
344	cat > routing << EOF
345ipv6_defaultrouter="fd00::1"
346ipv6_route_${myiface}="fd00::1 -prefixlen 128 -interface ${myiface}"
347ipv6_static_routes="${myiface}"
348EOF
349	atf_check -o file:network cat "${PWD}"/etc/rc.conf.d/network
350	atf_check -o file:routing cat "${PWD}"/etc/rc.conf.d/routing
351}
352
353config2_network_static_v4_body()
354{
355	mkdir -p media/nuageinit
356	printf "{}" > media/nuageinit/meta_data.json
357	mynetworks=$(ifconfig -l ether)
358	if [ -z "$mynetworks" ]; then
359		atf_skip "a network interface is needed"
360	fi
361	set -- $mynetworks
362	myiface=$1
363	myaddr=$(ifconfig $myiface ether | awk '/ether/ { print $2 }')
364cat > media/nuageinit/network_data.json << EOF
365{
366    "links": [
367        {
368            "ethernet_mac_address": "$myaddr",
369            "id": "iface0",
370            "mtu": null
371        }
372    ],
373    "networks": [
374        {
375            "id": "network0",
376            "link": "iface0",
377            "type": "ipv4",
378            "ip_address": "10.184.0.244",
379            "netmask": "255.255.240.0",
380            "routes": [
381                {
382                    "network": "10.0.0.0",
383                    "netmask": "255.0.0.0",
384                    "gateway": "11.0.0.1"
385                },
386                {
387                    "network": "0.0.0.0",
388                    "netmask": "0.0.0.0",
389                    "gateway": "23.253.157.1"
390                }
391            ]
392        }
393    ]
394}
395EOF
396	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
397	cat > network << EOF
398ifconfig_${myiface}="inet 10.184.0.244 netmask 255.255.240.0"
399EOF
400	cat > routing << EOF
401route_cloudinit1_${myiface}="-net 10.0.0.0 11.0.0.1 255.0.0.0"
402defaultrouter="23.253.157.1"
403static_routes="cloudinit1_${myiface}"
404EOF
405	atf_check -o file:network cat "${PWD}"/etc/rc.conf.d/network
406	atf_check -o file:routing cat "${PWD}"/etc/rc.conf.d/routing
407}
408
409config2_ssh_keys_head()
410{
411	atf_set "require.user" root
412}
413config2_ssh_keys_body()
414{
415	here=$(pwd)
416	export NUAGE_FAKE_ROOTDIR=$(pwd)
417	mkdir -p media/nuageinit
418	touch media/nuageinit/meta_data.json
419	cat > media/nuageinit/user-data << EOF
420#cloud-config
421ssh_keys:
422  rsa_private: |
423    -----BEGIN RSA PRIVATE KEY-----
424    MIIBxwIBAAJhAKD0YSHy73nUgysO13XsJmd4fHiFyQ+00R7VVu2iV9Qco
425    ...
426    -----END RSA PRIVATE KEY-----
427  rsa_public: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEAoPRhIfLvedSDKw7Xd ...
428  ed25519_private: |
429    -----BEGIN OPENSSH PRIVATE KEY-----
430    blabla
431    ...
432    -----END OPENSSH PRIVATE KEY-----
433  ed25519_public: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+MH4E8KO32N5CXRvXVqvyZVl0+6ue4DobdhU0FqFd+
434EOF
435	mkdir -p etc/ssh
436	cat > etc/master.passwd << EOF
437root:*:0:0::0:0:Charlie &:/root:/bin/csh
438sys:*:1:0::0:0:Sys:/home/sys:/bin/csh
439EOF
440	pwd_mkdb -d etc ${here}/etc/master.passwd
441	cat > etc/group << EOF
442wheel:*:0:root
443users:*:1:
444EOF
445	atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit config-2
446	_expected="-----BEGIN RSA PRIVATE KEY-----
447MIIBxwIBAAJhAKD0YSHy73nUgysO13XsJmd4fHiFyQ+00R7VVu2iV9Qco
448...
449-----END RSA PRIVATE KEY-----
450"
451	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_rsa_key
452	_expected="ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEAoPRhIfLvedSDKw7Xd ...\n"
453	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_rsa_key.pub
454	_expected="-----BEGIN OPENSSH PRIVATE KEY-----
455blabla
456...
457-----END OPENSSH PRIVATE KEY-----\n"
458	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_ed25519_key
459	_expected="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+MH4E8KO32N5CXRvXVqvyZVl0+6ue4DobdhU0FqFd+\n"
460	atf_check -o inline:"${_expected}" cat ${PWD}/etc/ssh/ssh_host_ed25519_key.pub
461}
462
463
464nocloud_userdata_cloudconfig_ssh_pwauth_head()
465{
466	atf_set "require.user" root
467}
468nocloud_userdata_cloudconfig_ssh_pwauth_body()
469{
470	mkdir -p etc
471	cat > etc/master.passwd << EOF
472root:*:0:0::0:0:Charlie &:/root:/bin/sh
473sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
474EOF
475	pwd_mkdb -d etc "${PWD}"/etc/master.passwd
476	cat > etc/group << EOF
477wheel:*:0:root
478users:*:1:
479EOF
480	mkdir -p media/nuageinit
481	printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
482	cat > media/nuageinit/user-data << 'EOF'
483#cloud-config
484ssh_pwauth: true
485EOF
486	mkdir -p etc/ssh/
487	touch etc/ssh/sshd_config
488
489	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
490	atf_check -o inline:"PasswordAuthentication yes\n" cat etc/ssh/sshd_config
491
492	# Same value we don't touch anything
493	printf "   PasswordAuthentication yes # I want password\n" > etc/ssh/sshd_config
494	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
495	atf_check -o inline:"   PasswordAuthentication yes # I want password\n" cat etc/ssh/sshd_config
496
497	printf "   PasswordAuthentication no # Should change\n" > etc/ssh/sshd_config
498	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
499	atf_check -o inline:"PasswordAuthentication yes\n" cat etc/ssh/sshd_config
500
501	cat > media/nuageinit/user-data << 'EOF'
502#cloud-config
503ssh_pwauth: false
504EOF
505
506	printf "   PasswordAuthentication no # no passwords\n" > etc/ssh/sshd_config
507	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
508	atf_check -o inline:"   PasswordAuthentication no # no passwords\n" cat etc/ssh/sshd_config
509
510	printf "   PasswordAuthentication yes # Should change\n" > etc/ssh/sshd_config
511	atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
512	atf_check -o inline:"PasswordAuthentication no\n" cat etc/ssh/sshd_config
513}
514
515atf_init_test_cases()
516{
517	atf_add_test_case args
518	atf_add_test_case nocloud
519	atf_add_test_case nocloud_userdata_script
520	atf_add_test_case nocloud_user_data_script
521	atf_add_test_case nocloud_userdata_cloudconfig_users
522	atf_add_test_case nocloud_network
523	atf_add_test_case config2
524	atf_add_test_case config2_pubkeys
525	atf_add_test_case config2_pubkeys_user_data
526	atf_add_test_case config2_pubkeys_meta_data
527	atf_add_test_case config2_network
528	atf_add_test_case config2_network_static_v4
529	atf_add_test_case config2_ssh_keys
530	atf_add_test_case nocloud_userdata_cloudconfig_ssh_pwauth
531}
532