Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154727453
D50021.id154532.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D50021.id154532.diff
View Options
diff --git a/libexec/nuageinit/nuage.lua b/libexec/nuageinit/nuage.lua
--- a/libexec/nuageinit/nuage.lua
+++ b/libexec/nuageinit/nuage.lua
@@ -1,7 +1,7 @@
---
-- SPDX-License-Identifier: BSD-2-Clause
--
--- Copyright(c) 2022 Baptiste Daroussin <bapt@FreeBSD.org>
+-- Copyright(c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org>
local unistd = require("posix.unistd")
local sys_stat = require("posix.sys.stat")
@@ -261,6 +261,106 @@
os.rename(sshd_config .. ".nuageinit", sshd_config)
end
+local function exec_change_password(user, password, type, expire)
+ local root = os.getenv("NUAGE_FAKE_ROOTDIR")
+ local cmd = "pw "
+ if root then
+ cmd = cmd .. "-R " .. root .. " "
+ end
+ local postcmd = " -H 0"
+ local input = password
+ if type ~= nil and type == "text" then
+ postcmd = " -h 0"
+ else
+ if password == "RANDOM" then
+ input = nil
+ postcmd = " -w random"
+ end
+ end
+ cmd = cmd .. "usermod " .. user .. postcmd
+ if expire then
+ cmd = cmd .. " -p 1"
+ else
+ cmd = cmd .. " -p 0"
+ end
+ local f = io.popen(cmd .. " >/dev/null", "w")
+ if input then
+ f:write(input)
+ end
+ -- ignore stdout to avoid printing the password in case of random password
+ local r = f:close(cmd)
+ if not r then
+ warnmsg("fail to change user password ".. user)
+ warnmsg(cmd)
+ end
+end
+
+local function change_password_from_line(line, expire)
+ local user, password = line:match("%s*(%w+):(%S+)%s*")
+ local type = nil
+ if user and password then
+ if password == "R" then
+ password = "RANDOM"
+ end
+ if not password:match("^%$%d+%$%w+%$") then
+ if password ~= "RANDOM" then
+ type = "text"
+ end
+ end
+ exec_change_password(user, password, type, expire)
+ end
+end
+
+local function chpasswd(obj)
+ if type(obj) ~= "table" then
+ warnmsg("Invalid chpasswd entry, expecting an object")
+ return
+ end
+ local expire = false
+ if obj.expire ~= nil then
+ if type(obj.expire) == "boolean" then
+ expire = obj.expire
+ else
+ warnmsg("Invalid type for chpasswd.expire, expecting a boolean, got a ".. type(obj.expire))
+ end
+ end
+ if obj.users ~= nil then
+ if type(obj.users) ~= "table" then
+ warnmsg("Invalid type for chpasswd.users, expecting a list, got a ".. type(obj.users))
+ goto list
+ end
+ for _, u in ipairs(obj.users) do
+ if type(u) ~= "table" then
+ warnmsg("Invalid chpasswd.users entry, expecting an object, got a " .. type(u))
+ goto next
+ end
+ if not u.name then
+ warnmsg("Invalid entry for chpasswd.users: missing 'name'")
+ goto next
+ end
+ if not u.password then
+ warnmsg("Invalid entry for chpasswd.users: missing 'password'")
+ goto next
+ end
+ exec_change_password(u.name, u.password, u.type, expire)
+ ::next::
+ end
+ end
+ ::list::
+ if obj.list ~= nil then
+ warnmsg("chpasswd.list is deprecated consider using chpasswd.users")
+ if type(obj.list) == "string" then
+ for line in obj.list:gmatch("[^\n]+") do
+ change_password_from_line(line, expire)
+ end
+ elseif type(obj.list) == "table" then
+ for _, u in ipairs(obj.list) do
+ change_password_from_line(u, expire)
+ end
+ end
+ end
+end
+
local n = {
warn = warnmsg,
err = errmsg,
@@ -270,7 +370,8 @@
adduser = adduser,
addgroup = addgroup,
addsshkey = addsshkey,
- update_sshd_config = update_sshd_config
+ update_sshd_config = update_sshd_config,
+ chpasswd = chpasswd
}
return n
diff --git a/libexec/nuageinit/nuageinit b/libexec/nuageinit/nuageinit
--- a/libexec/nuageinit/nuageinit
+++ b/libexec/nuageinit/nuageinit
@@ -2,7 +2,7 @@
---
-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
--
--- Copyright(c) 2022 Baptiste Daroussin <bapt@FreeBSD.org>
+-- Copyright(c) 2022-2025 Baptiste Daroussin <bapt@FreeBSD.org>
local nuage = require("nuage")
local ucl = require("ucl")
@@ -359,6 +359,10 @@
end
nuage.update_sshd_config("PasswordAuthentication", value)
end
+ if obj.chpasswd ~= nil then
+ nuage.chpasswd(obj.chpasswd)
+ end
+
else
local res, err = os.execute(path .. "/" .. ud)
if not res then
diff --git a/libexec/nuageinit/tests/nuageinit.sh b/libexec/nuageinit/tests/nuageinit.sh
--- a/libexec/nuageinit/tests/nuageinit.sh
+++ b/libexec/nuageinit/tests/nuageinit.sh
@@ -20,6 +20,9 @@
atf_test_case config2_network_static_v4
atf_test_case config2_ssh_keys
atf_test_case nocloud_userdata_cloudconfig_ssh_pwauth
+atf_test_case nocloud_userdata_cloudconfig_chpasswd
+atf_test_case nocloud_userdata_cloudconfig_chpasswd_list_string
+atf_test_case nocloud_userdata_cloudconfig_chpasswd_list_list
args_body()
{
@@ -512,6 +515,175 @@
atf_check -o inline:"PasswordAuthentication no\n" cat etc/ssh/sshd_config
}
+nocloud_userdata_cloudconfig_chpasswd_head()
+{
+ atf_set "require.user" root
+}
+nocloud_userdata_cloudconfig_chpasswd_body()
+{
+ mkdir -p etc
+ cat > etc/master.passwd << EOF
+root:*:0:0::0:0:Charlie &:/root:/bin/sh
+sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
+user:*:1:0::0:0:Sys:/home/sys:/bin/sh
+EOF
+ pwd_mkdb -d etc "${PWD}"/etc/master.passwd
+ cat > etc/group << EOF
+wheel:*:0:root
+users:*:1:
+EOF
+ mkdir -p media/nuageinit
+ printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: true
+ users:
+ - { user: "sys", password: RANDOM }
+EOF
+
+ atf_check -o empty -e inline:"nuageinit: Invalid entry for chpasswd.users: missing 'name'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ # nothing modified
+ atf_check -o inline:"sys:*:1:0::0:0:Sys:/home/sys:/bin/sh\n" pw -R $(pwd) usershow sys
+
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: true
+ users:
+ - { name: "sys", pwd: RANDOM }
+EOF
+ atf_check -o empty -e inline:"nuageinit: Invalid entry for chpasswd.users: missing 'password'\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ # nothing modified
+ atf_check -o inline:"sys:*:1:0::0:0:Sys:/home/sys:/bin/sh\n" pw -R $(pwd) usershow sys
+
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: false
+ users:
+ - { name: "sys", password: RANDOM }
+EOF
+ # not empty because the password is printed to stdout
+ atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ atf_check -o match:'sys:\$.*:1:0::0:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
+
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: true
+ users:
+ - { name: "sys", password: RANDOM }
+EOF
+ # not empty because the password is printed to stdout
+ atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ atf_check -o match:'sys:\$.*:1:0::1:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
+
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: true
+ users:
+ - { name: "user", password: "$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/" }
+EOF
+ # not empty because the password is printed to stdout
+ atf_check -o empty -e empty /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ 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
+}
+
+
+nocloud_userdata_cloudconfig_chpasswd_list_string_head()
+{
+ atf_set "require.user" root
+}
+nocloud_userdata_cloudconfig_chpasswd_list_string_body()
+{
+ mkdir -p etc
+ cat > etc/master.passwd << EOF
+root:*:0:0::0:0:Charlie &:/root:/bin/sh
+sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
+user:*:1:0::0:0:Sys:/home/sys:/bin/sh
+EOF
+ pwd_mkdb -d etc "${PWD}"/etc/master.passwd
+ cat > etc/group << EOF
+wheel:*:0:root
+users:*:1:
+EOF
+ mkdir -p media/nuageinit
+ printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: true
+ list: |
+ sys:RANDOM
+EOF
+
+ atf_check -o empty -e inline:"nuageinit: chpasswd.list is deprecated consider using chpasswd.users\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ atf_check -o match:'sys:\$.*:1:0::1:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
+
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: false
+ list: |
+ sys:plop
+ user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
+ root:R
+EOF
+
+ atf_check -o empty -e ignore /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ atf_check -o match:'sys:\$.*:1:0::0:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
+ 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
+ atf_check -o match:'root:\$.*:0:0::0:0:Charlie &:/root:/bin/sh$' pw -R $(pwd) usershow root
+}
+
+nocloud_userdata_cloudconfig_chpasswd_list_list_head()
+{
+ atf_set "require.user" root
+}
+nocloud_userdata_cloudconfig_chpasswd_list_list_body()
+{
+ mkdir -p etc
+ cat > etc/master.passwd << EOF
+root:*:0:0::0:0:Charlie &:/root:/bin/sh
+sys:*:1:0::0:0:Sys:/home/sys:/bin/sh
+user:*:1:0::0:0:Sys:/home/sys:/bin/sh
+EOF
+ pwd_mkdb -d etc "${PWD}"/etc/master.passwd
+ cat > etc/group << EOF
+wheel:*:0:root
+users:*:1:
+EOF
+ mkdir -p media/nuageinit
+ printf "instance-id: iid-local01\n" > "${PWD}"/media/nuageinit/meta-data
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: true
+ list:
+ - sys:RANDOM
+EOF
+
+ atf_check -o empty -e inline:"nuageinit: chpasswd.list is deprecated consider using chpasswd.users\n" /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ atf_check -o match:'sys:\$.*:1:0::1:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
+
+ cat > media/nuageinit/user-data << 'EOF'
+#cloud-config
+chpasswd:
+ expire: false
+ list:
+ - sys:plop
+ - user:$6$j212wezy$7H/1LT4f9/N3wpgNunhsIqtMj62OKiS3nyNwuizouQc3u7MbYCarYeAHWYPYb2FT.lbioDm2RrkJPb9BZMN1O/
+ - root:R
+EOF
+
+ atf_check -o empty -e ignore /usr/libexec/nuageinit "${PWD}"/media/nuageinit nocloud
+ atf_check -o match:'sys:\$.*:1:0::0:0:Sys:/home/sys:/bin/sh$' pw -R $(pwd) usershow sys
+ 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
+ atf_check -o match:'root:\$.*:0:0::0:0:Charlie &:/root:/bin/sh$' pw -R $(pwd) usershow root
+}
+
atf_init_test_cases()
{
atf_add_test_case args
@@ -528,4 +700,7 @@
atf_add_test_case config2_network_static_v4
atf_add_test_case config2_ssh_keys
atf_add_test_case nocloud_userdata_cloudconfig_ssh_pwauth
+ atf_add_test_case nocloud_userdata_cloudconfig_chpasswd
+ atf_add_test_case nocloud_userdata_cloudconfig_chpasswd_list_string
+ atf_add_test_case nocloud_userdata_cloudconfig_chpasswd_list_list
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 30, 8:04 AM (11 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32297554
Default Alt Text
D50021.id154532.diff (10 KB)
Attached To
Mode
D50021: nuageinit: implement chpasswd
Attached
Detach File
Event Timeline
Log In to Comment