From c947b96e54635fc1015fc575fc37b67c7c8f696e Mon Sep 17 00:00:00 2001 From: Jeffrey 'jf' Lim Date: Wed, 23 Mar 2022 19:10:03 +0800 Subject: [PATCH 1/5] raise ValueError when "no_create_home" or "system" is set and ssh_authorized_keys is also provided --- cloudinit/config/cc_users_groups.py | 9 +++++++++ doc/examples/cloud-config-user-groups.txt | 2 ++ 2 files changed, 11 insertions(+) diff --git a/cloudinit/config/cc_users_groups.py b/cloudinit/config/cc_users_groups.py index d3c945e6ca2..3b73d3c550e 100644 --- a/cloudinit/config/cc_users_groups.py +++ b/cloudinit/config/cc_users_groups.py @@ -186,6 +186,15 @@ def handle(name, cfg, cloud, _log, _args): else: config["ssh_redirect_user"] = default_user config["cloud_public_ssh_keys"] = cloud_keys + + if ( + config.get("no_create_home") or config.get("system") + ) and config.get("ssh_authorized_keys"): + raise ValueError( + "Not creating user %s. ssh_authorized_keys cannot be" + " provided with no_create_home: true or system: true" % user + ) + cloud.distro.create_user(user, **config) diff --git a/doc/examples/cloud-config-user-groups.txt b/doc/examples/cloud-config-user-groups.txt index 987d9508231..a66b0d75b5f 100644 --- a/doc/examples/cloud-config-user-groups.txt +++ b/doc/examples/cloud-config-user-groups.txt @@ -87,6 +87,8 @@ users: # no_log_init: When set to true, do not initialize lastlog and faillog database. # ssh_import_id: Optional. Import SSH ids # ssh_authorized_keys: Optional. [list] Add keys to user's authorized keys file +# An error will be raised if no_create_home or system is +# also set. # ssh_redirect_user: Optional. [bool] Set true to block ssh logins for cloud # ssh public keys and emit a message redirecting logins to # use instead. This option only disables cloud From 7f5b1c04e08eba11ef2176207ab9a0699127949f Mon Sep 17 00:00:00 2001 From: Jeffrey 'jf' Lim Date: Sat, 9 Apr 2022 14:09:58 +0800 Subject: [PATCH 2/5] Expand "no home" vs "create home" conflicts --- cloudinit/config/cc_users_groups.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/cloudinit/config/cc_users_groups.py b/cloudinit/config/cc_users_groups.py index 3b73d3c550e..75364949cfc 100644 --- a/cloudinit/config/cc_users_groups.py +++ b/cloudinit/config/cc_users_groups.py @@ -152,14 +152,31 @@ LOG = logging.getLogger(__name__) +# NO_HOME and NEED_HOME are mutually exclusive options +NO_HOME = ("no_create_home", "system") +NEED_HOME = ("ssh_authorized_keys", "ssh_import_id", "ssh_redirect_user") + def handle(name, cfg, cloud, _log, _args): (users, groups) = ug_util.normalize_users_groups(cfg, cloud.distro) (default_user, _user_config) = ug_util.extract_default(users) cloud_keys = cloud.get_public_ssh_keys() or [] + + no_homedir_options = ("no_create_home", "system") + for (name, members) in groups.items(): cloud.distro.create_group(name, members) + for (user, config) in users.items(): + + no_home = [key for key in NO_HOME if config.get(key)] + need_home = [key for key in NEED_HOME if config.get(key)] + if no_home and need_home: + raise ValueError( + f"Not creating user {user}. Key(s) {need_home.join(',')}" + f" cannot be provided with {no_home.join(',')}" + ) + ssh_redirect_user = config.pop("ssh_redirect_user", False) if ssh_redirect_user: if "ssh_authorized_keys" in config or "ssh_import_id" in config: @@ -187,14 +204,6 @@ def handle(name, cfg, cloud, _log, _args): config["ssh_redirect_user"] = default_user config["cloud_public_ssh_keys"] = cloud_keys - if ( - config.get("no_create_home") or config.get("system") - ) and config.get("ssh_authorized_keys"): - raise ValueError( - "Not creating user %s. ssh_authorized_keys cannot be" - " provided with no_create_home: true or system: true" % user - ) - cloud.distro.create_user(user, **config) From 3428f17418736281c42dccf7480cc5f71d574db5 Mon Sep 17 00:00:00 2001 From: Jeffrey 'jf' Lim Date: Sat, 9 Apr 2022 14:12:15 +0800 Subject: [PATCH 3/5] cloudinit/config/cc_ssh_authkey_fingerprints.py: log debug note about skipping printing when no home is created --- cloudinit/config/cc_ssh_authkey_fingerprints.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cloudinit/config/cc_ssh_authkey_fingerprints.py b/cloudinit/config/cc_ssh_authkey_fingerprints.py index c2d3b0d1c55..25f445c1304 100755 --- a/cloudinit/config/cc_ssh_authkey_fingerprints.py +++ b/cloudinit/config/cc_ssh_authkey_fingerprints.py @@ -123,6 +123,10 @@ def handle(name, cfg, cloud, log, _args): (users, _groups) = ug_util.normalize_users_groups(cfg, cloud.distro) for (user_name, _cfg) in users.items(): if _cfg.get("no_create_home") or _cfg.get("system"): + log.debug( + "Skipping printing of ssh fingerprints for user '%s' because no home directory is created", + user_name, + ) continue (key_fn, key_entries) = ssh_util.extract_authorized_keys(user_name) From 74e8ea796808c856be5d3ea515d55b4b184c2603 Mon Sep 17 00:00:00 2001 From: Jeffrey 'jf' Lim Date: Mon, 11 Apr 2022 10:33:42 +0800 Subject: [PATCH 4/5] Fix tests --- cloudinit/config/cc_ssh_authkey_fingerprints.py | 3 ++- cloudinit/config/cc_users_groups.py | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cloudinit/config/cc_ssh_authkey_fingerprints.py b/cloudinit/config/cc_ssh_authkey_fingerprints.py index 25f445c1304..db5c1454904 100755 --- a/cloudinit/config/cc_ssh_authkey_fingerprints.py +++ b/cloudinit/config/cc_ssh_authkey_fingerprints.py @@ -124,7 +124,8 @@ def handle(name, cfg, cloud, log, _args): for (user_name, _cfg) in users.items(): if _cfg.get("no_create_home") or _cfg.get("system"): log.debug( - "Skipping printing of ssh fingerprints for user '%s' because no home directory is created", + "Skipping printing of ssh fingerprints for user '%s' because " + "no home directory is created", user_name, ) continue diff --git a/cloudinit/config/cc_users_groups.py b/cloudinit/config/cc_users_groups.py index 75364949cfc..0dee4aa06e1 100644 --- a/cloudinit/config/cc_users_groups.py +++ b/cloudinit/config/cc_users_groups.py @@ -162,8 +162,6 @@ def handle(name, cfg, cloud, _log, _args): (default_user, _user_config) = ug_util.extract_default(users) cloud_keys = cloud.get_public_ssh_keys() or [] - no_homedir_options = ("no_create_home", "system") - for (name, members) in groups.items(): cloud.distro.create_group(name, members) From 811deb4d52737f86f104ddec58a12da0e84a847e Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Tue, 26 Apr 2022 16:53:55 -0600 Subject: [PATCH 5/5] cc_users_groups: fix error message join add needed unittest --- cloudinit/config/cc_users_groups.py | 4 ++-- .../unittests/config/test_cc_users_groups.py | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cloudinit/config/cc_users_groups.py b/cloudinit/config/cc_users_groups.py index 0dee4aa06e1..96e63242c63 100644 --- a/cloudinit/config/cc_users_groups.py +++ b/cloudinit/config/cc_users_groups.py @@ -171,8 +171,8 @@ def handle(name, cfg, cloud, _log, _args): need_home = [key for key in NEED_HOME if config.get(key)] if no_home and need_home: raise ValueError( - f"Not creating user {user}. Key(s) {need_home.join(',')}" - f" cannot be provided with {no_home.join(',')}" + f"Not creating user {user}. Key(s) {', '.join(need_home)}" + f" cannot be provided with {', '.join(no_home)}" ) ssh_redirect_user = config.pop("ssh_redirect_user", False) diff --git a/tests/unittests/config/test_cc_users_groups.py b/tests/unittests/config/test_cc_users_groups.py index 9210c1f6bd6..af8bdc3027b 100644 --- a/tests/unittests/config/test_cc_users_groups.py +++ b/tests/unittests/config/test_cc_users_groups.py @@ -192,6 +192,27 @@ def test_users_with_ssh_redirect_user_default_str(self, m_user, m_group): ) m_group.assert_not_called() + def test_users_without_home_cannot_import_ssh_keys(self, m_user, m_group): + cfg = { + "users": [ + "default", + { + "name": "me2", + "ssh_import_id": ["snowflake"], + "no_create_home": True, + }, + ] + } + cloud = self.tmp_cloud(distro="ubuntu", sys_cfg={}, metadata={}) + with self.assertRaises(ValueError) as context_manager: + cc_users_groups.handle("modulename", cfg, cloud, None, None) + m_group.assert_not_called() + self.assertEqual( + "Not creating user me2. Key(s) ssh_import_id cannot be provided" + " with no_create_home", + str(context_manager.exception), + ) + def test_users_with_ssh_redirect_user_non_default(self, m_user, m_group): """Warn when ssh_redirect_user is not 'default'.""" cfg = {