Compare commits
10 Commits
ba185e7442
...
93232dc147
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93232dc147 | ||
|
|
7dab8f253d | ||
|
|
3f5fd53166 | ||
|
|
063a9ea5f3 | ||
|
|
90948544f0 | ||
|
|
bcadb2788d | ||
|
|
34d34f17fb | ||
|
|
a605a22157 | ||
|
|
91784fe229 | ||
|
|
bf59da1c5c |
90
backport-CVE-2022-2084.patch
Normal file
90
backport-CVE-2022-2084.patch
Normal file
@ -0,0 +1,90 @@
|
||||
From 4d467b14363d800b2185b89790d57871f11ea88c Mon Sep 17 00:00:00 2001
|
||||
From: James Falcon <james.falcon@canonical.com>
|
||||
Date: Wed, 29 Jun 2022 17:27:44 -0500
|
||||
Subject: [PATCH] Remove schema errors from log (#1551)
|
||||
|
||||
When schema errors are encountered, the section of userdata in question
|
||||
gets printed to the cloud-init log. As this could contain sensitive
|
||||
data, so log a generic warning instead and redirect user to run
|
||||
cloud-init schema --system as root.
|
||||
|
||||
LP: #1978422
|
||||
CVE: 2022-2084
|
||||
---
|
||||
cloudinit/config/schema.py | 15 ++++++++++++---
|
||||
tests/unittests/test_handler/test_schema.py | 17 +++++++++++++++++
|
||||
2 files changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/config/schema.py b/cloudinit/config/schema.py
|
||||
index 807c3ee..cc0a2a5 100644
|
||||
--- a/cloudinit/config/schema.py
|
||||
+++ b/cloudinit/config/schema.py
|
||||
@@ -58,7 +58,7 @@ class SchemaValidationError(ValueError):
|
||||
super(SchemaValidationError, self).__init__(message)
|
||||
|
||||
|
||||
-def validate_cloudconfig_schema(config, schema, strict=False):
|
||||
+def validate_cloudconfig_schema(config, schema, strict=False, log_details=True):
|
||||
"""Validate provided config meets the schema definition.
|
||||
|
||||
@param config: Dict of cloud configuration settings validated against
|
||||
@@ -67,6 +67,9 @@ def validate_cloudconfig_schema(config, schema, strict=False):
|
||||
for the cloud config module (config.cc_*).
|
||||
@param strict: Boolean, when True raise SchemaValidationErrors instead of
|
||||
logging warnings.
|
||||
+ @param log_details: Boolean, when True logs details of validation errors.
|
||||
+ If there are concerns about logging sensitive userdata, this should
|
||||
+ be set to False.
|
||||
|
||||
@raises: SchemaValidationError when provided config does not validate
|
||||
against the provided schema.
|
||||
@@ -84,10 +87,16 @@ def validate_cloudconfig_schema(config, schema, strict=False):
|
||||
errors += ((path, error.message),)
|
||||
if errors:
|
||||
if strict:
|
||||
+ # This could output/log sensitive data
|
||||
raise SchemaValidationError(errors)
|
||||
- else:
|
||||
+ if log_details:
|
||||
messages = ['{0}: {1}'.format(k, msg) for k, msg in errors]
|
||||
- logging.warning('Invalid config:\n%s', '\n'.join(messages))
|
||||
+ details = "\n" + "\n".join(messages)
|
||||
+ else:
|
||||
+ details = (
|
||||
+ "Please run 'sudo cloud-init devel schema --system' or 'cloud-init devel schema -c config-file' to see the schema errors."
|
||||
+ )
|
||||
+ logging.warning('Invalid config:%s', details)
|
||||
|
||||
|
||||
def annotated_cloudconfig_file(cloudconfig, original_content, schema_errors):
|
||||
diff --git a/tests/unittests/test_handler/test_schema.py b/tests/unittests/test_handler/test_schema.py
|
||||
index e69a47a..85f281d 100644
|
||||
--- a/tests/unittests/test_handler/test_schema.py
|
||||
+++ b/tests/unittests/test_handler/test_schema.py
|
||||
@@ -78,6 +78,23 @@ class ValidateCloudConfigSchemaTest(CiTestCase):
|
||||
"Invalid config:\np1: -1 is not of type 'string'\n",
|
||||
self.logs.getvalue())
|
||||
|
||||
+ @skipUnlessJsonSchema()
|
||||
+ def test_validateconfig_schema_sensitive(self):
|
||||
+ """When log_details=False, ensure details are omitted"""
|
||||
+ schema = {
|
||||
+ "properties": {"hashed_password": {"type": "string"}},
|
||||
+ "additionalProperties": False,
|
||||
+ }
|
||||
+ validate_cloudconfig_schema(
|
||||
+ {"hashed-password": "secret"},
|
||||
+ schema,
|
||||
+ strict=False,
|
||||
+ log_details=False,
|
||||
+ )
|
||||
+ self.assertIn(
|
||||
+ "Please run 'sudo cloud-init devel schema --system' or 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
+ self.logs.getvalue())
|
||||
+
|
||||
@skipUnlessJsonSchema()
|
||||
def test_validateconfig_schema_emits_warning_on_missing_jsonschema(self):
|
||||
"""Warning from validate_cloudconfig_schema when missing jsonschema."""
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,138 @@
|
||||
From a378b7e4f47375458651c0972e7cd813f6fe0a6b Mon Sep 17 00:00:00 2001
|
||||
From: James Falcon <james.falcon@canonical.com>
|
||||
Date: Wed, 26 Apr 2023 15:11:55 -0500
|
||||
Subject: [PATCH] Make user/vendor data sensitive and remove log permissions
|
||||
(#2144)
|
||||
|
||||
Because user data and vendor data may contain sensitive information,
|
||||
this commit ensures that any user data or vendor data written to
|
||||
instance-data.json gets redacted and is only available to root user.
|
||||
|
||||
Also, modify the permissions of cloud-init.log to be 640, so that
|
||||
sensitive data leaked to the log isn't world readable.
|
||||
Additionally, remove the logging of user data and vendor data to
|
||||
cloud-init.log from the Vultr datasource.
|
||||
|
||||
LP: #2013967
|
||||
CVE: CVE-2023-1786
|
||||
---
|
||||
cloudinit/sources/__init__.py | 28 +++++++++++++++++++++++++---
|
||||
cloudinit/stages.py | 4 +++-
|
||||
cloudinit/sources/tests/test_init.py | 27 ++++++++++++++++++++++++++-
|
||||
3 files changed, 49 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
|
||||
index 90521ba2..9d91512f 100644
|
||||
--- a/cloudinit/sources/__init__.py
|
||||
+++ b/cloudinit/sources/__init__.py
|
||||
@@ -111,7 +111,10 @@ def process_instance_metadata(metadata, key_path="", sensitive_keys=()):
|
||||
sub_key_path = key_path + '/' + key
|
||||
else:
|
||||
sub_key_path = key
|
||||
- if key in sensitive_keys or sub_key_path in sensitive_keys:
|
||||
+ if (
|
||||
+ key.lower() in sensitive_keys
|
||||
+ or sub_key_path.lower() in sensitive_keys
|
||||
+ ):
|
||||
md_copy['sensitive_keys'].append(sub_key_path)
|
||||
if isinstance(val, str) and val.startswith('ci-b64:'):
|
||||
md_copy['base64_encoded_keys'].append(sub_key_path)
|
||||
@@ -133,6 +136,12 @@ def redact_sensitive_keys(metadata, redact_value=REDACT_SENSITIVE_VALUE):
|
||||
|
||||
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)
|
||||
@@ -140,9 +149,14 @@ def redact_sensitive_keys(metadata, redact_value=REDACT_SENSITIVE_VALUE):
|
||||
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
|
||||
|
||||
|
||||
@@ -215,7 +229,18 @@ class DataSource(CloudInitPickleMixin, metaclass=abc.ABCMeta):
|
||||
|
||||
# N-tuple of keypaths or keynames redact from instance-data.json for
|
||||
# non-root users
|
||||
- sensitive_metadata_keys = ('security-credentials',)
|
||||
+ sensitive_metadata_keys = (
|
||||
+ "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",
|
||||
+ )
|
||||
|
||||
def __init__(self, sys_cfg, distro, paths, ud_proc=None):
|
||||
self.sys_cfg = sys_cfg
|
||||
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
|
||||
index 65f952e7..509d8f7f 100644
|
||||
--- a/cloudinit/stages.py
|
||||
+++ b/cloudinit/stages.py
|
||||
@@ -203,7 +203,9 @@ class Init(object):
|
||||
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 = {}
|
||||
diff --git a/cloudinit/sources/tests/test_init.py b/cloudinit/sources/tests/test_init.py
|
||||
index 96e4dd90..005a571b 100644
|
||||
--- a/cloudinit/sources/tests/test_init.py
|
||||
+++ b/cloudinit/sources/tests/test_init.py
|
||||
@@ -329,9 +329,24 @@ class TestDataSource(CiTestCase):
|
||||
'local-hostname': 'test-subclass-hostname',
|
||||
'region': 'myregion',
|
||||
'some': {'security-credentials': {
|
||||
- 'cred1': 'sekret', 'cred2': 'othersekret'}}})
|
||||
+ 'cred1': 'sekret', 'cred2': 'othersekret'
|
||||
+ }
|
||||
+ },
|
||||
+ },
|
||||
+ )
|
||||
self.assertEqual(
|
||||
- ('security-credentials',), datasource.sensitive_metadata_keys)
|
||||
+ (
|
||||
+ "merged_cfg",
|
||||
+ "security-credentials",
|
||||
+ "userdata",
|
||||
+ "user-data",
|
||||
+ "user_data",
|
||||
+ "vendordata",
|
||||
+ "vendor-data",
|
||||
+ "ds/vendor_data",
|
||||
+ ),
|
||||
+ datasource.sensitive_metadata_keys,
|
||||
+ )
|
||||
datasource.get_data()
|
||||
json_file = self.tmp_path(INSTANCE_JSON_FILE, tmp)
|
||||
sensitive_json_file = self.tmp_path(INSTANCE_JSON_SENSITIVE_FILE, tmp)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
28
backport-Create-the-log-file-with-640-permissions-858.patch
Normal file
28
backport-Create-the-log-file-with-640-permissions-858.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 29ac50f2b9e7634fc59fc161d77d27e970ae8080 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Schweikert <rjschwei@suse.com>
|
||||
Date: Wed, 2 Jun 2021 17:10:32 -0400
|
||||
Subject: [PATCH] - Create the log file with 640 permissions (#858)
|
||||
|
||||
Security scanners are often simple minded and complain on arbitrary
|
||||
settings such as file permissions. For /var/log/* having world read is
|
||||
one of these cases.
|
||||
---
|
||||
cloudinit/stages.py | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
|
||||
index bbded1e9..3688be2e 100644
|
||||
--- a/cloudinit/stages.py
|
||||
+++ b/cloudinit/stages.py
|
||||
@@ -156,7 +156,7 @@ class Init(object):
|
||||
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, preserve_mode=True)
|
||||
+ util.ensure_file(log_file, mode=0o640, preserve_mode=True)
|
||||
perms = self.cfg.get('syslog_fix_perms')
|
||||
if not perms:
|
||||
perms = {}
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
From 00dbaf1e9ab0e59d81662f0f3561897bef499a3f Mon Sep 17 00:00:00 2001
|
||||
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
|
||||
Date: Mon, 9 Aug 2021 16:49:56 +0200
|
||||
Subject: [PATCH] add get_permissions/get_owner/get_group/get_user_groups
|
||||
|
||||
---
|
||||
cloudinit/util.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 46 insertions(+)
|
||||
|
||||
diff --git a/cloudinit/util.py b/cloudinit/util.py
|
||||
index 88d6d53..2379177 100644
|
||||
--- a/cloudinit/util.py
|
||||
+++ b/cloudinit/util.py
|
||||
@@ -36,6 +36,7 @@ from errno import ENOENT, ENOEXEC
|
||||
|
||||
from base64 import b64decode, b64encode
|
||||
from six.moves.urllib import parse as urlparse
|
||||
+from typing import List
|
||||
|
||||
import six
|
||||
|
||||
@@ -1887,6 +1888,51 @@ def chmod(path, mode):
|
||||
with SeLinuxGuard(path):
|
||||
os.chmod(path, real_mode)
|
||||
|
||||
+def get_permissions(path: str) -> int:
|
||||
+ """
|
||||
+ Returns the octal permissions of the file/folder pointed by the path,
|
||||
+ encoded as an int.
|
||||
+
|
||||
+ @param path: The full path of the file/folder.
|
||||
+ """
|
||||
+
|
||||
+ return stat.S_IMODE(os.stat(path).st_mode)
|
||||
+
|
||||
+
|
||||
+def get_owner(path: str) -> str:
|
||||
+ """
|
||||
+ Returns the owner of the file/folder pointed by the path.
|
||||
+
|
||||
+ @param path: The full path of the file/folder.
|
||||
+ """
|
||||
+ st = os.stat(path)
|
||||
+ return pwd.getpwuid(st.st_uid).pw_name
|
||||
+
|
||||
+
|
||||
+def get_group(path: str) -> str:
|
||||
+ """
|
||||
+ Returns the group of the file/folder pointed by the path.
|
||||
+
|
||||
+ @param path: The full path of the file/folder.
|
||||
+ """
|
||||
+ st = os.stat(path)
|
||||
+ return grp.getgrgid(st.st_gid).gr_name
|
||||
+
|
||||
+
|
||||
+def get_user_groups(username: str) -> List[str]:
|
||||
+ """
|
||||
+ Returns a list of all groups to which the user belongs
|
||||
+
|
||||
+ @param username: the user we want to check
|
||||
+ """
|
||||
+ groups = []
|
||||
+ for group in grp.getgrall():
|
||||
+ if username in group.gr_mem:
|
||||
+ groups.append(group.gr_name)
|
||||
+
|
||||
+ gid = pwd.getpwnam(username).pw_gid
|
||||
+ groups.append(grp.getgrgid(gid).gr_name)
|
||||
+ return groups
|
||||
|
||||
def write_file(filename, content, mode=0o644, omode="wb", copy_mode=False):
|
||||
"""
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,146 @@
|
||||
From 879945f56103d937a7fee84bfe7662dc2a5be708 Mon Sep 17 00:00:00 2001
|
||||
From: sxt1001 <shixuantong1@huawei.com>
|
||||
Date: Thu, 17 Oct 2024 20:45:07 +0800
|
||||
Subject: [PATCH] feat: Ensure random passwords contain multiple
|
||||
character
|
||||
types (#5815)
|
||||
|
||||
Reference:https://github.com/canonical/cloud-init/commit/879945f56103d937a7fee84bfe7662dc2a5be708
|
||||
Conflict:(1)change cloudinit/config/tests/test_set_passwords.py not
|
||||
tests/unittests/config/test_cc_set_passwords.py
|
||||
(2)add "import pytest" for test_set_passwords.py
|
||||
|
||||
The complexity of the random password generated by the
|
||||
rand_user_password() method may not meet the security configuration
|
||||
requirements of the system authentication module. This can cause
|
||||
chpasswd to fail.
|
||||
|
||||
This commit ensures we generate a password using 4 different character
|
||||
classes.
|
||||
|
||||
Fixes GH-5814
|
||||
|
||||
Co-authored-by: James Falcon <james.falcon@canonical.com>
|
||||
---
|
||||
cloudinit/config/cc_set_passwords.py | 35 ++++++++++++++----
|
||||
cloudinit/config/tests/test_set_passwords.py | 38 ++++++++++++++++++++
|
||||
2 files changed, 66 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py
|
||||
index d409447..c032f3c 100755
|
||||
--- a/cloudinit/config/cc_set_passwords.py
|
||||
+++ b/cloudinit/config/cc_set_passwords.py
|
||||
@@ -78,20 +78,16 @@ password.
|
||||
"""
|
||||
|
||||
import re
|
||||
+import random
|
||||
+import string
|
||||
|
||||
from cloudinit.distros import ug_util
|
||||
from cloudinit import log as logging
|
||||
from cloudinit.ssh_util import update_ssh_config
|
||||
from cloudinit import util
|
||||
|
||||
-from string import ascii_letters, digits
|
||||
-
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
-# We are removing certain 'painful' letters/numbers
|
||||
-PW_SET = (''.join([x for x in ascii_letters + digits
|
||||
- if x not in 'loLOI01']))
|
||||
-
|
||||
|
||||
def handle_ssh_pwauth(pw_auth, service_cmd=None, service_name="ssh"):
|
||||
"""Apply sshd PasswordAuthentication changes.
|
||||
@@ -238,7 +234,32 @@ def handle(_name, cfg, cloud, log, args):
|
||||
|
||||
|
||||
def rand_user_password(pwlen=20):
|
||||
- return util.rand_str(pwlen, select_from=PW_SET)
|
||||
+ if pwlen < 4:
|
||||
+ raise ValueError("Password length must be at least 4 characters.")
|
||||
+
|
||||
+ # There are often restrictions on the minimum number of character
|
||||
+ # classes required in a password, so ensure we at least one character
|
||||
+ # from each class.
|
||||
+ res_rand_list = [
|
||||
+ random.choice(string.digits),
|
||||
+ random.choice(string.ascii_lowercase),
|
||||
+ random.choice(string.ascii_uppercase),
|
||||
+ random.choice(string.punctuation),
|
||||
+ ]
|
||||
+
|
||||
+ res_rand_list.extend(
|
||||
+ list(
|
||||
+ util.rand_str(
|
||||
+ pwlen - len(res_rand_list),
|
||||
+ select_from=string.digits
|
||||
+ + string.ascii_lowercase
|
||||
+ + string.ascii_uppercase
|
||||
+ + string.punctuation,
|
||||
+ )
|
||||
+ )
|
||||
+ )
|
||||
+ random.shuffle(res_rand_list)
|
||||
+ return "".join(res_rand_list)
|
||||
|
||||
|
||||
def chpasswd(distro, plist_in, hashed=False):
|
||||
diff --git a/cloudinit/config/tests/test_set_passwords.py b/cloudinit/config/tests/test_set_passwords.py
|
||||
index 1350c34..49842a1 100644
|
||||
--- a/cloudinit/config/tests/test_set_passwords.py
|
||||
+++ b/cloudinit/config/tests/test_set_passwords.py
|
||||
@@ -1,6 +1,7 @@
|
||||
# This file is part of cloud-init. See LICENSE file for license information.
|
||||
|
||||
import mock
|
||||
+import pytest
|
||||
|
||||
from cloudinit.config import cc_set_passwords as setpass
|
||||
from cloudinit.tests.helpers import CiTestCase
|
||||
@@ -170,4 +171,41 @@ class TestSetPasswordsHandle(CiTestCase):
|
||||
else:
|
||||
self.fail("Password not emitted to console")
|
||||
|
||||
+class TestRandUserPassword:
|
||||
+ def _get_str_class_num(self, str):
|
||||
+ return sum(
|
||||
+ [
|
||||
+ any(c.islower() for c in str),
|
||||
+ any(c.isupper() for c in str),
|
||||
+ any(c.isupper() for c in str),
|
||||
+ any(c in string.punctuation for c in str),
|
||||
+ ]
|
||||
+ )
|
||||
+
|
||||
+ @pytest.mark.parametrize(
|
||||
+ "strlen, expected_result",
|
||||
+ [
|
||||
+ (1, ValueError),
|
||||
+ (2, ValueError),
|
||||
+ (3, ValueError),
|
||||
+ (4, 4),
|
||||
+ (5, 4),
|
||||
+ (5, 4),
|
||||
+ (6, 4),
|
||||
+ (20, 4),
|
||||
+ ],
|
||||
+ )
|
||||
+ def test_rand_user_password(self, strlen, expected_result):
|
||||
+ if expected_result is ValueError:
|
||||
+ with pytest.raises(
|
||||
+ expected_result,
|
||||
+ match="Password length must be at least 4 characters.",
|
||||
+ ):
|
||||
+ setpass.rand_user_password(strlen)
|
||||
+ else:
|
||||
+ rand_password = setpass.rand_user_password(strlen)
|
||||
+ assert len(rand_password) == strlen
|
||||
+ assert self._get_str_class_num(rand_password) == expected_result
|
||||
+
|
||||
+
|
||||
# vi: ts=4 expandtab
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
From 2fb656fd991d788ed54e098815d93458e46f069e Mon Sep 17 00:00:00 2001
|
||||
From: Brett Holman <brett.holman@canonical.com>
|
||||
Date: Fri, 24 Nov 2023 15:54:09 +0000
|
||||
Subject: [PATCH] fix: Don't loosen the permissions of the log file (#4628)
|
||||
|
||||
Reference:https://github.com/canonical/cloud-init/commit/2fb656fd991d788ed54e098815d93458e46f069e
|
||||
|
||||
Previous implementations loosened permissions in non-default scenarios.
|
||||
|
||||
Fixes GH-4243
|
||||
---
|
||||
cloudinit/stages.py | 15 ++++++++++++++-
|
||||
cloudinit/tests/test_stages.py | 16 ++++++++++++++++
|
||||
2 files changed, 30 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
|
||||
index 633f57a..5e7733a 100644
|
||||
--- a/cloudinit/stages.py
|
||||
+++ b/cloudinit/stages.py
|
||||
@@ -15,6 +15,7 @@ from cloudinit.settings import (
|
||||
FREQUENCIES, CLOUD_CONFIG, PER_INSTANCE, RUN_CLOUD_CONFIG)
|
||||
|
||||
from cloudinit import handlers
|
||||
+from contextlib import suppress
|
||||
|
||||
# Default handlers (used if not overridden)
|
||||
from cloudinit.handlers.boot_hook import BootHookPartHandler
|
||||
@@ -146,13 +147,25 @@ class Init(object):
|
||||
def initialize(self):
|
||||
self._initialize_filesystem()
|
||||
|
||||
+ @staticmethod
|
||||
+ def _get_strictest_mode(mode_1: int, mode_2: int) -> int:
|
||||
+ return mode_1 & mode_2
|
||||
+
|
||||
def _initialize_filesystem(self):
|
||||
+ mode = 0o640
|
||||
+
|
||||
util.ensure_dirs(self._initial_subdirs())
|
||||
log_file = util.get_cfg_option_str(self.cfg, 'def_log_file')
|
||||
if log_file:
|
||||
# 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)
|
||||
+ with suppress(OSError):
|
||||
+ mode = self._get_strictest_mode(
|
||||
+ 0o640, util.get_permissions(log_file)
|
||||
+ )
|
||||
+
|
||||
+ # set file mode to the strictest of 0o640 and the current mode
|
||||
+ util.ensure_file(log_file, mode, preserve_mode=False)
|
||||
perms = self.cfg.get('syslog_fix_perms')
|
||||
if not perms:
|
||||
perms = {}
|
||||
diff --git a/cloudinit/tests/test_stages.py b/cloudinit/tests/test_stages.py
|
||||
index d5c9c0e..42facb7 100644
|
||||
--- a/cloudinit/tests/test_stages.py
|
||||
+++ b/cloudinit/tests/test_stages.py
|
||||
@@ -3,6 +3,7 @@
|
||||
"""Tests related to cloudinit.stages module."""
|
||||
|
||||
import os
|
||||
+import pytest
|
||||
|
||||
from cloudinit import stages
|
||||
from cloudinit import sources
|
||||
@@ -341,4 +342,19 @@ class TestInit(CiTestCase):
|
||||
self.init.distro.apply_network_config.assert_called_with(
|
||||
net_cfg, bring_up=True)
|
||||
|
||||
+@pytest.mark.parametrize(
|
||||
+ "mode_1, mode_2, expected",
|
||||
+ [
|
||||
+ (0o777, 0o640, 0o640),
|
||||
+ (0o640, 0o777, 0o640),
|
||||
+ (0o640, 0o541, 0o440),
|
||||
+ (0o111, 0o050, 0o010),
|
||||
+ (0o631, 0o640, 0o600),
|
||||
+ (0o661, 0o640, 0o640),
|
||||
+ (0o453, 0o611, 0o411),
|
||||
+ ],
|
||||
+)
|
||||
+def test_strictest_permissions(mode_1, mode_2, expected):
|
||||
+ assert expected == stages.Init._get_strictest_mode(mode_1, mode_2)
|
||||
+
|
||||
# vi: ts=4 expandtab
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
From f5b3ad741679cd42d2c145e574168dafe3ac15c1 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Watkins <oddbloke@ubuntu.com>
|
||||
Date: Fri, 23 Oct 2020 15:20:18 -0400
|
||||
Subject: [PATCH] stages: don't reset permissions of cloud-init.log every boot
|
||||
(#624)
|
||||
|
||||
ensure_file needed modification to support doing this, so this commit
|
||||
also includes the following changes:
|
||||
|
||||
test_util: add tests for util.ensure_file
|
||||
util: add preserve_mode parameter to ensure_file
|
||||
util: add (partial) type annotations to ensure_file
|
||||
|
||||
LP: #1900837
|
||||
---
|
||||
cloudinit/stages.py | 2 +-
|
||||
cloudinit/tests/test_util.py | 45 ++++++++++++++++++++++++
|
||||
cloudinit/util.py | 8 +++--
|
||||
3 files changed, 52 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
|
||||
index 765f4aab..0cce6e80 100644
|
||||
--- a/cloudinit/stages.py
|
||||
+++ b/cloudinit/stages.py
|
||||
@@ -148,7 +148,7 @@ class Init(object):
|
||||
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)
|
||||
+ util.ensure_file(log_file, preserve_mode=True)
|
||||
perms = self.cfg.get('syslog_fix_perms')
|
||||
if not perms:
|
||||
perms = {}
|
||||
diff --git a/cloudinit/tests/test_util.py b/cloudinit/tests/test_util.py
|
||||
index 096a3037..77714928 100644
|
||||
--- a/cloudinit/tests/test_util.py
|
||||
+++ b/cloudinit/tests/test_util.py
|
||||
@@ -771,4 +771,49 @@ class TestRedirectOutputPreexecFn:
|
||||
|
||||
assert 0 == m_setgid.call_count
|
||||
|
||||
+@mock.patch("cloudinit.util.write_file")
|
||||
+class TestEnsureFile:
|
||||
+ """Tests for ``cloudinit.util.ensure_file``."""
|
||||
+
|
||||
+ def test_parameters_passed_through(self, m_write_file):
|
||||
+ """Test the parameters in the signature are passed to write_file."""
|
||||
+ util.ensure_file(
|
||||
+ mock.sentinel.path,
|
||||
+ mode=mock.sentinel.mode,
|
||||
+ preserve_mode=mock.sentinel.preserve_mode,
|
||||
+ )
|
||||
+
|
||||
+ assert 1 == m_write_file.call_count
|
||||
+ args, kwargs = m_write_file.call_args
|
||||
+ assert (mock.sentinel.path,) == args
|
||||
+ assert mock.sentinel.mode == kwargs["mode"]
|
||||
+ assert mock.sentinel.preserve_mode == kwargs["preserve_mode"]
|
||||
+
|
||||
+ @pytest.mark.parametrize(
|
||||
+ "kwarg,expected",
|
||||
+ [
|
||||
+ # Files should be world-readable by default
|
||||
+ ("mode", 0o644),
|
||||
+ # The previous behaviour of not preserving mode should be retained
|
||||
+ ("preserve_mode", False),
|
||||
+ ],
|
||||
+ )
|
||||
+ def test_defaults(self, m_write_file, kwarg, expected):
|
||||
+ """Test that ensure_file defaults appropriately."""
|
||||
+ util.ensure_file(mock.sentinel.path)
|
||||
+
|
||||
+ assert 1 == m_write_file.call_count
|
||||
+ _args, kwargs = m_write_file.call_args
|
||||
+ assert expected == kwargs[kwarg]
|
||||
+
|
||||
+ def test_static_parameters_are_passed(self, m_write_file):
|
||||
+ """Test that the static write_files parameters are passed correctly."""
|
||||
+ util.ensure_file(mock.sentinel.path)
|
||||
+
|
||||
+ assert 1 == m_write_file.call_count
|
||||
+ _args, kwargs = m_write_file.call_args
|
||||
+ assert "" == kwargs["content"]
|
||||
+ assert "ab" == kwargs["omode"]
|
||||
+
|
||||
+
|
||||
# vi: ts=4 expandtab
|
||||
diff --git a/cloudinit/util.py b/cloudinit/util.py
|
||||
index e47f1cf6..83727544 100644
|
||||
--- a/cloudinit/util.py
|
||||
+++ b/cloudinit/util.py
|
||||
@@ -1804,8 +1804,10 @@ def append_file(path, content):
|
||||
write_file(path, content, omode="ab", mode=None)
|
||||
|
||||
|
||||
-def ensure_file(path, mode=0o644):
|
||||
- write_file(path, content='', omode="ab", mode=mode)
|
||||
+def ensure_file(path, mode=0o644, preserve_mode=False):
|
||||
+ write_file(
|
||||
+ path, content="", omode="ab", mode=mode, copy_mode=preserve_mode
|
||||
+ )
|
||||
|
||||
|
||||
def safe_int(possible_int):
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 4c156a80375c01433cdd00546c6278edb0bb6025 Mon Sep 17 00:00:00 2001
|
||||
From: sxt1001 <shixuantong1@huawei.com>
|
||||
Date: Mon, 21 Oct 2024 23:40:25 +0800
|
||||
Subject: [PATCH] test: Fix duplicate judgment conditions in password
|
||||
generation (#5835)
|
||||
|
||||
Reference:https://github.com/canonical/cloud-init/commit/4c156a80375c01433cdd00546c6278edb0bb6025
|
||||
Conflict:NA
|
||||
|
||||
The problem was introduced by commit 879945f
|
||||
---
|
||||
cloudinit/config/tests/test_set_passwords.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cloudinit/config/tests/test_set_passwords.py b/cloudinit/config/tests/test_set_passwords.py
|
||||
index 73cb3d490..c068f62d8 100644
|
||||
--- a/cloudinit/config/tests/test_set_passwords.py
|
||||
+++ b/cloudinit/config/tests/test_set_passwords.py
|
||||
@@ -566,7 +566,7 @@ class TestRandUserPassword:
|
||||
[
|
||||
any(c.islower() for c in str),
|
||||
any(c.isupper() for c in str),
|
||||
- any(c.isupper() for c in str),
|
||||
+ any(c.isdigit() for c in str),
|
||||
any(c in string.punctuation for c in str),
|
||||
]
|
||||
)
|
||||
--
|
||||
2.33.0
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
Name: cloud-init
|
||||
Version: 19.4
|
||||
Release: 10
|
||||
Release: 15
|
||||
Summary: the defacto multi-distribution package that handles early initialization of a cloud instance.
|
||||
License: ASL 2.0 or GPLv3
|
||||
URL: http://launchpad.net/cloud-init
|
||||
@ -17,6 +17,16 @@ Patch6: backport-CVE-2020-8631-utils-use-SystemRandom-when-generating-random-pas
|
||||
Patch7: backport-CVE-2020-8632-cc_set_password-increase-random-pwlength-from-9-to-2.patch
|
||||
Patch8: backport-CVE-2021-3429-write-passwords-only-to-serial-console-lock-down-clo.patch
|
||||
Patch9: backport-testing-add-additional-mocks-to-test_net-tests-1356.patch
|
||||
Patch10:fix-a-small-unitest-error.patch
|
||||
Patch11: backport-CVE-2022-2084.patch
|
||||
Patch12: remove-schema-errors-from-log-for-cloudinit-config-cc_.patch
|
||||
Patch13: backport-stages-don-t-reset-permissions-of-cloud-init.log-eve.patch
|
||||
Patch14: backport-Create-the-log-file-with-640-permissions-858.patch
|
||||
Patch15: backport-CVE-2023-1786-Make-user-vendor-data-sensitive-and-remove-log-permi.patch
|
||||
Patch16: backport-fix-Don-t-loosen-the-permissions-of-the-log-file.patch
|
||||
Patch17: backport-add-get_permissions-get_owner-get_group-get_user_gro.patch
|
||||
Patch18: backport-feat-Ensure-random-passwords-contain-multiple-charac.patch
|
||||
Patch19: backport-test-Fix-duplicate-judgment-conditions-in-password-g.patch
|
||||
|
||||
Patch9000: Fix-the-error-level-logs-displayed-for-the-cloud-init-local-service.patch
|
||||
|
||||
@ -125,6 +135,21 @@ fi
|
||||
%exclude /usr/share/doc/*
|
||||
|
||||
%changelog
|
||||
* Mon Nov 04 2024 shixuantong <shixuantong1@huawei.com> - 19.4-15
|
||||
- Ensure random passwords contain multiple character types
|
||||
|
||||
* Thu Dec 14 2023 shixuantong <shixuantong1@huawei.com> - 19.4-14
|
||||
- fix: Don't loosen the permissions of the log file
|
||||
|
||||
* Wed May 24 2023 fuanan <fuanan3@h-partners.com> - 19.4-13
|
||||
- fix CVE-2023-1786
|
||||
|
||||
* Sun May 14 2023 shixuantong <shixuantong1@huawei.com> - 19.4-12
|
||||
- fix CVE-2022-2084
|
||||
|
||||
* Sun Apr 23 2023 shixuantong <shixuantong1@huawei.com> - 19.4-11
|
||||
- Fix a unitest error
|
||||
|
||||
* Thu Feb 02 2023 shixuantong <shixuantong1@huawei.com> - 19.4-10
|
||||
- revert make the same authentication behavior for arm and x86 machine
|
||||
|
||||
|
||||
26
fix-a-small-unitest-error.patch
Normal file
26
fix-a-small-unitest-error.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From ad6a8ee26ae553e9d7a9aff4e348867d32eadcf0 Mon Sep 17 00:00:00 2001
|
||||
From: yuelg <yuelg@chinaunicom.cn>
|
||||
Date: Thu, 20 Apr 2023 18:16:21 +0800
|
||||
Subject: [PATCH 1/1] fix a small unitest error
|
||||
|
||||
Signed-off-by: yuelg <yuelg@chinaunicom.cn>
|
||||
---
|
||||
tests/unittests/test_templating.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/unittests/test_templating.py b/tests/unittests/test_templating.py
|
||||
index c36e6eb..39ff032 100644
|
||||
--- a/tests/unittests/test_templating.py
|
||||
+++ b/tests/unittests/test_templating.py
|
||||
@@ -60,7 +60,7 @@ class TestTemplates(test_helpers.CiTestCase):
|
||||
blob = "blahblah $blah"
|
||||
(template_type, _renderer, _contents) = templater.detect_template(blob)
|
||||
self.assertIn("cheetah", template_type)
|
||||
- self.assertEqual(blob, contents)
|
||||
+ self.assertEqual(blob, _contents)
|
||||
|
||||
blob = '##template:something-new'
|
||||
self.assertRaises(ValueError, templater.detect_template, blob)
|
||||
--
|
||||
2.33.0
|
||||
|
||||
194
remove-schema-errors-from-log-for-cloudinit-config-cc_.patch
Normal file
194
remove-schema-errors-from-log-for-cloudinit-config-cc_.patch
Normal file
@ -0,0 +1,194 @@
|
||||
From 4aec33275d56c398234af45ca1dc51dd7995360f Mon Sep 17 00:00:00 2001
|
||||
From: sxt1001 <shixuantong1@huawei.com>
|
||||
Date: Sun, 14 May 2023 23:24:15 +0800
|
||||
Subject: [PATCH] remove schema errors from log for cloudinit/config/cc_*
|
||||
|
||||
---
|
||||
cloudinit/config/cc_bootcmd.py | 2 +-
|
||||
cloudinit/config/cc_ntp.py | 2 +-
|
||||
cloudinit/config/cc_resizefs.py | 2 +-
|
||||
cloudinit/config/cc_runcmd.py | 2 +-
|
||||
cloudinit/config/cc_snap.py | 2 +-
|
||||
cloudinit/config/cc_ubuntu_advantage.py | 2 +-
|
||||
cloudinit/config/cc_ubuntu_drivers.py | 2 +-
|
||||
cloudinit/config/tests/test_snap.py | 5 ++---
|
||||
tests/unittests/test_handler/test_handler_bootcmd.py | 8 ++++----
|
||||
tests/unittests/test_handler/test_handler_resizefs.py | 4 ++--
|
||||
tests/unittests/test_handler/test_handler_runcmd.py | 8 ++++----
|
||||
11 files changed, 19 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/cloudinit/config/cc_bootcmd.py b/cloudinit/config/cc_bootcmd.py
|
||||
index 6813f53..cee7585 100644
|
||||
--- a/cloudinit/config/cc_bootcmd.py
|
||||
+++ b/cloudinit/config/cc_bootcmd.py
|
||||
@@ -83,7 +83,7 @@ def handle(name, cfg, cloud, log, _args):
|
||||
" no 'bootcmd' key in configuration"), name)
|
||||
return
|
||||
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
with temp_utils.ExtendedTemporaryFile(suffix=".sh") as tmpf:
|
||||
try:
|
||||
content = util.shellify(cfg["bootcmd"])
|
||||
diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py
|
||||
index 926dfea..5481f54 100644
|
||||
--- a/cloudinit/config/cc_ntp.py
|
||||
+++ b/cloudinit/config/cc_ntp.py
|
||||
@@ -502,7 +502,7 @@ def handle(name, cfg, cloud, log, _args):
|
||||
"'ntp' key existed in config, but not a dictionary type,"
|
||||
" is a {_type} instead".format(_type=type_utils.obj_name(ntp_cfg)))
|
||||
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
|
||||
# Allow users to explicitly enable/disable
|
||||
enabled = ntp_cfg.get('enabled', True)
|
||||
diff --git a/cloudinit/config/cc_resizefs.py b/cloudinit/config/cc_resizefs.py
|
||||
index 01dfc12..88fc89e 100644
|
||||
--- a/cloudinit/config/cc_resizefs.py
|
||||
+++ b/cloudinit/config/cc_resizefs.py
|
||||
@@ -233,7 +233,7 @@ def handle(name, cfg, _cloud, log, args):
|
||||
resize_root = args[0]
|
||||
else:
|
||||
resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
if not util.translate_bool(resize_root, addons=[NOBLOCK]):
|
||||
log.debug("Skipping module named %s, resizing disabled", name)
|
||||
return
|
||||
diff --git a/cloudinit/config/cc_runcmd.py b/cloudinit/config/cc_runcmd.py
|
||||
index 1f75d6c..6a2ff44 100644
|
||||
--- a/cloudinit/config/cc_runcmd.py
|
||||
+++ b/cloudinit/config/cc_runcmd.py
|
||||
@@ -84,7 +84,7 @@ def handle(name, cfg, cloud, log, _args):
|
||||
" no 'runcmd' key in configuration"), name)
|
||||
return
|
||||
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
out_fn = os.path.join(cloud.get_ipath('scripts'), "runcmd")
|
||||
cmd = cfg["runcmd"]
|
||||
try:
|
||||
diff --git a/cloudinit/config/cc_snap.py b/cloudinit/config/cc_snap.py
|
||||
index 90724b8..6e17595 100644
|
||||
--- a/cloudinit/config/cc_snap.py
|
||||
+++ b/cloudinit/config/cc_snap.py
|
||||
@@ -220,7 +220,7 @@ def handle(name, cfg, cloud, log, args):
|
||||
" no 'snap' key in configuration"), name)
|
||||
return
|
||||
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
if util.is_true(cfgin.get('squashfuse_in_container', False)):
|
||||
maybe_install_squashfuse(cloud)
|
||||
add_assertions(cfgin.get('assertions', []))
|
||||
diff --git a/cloudinit/config/cc_ubuntu_advantage.py b/cloudinit/config/cc_ubuntu_advantage.py
|
||||
index f846e9a..f7bb82d 100644
|
||||
--- a/cloudinit/config/cc_ubuntu_advantage.py
|
||||
+++ b/cloudinit/config/cc_ubuntu_advantage.py
|
||||
@@ -164,7 +164,7 @@ def handle(name, cfg, cloud, log, args):
|
||||
LOG.debug("Skipping module named %s,"
|
||||
" no 'ubuntu_advantage' configuration found", name)
|
||||
return
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
if 'commands' in ua_section:
|
||||
msg = (
|
||||
'Deprecated configuration "ubuntu-advantage: commands" provided.'
|
||||
diff --git a/cloudinit/config/cc_ubuntu_drivers.py b/cloudinit/config/cc_ubuntu_drivers.py
|
||||
index 297451d..8b84501 100644
|
||||
--- a/cloudinit/config/cc_ubuntu_drivers.py
|
||||
+++ b/cloudinit/config/cc_ubuntu_drivers.py
|
||||
@@ -156,5 +156,5 @@ def handle(name, cfg, cloud, log, _args):
|
||||
log.debug("Skipping module named %s, no 'drivers' key in config", name)
|
||||
return
|
||||
|
||||
- validate_cloudconfig_schema(cfg, schema)
|
||||
+ validate_cloudconfig_schema(cfg, schema, log_details=False)
|
||||
install_drivers(cfg['drivers'], cloud.distro.install_packages)
|
||||
diff --git a/cloudinit/config/tests/test_snap.py b/cloudinit/config/tests/test_snap.py
|
||||
index 3c47289..794e8e6 100644
|
||||
--- a/cloudinit/config/tests/test_snap.py
|
||||
+++ b/cloudinit/config/tests/test_snap.py
|
||||
@@ -457,9 +457,8 @@ class TestHandle(CiTestCase):
|
||||
'cloudinit.config.cc_snap',
|
||||
{'ASSERTIONS_FILE': {'new': assert_file}},
|
||||
handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
|
||||
- self.assertEqual(
|
||||
- "WARNING: Invalid config:\nsnap: Additional properties are not"
|
||||
- " allowed ('invalid' was unexpected)\n",
|
||||
+ self.assertIn(
|
||||
+ "Invalid config:Please run 'sudo cloud-init devel schema --system' or 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
self.logs.getvalue())
|
||||
|
||||
|
||||
diff --git a/tests/unittests/test_handler/test_handler_bootcmd.py b/tests/unittests/test_handler/test_handler_bootcmd.py
|
||||
index a76760f..eb77252 100644
|
||||
--- a/tests/unittests/test_handler/test_handler_bootcmd.py
|
||||
+++ b/tests/unittests/test_handler/test_handler_bootcmd.py
|
||||
@@ -79,7 +79,8 @@ class TestBootcmd(CiTestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
handle('cc_bootcmd', invalid_config, cc, LOG, [])
|
||||
self.assertIn(
|
||||
- 'Invalid config:\nbootcmd: 1 is not of type \'array\'',
|
||||
+ "Invalid config:Please run 'sudo cloud-init devel schema --system' or"
|
||||
+ " 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
self.logs.getvalue())
|
||||
self.assertIn('Failed to shellify', self.logs.getvalue())
|
||||
|
||||
@@ -96,9 +97,8 @@ class TestBootcmd(CiTestCase):
|
||||
with self.assertRaises(TypeError) as context_manager:
|
||||
handle('cc_bootcmd', invalid_config, cc, LOG, [])
|
||||
expected_warnings = [
|
||||
- 'bootcmd.1: 20 is not valid under any of the given schemas',
|
||||
- 'bootcmd.3: {\'a\': \'n\'} is not valid under any of the given'
|
||||
- ' schema'
|
||||
+ "Invalid config:Please run 'sudo cloud-init devel schema --system' or"
|
||||
+ " 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
]
|
||||
logs = self.logs.getvalue()
|
||||
for warning in expected_warnings:
|
||||
diff --git a/tests/unittests/test_handler/test_handler_resizefs.py b/tests/unittests/test_handler/test_handler_resizefs.py
|
||||
index db9a041..eda27b4 100644
|
||||
--- a/tests/unittests/test_handler/test_handler_resizefs.py
|
||||
+++ b/tests/unittests/test_handler/test_handler_resizefs.py
|
||||
@@ -82,8 +82,8 @@ class TestResizefs(CiTestCase):
|
||||
handle('cc_resizefs', cfg, _cloud=None, log=LOG, args=[])
|
||||
logs = self.logs.getvalue()
|
||||
self.assertIn(
|
||||
- "WARNING: Invalid config:\nresize_rootfs: 'junk' is not one of"
|
||||
- " [True, False, 'noblock']",
|
||||
+ "Invalid config:Please run 'sudo cloud-init devel schema --system' or"
|
||||
+ " 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
logs)
|
||||
self.assertIn(
|
||||
'DEBUG: Skipping module named cc_resizefs, resizing disabled\n',
|
||||
diff --git a/tests/unittests/test_handler/test_handler_runcmd.py b/tests/unittests/test_handler/test_handler_runcmd.py
|
||||
index 9ce334a..5fea44e 100644
|
||||
--- a/tests/unittests/test_handler/test_handler_runcmd.py
|
||||
+++ b/tests/unittests/test_handler/test_handler_runcmd.py
|
||||
@@ -62,7 +62,8 @@ class TestRuncmd(FilesystemMockingTestCase):
|
||||
cc = self._get_cloud('ubuntu')
|
||||
handle('cc_runcmd', invalid_config, cc, LOG, [])
|
||||
self.assertIn(
|
||||
- 'Invalid config:\nruncmd: 1 is not of type \'array\'',
|
||||
+ "Invalid config:Please run 'sudo cloud-init devel schema --system' or"
|
||||
+ " 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
self.logs.getvalue())
|
||||
self.assertIn('Failed to shellify', self.logs.getvalue())
|
||||
|
||||
@@ -78,9 +79,8 @@ class TestRuncmd(FilesystemMockingTestCase):
|
||||
cc = self._get_cloud('ubuntu')
|
||||
handle('cc_runcmd', invalid_config, cc, LOG, [])
|
||||
expected_warnings = [
|
||||
- 'runcmd.1: 20 is not valid under any of the given schemas',
|
||||
- 'runcmd.3: {\'a\': \'n\'} is not valid under any of the given'
|
||||
- ' schema'
|
||||
+ "Invalid config:Please run 'sudo cloud-init devel schema --system' or"
|
||||
+ " 'cloud-init devel schema -c config-file' to see the schema errors.",
|
||||
]
|
||||
logs = self.logs.getvalue()
|
||||
for warning in expected_warnings:
|
||||
--
|
||||
2.33.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user