From: Aleš Mrázek Date: Tue, 20 Jun 2023 08:37:50 +0000 (+0200) Subject: manager: datamodel: types: PinSha256 custom type X-Git-Tag: v6.0.2~31^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e43be19a6b2bec2b97177e3be15325d23a0872c;p=thirdparty%2Fknot-resolver.git manager: datamodel: types: PinSha256 custom type --- diff --git a/manager/etc/knot-resolver/config.dev.yml b/manager/etc/knot-resolver/config.dev.yml index 859de8f51..fc7d608a3 100644 --- a/manager/etc/knot-resolver/config.dev.yml +++ b/manager/etc/knot-resolver/config.dev.yml @@ -56,7 +56,9 @@ forward: transport: tls hostname: odvr.nic.cz - address: [ 192.0.2.1, 192.0.2.2 ] - pin-sha256: ['YQ==', 'Wg=='] + pin-sha256: + - YmE3ODE2YmY4ZjAx+2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk/MTc3YTljYjQxMGZmNjFmMjAwMTVhZA== + - OTJmODU3ZDMyOWMwOWNlNTU4Y2M0YWNjMjI5NWE2NWJlMzY4MzRmMzY3NGU3NDAwNTI1YjMxZTMxYTgzMzQwMQ== - subtree: 1.168.192.in-addr.arpa options: dnssec: false diff --git a/manager/knot_resolver_manager/datamodel/forward_schema.py b/manager/knot_resolver_manager/datamodel/forward_schema.py index 4a003d6a7..66f50c4a7 100644 --- a/manager/knot_resolver_manager/datamodel/forward_schema.py +++ b/manager/knot_resolver_manager/datamodel/forward_schema.py @@ -2,7 +2,7 @@ from typing import List, Optional, Union from typing_extensions import Literal -from knot_resolver_manager.datamodel.types import DomainName, File, IPAddressOptionalPort, ListOrItem +from knot_resolver_manager.datamodel.types import DomainName, File, IPAddressOptionalPort, ListOrItem, PinSha256 from knot_resolver_manager.utils.modeling import ConfigSchema @@ -20,7 +20,7 @@ class ForwardServerSchema(ConfigSchema): address: ListOrItem[IPAddressOptionalPort] transport: Optional[Literal["tls"]] = None - pin_sha256: Optional[ListOrItem[str]] = None + pin_sha256: Optional[ListOrItem[PinSha256]] = None hostname: Optional[DomainName] = None ca_file: Optional[File] = None diff --git a/manager/knot_resolver_manager/datamodel/types/__init__.py b/manager/knot_resolver_manager/datamodel/types/__init__.py index 7f06951a0..0b708c4a9 100644 --- a/manager/knot_resolver_manager/datamodel/types/__init__.py +++ b/manager/knot_resolver_manager/datamodel/types/__init__.py @@ -20,6 +20,7 @@ from .types import ( IPv6Network, IPv6Network96, Percent, + PinSha256, PortNumber, SizeUnit, TimeUnit, @@ -48,6 +49,7 @@ __all__ = [ "IPv6Network96", "ListOrItem", "Percent", + "PinSha256", "PortNumber", "SizeUnit", "TimeUnit", diff --git a/manager/knot_resolver_manager/datamodel/types/types.py b/manager/knot_resolver_manager/datamodel/types/types.py index 1f32ea71f..14be0122d 100644 --- a/manager/knot_resolver_manager/datamodel/types/types.py +++ b/manager/knot_resolver_manager/datamodel/types/types.py @@ -131,6 +131,14 @@ class IDPattern(PatternBase): _re = re.compile(r"^(?!-)[a-z0-9-]*[a-z0-9]+$") +class PinSha256(PatternBase): + """ + A string that stores base64 encoded sha256. + """ + + _re = re.compile(r"^[A-Za-z\d+/]{86}==$") + + class InterfacePort(StrBase): addr: Union[None, ipaddress.IPv4Address, ipaddress.IPv6Address] = None if_name: Optional[InterfaceName] = None diff --git a/manager/tests/unit/datamodel/templates/test_common_macros.py b/manager/tests/unit/datamodel/templates/test_common_macros.py index d730fb9da..b2f363b25 100644 --- a/manager/tests/unit/datamodel/templates/test_common_macros.py +++ b/manager/tests/unit/datamodel/templates/test_common_macros.py @@ -70,7 +70,15 @@ def test_tls_servers_table(): # the ca-file is a dummy, because it's existence is checked {"address": ["2001:DB8::d0c"], "hostname": "res.example.com", "ca-file": "/etc/passwd"} ) - t = [d, ForwardServerSchema({"address": ["192.0.2.1"], "pin-sha256": "YQ=="})] + t = [ + d, + ForwardServerSchema( + { + "address": "192.0.2.1", + "pin-sha256": "OTJmODU3ZDMyOWMwOWNlNTU4Y2M0YWNjMjI5NWE2NWJlMzY4MzRmMzY3NGU3NDAwNTI1YjMxZTMxYTgzMzQwMQ==", + } + ), + ] tmpl_str = """{% from 'macros/common_macros.lua.j2' import tls_servers_table %} {{ tls_servers_table(x) }}""" diff --git a/manager/tests/unit/datamodel/types/test_custom_types.py b/manager/tests/unit/datamodel/types/test_custom_types.py index b9d6f5672..31d9cd2ff 100644 --- a/manager/tests/unit/datamodel/types/test_custom_types.py +++ b/manager/tests/unit/datamodel/types/test_custom_types.py @@ -18,6 +18,7 @@ from knot_resolver_manager.datamodel.types import ( IPv4Address, IPv6Address, IPv6Network96, + PinSha256, PortNumber, SizeUnit, TimeUnit, @@ -91,6 +92,31 @@ def test_checked_path(): assert str(TestSchema({"p": "/tmp"}).p) == "/tmp" +@pytest.mark.parametrize( + "val", + [ + "YmE3ODE2YmY4ZjAx+2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk/MTc3YTljYjQxMGZmNjFmMjAwMTVhZA==", + "OTJmODU3ZDMyOWMwOWNlNTU4Y2M0YWNjMjI5NWE2NWJlMzY4MzRmMzY3NGU3NDAwNTI1YjMxZTMxYTgzMzQwMQ==", + ], +) +def test_pin_sha256_valid(val: str): + o = PinSha256(val) + assert str(o) == val + + +@pytest.mark.parametrize( + "val", + [ + "!YmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljjQxMGZmNjFmMjAwMTVhZA==", + "OTJmODU3ZDMyOWMwOWNlNTU4Y2M0YWNjMjI5NWE2NWJlMzY4MzRmMzY3NGU3NDAwNTI1YjMxZTMxYTgzMzQwMQ", + "YmFzZTY0IQ", + ], +) +def test_pin_sha256_invalid(val: str): + with raises(ValueError): + PinSha256(val) + + @pytest.mark.parametrize( "val", [