mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-05 09:05:40 +00:00
If the zone already contains ZONEMD records, they will be updated when signing the zone. If not, ZONEMD records can be added by using the "-Z" option: for instance, "dnssec-signzone -Z - -S example.com". Also, dnssec-verify now verifies the ZONEMD records, if any are present. If run with the "-Z" flag, ZONEMD is mandatory, and the zone will be rejected if it is not present. Some zones in the mirror system test are now signed with ZONEMD.
221 lines
5.7 KiB
Python
221 lines
5.7 KiB
Python
# 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
|
|
|
|
pytestmark = pytest.mark.extra_artifacts(
|
|
[
|
|
"verify.out.*",
|
|
"zones/K*",
|
|
"zones/dsset-*",
|
|
"zones/*.bad",
|
|
"zones/*.good",
|
|
"zones/*.out*",
|
|
"zones/*.tmp",
|
|
"zones/updated*",
|
|
]
|
|
)
|
|
|
|
VERIFY = os.environ.get("VERIFY")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"zone",
|
|
[
|
|
"ksk-only.nsec3",
|
|
"ksk-only.nsec",
|
|
"ksk+zsk.nsec3.apex-dname",
|
|
"ksk+zsk.nsec3",
|
|
"ksk+zsk.nsec.apex-dname",
|
|
"ksk+zsk.nsec",
|
|
"ksk+zsk.optout",
|
|
"zsk-only.nsec3",
|
|
"zsk-only.nsec",
|
|
],
|
|
)
|
|
def test_verify_good_zone_files(zone):
|
|
isctest.run.cmd([VERIFY, "-z", "-o", zone, f"zones/{zone}.good"])
|
|
|
|
|
|
def test_verify_good_zone_nsec_next_name_case_mismatch():
|
|
isctest.run.cmd(
|
|
[
|
|
VERIFY,
|
|
"-o",
|
|
"nsec-next-name-case-mismatch",
|
|
"zones/nsec-next-name-case-mismatch.good",
|
|
],
|
|
)
|
|
|
|
|
|
def get_bad_zone_output(zone):
|
|
only_opt = ["-z"] if re.match(r"[zk]sk-only", zone) else []
|
|
output = isctest.run.cmd(
|
|
[VERIFY, *only_opt, "-o", zone, f"zones/{zone}.bad"],
|
|
raise_on_exception=False,
|
|
)
|
|
stream = (output.stdout + output.stderr).decode("utf-8").replace("\n", "")
|
|
return stream
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"zone",
|
|
[
|
|
"ksk-only.dnskeyonly",
|
|
"ksk+zsk.dnskeyonly",
|
|
"zsk-only.dnskeyonly",
|
|
],
|
|
)
|
|
def test_verify_bad_zone_files_dnskeyonly(zone):
|
|
assert re.match(r".*DNSKEY is not signed.*", get_bad_zone_output(zone))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"zone",
|
|
[
|
|
"ksk-only.nsec3.expired",
|
|
"ksk-only.nsec.expired",
|
|
"ksk+zsk.nsec3.expired",
|
|
"ksk+zsk.nsec.expired",
|
|
"ksk+zsk.nsec.ksk-expired",
|
|
"zsk-only.nsec3.expired",
|
|
"zsk-only.nsec.expired",
|
|
"ksk+zsk.nsec3.ksk-expired",
|
|
],
|
|
)
|
|
def test_verify_bad_zone_files_expired(zone):
|
|
assert re.match(
|
|
r".*signature has expired.*|.*No self-signed .*DNSKEY found.*",
|
|
get_bad_zone_output(zone),
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"zone",
|
|
[
|
|
"ksk+zsk.nsec.out-of-zone-nsec",
|
|
"ksk+zsk.nsec.below-bottom-of-zone-nsec",
|
|
"ksk+zsk.nsec.below-dname-nsec",
|
|
],
|
|
)
|
|
def test_verify_bad_zone_files_unexpected_nsec_rrset(zone):
|
|
assert re.match(r".*unexpected NSEC RRset at.*", get_bad_zone_output(zone))
|
|
|
|
|
|
def test_verify_bad_zone_files_bad_nsec_record():
|
|
assert re.match(
|
|
r".*Bad NSEC record for.*, next name mismatch.*",
|
|
get_bad_zone_output("ksk+zsk.nsec.broken-chain"),
|
|
)
|
|
|
|
|
|
def test_verify_bad_zone_files_bad_bitmap():
|
|
assert re.match(
|
|
r".*bit map mismatch.*", get_bad_zone_output("ksk+zsk.nsec.bad-bitmap")
|
|
)
|
|
|
|
|
|
def test_verify_bad_zone_files_missing_nsec3_record():
|
|
assert re.match(
|
|
r".*Missing NSEC3 record for.*",
|
|
get_bad_zone_output("ksk+zsk.nsec3.missing-empty"),
|
|
)
|
|
|
|
|
|
def test_verify_bad_zone_files_no_dnssec_keys():
|
|
assert re.match(
|
|
r".*Zone contains no DNSSEC keys.*", get_bad_zone_output("unsigned")
|
|
)
|
|
|
|
|
|
def test_verify_bad_zone_files_unequal_nsec3_chains():
|
|
assert re.match(
|
|
r".*Expected and found NSEC3 chains not equal.*",
|
|
get_bad_zone_output("ksk+zsk.nsec3.extra-nsec3"),
|
|
)
|
|
|
|
|
|
# checking error message when -o is not used
|
|
# and a SOA record not at top of zone is found
|
|
def test_verify_soa_not_at_top_error():
|
|
# when -o is not used, origin is set to zone file name,
|
|
# which should cause an error in this case
|
|
output = isctest.run.cmd(
|
|
[VERIFY, "zones/ksk+zsk.nsec.good"], raise_on_exception=False
|
|
).stderr.decode("utf-8")
|
|
assert "not at top of zone" in output
|
|
assert "use -o to specify a different zone origin" in output
|
|
|
|
|
|
# checking error message when an invalid -o is specified
|
|
# and a SOA record not at top of zone is found
|
|
def test_verify_invalid_o_option_soa_not_at_top_error():
|
|
output = isctest.run.cmd(
|
|
[VERIFY, "-o", "invalid.origin", "zones/ksk+zsk.nsec.good"],
|
|
raise_on_exception=False,
|
|
).stderr.decode("utf-8")
|
|
assert "not at top of zone" in output
|
|
assert "use -o to specify a different zone origin" not in output
|
|
|
|
|
|
# checking dnssec-verify -J reads journal file
|
|
def test_verify_j_reads_journal_file():
|
|
output = isctest.run.cmd(
|
|
[
|
|
VERIFY,
|
|
"-o",
|
|
"updated",
|
|
"-J",
|
|
"zones/updated.other.jnl",
|
|
"zones/updated.other",
|
|
]
|
|
).stdout.decode("utf-8")
|
|
assert "Loading zone 'updated' from file 'zones/updated.other'" in output
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"zone",
|
|
[
|
|
"ksk+zsk.zonemd.nsec",
|
|
"ksk+zsk.zonemd.nsec3",
|
|
],
|
|
)
|
|
def test_verify_zonemd(zone):
|
|
output = isctest.run.cmd(
|
|
[VERIFY, "-o", zone, f"zones/{zone}.good"],
|
|
raise_on_exception=False,
|
|
log_stdout=True,
|
|
)
|
|
stream = (output.stdout + output.stderr).decode("utf-8").replace("\n", "")
|
|
assert "ZONEMD verification: success" in stream
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"zone",
|
|
[
|
|
"ksk+zsk.nsec",
|
|
"ksk+zsk.nsec3",
|
|
],
|
|
)
|
|
def test_verify_no_zonemd(zone):
|
|
output = isctest.run.cmd(
|
|
[VERIFY, "-Zo", zone, f"zones/{zone}.good"],
|
|
raise_on_exception=False,
|
|
log_stdout=True,
|
|
)
|
|
stream = (output.stdout + output.stderr).decode("utf-8").replace("\n", "")
|
|
assert "Valid ZONEMD required but not present" in stream
|