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