diff options
Diffstat (limited to 'libexec/nuageinit')
-rw-r--r-- | libexec/nuageinit/nuage.lua | 87 | ||||
-rwxr-xr-x | libexec/nuageinit/nuageinit | 273 | ||||
-rw-r--r-- | libexec/nuageinit/nuageinit.7 | 123 | ||||
-rw-r--r-- | libexec/nuageinit/tests/Makefile | 1 | ||||
-rw-r--r-- | libexec/nuageinit/tests/nuage.sh | 10 | ||||
-rw-r--r-- | libexec/nuageinit/tests/nuageinit.sh | 17 | ||||
-rw-r--r-- | libexec/nuageinit/tests/settimezone.lua | 5 | ||||
-rw-r--r-- | libexec/nuageinit/tests/utils.sh | 1 |
8 files changed, 473 insertions, 44 deletions
diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua index 493ae11d6ca7..ef3cfd994fe1 100644 --- a/libexec/nuageinit/nuage.lua +++ b/libexec/nuageinit/nuage.lua @@ -2,11 +2,23 @@ -- SPDX-License-Identifier: BSD-2-Clause -- -- Copyright(c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org> +-- Copyright(c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org> local unistd = require("posix.unistd") local sys_stat = require("posix.sys.stat") local lfs = require("lfs") +local function getlocalbase() + local f = io.popen("sysctl -in user.localbase 2> /dev/null") + local localbase = f:read("*l") + f:close() + if localbase == nil or localbase:len() == 0 then + -- fallback + localbase = "/usr/local" + end + return localbase +end + local function decode_base64(input) local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' input = string.gsub(input, '[^'..b..'=]', '') @@ -276,11 +288,59 @@ local function addsshkey(homedir, key) end end +local function adddoas(pwd) + local chmodetcdir = false + local chmoddoasconf = false + local root = os.getenv("NUAGE_FAKE_ROOTDIR") + local localbase = getlocalbase() + local etcdir = localbase .. "/etc" + if root then + etcdir= root .. etcdir + end + local doasconf = etcdir .. "/doas.conf" + local doasconf_attr = lfs.attributes(doasconf) + if doasconf_attr == nil then + chmoddoasconf = true + local dirattrs = lfs.attributes(etcdir) + if dirattrs == nil then + local r, err = mkdir_p(etcdir) + if not r then + return nil, err .. " (creating " .. etcdir .. ")" + end + chmodetcdir = true + end + end + local f = io.open(doasconf, "a") + if not f then + warnmsg("impossible to open " .. doasconf) + return + end + if type(pwd.doas) == "string" then + local rule = pwd.doas + rule = rule:gsub("%%u", pwd.name) + f:write(rule .. "\n") + elseif type(pwd.doas) == "table" then + for _, str in ipairs(pwd.doas) do + local rule = str + rule = rule:gsub("%%u", pwd.name) + f:write(rule .. "\n") + end + end + f:close() + if chmoddoasconf then + chmod(doasconf, "0640") + end + if chmodetcdir then + chmod(etcdir, "0755") + end +end + local function addsudo(pwd) local chmodsudoersd = false local chmodsudoers = false local root = os.getenv("NUAGE_FAKE_ROOTDIR") - local sudoers_dir = "/usr/local/etc/sudoers.d" + local localbase = getlocalbase() + local sudoers_dir = localbase .. "/etc/sudoers.d" if root then sudoers_dir= root .. sudoers_dir end @@ -311,10 +371,10 @@ local function addsudo(pwd) end f:close() if chmodsudoers then - chmod(sudoers, "0640") + chmod(sudoers, "0440") end if chmodsudoersd then - chmod(sudoers, "0740") + chmod(sudoers_dir, "0750") end end @@ -451,6 +511,23 @@ local function chpasswd(obj) end end +local function settimezone(timezone) + if timezone == nil then + return + end + local root = os.getenv("NUAGE_FAKE_ROOTDIR") + if not root then + root = "/" + end + + f, _, rc = os.execute("tzsetup -s -C " .. root .. " " .. timezone) + + if not f then + warnmsg("Impossible to configure time zone ( rc = " .. rc .. " )") + return + end +end + local function pkg_bootstrap() if os.getenv("NUAGE_RUN_TESTS") then return true @@ -480,7 +557,7 @@ local function install_package(package) end local function run_pkg_cmd(subcmd) - local cmd = "pkg " .. subcmd .. " -y" + local cmd = "env ASSUME_ALWAYS_YES=yes pkg " .. subcmd if os.getenv("NUAGE_RUN_TESTS") then print(cmd) return true @@ -556,6 +633,7 @@ local n = { dirname = dirname, mkdir_p = mkdir_p, sethostname = sethostname, + settimezone = settimezone, adduser = adduser, addgroup = addgroup, addsshkey = addsshkey, @@ -566,6 +644,7 @@ local n = { update_packages = update_packages, upgrade_packages = upgrade_packages, addsudo = addsudo, + adddoas = adddoas, addfile = addfile } diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit index 0fcdc7274db3..29340a3d91ea 100755 --- a/libexec/nuageinit/nuageinit +++ b/libexec/nuageinit/nuageinit @@ -3,6 +3,7 @@ -- SPDX-License-Identifier: BSD-2-Clause-FreeBSD -- -- Copyright(c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org> +-- Copyright(c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org> local nuage = require("nuage") local ucl = require("ucl") @@ -46,7 +47,15 @@ local function open_config(name) return openat("/etc/rc.conf.d", name) end -local function get_ifaces() +local function open_resolv_conf() + return openat("/etc", "resolv.conf") +end + +local function open_resolvconf_conf() + return openat("/etc", "resolvconf.conf") +end + +local function get_ifaces_by_mac() local parser = ucl.parser() -- grab ifaces local ns = io.popen("netstat -i --libxo json") @@ -77,6 +86,10 @@ local function sethostname(obj) end end +local function settimezone(obj) + nuage.settimezone(obj.timezone) +end + local function groups(obj) if obj.groups == nil then return end @@ -127,6 +140,9 @@ local function users(obj) if u.sudo then nuage.addsudo(u) end + if u.doas then + nuage.adddoas(u) + end else nuage.warn("invalid type : " .. type(u) .. " for users entry number " .. n) end @@ -171,6 +187,59 @@ local function ssh_authorized_keys(obj) end end +local function nameservers(interface, obj) + local resolvconf_conf_handler = open_resolvconf_conf() + + if obj.search then + local with_space = false + + resolvconf_conf_handler:write('search_domains="') + + for _, d in ipairs(obj.search) do + if with_space then + resolvconf_conf_handler:write(" " .. d) + else + resolvconf_conf_handler:write(d) + with_space = true + end + end + + resolvconf_conf_handler:write('"\n') + end + + if obj.addresses then + local with_space = false + + resolvconf_conf_handler:write('name_servers="') + + for _, a in ipairs(obj.addresses) do + if with_space then + resolvconf_conf_handler:write(" " .. a) + else + resolvconf_conf_handler:write(a) + with_space = true + end + end + + resolvconf_conf_handler:write('"\n') + end + + resolvconf_conf_handler:close() + + local resolv_conf = root .. "/etc/resolv.conf" + + resolv_conf_attr = lfs.attributes(resolv_conf) + + if resolv_conf_attr == nil then + resolv_conf_handler = open_resolv_conf() + resolv_conf_handler:close() + end + + if not os.execute("resolvconf -a " .. interface .. " < " .. resolv_conf) then + nuage.warn("Failed to execute resolvconf(8)") + end +end + local function install_packages(packages) if not nuage.pkg_bootstrap() then nuage.warn("Failed to bootstrap pkg, skip installing packages") @@ -187,6 +256,85 @@ local function install_packages(packages) end end +local function list_ifaces() + local proc = io.popen("ifconfig -l") + local raw_ifaces = proc:read("*a") + proc:close() + local ifaces = {} + for i in raw_ifaces:gmatch("[^%s]+") do + table.insert(ifaces, i) + end + return ifaces +end + +local function get_ifaces_by_driver() + local proc = io.popen("ifconfig -D") + local drivers = {} + local last_interface = nil + for line in proc:lines() do + local interface = line:match("^([%S]+): ") + + if interface then + last_interface = interface + end + + local driver = line:match("^[%s]+drivername: ([%S]+)$") + + if driver then + drivers[driver] = last_interface + end + end + proc:close() + + return drivers +end + +local function match_rules(rules) + -- To comply with the cloud-init specification, all rules must match and a table + -- with the matching interfaces must be returned. This changes the way we initially + -- thought about our implementation, since at first we only needed one interface, + -- but cloud-init performs actions on a group of matching interfaces. + local interfaces = {} + if rules.macaddress then + local ifaces = get_ifaces_by_mac() + local interface = ifaces[rules.macaddress] + if not interface then + nuage.warn("not interface matching by MAC address: " .. rules.macaddress) + return + end + interfaces[interface] = 1 + end + if rules.name then + local match = false + for _, i in pairs(list_ifaces()) do + if i:match(rules.name) then + match = true + interfaces[i] = 1 + end + end + if not match then + nuage.warn("not interface matching by name: " .. rules.name) + return + end + end + if rules.driver then + local match = false + local drivers = get_ifaces_by_driver() + for d in pairs(drivers) do + if d:match(rules.driver) then + match = true + interface = drivers[d] + interfaces[interface] = 1 + end + end + if not match then + nuage.warn("not interface matching by driver: " .. rules.driver) + return + end + end + return interfaces +end + local function write_files(files, defer) if not files then return @@ -210,41 +358,76 @@ end local function network_config(obj) if obj.network == nil then return end - local ifaces = get_ifaces() local network = open_config("network") local routing = open_config("routing") local ipv6 = {} - for _, v in pairs(obj.network.ethernets) do - if not v.match then - goto next + local set_defaultrouter = true + local set_defaultrouter6 = true + local set_nameservers = true + for i, v in pairs(obj.network.ethernets) do + local interfaces = {} + if v.match then + interfaces = match_rules(v.match) + + if next(interfaces) == nil then + goto next + end + else + interfaces[i] = 1 end - if not v.match.macaddress then - goto next + local extra_opts = "" + if v.wakeonlan then + extra_opts = extra_opts .. " wol" end - if not ifaces[v.match.macaddress] then - nuage.warn("not interface matching: " .. v.match.macaddress) - goto next + if v.mtu then + if type(v.mtu) == "number" then + mtu = tostring(v.mtu) + else + mtu = v.mtu + end + if mtu:match("%d") then + extra_opts = extra_opts .. " mtu " .. mtu + else + nuage.warn("MTU is not set because the specified value is invalid: " .. mtu) + end end - local interface = ifaces[v.match.macaddress] - if v.dhcp4 then - network:write("ifconfig_" .. interface .. '="DHCP"\n') - elseif v.addresses then - for _, a in pairs(v.addresses) do - if a:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)") then - network:write("ifconfig_" .. interface .. '="inet ' .. a .. '"\n') - else - network:write("ifconfig_" .. interface .. '_ipv6="inet6 ' .. a .. '"\n') - ipv6[#ipv6 + 1] = interface + for interface in pairs(interfaces) do + if v.match and v.match.macaddress and v["set-name"] then + local ifaces = get_ifaces_by_mac() + local matched = ifaces[v.match.macaddress] + if matched and matched == interface then + network:write("ifconfig_" .. interface .. '_name=' .. v["set-name"] .. '\n') + interface = v["set-name"] + end + end + if v.dhcp4 then + network:write("ifconfig_" .. interface .. '="DHCP"' .. extra_opts .. '\n') + elseif v.addresses then + for _, a in pairs(v.addresses) do + if a:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)") then + network:write("ifconfig_" .. interface .. '="inet ' .. a .. extra_opts .. '"\n') + else + network:write("ifconfig_" .. interface .. '_ipv6="inet6 ' .. a .. extra_opts .. '"\n') + ipv6[#ipv6 + 1] = interface + end + end + if set_nameservers and v.nameservers then + set_nameservers = false + nameservers(interface, v.nameservers) + end + if set_defaultrouter and v.gateway4 then + set_defaultrouter = false + routing:write('defaultrouter="' .. v.gateway4 .. '"\n') + end + if v.gateway6 then + if set_defaultrouter6 then + set_defaultrouter6 = false + routing:write('ipv6_defaultrouter="' .. v.gateway6 .. '"\n') + end + routing:write("ipv6_route_" .. interface .. '="' .. v.gateway6) + routing:write(" -prefixlen 128 -interface " .. interface .. '"\n') end end - end - if v.gateway4 then - routing:write('defaultrouter="' .. v.gateway4 .. '"\n') - end - if v.gateway6 then - routing:write('ipv6_defaultrouter="' .. v.gateway6 .. '"\n') - routing:write("ipv6_route_" .. interface .. '="' .. v.gateway6) - routing:write(" -prefixlen 128 -interface " .. interface .. '"\n') end ::next:: end @@ -316,7 +499,7 @@ local function config2_network(p) end local obj = parser:get_object() - local ifaces = get_ifaces() + local ifaces = get_ifaces_by_mac() if not ifaces then nuage.warn("no network interfaces found") return @@ -403,6 +586,26 @@ local function config2_network(p) routing:close() end +local function parse_network_config() + local nc_file = ni_path .. "/network-config" + local nc_file_attr = lfs.attributes(nc_file) + if nc_file_attr == nil then + return + end + local f, err = io.open(nc_file) + if err then + nuage.err("error parsing nocloud network-config: " .. err) + end + local obj = yaml.load(f:read("*a")) + f:close() + if not obj then + nuage.err("error parsing nocloud network-config") + end + local netobj = {} + netobj["network"] = obj + return netobj +end + if citype == "config-2" then local parser = ucl.parser() local res, err = parser:parse_file(ni_path .. "/meta_data.json") @@ -468,6 +671,7 @@ f:close() if line == "#cloud-config" then local pre_network_calls = { sethostname, + settimezone, groups, create_default_user, ssh_keys, @@ -498,7 +702,16 @@ if line == "#cloud-config" then end for i = 1, #calls_table do - calls_table[i](obj) + if citype == "nocloud" and calls_table[i] == network_config then + netobj = parse_network_config() + if netobj == nil then + network_config(obj) + else + network_config(netobj) + end + else + calls_table[i](obj) + end end elseif line:sub(1, 2) == "#!" then -- delay for execution at rc.local time -- diff --git a/libexec/nuageinit/nuageinit.7 b/libexec/nuageinit/nuageinit.7 index 327ce160e151..b527c984970c 100644 --- a/libexec/nuageinit/nuageinit.7 +++ b/libexec/nuageinit/nuageinit.7 @@ -1,6 +1,7 @@ .\" SPDX-License-Identifier: BSD-2-Clause .\" .\" Copyright (c) 2025 Baptiste Daroussin <bapt@FreeBSD.org> +.\" Copyright (c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org> .\" .Dd June 26, 2025 .Dt NUAGEINIT 7 @@ -143,6 +144,11 @@ Specify a fully qualified domain name for the instance. Specify the hostname of the instance if .Qq Ic fqdn is not set. +.It Ic timezone +Sets the system timezone based on the value provided. +.Pp +See also +.Xr tzfile 3 Ns . .It Ic groups An array of strings or objects to be created: .Bl -bullet @@ -176,6 +182,96 @@ boolean which determines the value of the configuration in .Pa /etc/ssh/sshd_config .It Ic network +Network configuration parameters. +.Pp +Specifying the following parameters from a file named +.Pa network-config +takes precedence over their specification from the +.Ic network +parameter of +.Pa user-data Ns . +.Bl -tag -width "ethernets" +.It Ic ethernets +Mapping representing a generic configuration for existing network interfaces. +.Pp +Each key is an interface name that is only used when no +.Sy match +rule is specified. +If +.Sy match +rules are specified, an arbitrary name can be used +.Po e.g.: id0 Pc Ns . +.Bl -tag -width "nameservers" +.It Ic match +This selects a subset of available physical devices by various hardware properties. +The following configuration will then apply to all matching devices, as soon as +they appear. +All specified properties must match. +The following properties for +creating matches are supported: +.Bl -tag -width "macaddress" +.It Ic macaddress +.No Device's MAC address in the form Sy xx:xx:xx:xx:xx:xx Ns . +Letters should be lowercase. +.It Ic name +Current interface name. +Lua pattern-matching expressions are supported. +.It Ic driver +Interface driver name and unit number of the interface. +Lua pattern-natching expressions +are supported. +.El +.It Ic set-name +When matching on unique properties such as MAC, match rules can be written so that they +match only one device. +Then this property can be used to give that device a more +specific/desirable/nicer name than the default. +.Pp +While multiple properties can be used in a match, +.Sy macaddress +is required for nuageinit to perform the rename. +.It Ic mtu +The MTU key represents a device's Maximum Transmission Unit, the largest size packet +or frame. +.It Ic wakeonlan +Enable wake on LAN. +Off by default. +.It Ic dhcp4 +Configure the interface to use DHCP. +.Pp +This takes precedence over +.Sy addresses +when both are specified. +.It Ic addresses +List of strings representing IPv4 or IPv6 addresses. +.It Ic gateway4 +Set default gateway for IPv4, for manual address configuration. +This requires setting +.Sy addresses +too. +.Pp +Since only one default router can be configured at a time, this parameter is applied +when processing the first entry, and any others are silently ignored. +.It Ic gateway6 +Set default gateway for IPv6, for manual address configuration. +This requires setting +.Sy addresses +too. +.Pp +Since only one default router can be configured at a time, this parameter is applied +when processing the first entry, and any others are silently ignored. +.It Ic nameservers +Set DNS servers and search domains, for manual address configuration. +.Pp +There are two supported fields: +.Bl -tag -width "addresses" +.It Ic search +Search list for host-name lookup. +.It Ic addresses +List of IPv4 or IPv6 name server addresses that the resolver should query. +.El +.El +.El .It Ic runcmd An array of commands to be run at the end of the boot process .It Ic packages @@ -186,7 +282,7 @@ Update the remote package metadata. Upgrade the packages installed to their latest version. .It Ic users Specify a list of users to be created: -.Bl -tag -width "plain_text_passwd" +.Bl -tag -width "ssh_authorized_keys" .It Ic name Name of the user. .It Ic gecos @@ -201,18 +297,25 @@ The list of other groups the user should belong to. A boolean which determines if the home directory should be created or not. .It Ic shell The shell that should be used for the user. +.It Ic ssh_authorized_keys +List of SSH keys for the user. .It Ic passwd The encrypted password for the user. .It Ic plain_text_passwd The password in plain text for the user. Ignored if an encrypted password is already provided. -.It Ic groups -The list of other groups the user should belong to. .It Ic locked Boolean to determine if the user account should be locked. .It Ic sudo -A string or an array of strings which which should be appended to -.Pa /usr/local/etc/sudoers.d/90-nuageinit-users +A string or an array of strings which should be appended to +.Pa ${LOCALBASE}/etc/sudoers.d/90-nuageinit-users +.It Ic doas +A string or an array of strings which should be appended to +.Pa ${LOCALBASE}/etc/doas.conf +.Pp +Instead of hardcoding the username, you can use +.Sy %u Ns , +which will be replaced by the current username. .El .Pp A special case exist: if the entry is a simple string with the value @@ -251,7 +354,7 @@ It accepts the following keys for each objects: The content to be written to the file. If this key is not existing then an empty file will be created. .It Ic encoding -Specifiy the encoding used for content. +Specify the encoding used for content. If not specified, then plain text is considered. Only .Ar b64 @@ -287,7 +390,7 @@ users: - name: user gecos: Foo B. Bar sudo: ALL=(ALL) NOPASSWD:ALL - ssh-authorized-keys: + ssh_authorized_keys: - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAr... packages: - neovim @@ -303,6 +406,12 @@ ssh_keys: ... -----END OPENSSH PRIVATE KEY----- ed25519_public: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+MH4E8KO32N5CXRvXVqvyZVl0+6ue4DobdhU0FqFd+ +network: + ethernets: + vtnet0: + addresses: + - 192.168.8.2/24 + gateway4: 192.168.8.1 .Ed .Sh SEE ALSO .Xr kenv 2 , diff --git a/libexec/nuageinit/tests/Makefile b/libexec/nuageinit/tests/Makefile index c69bc28a4c86..dc8997717b59 100644 --- a/libexec/nuageinit/tests/Makefile +++ b/libexec/nuageinit/tests/Makefile @@ -15,6 +15,7 @@ ${PACKAGE}FILES+= adduser_passwd.lua ${PACKAGE}FILES+= dirname.lua ${PACKAGE}FILES+= err.lua ${PACKAGE}FILES+= sethostname.lua +${PACKAGE}FILES+= settimezone.lua ${PACKAGE}FILES+= warn.lua ${PACKAGE}FILES+= addfile.lua diff --git a/libexec/nuageinit/tests/nuage.sh b/libexec/nuageinit/tests/nuage.sh index 56651c8c5bb7..57d83b62928a 100644 --- a/libexec/nuageinit/tests/nuage.sh +++ b/libexec/nuageinit/tests/nuage.sh @@ -1,5 +1,6 @@ #- # Copyright (c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org> +# Copyright (c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org> # # SPDX-License-Identifier: BSD-2-Clause # @@ -7,12 +8,21 @@ export NUAGE_FAKE_ROOTDIR="$PWD" atf_test_case sethostname +atf_test_case settimezone atf_test_case addsshkey atf_test_case adduser atf_test_case adduser_passwd atf_test_case addgroup atf_test_case addfile +settimezone_body() +{ + atf_check /usr/libexec/flua $(atf_get_srcdir)/settimezone.lua + if [ ! -f etc/localtime ]; then + atf_fail "localtime not written" + fi +} + sethostname_body() { atf_check /usr/libexec/flua $(atf_get_srcdir)/sethostname.lua diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh index 849f1c258b62..2b7c5226c97a 100644 --- a/libexec/nuageinit/tests/nuageinit.sh +++ b/libexec/nuageinit/tests/nuageinit.sh @@ -1,5 +1,6 @@ #- # Copyright (c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org> +# Copyright (c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org> # # SPDX-License-Identifier: BSD-2-Clause # @@ -119,12 +120,16 @@ users: gecos: Foo B. Bar primary_group: foobar sudo: ALL=(ALL) NOPASSWD:ALL + doas: permit persist %u as root groups: users passwd: $6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/ - name: bla sudo: - "ALL=(ALL) NOPASSWD:/usr/sbin/pw" - "ALL=(ALL) ALL" + doas: + - "deny %u as foobar" + - "permit persist %u as root cmd whoami" EOF atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud atf_check /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet @@ -147,7 +152,13 @@ EOF sed -i "" "s/freebsd:.*:1001/freebsd:freebsd:1001/" "${PWD}"/etc/master.passwd atf_check -o file:expectedpasswd cat "${PWD}"/etc/master.passwd atf_check -o file:expectedgroup cat "${PWD}"/etc/group - atf_check -o inline:"foobar ALL=(ALL) NOPASSWD:ALL\nbla ALL=(ALL) NOPASSWD:/usr/sbin/pw\nbla ALL=(ALL) ALL\n" cat ${PWD}/usr/local/etc/sudoers.d/90-nuageinit-users + localbase=`sysctl -ni user.localbase 2> /dev/null` + if [ -z "${localbase}" ]; then + # fallback + localbase="/usr/local" + fi + 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" + 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" } nocloud_network_head() @@ -815,7 +826,7 @@ config2_userdata_update_packages_body() package_update: true EOF chmod 755 "${PWD}"/media/nuageinit/user_data - atf_check -o inline:"pkg update -y\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet + atf_check -o inline:"env ASSUME_ALWAYS_YES=yes pkg update\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet } config2_userdata_upgrade_packages_body() @@ -829,7 +840,7 @@ config2_userdata_upgrade_packages_body() package_upgrade: true EOF chmod 755 "${PWD}"/media/nuageinit/user_data - atf_check -o inline:"pkg upgrade -y\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet + atf_check -o inline:"env ASSUME_ALWAYS_YES=yes pkg upgrade\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit postnet } config2_userdata_shebang_body() diff --git a/libexec/nuageinit/tests/settimezone.lua b/libexec/nuageinit/tests/settimezone.lua new file mode 100644 index 000000000000..a8cacf09f4e7 --- /dev/null +++ b/libexec/nuageinit/tests/settimezone.lua @@ -0,0 +1,5 @@ +#!/usr/libexec/flua + +local n = require("nuage") + +n.settimezone("UTC") diff --git a/libexec/nuageinit/tests/utils.sh b/libexec/nuageinit/tests/utils.sh index 26f117d81d60..76cd7e045473 100644 --- a/libexec/nuageinit/tests/utils.sh +++ b/libexec/nuageinit/tests/utils.sh @@ -1,5 +1,6 @@ #- # Copyright (c) 2022 Baptiste Daroussin <bapt@FreeBSD.org> +# Copyright (c) 2025 Jesús Daniel Colmenares Oviedo <dtxdf@FreeBSD.org> # # SPDX-License-Identifier: BSD-2-Clause # |