← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~goneri/cloud-init:freebsd_set_password into cloud-init:master

 

Gonéri Le Bouder has proposed merging ~goneri/cloud-init:freebsd_set_password into cloud-init:master.

Commit message:
set_passwords: support for FreeBSD

Add FreeBSD support to `cc_set_passwords`.
FreeBSD does not come with chpasswd binary, a chpasswd port[1] exists
but it's not the same tool than the one from Linux[2].

Finally, NetBSD and OpenBSD don't have the chpasswd binary at all, so
an abstraction layer will be needed.

This patch moves the Linux specific in the Distro class, this allow
anyone to override the default implementation. It also provides an
implementation for FreeBSD.

[1]: https://www.freshports.org/www/chpasswd/
[2]: https://github.com/shadow-maint/shadow/blob/master/src/chpasswd.c

Requested reviews:
  cloud-init commiters (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~goneri/cloud-init/+git/cloud-init/+merge/368507
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~goneri/cloud-init:freebsd_set_password into cloud-init:master.
diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py
index 4585e4d..90ea460 100755
--- a/cloudinit/config/cc_set_passwords.py
+++ b/cloudinit/config/cc_set_passwords.py
@@ -164,35 +164,32 @@ def handle(_name, cfg, cloud, log, args):
         for line in plist:
             u, p = line.split(':', 1)
             if prog.match(p) is not None and ":" not in p:
-                hashed_plist_in.append("%s:%s" % (u, p))
+                hashed_plist_in.append((u, p))
                 hashed_users.append(u)
             else:
                 if p == "R" or p == "RANDOM":
                     p = rand_user_password()
                     randlist.append("%s:%s" % (u, p))
-                plist_in.append("%s:%s" % (u, p))
+                plist_in.append((u, p))
                 users.append(u)
 
-        ch_in = '\n'.join(plist_in) + '\n'
         if users:
             try:
                 log.debug("Changing password for %s:", users)
-                util.subp(['chpasswd'], ch_in)
+                cloud.distro.user_passwords(plist_in, 'clear')
             except Exception as e:
                 errors.append(e)
                 util.logexc(
-                    log, "Failed to set passwords with chpasswd for %s", users)
+                    log, "Failed to set passwords for %s", users)
 
-        hashed_ch_in = '\n'.join(hashed_plist_in) + '\n'
         if hashed_users:
             try:
                 log.debug("Setting hashed password for %s:", hashed_users)
-                util.subp(['chpasswd', '-e'], hashed_ch_in)
+                cloud.distro.user_passwords(hashed_plist_in, 'hashed')
             except Exception as e:
                 errors.append(e)
                 util.logexc(
-                    log, "Failed to set hashed passwords with chpasswd for %s",
-                    hashed_users)
+                    log, "Failed to set hashed passwords for %s", hashed_users)
 
         if len(randlist):
             blurb = ("Set the following 'random' passwords\n",
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index 20c994d..dbeed7e 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -715,6 +715,18 @@ class Distro(object):
                 util.subp(['usermod', '-a', '-G', name, member])
                 LOG.info("Added user '%s' to group '%s'", member, name)
 
+    def user_passwords(self, entries, format):
+        ch_in = ""
+        for i in entries:
+            user, password = i
+            ch_in += "%s:%s\n" % (user, password)
+        if format == 'clear':
+            util.subp(['chpasswd'], ch_in)
+        elif format == 'hashed':
+            util.subp(['chpasswd', '-e'], ch_in)
+        else:
+            LOG.warning("user_passwords: unexpected format: %s", format)
+
 
 def _get_package_mirror_info(mirror_info, data_source=None,
                              mirror_filter=util.search_for_mirror):
diff --git a/cloudinit/distros/freebsd.py b/cloudinit/distros/freebsd.py
index ff22d56..aae5ce3 100644
--- a/cloudinit/distros/freebsd.py
+++ b/cloudinit/distros/freebsd.py
@@ -650,4 +650,12 @@ class Distro(distros.Distro):
         self._runner.run("update-sources", self.package_command,
                          ["update"], freq=PER_INSTANCE)
 
+    def user_passwords(self, entries, format):
+        for i in entries:
+            user, password = i
+            if format == 'clear':
+                util.subp(['pw', 'mod', 'user', user, '-h', '0'], password)
+            else:
+                util.subp(['chpass', '-p', password, user])
+
 # vi: ts=4 expandtab
diff --git a/tools/build-on-freebsd b/tools/build-on-freebsd
index dc3b974..5c62bd4 100755
--- a/tools/build-on-freebsd
+++ b/tools/build-on-freebsd
@@ -9,7 +9,6 @@ fail() { echo "FAILED:" "$@" 1>&2; exit 1; }
 depschecked=/tmp/c-i.dependencieschecked
 pkgs="
    bash
-   chpasswd
    dmidecode
    e2fsprogs
    py27-Jinja2