From 4d467b14363d800b2185b89790d57871f11ea88c Mon Sep 17 00:00:00 2001 From: James Falcon 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 456bab2..a1e1a54 100644 --- a/cloudinit/config/schema.py +++ b/cloudinit/config/schema.py @@ -72,7 +72,7 @@ def is_schema_byte_string(checker, instance): isinstance(instance, (bytes,))) -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 @@ -81,6 +81,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. @@ -118,10 +121,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 1dae223..5650c88 100644 --- a/tests/unittests/test_handler/test_schema.py +++ b/tests/unittests/test_handler/test_schema.py @@ -86,6 +86,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