Skip to content

Commit e171b68

Browse files
TheRealFalconholmanb
authored andcommitted
chore: make jsonschema remote retrieval explicit
We were seeing this warning during unit tests: DeprecationWarning: Automatically retrieving remote references can be a security vulnerability and is discouraged by the JSON Schema specifications. Relying on this behavior is deprecated and will shortly become an error. If you are sure you want to remotely retrieve your reference and that it is safe to do so, you can find instructions for doing so via referencing.Registry in the referencing documentation (https://referencing.readthedocs.org). In particular, the change is based on: https://referencing.readthedocs.io/en/stable/intro/#dynamically-retrieving-resources
1 parent 6565655 commit e171b68

File tree

1 file changed

+50
-10
lines changed

1 file changed

+50
-10
lines changed

cloudinit/config/schema.py

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import re
88
import shutil
99
import sys
10+
import urllib.parse
1011
from collections import defaultdict
1112
from contextlib import suppress
1213
from copy import deepcopy
@@ -50,6 +51,8 @@
5051

5152
LOG = logging.getLogger(__name__)
5253

54+
REMOTE_SCHEMA_BASE = "https://raw.githubusercontent.com/canonical/cloud-init/main/cloudinit/config/schemas/" # noqa: E501
55+
5356

5457
# Note versions.schema.json is publicly consumed by schemastore.org.
5558
# If we change the location of versions.schema.json in github, we need
@@ -658,6 +661,50 @@ def netplan_validate_network_schema(
658661
return True
659662

660663

664+
def _resource_retriever(uri):
665+
"""Retrieve a "referencing" Resource from a given URI."""
666+
import referencing
667+
import referencing.exceptions
668+
669+
parsed = urllib.parse.urlparse(uri)
670+
if parsed.scheme == "file":
671+
local_path = urllib.parse.unquote(parsed.path)
672+
else:
673+
raise referencing.exceptions.NoSuchResource(f"Unsupported URI: {uri}")
674+
return referencing.Resource.from_contents(
675+
json.loads(load_text_file(local_path))
676+
)
677+
678+
679+
def _get_validator(schema: dict, strict_metaschema: bool):
680+
"""Get a JSON schema validator for the given schema."""
681+
try:
682+
(cloudinitValidator, FormatChecker) = get_jsonschema_validator()
683+
if strict_metaschema:
684+
validate_cloudconfig_metaschema(
685+
cloudinitValidator, schema, throw=False
686+
)
687+
except ImportError:
688+
LOG.debug("Ignoring schema validation. jsonschema is not present")
689+
return None
690+
691+
# The lowest supported version of jsonschema does not use "referencing",
692+
# but newer versions of jsonschema threaten to throw errors in the future
693+
# when using functionality that doesn't include "referencing".
694+
# Once the lowest supported version of jsonschema is 4.18.0 or greater, the
695+
# except clause can be removed.
696+
try:
697+
import referencing
698+
699+
registry = referencing.Registry(retrieve=_resource_retriever) # type: ignore
700+
validator = cloudinitValidator(
701+
schema, format_checker=FormatChecker(), registry=registry
702+
)
703+
except ImportError:
704+
validator = cloudinitValidator(schema, format_checker=FormatChecker())
705+
return validator
706+
707+
661708
@performance.timed("Validating schema")
662709
def validate_cloudconfig_schema(
663710
config: dict,
@@ -721,17 +768,10 @@ def validate_cloudconfig_schema(
721768

722769
if schema is None:
723770
schema = get_schema(schema_type)
724-
try:
725-
(cloudinitValidator, FormatChecker) = get_jsonschema_validator()
726-
if strict_metaschema:
727-
validate_cloudconfig_metaschema(
728-
cloudinitValidator, schema, throw=False
729-
)
730-
except ImportError:
731-
LOG.debug("Ignoring schema validation. jsonschema is not present")
732-
return False
733771

734-
validator = cloudinitValidator(schema, format_checker=FormatChecker())
772+
validator = _get_validator(schema, strict_metaschema)
773+
if not validator:
774+
return False
735775

736776
errors: SchemaProblems = []
737777
deprecations: SchemaProblems = []

0 commit comments

Comments
 (0)