Skip to content

Commit f39d7be

Browse files
authored
Merge pull request #5801 from microsoft/sammeluch/1.0-release-fix
Merge cloud-init fix into 1.0 branch
2 parents 8fc1811 + b2a9d9a commit f39d7be

File tree

3 files changed

+196
-37
lines changed

3 files changed

+196
-37
lines changed

SPECS/cloud-init/CVE-2022-2084.patch

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
diff -ruN a/cloudinit/config/schema.py b/cloudinit/config/schema.py
2+
--- a/cloudinit/config/schema.py 2021-11-02 12:35:08.000000000 -0700
3+
+++ b/cloudinit/config/schema.py 2023-06-28 13:10:31.476935314 -0700
4+
@@ -14,6 +14,8 @@
5+
import sys
6+
import yaml
7+
8+
+
9+
+LOG = logging.getLogger(__name__)
10+
_YAML_MAP = {True: 'true', False: 'false', None: 'null'}
11+
SCHEMA_UNDEFINED = b'UNDEFINED'
12+
CLOUD_CONFIG_HEADER = b'#cloud-config'
13+
@@ -72,7 +74,7 @@
14+
isinstance(instance, (bytes,)))
15+
16+
17+
-def validate_cloudconfig_schema(config, schema, strict=False):
18+
+def validate_cloudconfig_schema(config, schema, strict=False, log_details: bool = True,):
19+
"""Validate provided config meets the schema definition.
20+
21+
@param config: Dict of cloud configuration settings validated against
22+
@@ -81,6 +83,9 @@
23+
for the cloud config module (config.cc_*).
24+
@param strict: Boolean, when True raise SchemaValidationErrors instead of
25+
logging warnings.
26+
+ @param log_details: Boolean, when True logs details of validation errors.
27+
+ If there are concerns about logging sensitive userdata, this should
28+
+ be set to False.
29+
30+
@raises: SchemaValidationError when provided config does not validate
31+
against the provided schema.
32+
@@ -118,11 +123,17 @@
33+
errors += ((path, error.message),)
34+
if errors:
35+
if strict:
36+
+ # This could output/log sensitive data
37+
raise SchemaValidationError(errors)
38+
+ if log_details:
39+
+ messages = ["{0}: {1}".format(k, msg) for k, msg in errors]
40+
+ details = "\n" + "\n".join(messages)
41+
else:
42+
- messages = ['{0}: {1}'.format(k, msg) for k, msg in errors]
43+
- logging.warning('Invalid config:\n%s', '\n'.join(messages))
44+
-
45+
+ details = (
46+
+ "Please run 'sudo cloud-init schema --system' to "
47+
+ "see the schema errors."
48+
+ )
49+
+ LOG.warning("Invalid cloud-config provided: %s", details)
50+
51+
def annotated_cloudconfig_file(cloudconfig, original_content, schema_errors):
52+
"""Return contents of the cloud-config file annotated with schema errors.
53+
Binary files a/cloudinit/__pycache__/__init__.cpython-36.pyc and b/cloudinit/__pycache__/__init__.cpython-36.pyc differ
54+
Binary files a/cloudinit/__pycache__/version.cpython-36.pyc and b/cloudinit/__pycache__/version.cpython-36.pyc differ
55+
diff -ruN a/tests/integration_tests/modules/test_cli.py b/tests/integration_tests/modules/test_cli.py
56+
--- a/tests/integration_tests/modules/test_cli.py 2021-11-02 12:35:08.000000000 -0700
57+
+++ b/tests/integration_tests/modules/test_cli.py 2023-06-28 21:13:45.841309945 -0700
58+
@@ -20,6 +20,20 @@
59+
"""
60+
61+
62+
+# The '-' in 'hashed-password' fails schema validation
63+
+INVALID_USER_DATA_SCHEMA = """\
64+
+#cloud-config
65+
+users:
66+
+ - default
67+
+ - name: newsuper
68+
+ gecos: Big Stuff
69+
+ groups: users, admin
70+
+ sudo: ALL=(ALL) NOPASSWD:ALL
71+
+ hashed-password: asdfasdf
72+
+ shell: /bin/bash
73+
+ lock_passwd: true
74+
+"""
75+
+
76+
@pytest.mark.sru_2020_11
77+
@pytest.mark.user_data(VALID_USER_DATA)
78+
def test_valid_userdata(client: IntegrationInstance):
79+
@@ -43,3 +57,25 @@
80+
assert not result.ok
81+
assert 'Cloud config schema errors' in result.stderr
82+
assert 'needs to begin with "#cloud-config"' in result.stderr
83+
+
84+
+
85+
+@pytest.mark.user_data(INVALID_USER_DATA_SCHEMA)
86+
+def test_invalid_userdata_schema(client: IntegrationInstance):
87+
+ """Test invalid schema represented as Warnings, not fatal
88+
+ PR #1175
89+
+ """
90+
+ result = client.execute("cloud-init status --long")
91+
+ assert result.ok
92+
+ log = client.read_from_file("/var/log/cloud-init.log")
93+
+ warning = (
94+
+ "[WARNING]: Invalid cloud-config provided: Please run "
95+
+ "'sudo cloud-init schema --system' to see the schema errors."
96+
+ )
97+
+ assert warning in log
98+
+ assert "asdfasdf" not in log
99+
+
100+
+ result = client.execute("cloud-init status --long")
101+
+ if not result.ok:
102+
+ raise AssertionError(
103+
+ f"Unexpected error from cloud-init status: {result}"
104+
+ )
105+
\ No newline at end of file
106+
diff -ruN a/tests/unittests/test_handler/test_schema.py b/tests/unittests/test_handler/test_schema.py
107+
--- a/tests/unittests/test_handler/test_schema.py 2021-11-02 12:35:08.000000000 -0700
108+
+++ b/tests/unittests/test_handler/test_schema.py 2023-06-28 21:17:02.071767654 -0700
109+
@@ -11,6 +11,7 @@
110+
from copy import copy
111+
import itertools
112+
import pytest
113+
+import logging
114+
from pathlib import Path
115+
from textwrap import dedent
116+
from yaml import safe_load
117+
@@ -83,10 +84,31 @@
118+
schema = {'properties': {'p1': {'type': 'string'}}}
119+
validate_cloudconfig_schema({'p1': -1}, schema, strict=False)
120+
self.assertIn(
121+
- "Invalid config:\np1: -1 is not of type 'string'\n",
122+
+ "Invalid config: \np1: -1 is not of type 'string'\n",
123+
self.logs.getvalue())
124+
125+
@skipUnlessJsonSchema()
126+
+ def test_validateconfig_schema_sensitive(self, caplog):
127+
+ """When log_details=False, ensure details are omitted"""
128+
+ schema = {
129+
+ "properties": {"hashed_password": {"type": "string"}},
130+
+ "additionalProperties": False,
131+
+ }
132+
+ validate_cloudconfig_schema(
133+
+ {"hashed-password": "secret"},
134+
+ schema,
135+
+ strict=False,
136+
+ log_details=False,
137+
+ )
138+
+ [(module, log_level, log_msg)] = caplog.record_tuples
139+
+ assert "cloudinit.config.schema" == module
140+
+ assert logging.WARNING == log_level
141+
+ assert (
142+
+ "Invalid cloud-config provided: Please run 'sudo cloud-init "
143+
+ "schema --system' to see the schema errors." == log_msg
144+
+ )
145+
+
146+
+ @skipUnlessJsonSchema()
147+
def test_validateconfig_schema_emits_warning_on_missing_jsonschema(self):
148+
"""Warning from validate_cloudconfig_schema when missing jsonschema."""
149+
schema = {'properties': {'p1': {'type': 'string'}}}

SPECS/cloud-init/CVE-2023-1786.patch

+42-36
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,16 @@ diff -ruN a/cloudinit/sources/DataSourceVultr.py b/cloudinit/sources/DataSourceV
6565

6666
diff -ruN a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
6767
--- a/cloudinit/sources/__init__.py 2021-11-02 12:35:08.000000000 -0700
68-
+++ b/cloudinit/sources/__init__.py 2023-06-15 14:29:08.864172606 -0700
68+
+++ b/cloudinit/sources/__init__.py 2023-06-29 16:07:33.755159240 -0700
69+
@@ -13,7 +13,7 @@
70+
import json
71+
import os
72+
from collections import namedtuple
73+
-from typing import Dict, List # noqa: F401
74+
+from typing import Dict, List, Tuple # noqa: F401
75+
76+
from cloudinit import dmi
77+
from cloudinit import importer
6978
@@ -103,7 +103,10 @@
7079
sub_key_path = key_path + '/' + key
7180
else:
@@ -128,9 +137,23 @@ diff -ruN a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
128137

129138
_ci_pkl_version = 1
130139

140+
diff -ruN a/cloudinit/stages.py b/cloudinit/stages.py
141+
--- a/cloudinit/stages.py 2021-11-02 12:35:08.000000000 -0700
142+
+++ b/cloudinit/stages.py 2023-06-29 16:32:03.259644654 -0700
143+
@@ -204,7 +204,9 @@
144+
util.ensure_dirs(self._initial_subdirs())
145+
log_file = util.get_cfg_option_str(self.cfg, 'def_log_file')
146+
if log_file:
147+
- util.ensure_file(log_file, mode=0o640, preserve_mode=True)
148+
+ # At this point the log file should have already been created
149+
+ # in the setupLogging function of log.py
150+
+ util.ensure_file(log_file, mode=0o640, preserve_mode=False)
151+
perms = self.cfg.get('syslog_fix_perms')
152+
if not perms:
153+
perms = {}
131154
diff -ruN a/cloudinit/sources/tests/test_init.py b/cloudinit/sources/tests/test_init.py
132155
--- a/cloudinit/sources/tests/test_init.py 2021-11-02 12:35:08.000000000 -0700
133-
+++ b/cloudinit/sources/tests/test_init.py 2023-06-15 14:44:39.886499541 -0700
156+
+++ b/cloudinit/sources/tests/test_init.py 2023-06-29 17:07:56.129540654 -0700
134157
@@ -353,10 +353,31 @@
135158
'availability_zone': 'myaz',
136159
'local-hostname': 'test-subclass-hostname',
@@ -166,58 +189,55 @@ diff -ruN a/cloudinit/sources/tests/test_init.py b/cloudinit/sources/tests/test_
166189
datasource.sensitive_metadata_keys)
167190
sys_info = {
168191
"python": "3.7",
169-
@@ -372,8 +393,12 @@
170-
expected = {
192+
@@ -373,7 +394,10 @@
171193
'base64_encoded_keys': [],
172194
'merged_cfg': REDACT_SENSITIVE_VALUE,
173-
- 'sensitive_keys': [
195+
'sensitive_keys': [
174196
- 'ds/meta_data/some/security-credentials', 'merged_cfg'],
175-
+ "sensitive_keys": [
176-
+ "ds/meta_data/VENDOR-DAta",
177-
+ "ds/meta_data/some/security-credentials",
178-
+ "ds/meta_data/someother/nested/userData",
179-
+ "merged_cfg",
180-
+ ],
197+
+ 'ds/meta_data/VENDOR-DAta',
198+
+ 'ds/meta_data/some/security-credentials',
199+
+ 'ds/meta_data/someother/nested/userData',
200+
+ 'merged_cfg'],
181201
'sys_info': sys_info,
182202
'v1': {
183203
'_beta_keys': ['subplatform'],
184-
@@ -381,6 +406,7 @@
204+
@@ -381,6 +405,7 @@
185205
'availability_zone': 'myaz',
186206
'cloud-name': 'subclasscloudname',
187207
'cloud_name': 'subclasscloudname',
188-
+ "cloud_id": "subclasscloudname",
208+
+ 'cloud_id': 'subclasscloudname',
189209
'distro': 'ubuntu',
190210
'distro_release': 'focal',
191211
'distro_version': '20.04',
192-
@@ -401,12 +427,18 @@
212+
@@ -401,12 +426,18 @@
193213
'ds': {
194214
'_doc': EXPERIMENTAL_TEXT,
195215
'meta_data': {
196-
+ "VENDOR-DAta": REDACT_SENSITIVE_VALUE,
216+
+ 'VENDOR-DAta': REDACT_SENSITIVE_VALUE,
197217
'availability_zone': 'myaz',
198218
'local-hostname': 'test-subclass-hostname',
199219
'region': 'myregion',
200220
- 'some': {'security-credentials': REDACT_SENSITIVE_VALUE}}}
201-
+ "some": {"security-credentials": REDACT_SENSITIVE_VALUE},
221+
+ 'some': {'security-credentials': REDACT_SENSITIVE_VALUE},
202222
+ "someother": {
203223
+ "nested": {"userData": REDACT_SENSITIVE_VALUE}
204224
+ },
205-
+ },
206-
+ },
225+
+ }
226+
+ }
207227
}
208228
- self.assertCountEqual(expected, redacted)
209229
+ self.assertEqual(expected, redacted)
210230
file_stat = os.stat(json_file)
211231
self.assertEqual(0o644, stat.S_IMODE(file_stat.st_mode))
212232

213-
@@ -432,7 +464,16 @@
233+
@@ -432,7 +463,16 @@
214234
"variant": "ubuntu", "dist": ["ubuntu", "20.04", "focal"]}
215235

216236
self.assertCountEqual(
217237
- ('merged_cfg', 'security-credentials',),
218238
+ (
219-
+ "merged_cfg",
220-
+ "security-credentials",
239+
+ 'merged_cfg',
240+
+ 'security-credentials',
221241
+ "userdata",
222242
+ "user-data",
223243
+ "user_data",
@@ -228,23 +248,9 @@ diff -ruN a/cloudinit/sources/tests/test_init.py b/cloudinit/sources/tests/test_
228248
datasource.sensitive_metadata_keys)
229249
with mock.patch("cloudinit.util.system_info", return_value=sys_info):
230250
datasource.get_data()
231-
diff -ruN a/cloudinit/stages.py b/cloudinit/stages.py
232-
--- a/cloudinit/stages.py 2021-11-02 12:35:08.000000000 -0700
233-
+++ b/cloudinit/stages.py 2023-06-15 14:33:32.175651581 -0700
234-
@@ -204,7 +204,9 @@
235-
util.ensure_dirs(self._initial_subdirs())
236-
log_file = util.get_cfg_option_str(self.cfg, 'def_log_file')
237-
if log_file:
238-
- util.ensure_file(log_file, mode=0o640, preserve_mode=True)
239-
+ # At this point the log file should have already been created
240-
+ # in the setupLogging function of log.py
241-
+ util.ensure_file(log_file, mode=0o640, preserve_mode=False)
242-
perms = self.cfg.get('syslog_fix_perms')
243-
if not perms:
244-
perms = {}
245251
diff -ruN a/cloudinit/tests/test_stages.py b/cloudinit/tests/test_stages.py
246252
--- a/cloudinit/tests/test_stages.py 2021-11-02 12:35:08.000000000 -0700
247-
+++ b/cloudinit/tests/test_stages.py 2023-06-15 14:49:05.304858409 -0700
253+
+++ b/cloudinit/tests/test_stages.py 2023-06-29 17:09:37.046934002 -0700
248254
@@ -458,21 +458,24 @@
249255
# Assert we create it 0o640 by default if it doesn't already exist
250256
assert 0o640 == stat.S_IMODE(log_file.stat().mode)

SPECS/cloud-init/cloud-init.spec

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Summary: Cloud instance init scripts
44
Name: cloud-init
55
Version: 21.4
6-
Release: 3%{?dist}
6+
Release: 4%{?dist}
77
License: GPLv3
88
Vendor: Microsoft Corporation
99
Distribution: Mariner
@@ -21,6 +21,7 @@ Patch4: mariner-21.4.patch
2121
# backport patch https://github.com/canonical/cloud-init/commit/0988fb89be06aeb08083ce609f755509d08fa459.patch to 21.4
2222
Patch5: azureds-set-ovf_is_accesible.patch
2323
Patch6: CVE-2023-1786.patch
24+
Patch7: CVE-2022-2084.patch
2425

2526
BuildRequires: automake
2627
BuildRequires: dbus
@@ -163,6 +164,9 @@ rm -rf %{buildroot}
163164
%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d/10-azure-kvp.cfg
164165

165166
%changelog
167+
* Mon Jul 03 2023 Minghe Ren <[email protected]> - 21.4-4
168+
- Add patch for CVE-2022-2084 and modify CVE-2023-1786.patch
169+
166170
* Thu Jun 15 2023 Minghe Ren <[email protected]> - 21.4-3
167171
- Add patch for CVE-2023-1786
168172

0 commit comments

Comments
 (0)