summaryrefslogtreecommitdiff
path: root/cloudinit/config/cc_set_passwords.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/config/cc_set_passwords.py')
-rwxr-xr-xcloudinit/config/cc_set_passwords.py86
1 files changed, 56 insertions, 30 deletions
diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py
index 5ef97376..4943d545 100755
--- a/cloudinit/config/cc_set_passwords.py
+++ b/cloudinit/config/cc_set_passwords.py
@@ -9,27 +9,40 @@
"""
Set Passwords
-------------
-**Summary:** Set user passwords
-
-Set system passwords and enable or disable ssh password authentication.
-The ``chpasswd`` config key accepts a dictionary containing a single one of two
-keys, either ``expire`` or ``list``. If ``expire`` is specified and is set to
-``false``, then the ``password`` global config key is used as the password for
-all user accounts. If the ``expire`` key is specified and is set to ``true``
-then user passwords will be expired, preventing the default system passwords
-from being used.
-
-If the ``list`` key is provided, a list of
-``username:password`` pairs can be specified. The usernames specified
-must already exist on the system, or have been created using the
-``cc_users_groups`` module. A password can be randomly generated using
-``username:RANDOM`` or ``username:R``. A hashed password can be specified
-using ``username:$6$salt$hash``. Password ssh authentication can be
-enabled, disabled, or left to system defaults using ``ssh_pwauth``.
+**Summary:** Set user passwords and enable/disable SSH password authentication
+
+This module consumes three top-level config keys: ``ssh_pwauth``, ``chpasswd``
+and ``password``.
+
+The ``ssh_pwauth`` config key determines whether or not sshd will be configured
+to accept password authentication. True values will enable password auth,
+false values will disable password auth, and the literal string ``unchanged``
+will leave it unchanged. Setting no value will also leave the current setting
+on-disk unchanged.
+
+The ``chpasswd`` config key accepts a dictionary containing either or both of
+``expire`` and ``list``.
+
+If the ``list`` key is provided, it should contain a list of
+``username:password`` pairs. This can be either a YAML list (of strings), or a
+multi-line string with one pair per line. Each user will have the
+corresponding password set. A password can be randomly generated by specifying
+``RANDOM`` or ``R`` as a user's password. A hashed password, created by a tool
+like ``mkpasswd``, can be specified; a regex
+(``r'\\$(1|2a|2y|5|6)(\\$.+){2}'``) is used to determine if a password value
+should be treated as a hash.
.. note::
- if using ``expire: true`` then a ssh authkey should be specified or it may
- not be possible to login to the system
+ The users specified must already exist on the system. Users will have been
+ created by the ``cc_users_groups`` module at this point.
+
+By default, all users on the system will have their passwords expired (meaning
+that they will have to be reset the next time the user logs in). To disable
+this behaviour, set ``expire`` under ``chpasswd`` to a false value.
+
+If a ``list`` of user/password pairs is not specified under ``chpasswd``, then
+the value of the ``password`` config key will be used to set the default user's
+password.
**Internal name:** ``cc_set_passwords``
@@ -99,7 +112,7 @@ def handle_ssh_pwauth(pw_auth, service_cmd=None, service_name="ssh"):
elif util.is_false(pw_auth):
cfg_val = 'no'
else:
- bmsg = "Leaving ssh config '%s' unchanged." % cfg_name
+ bmsg = "Leaving SSH config '%s' unchanged." % cfg_name
if pw_auth is None or pw_auth.lower() == 'unchanged':
LOG.debug("%s ssh_pwauth=%s", bmsg, pw_auth)
else:
@@ -108,7 +121,7 @@ def handle_ssh_pwauth(pw_auth, service_cmd=None, service_name="ssh"):
updated = update_ssh_config({cfg_name: cfg_val})
if not updated:
- LOG.debug("No need to restart ssh service, %s not updated.", cfg_name)
+ LOG.debug("No need to restart SSH service, %s not updated.", cfg_name)
return
if 'systemctl' in service_cmd:
@@ -116,7 +129,7 @@ def handle_ssh_pwauth(pw_auth, service_cmd=None, service_name="ssh"):
else:
cmd = list(service_cmd) + [service_name, "restart"]
util.subp(cmd)
- LOG.debug("Restarted the ssh daemon.")
+ LOG.debug("Restarted the SSH daemon.")
def handle(_name, cfg, cloud, log, args):
@@ -151,7 +164,7 @@ def handle(_name, cfg, cloud, log, args):
if user:
plist = ["%s:%s" % (user, password)]
else:
- log.warn("No default or defined user to change password for.")
+ log.warning("No default or defined user to change password for.")
errors = []
if plist:
@@ -160,24 +173,27 @@ def handle(_name, cfg, cloud, log, args):
hashed_users = []
randlist = []
users = []
- prog = re.compile(r'\$[1,2a,2y,5,6](\$.+){2}')
+ # N.B. This regex is included in the documentation (i.e. the module
+ # docstring), so any changes to it should be reflected there.
+ prog = re.compile(r'\$(1|2a|2y|5|6)(\$.+){2}')
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(line)
hashed_users.append(u)
else:
+ # in this else branch, we potentially change the password
+ # hence, a deviation from .append(line)
if p == "R" or p == "RANDOM":
p = rand_user_password()
randlist.append("%s:%s" % (u, p))
plist_in.append("%s:%s" % (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)
+ chpasswd(cloud.distro, ch_in)
except Exception as e:
errors.append(e)
util.logexc(
@@ -187,7 +203,7 @@ def handle(_name, cfg, cloud, log, args):
if hashed_users:
try:
log.debug("Setting hashed password for %s:", hashed_users)
- util.subp(['chpasswd', '-e'], hashed_ch_in)
+ chpasswd(cloud.distro, hashed_ch_in, hashed=True)
except Exception as e:
errors.append(e)
util.logexc(
@@ -203,7 +219,7 @@ def handle(_name, cfg, cloud, log, args):
expired_users = []
for u in users:
try:
- util.subp(['passwd', '--expire', u])
+ cloud.distro.expire_passwd(u)
expired_users.append(u)
except Exception as e:
errors.append(e)
@@ -220,7 +236,17 @@ def handle(_name, cfg, cloud, log, args):
raise errors[-1]
-def rand_user_password(pwlen=9):
+def rand_user_password(pwlen=20):
return util.rand_str(pwlen, select_from=PW_SET)
+
+def chpasswd(distro, plist_in, hashed=False):
+ if util.is_FreeBSD():
+ for pentry in plist_in.splitlines():
+ u, p = pentry.split(":")
+ distro.set_passwd(u, p, hashed=hashed)
+ else:
+ cmd = ['chpasswd'] + (['-e'] if hashed else [])
+ util.subp(cmd, plist_in)
+
# vi: ts=4 expandtab