summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2019-03-06 20:23:35 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2019-03-06 20:23:35 +0000
commit7c07af289b77ce9ae2e20c6f2638a54e63f016ef (patch)
tree3e455655768905d50379e71e8c818f883b38219f
parent43f5850767f2412c63a5e75d47598e5d0479fd25 (diff)
downloadvyos-cloud-init-7c07af289b77ce9ae2e20c6f2638a54e63f016ef.tar.gz
vyos-cloud-init-7c07af289b77ce9ae2e20c6f2638a54e63f016ef.zip
Support locking user with usermod if passwd is not available.
In some cases, the 'passwd' command might not be available, but 'usermod' might be. In debian systems both are provided by the 'passwd' package. In Redhat/Centos passwd comes from 'passwd' package while 'usermod' comes from `shadow-utils` This should just support either one with no real cost other than the check.
-rw-r--r--cloudinit/distros/__init__.py13
-rw-r--r--tests/unittests/test_distros/test_create_users.py28
2 files changed, 37 insertions, 4 deletions
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index ef618c28..20c994dc 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -577,11 +577,16 @@ class Distro(object):
"""
Lock the password of a user, i.e., disable password logins
"""
+ # passwd must use short '-l' due to SLES11 lacking long form '--lock'
+ lock_tools = (['passwd', '-l', name], ['usermod', '--lock', name])
try:
- # Need to use the short option name '-l' instead of '--lock'
- # (which would be more descriptive) since SLES 11 doesn't know
- # about long names.
- util.subp(['passwd', '-l', name])
+ cmd = next(l for l in lock_tools if util.which(l[0]))
+ except StopIteration:
+ raise RuntimeError((
+ "Unable to lock user account '%s'. No tools available. "
+ " Tried: %s.") % (name, [c[0] for c in lock_tools]))
+ try:
+ util.subp(cmd)
except Exception as e:
util.logexc(LOG, 'Failed to disable password for user %s', name)
raise e
diff --git a/tests/unittests/test_distros/test_create_users.py b/tests/unittests/test_distros/test_create_users.py
index c3f258d5..40624952 100644
--- a/tests/unittests/test_distros/test_create_users.py
+++ b/tests/unittests/test_distros/test_create_users.py
@@ -240,4 +240,32 @@ class TestCreateUser(CiTestCase):
[mock.call(set(['auth1']), user), # not disabled
mock.call(set(['key1']), 'foouser', options=disable_prefix)])
+ @mock.patch("cloudinit.distros.util.which")
+ def test_lock_with_usermod_if_no_passwd(self, m_which, m_subp,
+ m_is_snappy):
+ """Lock uses usermod --lock if no 'passwd' cmd available."""
+ m_which.side_effect = lambda m: m in ('usermod',)
+ self.dist.lock_passwd("bob")
+ self.assertEqual(
+ [mock.call(['usermod', '--lock', 'bob'])],
+ m_subp.call_args_list)
+
+ @mock.patch("cloudinit.distros.util.which")
+ def test_lock_with_passwd_if_available(self, m_which, m_subp,
+ m_is_snappy):
+ """Lock with only passwd will use passwd."""
+ m_which.side_effect = lambda m: m in ('passwd',)
+ self.dist.lock_passwd("bob")
+ self.assertEqual(
+ [mock.call(['passwd', '-l', 'bob'])],
+ m_subp.call_args_list)
+
+ @mock.patch("cloudinit.distros.util.which")
+ def test_lock_raises_runtime_if_no_commands(self, m_which, m_subp,
+ m_is_snappy):
+ """Lock with no commands available raises RuntimeError."""
+ m_which.return_value = None
+ with self.assertRaises(RuntimeError):
+ self.dist.lock_passwd("bob")
+
# vi: ts=4 expandtab