diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua index 81fb40c0d8eb..10451dc0bdc4 100644 --- a/libexec/nuageinit/nuage.lua +++ b/libexec/nuageinit/nuage.lua @@ -1,226 +1,228 @@ -- SPDX-License-Identifier: BSD-2-Clause -- -- Copyright(c) 2022 Baptiste Daroussin local pu = require("posix.unistd") local function warnmsg(str) io.stderr:write(str.."\n") end local function errmsg(str) io.stderr:write(str.."\n") os.exit(1) end local function dirname(oldpath) if not oldpath then return nil end local path = oldpath:gsub("[^/]+/*$", "") if path == "" then return nil end return path end local function mkdir_p(path) if lfs.attributes(path, "mode") ~= nil then return true end local r,err = mkdir_p(dirname(path)) if not r then return nil,err.." (creating "..path..")" end return lfs.mkdir(path) end local function sethostname(hostname) if hostname == nil then return end local root = os.getenv("NUAGE_FAKE_ROOTDIR") if not root then root = "" end local hostnamepath = root .. "/etc/rc.conf.d/hostname" mkdir_p(dirname(hostnamepath)) local f,err = io.open(hostnamepath, "w") if not f then warnmsg("Impossible to open "..hostnamepath .. ":" ..err) return end f:write("hostname=\""..hostname.."\"\n") f:close() end local function splitlist(list) local ret = {} if type(list) == "string" then for str in list:gmatch("([^, ]+)") do ret[#ret + 1] = str end elseif type(list) == "table" then ret = list else warnmsg("Invalid type ".. type(list) ..", expecting table or string") end return ret end local function adduser(pwd) if (type(pwd) ~= "table") then warnmsg("Argument should be a table") return nil end local root = os.getenv("NUAGE_FAKE_ROOTDIR") local cmd = "pw " if root then cmd = cmd .. "-R " .. root .. " " end local f = io.popen(cmd .. " usershow " ..pwd.name .. " -7 2>/dev/null") local pwdstr = f:read("*a") f:close() if pwdstr:len() ~= 0 then return pwdstr:match("%a+:.+:%d+:%d+:.*:(.*):.*") end if not pwd.gecos then pwd.gecos = pwd.name .. " User" end if not pwd.home then pwd.home = "/home/" .. pwd.name end local extraargs="" if pwd.groups then local list = splitlist(pwd.groups) extraargs = " -G ".. table.concat(list, ',') end -- pw will automatically create a group named after the username -- do not add a -g option in this case if pwd.primary_group and pwd.primary_group ~= pwd.name then extraargs = extraargs .. " -g " .. pwd.primary_group end if not pwd.no_create_home then extraargs = extraargs .. " -m " end if not pwd.shell then pwd.shell = "/bin/sh" end local precmd = "" local postcmd = "" if pwd.passwd then precmd = "echo "..pwd.passwd .. "| " postcmd = " -H 0 " elseif pwd.plain_text_passwd then precmd = "echo "..pwd.plain_text_passwd .. "| " postcmd = " -h 0 " end cmd = precmd .. "pw " if root then cmd = cmd .. "-R " .. root .. " " end cmd = cmd .. "useradd -n ".. pwd.name .. " -M 0755 -w none " cmd = cmd .. extraargs .. " -c '".. pwd.gecos cmd = cmd .. "' -d '" .. pwd.home .. "' -s "..pwd.shell .. postcmd local r = os.execute(cmd) if not r then warnmsg("nuageinit: fail to add user "..pwd.name); warnmsg(cmd) return nil end if pwd.locked then cmd = "pw " if root then cmd = cmd .. "-R " .. root .. " " end cmd = cmd .. "lock " .. pwd.name os.execute(cmd) end return pwd.home end local function addgroup(grp) if (type(grp) ~= "table") then warnmsg("Argument should be a table") return false end local root = os.getenv("NUAGE_FAKE_ROOTDIR") local cmd = "pw " if root then cmd = cmd .. "-R " .. root .. " " end local f = io.popen(cmd .. " groupshow " ..grp.name .. " 2>/dev/null") local grpstr = f:read("*a") f:close() if grpstr:len() ~= 0 then return true end local extraargs = "" if grp.members then local list = splitlist(grp.members) extraargs = " -M " .. table.concat(list, ',') end cmd = "pw " if root then cmd = cmd .. "-R " .. root .. " " end cmd = cmd .. "groupadd -n ".. grp.name .. extraargs local r = os.execute(cmd) if not r then warnmsg("nuageinit: fail to add group ".. grp.name); warnmsg(cmd) return false end return true end local function addsshkey(homedir, key) local chownak = false local chowndotssh = false local root = os.getenv("NUAGE_FAKE_ROOTDIR") if root then homedir = root .. "/" .. homedir end local ak_path = homedir .. "/.ssh/authorized_keys" local dotssh_path = homedir .. "/.ssh" local dirattrs = lfs.attributes(ak_path) if dirattrs == nil then chownak = true dirattrs = lfs.attributes(dotssh_path) if dirattrs == nil then if not lfs.mkdir(dotssh_path) then warnmsg("nuageinit: impossible to create ".. dotssh_path) return end chowndotssh = true dirattrs = lfs.attributes(homedir) end end local f = io.open(ak_path, "a") if not f then warnmsg("nuageinit: impossible to open "..ak_path) return end f:write(key .. "\n") f:close() if chownak then + os.execute("chmod 0600 " .. ak_path) pu.chown(ak_path, dirattrs.uid, dirattrs.gid) end if chowndotssh then + os.execute("chmod 0700 " .. dotssh_path) pu.chown(dotssh_path, dirattrs.uid, dirattrs.gid) end end local n = { warn = warnmsg, err = errmsg, sethostname = sethostname, adduser = adduser, addgroup = addgroup, addsshkey = addsshkey, dirname = dirname, mkdir_p = mkdir_p, } return n diff --git a/libexec/nuageinit/tests/nuage.sh b/libexec/nuageinit/tests/nuage.sh index bbf306eae51f..531c171a3271 100644 --- a/libexec/nuageinit/tests/nuage.sh +++ b/libexec/nuageinit/tests/nuage.sh @@ -1,52 +1,54 @@ atf_test_case sethostname atf_test_case addsshkey atf_test_case adduser atf_test_case addgroup sethostname_body() { export NUAGE_FAKE_ROOTDIR="$(pwd)" atf_check /usr/libexec/flua $(atf_get_srcdir)/sethostname.lua if [ ! -f etc/rc.conf.d/hostname ]; then atf_fail "hostname not written" fi atf_check -o inline:"hostname=\"myhostname\"\n" cat etc/rc.conf.d/hostname } addsshkey_body() { atf_check /usr/libexec/flua $(atf_get_srcdir)/addsshkey.lua if [ ! -f .ssh/authorized_keys ]; then atf_fail "ssh key not added" fi + atf_check -o inline:".ssh: 040700 [drwx------ ] -> 040700 [drwx------ ]\n" chmod -vv 0700 .ssh + atf_check -o inline:".ssh/authorized_keys: 0100600 [-rw------- ] -> 0100600 [-rw------- ]\n" chmod -vv 0600 .ssh/authorized_keys atf_check -o inline:"mykey\n" cat .ssh/authorized_keys atf_check /usr/libexec/flua $(atf_get_srcdir)/addsshkey.lua atf_check -o inline:"mykey\nmykey\n" cat .ssh/authorized_keys } adduser_body() { export NUAGE_FAKE_ROOTDIR="$(pwd)" if [ $(id -u) -ne 0 ]; then atf_skip "root required" fi mkdir etc printf "root:*:0:0::0:0:Charlie &:/root:/bin/csh\n" > etc/master.passwd pwd_mkdb -d etc etc/master.passwd printf "wheel:*:0:root\n" > etc/group atf_check -e inline:"Argument should be a table\nArgument should be a table\n" /usr/libexec/flua $(atf_get_srcdir)/adduser.lua test -d home/impossible_username || atf_fail "home not created" atf_check -o inline:"impossible_username::1001:1001::0:0:impossible_username User:/home/impossible_username:/bin/sh\n" grep impossible_username etc/master.passwd } addgroup_body() { export NUAGE_FAKE_ROOTDIR="$(pwd)" mkdir etc printf "wheel:*:0:root\n" > etc/group atf_check -e inline:"Argument should be a table\nArgument should be a table\n" /usr/libexec/flua $(atf_get_srcdir)/addgroup.lua atf_check -o inline:"impossible_groupname:*:1001:\n" grep impossible_groupname etc/group } atf_init_test_cases() { atf_add_test_case sethostname atf_add_test_case addsshkey atf_add_test_case adduser atf_add_test_case addgroup }