mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +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 time
|
||||
|
||||
from dns import edns, flags, name, rcode, rdataclass, rdatatype
|
||||
from dns import edns, flags, name, rdataclass, rdatatype
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -1184,49 +1184,6 @@ def test_expired_signatures(servers):
|
||||
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():
|
||||
# test legacy upper-case signer name validation
|
||||
msg = isctest.query.create("upper.example", "SOA")
|
||||
@@ -1318,132 +1275,6 @@ def test_pending_ds(servers):
|
||||
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():
|
||||
# check that unknown DNSKEY algorithm validates as insecure
|
||||
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(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 time
|
||||
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user