← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~pzakha/cloud-init:userdata into cloud-init:master

 

Pavel Zakharov has proposed merging ~pzakha/cloud-init:userdata into cloud-init:master.

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

For more details, see:
https://code.launchpad.net/~pzakha/cloud-init/+git/cloud-init/+merge/367721

This adds 2 new configurations to allow disabling ssh key and user-data passing.

The motivation behind this is as we publish a closed appliance on the various cloud marketplaces, we do not want our customers to log into the VM and temper with it.

The downstream change for this is here:  https://github.com/delphix/cloud-init/pull/4.

TODO
Add documentation for the new configuration parameters.

TESTING
- unit tests
- tested that setting allow_public_ssh_keys: false prevents logging into a freshly cloned VM on AWS with a public key.
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~pzakha/cloud-init:userdata into cloud-init:master.
diff --git a/cloudinit/config/cc_ssh.py b/cloudinit/config/cc_ssh.py
index f8f7cb3..e1542ee 100755
--- a/cloudinit/config/cc_ssh.py
+++ b/cloudinit/config/cc_ssh.py
@@ -182,8 +182,19 @@ def handle(_name, cfg, cloud, log, _args):
         disable_root = util.get_cfg_option_bool(cfg, "disable_root", True)
         disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts",
                                                     ssh_util.DISABLE_USER_OPTS)
+        if 'allow_public_ssh_keys' in cfg:
+            allow_public_ssh_keys = cfg['allow_public_ssh_keys']
+        else:
+            allow_public_ssh_keys = True
+
+        if allow_public_ssh_keys:
+            log.debug('allow_public_ssh_keys = True: Public ssh keys consumed')
+            keys = cloud.get_public_ssh_keys() or []
+        else:
+            log.debug('allow_public_ssh_keys = False: Public ssh keys '
+                      'discarded')
+            keys = []
 
-        keys = cloud.get_public_ssh_keys() or []
         if "ssh_authorized_keys" in cfg:
             cfgkeys = cfg["ssh_authorized_keys"]
             keys.extend(cfgkeys)
diff --git a/cloudinit/config/tests/test_ssh.py b/cloudinit/config/tests/test_ssh.py
index c8a4271..5e67cd6 100644
--- a/cloudinit/config/tests/test_ssh.py
+++ b/cloudinit/config/tests/test_ssh.py
@@ -4,6 +4,9 @@
 from cloudinit.config import cc_ssh
 from cloudinit import ssh_util
 from cloudinit.tests.helpers import CiTestCase, mock
+import logging
+
+LOG = logging.getLogger(__name__)
 
 MODPATH = "cloudinit.config.cc_ssh."
 
@@ -66,7 +69,7 @@ class TestHandleSsh(CiTestCase):
         m_nug.return_value = ([], {})
         cloud = self.tmp_cloud(
             distro='ubuntu', metadata={'public-keys': keys})
-        cc_ssh.handle("name", cfg, cloud, None, None)
+        cc_ssh.handle("name", cfg, cloud, LOG, None)
         options = ssh_util.DISABLE_USER_OPTS.replace("$USER", "NONE")
         options = options.replace("$DISABLE_USER", "root")
         m_glob.assert_called_once_with('/etc/ssh/ssh_host_*key*')
@@ -94,7 +97,7 @@ class TestHandleSsh(CiTestCase):
         m_nug.return_value = ({user: {"default": user}}, {})
         cloud = self.tmp_cloud(
             distro='ubuntu', metadata={'public-keys': keys})
-        cc_ssh.handle("name", cfg, cloud, None, None)
+        cc_ssh.handle("name", cfg, cloud, LOG, None)
 
         options = ssh_util.DISABLE_USER_OPTS.replace("$USER", user)
         options = options.replace("$DISABLE_USER", "root")
@@ -119,7 +122,7 @@ class TestHandleSsh(CiTestCase):
         m_nug.return_value = ({user: {"default": user}}, {})
         cloud = self.tmp_cloud(
             distro='ubuntu', metadata={'public-keys': keys})
-        cc_ssh.handle("name", cfg, cloud, None, None)
+        cc_ssh.handle("name", cfg, cloud, LOG, None)
 
         options = ssh_util.DISABLE_USER_OPTS.replace("$USER", user)
         options = options.replace("$DISABLE_USER", "root")
@@ -144,7 +147,7 @@ class TestHandleSsh(CiTestCase):
         cloud = self.tmp_cloud(
             distro='ubuntu', metadata={'public-keys': keys})
         cloud.get_public_ssh_keys = mock.Mock(return_value=keys)
-        cc_ssh.handle("name", cfg, cloud, None, None)
+        cc_ssh.handle("name", cfg, cloud, LOG, None)
 
         self.assertEqual([mock.call(set(keys), user),
                           mock.call(set(keys), "root", options="")],
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index da7d349..94b3f0f 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -548,7 +548,17 @@ class Init(object):
         with events.ReportEventStack("consume-user-data",
                                      "reading and applying user-data",
                                      parent=self.reporter):
-            self._consume_userdata(frequency)
+            cfg = self.cfg
+            if 'allow_userdata' in cfg:
+                allow_userdata = cfg['allow_userdata']
+            else:
+                allow_userdata = True
+
+            if allow_userdata:
+                LOG.debug('allow_userdata = True: consuming user-data')
+                self._consume_userdata(frequency)
+            else:
+                LOG.debug('allow_userdata = False: discarding user-data')
         with events.ReportEventStack("consume-vendor-data",
                                      "reading and applying vendor-data",
                                      parent=self.reporter):

Follow ups