mirror of
https://github.com/Such-Software/adaptive-multi-protocol-gateway.git
synced 2026-10-17 07:31:32 +02:00
Fix Namecheap non-MX preference normalization
Ignore Namecheap MXPref placeholders outside MX records, add round-trip regression coverage, and keep the declared pytest gate collectable.
This commit is contained in:
+7
-2
@@ -1023,13 +1023,18 @@ class NamecheapDNSProvider:
|
|||||||
for element in root.iter():
|
for element in root.iter():
|
||||||
if _xml_localname(element.tag) != "host":
|
if _xml_localname(element.tag) != "host":
|
||||||
continue
|
continue
|
||||||
|
record_type = (element.get("Type") or "").upper()
|
||||||
records.append(
|
records.append(
|
||||||
ProviderDNSRecord(
|
ProviderDNSRecord(
|
||||||
name=element.get("Name") or "@",
|
name=element.get("Name") or "@",
|
||||||
type=(element.get("Type") or "").upper(),
|
type=record_type,
|
||||||
value=element.get("Address") or "",
|
value=element.get("Address") or "",
|
||||||
ttl=int(element.get("TTL") or DEFAULT_TTL),
|
ttl=int(element.get("TTL") or DEFAULT_TTL),
|
||||||
mx_pref=_optional_int(element.get("MXPref")),
|
mx_pref=(
|
||||||
|
_optional_int(element.get("MXPref"))
|
||||||
|
if record_type == "MX"
|
||||||
|
else None
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return DNSZoneSnapshot(
|
return DNSZoneSnapshot(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from ampg.dns import DNSZoneSnapshot, ProviderDNSRecord
|
from ampg.dns import DNSZoneSnapshot, NamecheapDNSProvider, ProviderDNSRecord
|
||||||
from ampg.dns_manifest import (
|
from ampg.dns_manifest import (
|
||||||
load_dns_manifest,
|
load_dns_manifest,
|
||||||
merge_dns_manifest_records,
|
merge_dns_manifest_records,
|
||||||
@@ -60,6 +60,29 @@ class FakeProvider:
|
|||||||
self.records = tuple(records)
|
self.records = tuple(records)
|
||||||
|
|
||||||
|
|
||||||
|
class NamecheapProviderTests(unittest.TestCase):
|
||||||
|
def test_non_mx_preference_placeholder_is_ignored(self):
|
||||||
|
response = """\
|
||||||
|
<ApiResponse Status="OK">
|
||||||
|
<CommandResponse>
|
||||||
|
<DomainDNSGetHostsResult>
|
||||||
|
<host Name="shop" Type="A" Address="192.0.2.1" TTL="300" MXPref="10" />
|
||||||
|
<host Name="@" Type="MX" Address="mx.example" TTL="300" MXPref="20" />
|
||||||
|
</DomainDNSGetHostsResult>
|
||||||
|
</CommandResponse>
|
||||||
|
</ApiResponse>
|
||||||
|
"""
|
||||||
|
provider = NamecheapDNSProvider.__new__(NamecheapDNSProvider)
|
||||||
|
provider._request = lambda _command, _params: response
|
||||||
|
provider._domain_params = lambda _domain: {"SLD": "example", "TLD": "test"}
|
||||||
|
|
||||||
|
snapshot = provider.get_hosts("example.test")
|
||||||
|
|
||||||
|
self.assertEqual("ok", snapshot.status)
|
||||||
|
self.assertIsNone(snapshot.records[0].mx_pref)
|
||||||
|
self.assertEqual(20, snapshot.records[1].mx_pref)
|
||||||
|
|
||||||
|
|
||||||
class DNSManifestTests(unittest.TestCase):
|
class DNSManifestTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.temporary = tempfile.TemporaryDirectory()
|
self.temporary = tempfile.TemporaryDirectory()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ def golden() -> dict:
|
|||||||
return json.loads(GOLDEN_PATH.read_text(encoding="utf-8"))
|
return json.loads(GOLDEN_PATH.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
|
||||||
def test_sign(secret: int, message: bytes) -> tuple[str, str]:
|
def _sign_for_test(secret: int, message: bytes) -> tuple[str, str]:
|
||||||
point = bip340.point_mul(secret, bip340.SECP256K1_GENERATOR)
|
point = bip340.point_mul(secret, bip340.SECP256K1_GENERATOR)
|
||||||
assert point is not None
|
assert point is not None
|
||||||
adjusted = secret if point[1] % 2 == 0 else bip340.SECP256K1_ORDER - secret
|
adjusted = secret if point[1] % 2 == 0 else bip340.SECP256K1_ORDER - secret
|
||||||
@@ -138,7 +138,7 @@ class ServiceManifestTest(unittest.TestCase):
|
|||||||
manifest = deepcopy(golden()["manifest"])
|
manifest = deepcopy(golden()["manifest"])
|
||||||
root_secret = int(golden()["test_secret_key"], 16)
|
root_secret = int(golden()["test_secret_key"], 16)
|
||||||
signing_secret = 4
|
signing_secret = 4
|
||||||
signing_key, _ = test_sign(signing_secret, bytes(32))
|
signing_key, _ = _sign_for_test(signing_secret, bytes(32))
|
||||||
delegation_payload = {
|
delegation_payload = {
|
||||||
"schema": sm.DELEGATION_SCHEMA,
|
"schema": sm.DELEGATION_SCHEMA,
|
||||||
"service_id": manifest["payload"]["service_id"],
|
"service_id": manifest["payload"]["service_id"],
|
||||||
@@ -148,10 +148,10 @@ class ServiceManifestTest(unittest.TestCase):
|
|||||||
"expires_at": "2037-01-01T00:00:00Z",
|
"expires_at": "2037-01-01T00:00:00Z",
|
||||||
"sequence": 1,
|
"sequence": 1,
|
||||||
}
|
}
|
||||||
root_key, delegation_signature = test_sign(
|
root_key, delegation_signature = _sign_for_test(
|
||||||
root_secret, sm.delegation_digest(delegation_payload)
|
root_secret, sm.delegation_digest(delegation_payload)
|
||||||
)
|
)
|
||||||
signing_key, manifest_signature = test_sign(
|
signing_key, manifest_signature = _sign_for_test(
|
||||||
signing_secret, sm.service_manifest_digest(manifest["payload"])
|
signing_secret, sm.service_manifest_digest(manifest["payload"])
|
||||||
)
|
)
|
||||||
manifest["delegation"] = {
|
manifest["delegation"] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user