File cloud-init-cve-2023-1786-redact-instance-data-json-main.patch of Package cloud-init.28546

--- cloudinit/sources/DataSourceLXD.py.orig
+++ cloudinit/sources/DataSourceLXD.py
@@ -173,6 +173,8 @@ class DataSourceLXD(sources.DataSource):
         "user.meta-data",
         "user.vendor-data",
         "user.user-data",
+        "cloud-init.user-data",
+        "cloud-init.vendor-data",
     )
 
     skip_hotplug_detect = True
--- cloudinit/sources/DataSourceVultr.py.orig
+++ cloudinit/sources/DataSourceVultr.py
@@ -5,6 +5,8 @@
 # Vultr Metadata API:
 # https://www.vultr.com/metadata/
 
+from typing import Tuple
+
 import cloudinit.sources.helpers.vultr as vultr
 from cloudinit import log as log
 from cloudinit import sources, util, version
@@ -27,6 +29,9 @@ BUILTIN_DS_CONFIG = {
 class DataSourceVultr(sources.DataSource):
 
     dsname = "Vultr"
+    sensitive_metadata_keys: Tuple[
+        str, ...
+    ] = sources.DataSource.sensitive_metadata_keys + ("startup-script",)
 
     def __init__(self, sys_cfg, distro, paths):
         super(DataSourceVultr, self).__init__(sys_cfg, distro, paths)
@@ -54,13 +59,8 @@ class DataSourceVultr(sources.DataSource
         self.get_datasource_data(self.metadata)
 
         # Dump some data so diagnosing failures is manageable
-        LOG.debug("Vultr Vendor Config:")
-        LOG.debug(util.json_dumps(self.metadata["vendor-data"]))
         LOG.debug("SUBID: %s", self.metadata["instance-id"])
         LOG.debug("Hostname: %s", self.metadata["local-hostname"])
-        if self.userdata_raw is not None:
-            LOG.debug("User-Data:")
-            LOG.debug(self.userdata_raw)
 
         return True
 
@@ -146,7 +146,4 @@ if __name__ == "__main__":
     config = md["vendor-data"]
     sysinfo = vultr.get_sysinfo()
 
-    print(util.json_dumps(sysinfo))
-    print(util.json_dumps(config))
-
 # vi: ts=4 expandtab
--- cloudinit/sources/__init__.py.orig
+++ cloudinit/sources/__init__.py
@@ -132,6 +132,12 @@ def redact_sensitive_keys(metadata, reda
 
     Replace any keys values listed in 'sensitive_keys' with redact_value.
     """
+    # While 'sensitive_keys' should already sanitized to only include what
+    # is in metadata, it is possible keys will overlap. For example, if
+    # "merged_cfg" and "merged_cfg/ds/userdata" both match, it's possible that
+    # "merged_cfg" will get replaced first, meaning "merged_cfg/ds/userdata"
+    # no longer represents a valid key.
+    # Thus, we still need to do membership checks in this function.
     if not metadata.get("sensitive_keys", []):
         return metadata
     md_copy = copy.deepcopy(metadata)
@@ -139,9 +145,14 @@ def redact_sensitive_keys(metadata, reda
         path_parts = key_path.split("/")
         obj = md_copy
         for path in path_parts:
-            if isinstance(obj[path], dict) and path != path_parts[-1]:
+            if (
+                path in obj
+                and isinstance(obj[path], dict)
+                and path != path_parts[-1]
+            ):
                 obj = obj[path]
-        obj[path] = redact_value
+        if path in obj:
+            obj[path] = redact_value
     return md_copy
 
 
@@ -249,6 +260,14 @@ class DataSource(CloudInitPickleMixin, m
     sensitive_metadata_keys: Tuple[str, ...] = (
         "merged_cfg",
         "security-credentials",
+        "userdata",
+        "user-data",
+        "user_data",
+        "vendordata",
+        "vendor-data",
+        # Provide ds/vendor_data to avoid redacting top-level
+        #  "vendor_data": {enabled: True}
+        "ds/vendor_data",
     )
 
     # True on datasources that may not see hotplugged devices reflected
--- cloudinit/stages.py.orig
+++ cloudinit/stages.py
@@ -203,7 +203,9 @@ class Init:
         util.ensure_dirs(self._initial_subdirs())
         log_file = util.get_cfg_option_str(self.cfg, "def_log_file")
         if log_file:
-            util.ensure_file(log_file, mode=0o640, preserve_mode=True)
+            # At this point the log file should have already been created
+            # in the setupLogging function of log.py
+            util.ensure_file(log_file, mode=0o640, preserve_mode=False)
             perms = self.cfg.get("syslog_fix_perms")
             if not perms:
                 perms = {}
--- tests/unittests/sources/test_init.py.orig
+++ tests/unittests/sources/test_init.py
@@ -464,6 +464,12 @@ class TestDataSource(CiTestCase):
             (
                 "merged_cfg",
                 "security-credentials",
+                "userdata",
+                "user-data",
+                "user_data",
+                "vendordata",
+                "vendor-data",
+                "ds/vendor_data",
             ),
             datasource.sensitive_metadata_keys,
         )
@@ -574,6 +580,12 @@ class TestDataSource(CiTestCase):
             (
                 "merged_cfg",
                 "security-credentials",
+                "userdata",
+                "user-data",
+                "user_data",
+                "vendordata",
+                "vendor-data",
+                "ds/vendor_data",
             ),
             datasource.sensitive_metadata_keys,
         )
--- tests/unittests/test_stages.py.orig
+++ tests/unittests/test_stages.py
@@ -606,19 +606,23 @@ class TestInit_InitializeFilesystem:
         # Assert we create it 0o640  by default if it doesn't already exist
         assert 0o640 == stat.S_IMODE(log_file.stat().mode)
 
-    def test_existing_file_permissions_are_not_modified(self, init, tmpdir):
-        """If the log file already exists, we should not modify its permissions
+    def test_existing_file_permissions(self, init, tmpdir):
+        """Test file permissions are set as expected.
+
+        CIS Hardening requires 640 permissions. These permissions are
+        currently hardcoded on every boot, but if there's ever a reason
+        to change this, we need to then ensure that they
+        are *not* set every boot.
 
         See https://bugs.launchpad.net/cloud-init/+bug/1900837.
         """
-        # Use a mode that will never be made the default so this test will
-        # always be valid
-        mode = 0o606
         log_file = tmpdir.join("cloud-init.log")
         log_file.ensure()
-        log_file.chmod(mode)
+        # Use a mode that will never be made the default so this test will
+        # always be valid
+        log_file.chmod(0o606)
         init._cfg = {"def_log_file": str(log_file)}
 
         init._initialize_filesystem()
 
-        assert mode == stat.S_IMODE(log_file.stat().mode)
+        assert 0o640 == stat.S_IMODE(log_file.stat().mode)
openSUSE Build Service is sponsored by