]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager: datamodel: types: PinSha256 custom type
authorAleš Mrázek <ales.mrazek@nic.cz>
Tue, 20 Jun 2023 08:37:50 +0000 (10:37 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Thu, 13 Jul 2023 07:50:09 +0000 (09:50 +0200)
manager/etc/knot-resolver/config.dev.yml
manager/knot_resolver_manager/datamodel/forward_schema.py
manager/knot_resolver_manager/datamodel/types/__init__.py
manager/knot_resolver_manager/datamodel/types/types.py
manager/tests/unit/datamodel/templates/test_common_macros.py
manager/tests/unit/datamodel/types/test_custom_types.py

index 859de8f51cbfdb524400783180ddff62670fee75..fc7d608a3361e8ef8e012e29011c4f76f7e31420 100644 (file)
@@ -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
index 4a003d6a75ce5a624c31d2a8444800ae3459292f..66f50c4a76e59501360811d7ffd0c20afb5a4219 100644 (file)
@@ -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
 
index 7f06951a08277b30b02e59abf8710a7dae720314..0b708c4a967ef9ec9213b37b8f668eb2a51b93d7 100644 (file)
@@ -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",
index 1f32ea71f58171e4e48b31830d9570ba70994415..14be0122da3b9da0f86d0157932e4cf3875f6936 100644 (file)
@@ -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
index d730fb9da53ff8d98c139c32f12ff9f683527c93..b2f363b25ef34a3115aec880f849951307671afd 100644 (file)
@@ -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) }}"""
 
index b9d6f56723fb56ba883c084ebaad4d1da5a8d060..31d9cd2fff1bf0b87e8b0f25dbc1ebc6049cf452 100644 (file)
@@ -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",
     [