mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 15:05:23 +00:00
Split up dnssec validation tests to multiple modules
Put each config into a separate module to avoid interfering with other tests.
This commit is contained in:
@@ -14,7 +14,7 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dns import edns, flags, name, rcode, rdataclass, rdatatype
|
from dns import edns, flags, name, rdataclass, rdatatype
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -1184,49 +1184,6 @@ def test_expired_signatures(servers):
|
|||||||
assert rrset.ttl <= 60
|
assert rrset.ttl <= 60
|
||||||
|
|
||||||
|
|
||||||
def test_accept_expired(servers, templates):
|
|
||||||
ns4 = servers["ns4"]
|
|
||||||
templates.render("ns4/named.conf", {"accept_expired": True})
|
|
||||||
ns4.reconfigure(log=False)
|
|
||||||
|
|
||||||
# test TTL of about-to-expire rrsets with accept-expired
|
|
||||||
ns4.rndc("flush", log=False)
|
|
||||||
msg = isctest.query.create("expiring.example", "SOA")
|
|
||||||
msg.flags |= flags.CD
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
msg = isctest.query.create("expiring.example", "SOA")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
for rrset in res1.answer:
|
|
||||||
assert rrset.ttl <= 3600
|
|
||||||
for rrset in res2.answer:
|
|
||||||
assert rrset.ttl <= 120
|
|
||||||
|
|
||||||
# test TTL is capped at RRSIG expiry time in the additional section
|
|
||||||
# with accept-expired
|
|
||||||
ns4.rndc("flush", log=False)
|
|
||||||
msg = isctest.query.create("expiring.example", "MX")
|
|
||||||
msg.flags |= flags.CD
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
msg = isctest.query.create("expiring.example", "MX")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
for rrset in res1.additional:
|
|
||||||
assert rrset.ttl <= 3600
|
|
||||||
for rrset in res2.additional:
|
|
||||||
assert rrset.ttl <= 120
|
|
||||||
|
|
||||||
# test TTL of expired rrsets with accept-expired
|
|
||||||
ns4.rndc("flush", log=False)
|
|
||||||
msg = isctest.query.create("expired.example", "SOA")
|
|
||||||
msg.flags |= flags.CD
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
msg = isctest.query.create("expired.example", "SOA")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
for rrset in res1.additional:
|
|
||||||
assert rrset.ttl <= 3600
|
|
||||||
for rrset in res2.additional:
|
|
||||||
assert rrset.ttl <= 120
|
|
||||||
|
|
||||||
|
|
||||||
def test_casing():
|
def test_casing():
|
||||||
# test legacy upper-case signer name validation
|
# test legacy upper-case signer name validation
|
||||||
msg = isctest.query.create("upper.example", "SOA")
|
msg = isctest.query.create("upper.example", "SOA")
|
||||||
@@ -1318,132 +1275,6 @@ def test_pending_ds(servers):
|
|||||||
isctest.check.noadflag(res)
|
isctest.check.noadflag(res)
|
||||||
|
|
||||||
|
|
||||||
def test_trust_anchors(servers, templates):
|
|
||||||
# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
|
|
||||||
#
|
|
||||||
# This nameserver is loaded with a bunch of trust anchors.
|
|
||||||
# Some of them are good (enabled.managed, enabled.trusted,
|
|
||||||
# secure.managed, secure.trusted), and some of them are bad
|
|
||||||
# (disabled.managed, revoked.managed, unsupported.managed,
|
|
||||||
# disabled.trusted, revoked.trusted, unsupported.trusted). Make sure
|
|
||||||
# that the bad trust anchors are ignored. This is tested by looking
|
|
||||||
# for the corresponding lines in the logfile.
|
|
||||||
ns5 = servers["ns5"]
|
|
||||||
templates.render("ns5/named.conf", {"many_anchors": True})
|
|
||||||
ns5.reconfigure(log=False)
|
|
||||||
|
|
||||||
# check that keys with unsupported/disabled algorithms are ignored
|
|
||||||
grep_q(
|
|
||||||
"ignoring static-key for 'disabled.trusted.': algorithm is disabled",
|
|
||||||
"ns5/named.run",
|
|
||||||
)
|
|
||||||
grep_q(
|
|
||||||
"ignoring static-key for 'disabled.managed.': algorithm is disabled",
|
|
||||||
"ns5/named.run",
|
|
||||||
)
|
|
||||||
grep_q(
|
|
||||||
"ignoring static-key for 'unsupported.trusted.': algorithm is unsupported",
|
|
||||||
"ns5/named.run",
|
|
||||||
)
|
|
||||||
grep_q(
|
|
||||||
"ignoring static-key for 'unsupported.managed.': algorithm is unsupported",
|
|
||||||
"ns5/named.run",
|
|
||||||
)
|
|
||||||
grep_q("ignoring static-key for 'revoked.trusted.': bad key type", "ns5/named.run")
|
|
||||||
grep_q("ignoring static-key for 'revoked.managed.': bad key type", "ns5/named.run")
|
|
||||||
|
|
||||||
# check that a key with supported algorithm validates as secure
|
|
||||||
msg = isctest.query.create("a.secure.trusted", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
if hasattr(res2, "extended_errors"):
|
|
||||||
assert not res2.extended_errors()
|
|
||||||
|
|
||||||
msg = isctest.query.create("a.secure.managed", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
if hasattr(res2, "extended_errors"):
|
|
||||||
assert not res2.extended_errors()
|
|
||||||
|
|
||||||
# check that an unsupported signing algorithm yields insecure
|
|
||||||
msg = isctest.query.create("a.unsupported.trusted", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
if hasattr(res2, "extended_errors"):
|
|
||||||
assert (
|
|
||||||
res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
|
|
||||||
)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.noadflag(res2)
|
|
||||||
|
|
||||||
msg = isctest.query.create("a.unsupported.managed", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
if hasattr(res2, "extended_errors"):
|
|
||||||
assert (
|
|
||||||
res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
|
|
||||||
)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.noadflag(res2)
|
|
||||||
|
|
||||||
# check that a disabled signing algorithm yields insecure
|
|
||||||
msg = isctest.query.create("a.disabled.trusted", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.noadflag(res2)
|
|
||||||
|
|
||||||
msg = isctest.query.create("a.disabled.managed", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.noadflag(res2)
|
|
||||||
|
|
||||||
# check that zone signed with an algorithm that's disabled for
|
|
||||||
# some other domain, but not for this one, validates as secure.
|
|
||||||
# "enabled.trusted." and "enabled.managed." do not match the
|
|
||||||
# "disable-algorithms" option, so no special rules apply. (static)
|
|
||||||
msg = isctest.query.create("a.enabled.trusted", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
|
|
||||||
msg = isctest.query.create("a.enabled.managed", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
|
|
||||||
# a revoked trust anchor is ignored when configured; check that
|
|
||||||
# this yields insecure.
|
|
||||||
msg = isctest.query.create("a.revoked.trusted", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.noadflag(res2)
|
|
||||||
|
|
||||||
msg = isctest.query.create("a.revoked.managed", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
|
||||||
isctest.check.noerror(res1)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.noadflag(res2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_unknown_algorithms():
|
def test_unknown_algorithms():
|
||||||
# check that unknown DNSKEY algorithm validates as insecure
|
# check that unknown DNSKEY algorithm validates as insecure
|
||||||
msg = isctest.query.create("dnskey-unknown.example", "A", dnssec=False)
|
msg = isctest.query.create("dnskey-unknown.example", "A", dnssec=False)
|
||||||
@@ -1513,117 +1344,3 @@ def test_unknown_algorithms():
|
|||||||
isctest.check.noerror(res1)
|
isctest.check.noerror(res1)
|
||||||
isctest.check.noerror(res2)
|
isctest.check.noerror(res2)
|
||||||
isctest.check.noadflag(res2)
|
isctest.check.noadflag(res2)
|
||||||
|
|
||||||
|
|
||||||
###################################
|
|
||||||
##### BEGIN MANAGED KEY TESTS #####
|
|
||||||
###################################
|
|
||||||
def test_switch_managed(servers, templates):
|
|
||||||
# switch to intializing trust anchor instead of static
|
|
||||||
ns4 = servers["ns4"]
|
|
||||||
assert os.path.exists("ns4/managed-keys.bind.jnl") is False
|
|
||||||
shutil.copyfile("ns4/managed-keys.bind.in", "ns4/managed-keys.bind")
|
|
||||||
templates.render("ns4/named.conf", {"managed_key": True})
|
|
||||||
ns4.reconfigure(log=False)
|
|
||||||
|
|
||||||
|
|
||||||
def test_secure_root_managed(servers):
|
|
||||||
# check that a query for a secure root validates
|
|
||||||
msg = isctest.query.create(".", "KEY")
|
|
||||||
res = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.noerror(res)
|
|
||||||
isctest.check.adflag(res)
|
|
||||||
|
|
||||||
# check that "rndc secroots" dumps the trusted keys
|
|
||||||
ns4 = servers["ns4"]
|
|
||||||
key = int(getfrom("ns1/managed.key.id"))
|
|
||||||
alg = os.environ["DEFAULT_ALGORITHM"]
|
|
||||||
expected = f"./{alg}/{key} ; managed"
|
|
||||||
response = ns4.rndc("secroots -", log=False).splitlines()
|
|
||||||
assert expected in response
|
|
||||||
assert len(response) == 10
|
|
||||||
|
|
||||||
|
|
||||||
def test_positive_validation_nsec_managed():
|
|
||||||
msg = isctest.query.create("a.example", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.2")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.same_answer(res1, res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_positive_validation_nsec3_managed():
|
|
||||||
msg = isctest.query.create("a.nsec3.example", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.same_answer(res1, res2)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_positive_validation_optout_managed():
|
|
||||||
msg = isctest.query.create("a.optout.example", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.same_answer(res1, res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_negative_validation_nsec_managed():
|
|
||||||
# nxdomain
|
|
||||||
msg = isctest.query.create("q.example", "A")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.2")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.same_answer(res1, res2)
|
|
||||||
isctest.check.nxdomain(res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_ds_managed():
|
|
||||||
# check root DS queries validate
|
|
||||||
msg = isctest.query.create(".", "DS")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.1")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.same_data(res1, res2)
|
|
||||||
isctest.check.adflag(res2)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
|
|
||||||
# check DS queries succeed at RFC 1918 empty zone
|
|
||||||
msg = isctest.query.create("10.in-addr.arpa", "DS")
|
|
||||||
res1 = isctest.query.tcp(msg, "10.53.0.2")
|
|
||||||
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
isctest.check.same_data(res1, res2)
|
|
||||||
isctest.check.noerror(res2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_keydata_storage(servers):
|
|
||||||
ns4 = servers["ns4"]
|
|
||||||
ns4.rndc("managed-keys sync", log=False)
|
|
||||||
with isctest.log.WatchLogFromStart("ns4/managed-keys.bind") as watcher:
|
|
||||||
watcher.wait_for_line(["KEYDATA", "next refresh:"])
|
|
||||||
|
|
||||||
|
|
||||||
############################################
|
|
||||||
##### BEGIN MULTIVIEW VALIDATION TESTS #####
|
|
||||||
############################################
|
|
||||||
def test_insecure_staticstub_delegation(servers, templates):
|
|
||||||
ns4 = servers["ns4"]
|
|
||||||
templates.render("ns4/named.conf", {"multi_view": True})
|
|
||||||
ns4.reconfigure(log=False)
|
|
||||||
|
|
||||||
# check insecure delegation between static-stub zones
|
|
||||||
msg = isctest.query.create("insecure.secure.example", "NS")
|
|
||||||
for _ in range(5):
|
|
||||||
res = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
if res.rcode() == rcode.SERVFAIL:
|
|
||||||
time.sleep(1)
|
|
||||||
continue
|
|
||||||
isctest.check.noerror(res)
|
|
||||||
|
|
||||||
msg = isctest.query.create("secure.example", "NS")
|
|
||||||
for _ in range(5):
|
|
||||||
res = isctest.query.tcp(msg, "10.53.0.4")
|
|
||||||
if res.rcode() == rcode.SERVFAIL:
|
|
||||||
time.sleep(1)
|
|
||||||
continue
|
|
||||||
isctest.check.noerror(res)
|
|
||||||
|
64
bin/tests/system/dnssec/tests_validation_accept_expired.py
Normal file
64
bin/tests/system/dnssec/tests_validation_accept_expired.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
# See the COPYRIGHT file distributed with this work for additional
|
||||||
|
# information regarding copyright ownership.
|
||||||
|
|
||||||
|
from dns import flags
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import isctest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
|
def reconfigure(servers, templates):
|
||||||
|
ns4 = servers["ns4"]
|
||||||
|
templates.render("ns4/named.conf", {"accept_expired": True})
|
||||||
|
ns4.reconfigure(log=False)
|
||||||
|
|
||||||
|
|
||||||
|
def test_accept_expired(servers):
|
||||||
|
ns4 = servers["ns4"]
|
||||||
|
|
||||||
|
# test TTL of about-to-expire rrsets with accept-expired
|
||||||
|
ns4.rndc("flush", log=False)
|
||||||
|
msg = isctest.query.create("expiring.example", "SOA")
|
||||||
|
msg.flags |= flags.CD
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
msg = isctest.query.create("expiring.example", "SOA")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
for rrset in res1.answer:
|
||||||
|
assert rrset.ttl <= 3600
|
||||||
|
for rrset in res2.answer:
|
||||||
|
assert rrset.ttl <= 120
|
||||||
|
|
||||||
|
# test TTL is capped at RRSIG expiry time in the additional section
|
||||||
|
# with accept-expired
|
||||||
|
ns4.rndc("flush", log=False)
|
||||||
|
msg = isctest.query.create("expiring.example", "MX")
|
||||||
|
msg.flags |= flags.CD
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
msg = isctest.query.create("expiring.example", "MX")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
for rrset in res1.additional:
|
||||||
|
assert rrset.ttl <= 3600
|
||||||
|
for rrset in res2.additional:
|
||||||
|
assert rrset.ttl <= 120
|
||||||
|
|
||||||
|
# test TTL of expired rrsets with accept-expired
|
||||||
|
ns4.rndc("flush", log=False)
|
||||||
|
msg = isctest.query.create("expired.example", "SOA")
|
||||||
|
msg.flags |= flags.CD
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
msg = isctest.query.create("expired.example", "SOA")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
for rrset in res1.additional:
|
||||||
|
assert rrset.ttl <= 3600
|
||||||
|
for rrset in res2.additional:
|
||||||
|
assert rrset.ttl <= 120
|
108
bin/tests/system/dnssec/tests_validation_managed_keys.py
Normal file
108
bin/tests/system/dnssec/tests_validation_managed_keys.py
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
# See the COPYRIGHT file distributed with this work for additional
|
||||||
|
# information regarding copyright ownership.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import isctest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
|
def reconfigure(servers, templates):
|
||||||
|
ns4 = servers["ns4"]
|
||||||
|
assert os.path.exists("ns4/managed-keys.bind.jnl") is False
|
||||||
|
shutil.copyfile("ns4/managed-keys.bind.in", "ns4/managed-keys.bind")
|
||||||
|
templates.render("ns4/named.conf", {"managed_key": True})
|
||||||
|
ns4.reconfigure(log=False)
|
||||||
|
|
||||||
|
|
||||||
|
# helper functions
|
||||||
|
def getfrom(file):
|
||||||
|
with open(file, encoding="utf-8") as f:
|
||||||
|
return f.read().strip()
|
||||||
|
|
||||||
|
|
||||||
|
def test_secure_root_managed(servers):
|
||||||
|
# check that a query for a secure root validates
|
||||||
|
msg = isctest.query.create(".", "KEY")
|
||||||
|
res = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.noerror(res)
|
||||||
|
isctest.check.adflag(res)
|
||||||
|
|
||||||
|
# check that "rndc secroots" dumps the trusted keys
|
||||||
|
ns4 = servers["ns4"]
|
||||||
|
key = int(getfrom("ns1/managed.key.id"))
|
||||||
|
alg = os.environ["DEFAULT_ALGORITHM"]
|
||||||
|
expected = f"./{alg}/{key} ; managed"
|
||||||
|
response = ns4.rndc("secroots -", log=False).splitlines()
|
||||||
|
assert expected in response
|
||||||
|
assert len(response) == 10
|
||||||
|
|
||||||
|
|
||||||
|
def test_positive_validation_nsec_managed():
|
||||||
|
msg = isctest.query.create("a.example", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.2")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.same_answer(res1, res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_positive_validation_nsec3_managed():
|
||||||
|
msg = isctest.query.create("a.nsec3.example", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.same_answer(res1, res2)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_positive_validation_optout_managed():
|
||||||
|
msg = isctest.query.create("a.optout.example", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.same_answer(res1, res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_negative_validation_nsec_managed():
|
||||||
|
# nxdomain
|
||||||
|
msg = isctest.query.create("q.example", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.2")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.same_answer(res1, res2)
|
||||||
|
isctest.check.nxdomain(res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ds_managed():
|
||||||
|
# check root DS queries validate
|
||||||
|
msg = isctest.query.create(".", "DS")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.1")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.same_data(res1, res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
|
||||||
|
# check DS queries succeed at RFC 1918 empty zone
|
||||||
|
msg = isctest.query.create("10.in-addr.arpa", "DS")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.2")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.same_data(res1, res2)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_keydata_storage(servers):
|
||||||
|
ns4 = servers["ns4"]
|
||||||
|
ns4.rndc("managed-keys sync", log=False)
|
||||||
|
with isctest.log.WatchLogFromStart("ns4/managed-keys.bind") as watcher:
|
||||||
|
watcher.wait_for_line(["KEYDATA", "next refresh:"])
|
137
bin/tests/system/dnssec/tests_validation_many_anchors.py
Normal file
137
bin/tests/system/dnssec/tests_validation_many_anchors.py
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
# See the COPYRIGHT file distributed with this work for additional
|
||||||
|
# information regarding copyright ownership.
|
||||||
|
|
||||||
|
from dns import edns
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import isctest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
|
def reconfigure(servers, templates):
|
||||||
|
ns5 = servers["ns5"]
|
||||||
|
templates.render("ns5/named.conf", {"many_anchors": True})
|
||||||
|
with ns5.watch_log_from_here() as watcher:
|
||||||
|
ns5.reconfigure(log=False)
|
||||||
|
watcher.wait_for_line(
|
||||||
|
[
|
||||||
|
"ignoring static-key for 'disabled.trusted.': algorithm is disabled",
|
||||||
|
"ignoring static-key for 'disabled.managed.': algorithm is disabled",
|
||||||
|
"ignoring static-key for 'unsupported.trusted.': algorithm is unsupported",
|
||||||
|
"ignoring static-key for 'unsupported.managed.': algorithm is unsupported",
|
||||||
|
"ignoring static-key for 'unsupported.managed.': algorithm is unsupported",
|
||||||
|
"ignoring static-key for 'revoked.trusted.': bad key type",
|
||||||
|
"ignoring static-key for 'revoked.managed.': bad key type",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_trust_anchors():
|
||||||
|
# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
|
||||||
|
#
|
||||||
|
# This nameserver is loaded with a bunch of trust anchors.
|
||||||
|
# Some of them are good (enabled.managed, enabled.trusted,
|
||||||
|
# secure.managed, secure.trusted), and some of them are bad
|
||||||
|
# (disabled.managed, revoked.managed, unsupported.managed,
|
||||||
|
# disabled.trusted, revoked.trusted, unsupported.trusted). Make sure
|
||||||
|
# that the bad trust anchors are ignored. This is tested by looking
|
||||||
|
# for the corresponding lines in the logfile.
|
||||||
|
|
||||||
|
# check that a key with supported algorithm validates as secure
|
||||||
|
msg = isctest.query.create("a.secure.trusted", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
if hasattr(res2, "extended_errors"):
|
||||||
|
assert not res2.extended_errors()
|
||||||
|
|
||||||
|
msg = isctest.query.create("a.secure.managed", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
if hasattr(res2, "extended_errors"):
|
||||||
|
assert not res2.extended_errors()
|
||||||
|
|
||||||
|
# check that an unsupported signing algorithm yields insecure
|
||||||
|
msg = isctest.query.create("a.unsupported.trusted", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
if hasattr(res2, "extended_errors"):
|
||||||
|
assert (
|
||||||
|
res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
|
||||||
|
)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.noadflag(res2)
|
||||||
|
|
||||||
|
msg = isctest.query.create("a.unsupported.managed", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
if hasattr(res2, "extended_errors"):
|
||||||
|
assert (
|
||||||
|
res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
|
||||||
|
)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.noadflag(res2)
|
||||||
|
|
||||||
|
# check that a disabled signing algorithm yields insecure
|
||||||
|
msg = isctest.query.create("a.disabled.trusted", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.noadflag(res2)
|
||||||
|
|
||||||
|
msg = isctest.query.create("a.disabled.managed", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.noadflag(res2)
|
||||||
|
|
||||||
|
# check that zone signed with an algorithm that's disabled for
|
||||||
|
# some other domain, but not for this one, validates as secure.
|
||||||
|
# "enabled.trusted." and "enabled.managed." do not match the
|
||||||
|
# "disable-algorithms" option, so no special rules apply. (static)
|
||||||
|
msg = isctest.query.create("a.enabled.trusted", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
|
||||||
|
msg = isctest.query.create("a.enabled.managed", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.adflag(res2)
|
||||||
|
|
||||||
|
# a revoked trust anchor is ignored when configured; check that
|
||||||
|
# this yields insecure.
|
||||||
|
msg = isctest.query.create("a.revoked.trusted", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.noadflag(res2)
|
||||||
|
|
||||||
|
msg = isctest.query.create("a.revoked.managed", "A")
|
||||||
|
res1 = isctest.query.tcp(msg, "10.53.0.3")
|
||||||
|
res2 = isctest.query.tcp(msg, "10.53.0.5")
|
||||||
|
isctest.check.noerror(res1)
|
||||||
|
isctest.check.noerror(res2)
|
||||||
|
isctest.check.noadflag(res2)
|
62
bin/tests/system/dnssec/tests_validation_multiview.py
Normal file
62
bin/tests/system/dnssec/tests_validation_multiview.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
# See the COPYRIGHT file distributed with this work for additional
|
||||||
|
# information regarding copyright ownership.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import isctest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module", autouse=True)
|
||||||
|
def reconfigure(servers, templates):
|
||||||
|
ns4 = servers["ns4"]
|
||||||
|
templates.render("ns4/named.conf", {"multi_view": True})
|
||||||
|
ns4.reconfigure(log=False)
|
||||||
|
|
||||||
|
|
||||||
|
def getfrom(file):
|
||||||
|
with open(file, encoding="utf-8") as f:
|
||||||
|
return f.read().strip()
|
||||||
|
|
||||||
|
|
||||||
|
def test_staticstub_delegations():
|
||||||
|
# check insecure delegation between static-stub zones
|
||||||
|
def docheck():
|
||||||
|
msg = isctest.query.create("insecure.secure.example", "NS")
|
||||||
|
res = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.noerror(res)
|
||||||
|
msg = isctest.query.create("secure.example", "NS")
|
||||||
|
res = isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
isctest.check.noerror(res)
|
||||||
|
return True
|
||||||
|
|
||||||
|
isctest.run.retry_with_timeout(docheck, 5)
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_logging(ns4):
|
||||||
|
# check that validator logging includes the view name with multiple views
|
||||||
|
pattern = re.compile("view rec: *validat")
|
||||||
|
with ns4.watch_log_from_start() as watcher:
|
||||||
|
msg = isctest.query.create("secure.example", "NS")
|
||||||
|
isctest.query.tcp(msg, "10.53.0.4")
|
||||||
|
watcher.wait_for_line(pattern)
|
||||||
|
|
||||||
|
|
||||||
|
def test_secure_roots(ns4):
|
||||||
|
# check that "rndc secroots" dumps the trusted keys with multiple views
|
||||||
|
key = int(getfrom("ns1/managed.key.id"))
|
||||||
|
alg = os.environ["DEFAULT_ALGORITHM"]
|
||||||
|
expected = f"./{alg}/{key} ; static"
|
||||||
|
response = ns4.rndc("secroots -", log=False).splitlines()
|
||||||
|
assert expected in response, response
|
||||||
|
assert len(response) == 17
|
@@ -13,8 +13,6 @@ import os
|
|||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
import isctest
|
import isctest
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user