mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Refactor NamedInstance.rndc() to use EnvCmd() interface
To unify the command handling, utilize EnvCmd() to handle rndc commands:
1. Remove isctest.rndc abstractions. They were intended for an upcoming
python-only implementation. A couple of years later, it doesn't seem
to be coming any time soon, so let's stick with the interface that
makes sense today, i.e. use the same command handling interface
everywhere.
2. Remove the specialized rndc.log in favor of the generic logging
already implemented by isctest.run.cmd(). I believe the cause of the
many rndc(log=False) invocations was that nobody wanted this extra
file. Yet, logging everything by default makes sense for debugging,
unless there's a good reason not to. In almost all cases, logging was
switched to the default (enabled).
3. With the NamedInstance.rndc() call now returning CmdResult rather
than combined stdout+stderr string, adjust all the invocations to use
`.out` or `.err` as necessary.
4. Replace some manual rndc invocation and its base argument
construction with the standardized nsX.rndc() call.
5. In cases where rndc is expected to fail, utilize
raise_on_exception=False and check the `.rc` from the result, rather
than handling an exception.
6. In addzone/tests_rndc_deadlock.py, refactor the test slightly to
avoid using EnvCmd() entirely to avoid spamming the logs. This test
calls rndc in a loop from multiple threads and such test case is an
exception which doesn't warrant changing the `isctest.run.cmd()`
implementation.
(cherry picked from commit f33e2b6d87)
This commit is contained in:
parent
0f64e490bb
commit
6f51eeb8ef
17 changed files with 107 additions and 283 deletions
|
|
@ -10,12 +10,12 @@
|
|||
# information regarding copyright ownership.
|
||||
|
||||
import concurrent.futures
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"ns*/*.nzf*",
|
||||
|
|
@ -43,20 +43,19 @@ def rndc_loop(test_state, domain, ns3):
|
|||
["delzone", domain],
|
||||
]
|
||||
|
||||
args = [os.environ["RNDC"]] + ns3.rndc_args.split()
|
||||
while not test_state["finished"]:
|
||||
for command in rndc_commands:
|
||||
ns3.rndc(" ".join(command), ignore_errors=True, log=False)
|
||||
# avoid using ns3.rndc() directly to avoid log spam
|
||||
subprocess.run(args + " ".join(command), timeout=10, check=False)
|
||||
|
||||
|
||||
def check_if_server_is_responsive(ns3):
|
||||
"""
|
||||
Check if server status can be successfully retrieved using "rndc status"
|
||||
"""
|
||||
try:
|
||||
ns3.rndc("status", log=False)
|
||||
return True
|
||||
except isctest.rndc.RNDCException:
|
||||
return False
|
||||
cmd = ns3.rndc("status", raise_on_exception=False)
|
||||
return cmd.rc == 0
|
||||
|
||||
|
||||
def test_rndc_deadlock(ns3):
|
||||
|
|
|
|||
|
|
@ -189,33 +189,6 @@ def keystate_check(server, zone, key):
|
|||
assert val != 0
|
||||
|
||||
|
||||
def rekey(zone):
|
||||
rndc = os.getenv("RNDC")
|
||||
assert rndc is not None
|
||||
|
||||
port = os.getenv("CONTROLPORT")
|
||||
assert port is not None
|
||||
|
||||
# rndc loadkeys.
|
||||
rndc_cmd = [
|
||||
rndc,
|
||||
"-c",
|
||||
"../_common/rndc.conf",
|
||||
"-p",
|
||||
port,
|
||||
"-s",
|
||||
"10.53.0.9",
|
||||
"loadkeys",
|
||||
zone,
|
||||
]
|
||||
controller = isctest.run.cmd(rndc_cmd)
|
||||
|
||||
if controller.rc != 0:
|
||||
isctest.log.error(f"rndc loadkeys {zone} failed")
|
||||
|
||||
assert controller.rc == 0
|
||||
|
||||
|
||||
class CheckDSTest(NamedTuple):
|
||||
zone: str
|
||||
logs_to_wait_for: Tuple[str]
|
||||
|
|
@ -472,7 +445,7 @@ def test_checkds(ns2, ns9, params):
|
|||
for log_string in params.logs_to_wait_for:
|
||||
line = f"zone {params.zone}/IN (signed): checkds: {log_string}"
|
||||
while line not in ns9.log:
|
||||
rekey(params.zone)
|
||||
ns9.rndc(f"loadkeys {params.zone}")
|
||||
time_remaining -= 1
|
||||
assert time_remaining, f'Timed out waiting for "{log_string}" to be logged'
|
||||
time.sleep(1)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ from . import check
|
|||
from . import instance
|
||||
from . import query
|
||||
from . import kasp
|
||||
from . import rndc
|
||||
from . import run
|
||||
from . import template
|
||||
from . import log
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
from typing import List, NamedTuple, Optional
|
||||
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
|
@ -21,9 +20,8 @@ import re
|
|||
import dns.message
|
||||
import dns.rcode
|
||||
|
||||
from .log import debug, info, WatchLogFromStart, WatchLogFromHere
|
||||
from .rndc import RNDCBinaryExecutor, RNDCException, RNDCExecutor
|
||||
from .run import perl
|
||||
from .log import debug, WatchLogFromStart, WatchLogFromHere
|
||||
from .run import CmdResult, EnvCmd, perl
|
||||
from .query import udp
|
||||
from .text import TextFile
|
||||
|
||||
|
|
@ -57,8 +55,6 @@ class NamedInstance:
|
|||
identifier: str,
|
||||
num: Optional[int] = None,
|
||||
ports: Optional[NamedPorts] = None,
|
||||
rndc_logger: Optional[logging.Logger] = None,
|
||||
rndc_executor: Optional[RNDCExecutor] = None,
|
||||
) -> None:
|
||||
"""
|
||||
`identifier` is the name of the instance's directory
|
||||
|
|
@ -71,12 +67,6 @@ class NamedInstance:
|
|||
this `named` instance is listening for various types of traffic (both
|
||||
DNS traffic and RNDC commands). Defaults to ports set by the test
|
||||
framework.
|
||||
|
||||
`rndc_logger` is the `logging.Logger` to use for logging RNDC
|
||||
commands sent to this `named` instance.
|
||||
|
||||
`rndc_executor` is an object implementing the `RNDCExecutor` interface
|
||||
that is used for executing RNDC commands on this `named` instance.
|
||||
"""
|
||||
self.directory = Path(identifier).absolute()
|
||||
if not self.directory.is_dir():
|
||||
|
|
@ -89,8 +79,14 @@ class NamedInstance:
|
|||
ports = NamedPorts.from_env()
|
||||
self.ports = ports
|
||||
self.log = TextFile(os.path.join(identifier, "named.run"))
|
||||
self._rndc_executor = rndc_executor or RNDCBinaryExecutor()
|
||||
self._rndc_logger = rndc_logger
|
||||
|
||||
self._rndc_conf = Path("../_common/rndc.conf").absolute()
|
||||
self._rndc = EnvCmd("RNDC", self.rndc_args)
|
||||
|
||||
@property
|
||||
def rndc_args(self) -> str:
|
||||
"""Base arguments for calling RNDC to control the instance."""
|
||||
return f"-c {self._rndc_conf} -s {self.ip} -p {self.ports.rndc}"
|
||||
|
||||
@property
|
||||
def ip(self) -> str:
|
||||
|
|
@ -108,52 +104,16 @@ class NamedInstance:
|
|||
assert num is None or num == parsed_num, "mismatched num and identifier"
|
||||
return parsed_num
|
||||
|
||||
def rndc(self, command: str, ignore_errors: bool = False, log: bool = True) -> str:
|
||||
def rndc(self, command: str, timeout=10, **kwargs) -> CmdResult:
|
||||
"""
|
||||
Send `command` to this named instance using RNDC. Return the server's
|
||||
response.
|
||||
|
||||
If the RNDC command fails, an `RNDCException` is raised unless
|
||||
`ignore_errors` is set to `True`.
|
||||
|
||||
The RNDC command will be logged to `rndc.log` (along with the server's
|
||||
response) unless `log` is set to `False`.
|
||||
|
||||
```python
|
||||
def test_foo(servers):
|
||||
# Send the "status" command to ns1. An `RNDCException` will be
|
||||
# raised if the RNDC command fails. This command will be logged.
|
||||
response = servers["ns1"].rndc("status")
|
||||
|
||||
# Send the "thaw foo" command to ns2. No exception will be raised
|
||||
# in case the RNDC command fails. This command will be logged
|
||||
# (even if it fails).
|
||||
response = servers["ns2"].rndc("thaw foo", ignore_errors=True)
|
||||
|
||||
# Send the "stop" command to ns3. An `RNDCException` will be
|
||||
# raised if the RNDC command fails, but this command will not be
|
||||
# logged (the server's response will still be returned to the
|
||||
# caller, though).
|
||||
response = servers["ns3"].rndc("stop", log=False)
|
||||
|
||||
# Send the "halt" command to ns4 in "fire & forget mode": no
|
||||
# exceptions will be raised and no logging will take place (the
|
||||
# server's response will still be returned to the caller, though).
|
||||
response = servers["ns4"].rndc("stop", ignore_errors=True, log=False)
|
||||
```
|
||||
To suppress exceptions, redirect outputs, control logging change
|
||||
timeout etc. use keyword arguments which are passed to
|
||||
isctest.cmd.run().
|
||||
"""
|
||||
try:
|
||||
response = self._rndc_executor.call(self.ip, self.ports.rndc, command)
|
||||
if log:
|
||||
self._rndc_log(command, response)
|
||||
except RNDCException as exc:
|
||||
response = str(exc)
|
||||
if log:
|
||||
self._rndc_log(command, response)
|
||||
if not ignore_errors:
|
||||
raise
|
||||
|
||||
return response
|
||||
return self._rndc(command, timeout=timeout, **kwargs)
|
||||
|
||||
def nsupdate(
|
||||
self, update_msg: dns.message.Message, expected_rcode=dns.rcode.NOERROR
|
||||
|
|
@ -199,31 +159,15 @@ class NamedInstance:
|
|||
"""
|
||||
return WatchLogFromHere(self.log.path, timeout)
|
||||
|
||||
def reconfigure(self, **kwargs) -> None:
|
||||
def reconfigure(self, **kwargs) -> CmdResult:
|
||||
"""
|
||||
Reconfigure this named `instance` and wait until reconfiguration is
|
||||
finished. Raise an `RNDCException` if reconfiguration fails.
|
||||
finished.
|
||||
"""
|
||||
with self.watch_log_from_here() as watcher:
|
||||
self.rndc("reconfig", **kwargs)
|
||||
cmd = self.rndc("reconfig", **kwargs)
|
||||
watcher.wait_for_line("any newly configured zones are now loaded")
|
||||
|
||||
def _rndc_log(self, command: str, response: str) -> None:
|
||||
"""
|
||||
Log an `rndc` invocation (and its output) to the `rndc.log` file in the
|
||||
current working directory.
|
||||
"""
|
||||
fmt = '%(ip)s: "%(command)s"\n%(separator)s\n%(response)s%(separator)s'
|
||||
args = {
|
||||
"ip": self.ip,
|
||||
"command": command,
|
||||
"separator": "-" * 80,
|
||||
"response": response,
|
||||
}
|
||||
if self._rndc_logger is None:
|
||||
info(fmt, args)
|
||||
else:
|
||||
self._rndc_logger.info(fmt, args)
|
||||
return cmd
|
||||
|
||||
def stop(self, args: Optional[List[str]] = None) -> None:
|
||||
"""Stop the instance."""
|
||||
|
|
|
|||
|
|
@ -838,19 +838,19 @@ def check_dnssecstatus(server, zone, keys, policy=None, view=None):
|
|||
# policy name is returned, and if all expected keys are listed.
|
||||
response = ""
|
||||
if view is None:
|
||||
response = server.rndc(f"dnssec -status {zone}", log=False)
|
||||
response = server.rndc(f"dnssec -status {zone}")
|
||||
else:
|
||||
response = server.rndc(f"dnssec -status {zone} in {view}", log=False)
|
||||
response = server.rndc(f"dnssec -status {zone} in {view}")
|
||||
|
||||
if policy is None:
|
||||
assert "Zone does not have dnssec-policy" in response
|
||||
assert "Zone does not have dnssec-policy" in response.out
|
||||
return
|
||||
|
||||
assert f"dnssec-policy: {policy}" in response
|
||||
assert f"dnssec-policy: {policy}" in response.out
|
||||
|
||||
for key in keys:
|
||||
if not key.external:
|
||||
assert f"key: {key.tag}" in response
|
||||
assert f"key: {key.tag}" in response.out
|
||||
|
||||
|
||||
def _check_signatures(
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
# 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 abc
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
class RNDCExecutor(abc.ABC):
|
||||
"""
|
||||
An interface which RNDC executors have to implement in order for the
|
||||
`NamedInstance` class to be able to use them.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def call(self, ip: str, port: int, command: str) -> str:
|
||||
"""
|
||||
Send RNDC `command` to the `named` instance at `ip:port` and return the
|
||||
server's response.
|
||||
"""
|
||||
|
||||
|
||||
class RNDCException(Exception):
|
||||
"""
|
||||
Raised by classes implementing the `RNDCExecutor` interface when sending an
|
||||
RNDC command fails for any reason.
|
||||
"""
|
||||
|
||||
|
||||
class RNDCBinaryExecutor(RNDCExecutor):
|
||||
"""
|
||||
An `RNDCExecutor` which sends RNDC commands to servers using the `rndc`
|
||||
binary.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
This class needs the `RNDC` environment variable to be set to the path
|
||||
to the `rndc` binary to use.
|
||||
"""
|
||||
rndc_path = os.environ.get("RNDC", "/bin/false")
|
||||
rndc_conf = os.path.join("..", "_common", "rndc.conf")
|
||||
self._base_cmdline = [rndc_path, "-c", rndc_conf]
|
||||
|
||||
def call(self, ip: str, port: int, command: str) -> str:
|
||||
"""
|
||||
Send RNDC `command` to the `named` instance at `ip:port` and return the
|
||||
server's response.
|
||||
"""
|
||||
cmdline = self._base_cmdline[:]
|
||||
cmdline.extend(["-s", ip])
|
||||
cmdline.extend(["-p", str(port)])
|
||||
cmdline.extend(command.split())
|
||||
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
cmdline, stderr=subprocess.STDOUT, timeout=10, encoding="utf-8"
|
||||
)
|
||||
except subprocess.SubprocessError as exc:
|
||||
msg = getattr(exc, "output", "RNDC exception occurred")
|
||||
raise RNDCException(msg) from exc
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from datetime import timedelta
|
||||
|
|
@ -200,7 +201,7 @@ def cb_ixfr_is_signed(expected_updates, params, ksks=None, zsks=None):
|
|||
f"expected updates {expected_updates} policy {policy} ksks {ksks} zsks {zsks}"
|
||||
)
|
||||
shutil.copyfile(f"ns2/{zone}.db.in2", f"ns2/{zone}.db")
|
||||
servers["ns2"].rndc(f"reload {zone}", log=False)
|
||||
servers["ns2"].rndc(f"reload {zone}")
|
||||
|
||||
def update_is_signed():
|
||||
parts = update.split()
|
||||
|
|
@ -314,7 +315,7 @@ def cb_remove_keyfiles(params, ksks=None, zsks=None):
|
|||
os.remove(k.statefile)
|
||||
|
||||
with servers["ns3"].watch_log_from_here() as watcher:
|
||||
servers["ns3"].rndc(f"loadkeys {zone}", log=False)
|
||||
servers["ns3"].rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(
|
||||
f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
)
|
||||
|
|
@ -806,9 +807,9 @@ def test_kasp_inherit_view(number, dynamic, inline_signing, txt_rdata, ns4):
|
|||
isctest.kasp.check_dnssecstatus(ns4, zone, keys, policy=policy, view=view)
|
||||
isctest.kasp.check_apex(ns4, zone, keys, [], tsig=tsig)
|
||||
# check zonestatus
|
||||
response = ns4.rndc(f"zonestatus {zone} in {view}", log=False)
|
||||
assert f"dynamic: {dynamic}" in response
|
||||
assert f"inline signing: {inline_signing}" in response
|
||||
response = ns4.rndc(f"zonestatus {zone} in {view}")
|
||||
assert f"dynamic: {dynamic}" in response.out
|
||||
assert f"inline signing: {inline_signing}" in response.out
|
||||
# check subdomain
|
||||
fqdn = f"{zone}."
|
||||
qname = f"view.{zone}."
|
||||
|
|
@ -869,7 +870,7 @@ def test_kasp_default(ns3):
|
|||
state_stat = os.stat(key.statefile)
|
||||
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"loadkeys {zone}", log=False)
|
||||
ns3.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
assert privkey_stat.st_mtime == os.stat(key.privatefile).st_mtime
|
||||
|
|
@ -878,7 +879,7 @@ def test_kasp_default(ns3):
|
|||
|
||||
# again
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"loadkeys {zone}", log=False)
|
||||
ns3.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
assert privkey_stat.st_mtime == os.stat(key.privatefile).st_mtime
|
||||
|
|
@ -888,7 +889,7 @@ def test_kasp_default(ns3):
|
|||
# modify unsigned zone file and check that new record is signed.
|
||||
isctest.log.info("check that an updated zone signs the new record")
|
||||
shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db")
|
||||
ns3.rndc(f"reload {zone}", log=False)
|
||||
ns3.rndc(f"reload {zone}")
|
||||
|
||||
def update_is_signed():
|
||||
parts = update.split()
|
||||
|
|
@ -909,7 +910,7 @@ def test_kasp_default(ns3):
|
|||
shutil.move(f"{key.privatefile}", f"{key.path}.offline")
|
||||
expectmsg = "zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"loadkeys {zone}", log=False)
|
||||
ns3.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"zone {zone}/IN (signed): {expectmsg}")
|
||||
# Nothing has changed.
|
||||
expected[0].private = False # noqa
|
||||
|
|
@ -986,7 +987,7 @@ def test_kasp_dynamic(ns3):
|
|||
# Update zone with freeze/thaw.
|
||||
isctest.log.info("check dynamic zone is updated and signed after freeze and thaw")
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"freeze {zone}", log=False)
|
||||
ns3.rndc(f"freeze {zone}")
|
||||
watcher.wait_for_line(f"freezing zone '{zone}/IN': success")
|
||||
|
||||
time.sleep(1)
|
||||
|
|
@ -995,7 +996,7 @@ def test_kasp_dynamic(ns3):
|
|||
time.sleep(1)
|
||||
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"thaw {zone}", log=False)
|
||||
ns3.rndc(f"thaw {zone}")
|
||||
watcher.wait_for_line(f"thawing zone '{zone}/IN': success")
|
||||
|
||||
expected_updates = [f"a.{zone}. A 10.0.0.1", f"d.{zone}. A 10.0.0.44"]
|
||||
|
|
@ -1024,7 +1025,7 @@ def test_kasp_dynamic(ns3):
|
|||
"check dynamic inline-signed zone is updated and signed after freeze and thaw"
|
||||
)
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"freeze {zone}", log=False)
|
||||
ns3.rndc(f"freeze {zone}")
|
||||
watcher.wait_for_line(f"freezing zone '{zone}/IN': success")
|
||||
|
||||
time.sleep(1)
|
||||
|
|
@ -1032,7 +1033,7 @@ def test_kasp_dynamic(ns3):
|
|||
time.sleep(1)
|
||||
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"thaw {zone}", log=False)
|
||||
ns3.rndc(f"thaw {zone}")
|
||||
watcher.wait_for_line(f"thawing zone '{zone}/IN': success")
|
||||
|
||||
expected_updates = [f"a.{zone}. A 10.0.0.11", f"d.{zone}. A 10.0.0.44"]
|
||||
|
|
@ -1089,7 +1090,7 @@ def test_kasp_checkds(ns3):
|
|||
ksk = ksks[0]
|
||||
|
||||
isctest.log.info("check if checkds -publish correctly sets DSPublish")
|
||||
ns3.rndc(f"dnssec -checkds -when {now} published {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -checkds -when {now} published {zone}")
|
||||
metadata = f"DSPublish: {now}"
|
||||
isctest.run.retry_with_timeout(wait_for_metadata, timeout=3)
|
||||
expected[0].metadata["DSState"] = "rumoured"
|
||||
|
|
@ -1097,7 +1098,7 @@ def test_kasp_checkds(ns3):
|
|||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
|
||||
isctest.log.info("check if checkds -withdrawn correctly sets DSRemoved")
|
||||
ns3.rndc(f"dnssec -checkds -when {now} withdrawn {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -checkds -when {now} withdrawn {zone}")
|
||||
metadata = f"DSRemoved: {now}"
|
||||
isctest.run.retry_with_timeout(wait_for_metadata, timeout=3)
|
||||
expected[0].metadata["DSState"] = "unretentive"
|
||||
|
|
@ -1137,8 +1138,8 @@ def test_kasp_checkds_doubleksk(ns3):
|
|||
isctest.log.info("check invalid checkds commands")
|
||||
|
||||
def check_error():
|
||||
response = ns3.rndc(test["command"], log=False)
|
||||
assert test["error"] in response
|
||||
response = ns3.rndc(test["command"], stderr=subprocess.STDOUT)
|
||||
assert test["error"] in response.out
|
||||
|
||||
test_cases = [
|
||||
{
|
||||
|
|
@ -1162,7 +1163,7 @@ def test_kasp_checkds_doubleksk(ns3):
|
|||
check_error()
|
||||
|
||||
isctest.log.info("check if checkds -publish -key correctly sets DSPublish")
|
||||
ns3.rndc(f"dnssec -checkds -when {now} -key {ksk.tag} published {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -checkds -when {now} -key {ksk.tag} published {zone}")
|
||||
metadata = f"DSPublish: {now}"
|
||||
isctest.run.retry_with_timeout(wait_for_metadata, timeout=3)
|
||||
expected[0].metadata["DSState"] = "rumoured"
|
||||
|
|
@ -1171,7 +1172,7 @@ def test_kasp_checkds_doubleksk(ns3):
|
|||
|
||||
isctest.log.info("check if checkds -withdrawn -key correctly sets DSRemoved")
|
||||
ksk = ksks[1]
|
||||
ns3.rndc(f"dnssec -checkds -when {now} -key {ksk.tag} withdrawn {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -checkds -when {now} -key {ksk.tag} withdrawn {zone}")
|
||||
metadata = f"DSRemoved: {now}"
|
||||
isctest.run.retry_with_timeout(wait_for_metadata, timeout=3)
|
||||
expected[1].metadata["DSState"] = "unretentive"
|
||||
|
|
@ -1204,7 +1205,7 @@ def test_kasp_checkds_csk(ns3):
|
|||
ksk = keys[0]
|
||||
|
||||
isctest.log.info("check if checkds -publish csk correctly sets DSPublish")
|
||||
ns3.rndc(f"dnssec -checkds -when {now} published {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -checkds -when {now} published {zone}")
|
||||
metadata = f"DSPublish: {now}"
|
||||
isctest.run.retry_with_timeout(wait_for_metadata, timeout=3)
|
||||
expected[0].metadata["DSState"] = "rumoured"
|
||||
|
|
@ -1212,7 +1213,7 @@ def test_kasp_checkds_csk(ns3):
|
|||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
|
||||
isctest.log.info("check if checkds -withdrawn csk correctly sets DSRemoved")
|
||||
ns3.rndc(f"dnssec -checkds -when {now} withdrawn {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -checkds -when {now} withdrawn {zone}")
|
||||
metadata = f"DSRemoved: {now}"
|
||||
isctest.run.retry_with_timeout(wait_for_metadata, timeout=3)
|
||||
expected[0].metadata["DSState"] = "unretentive"
|
||||
|
|
@ -1596,7 +1597,7 @@ def test_kasp_zsk_retired(ns3):
|
|||
|
||||
# Load again, make sure the purged key is not an issue when verifying keys.
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"loadkeys {zone}", log=False)
|
||||
ns3.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
msg = f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
|
|
@ -1620,7 +1621,7 @@ def test_kasp_purge_keys(ns4):
|
|||
# Reconfig, make sure the purged key is not an issue when verifying keys.
|
||||
shutil.copyfile("ns4/purgekeys2.conf", "ns4/purgekeys.conf")
|
||||
with ns4.watch_log_from_here() as watcher:
|
||||
ns4.rndc("reconfig", log=False)
|
||||
ns4.rndc("reconfig")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
msg = f"zone {zone}/IN/example1 (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
|
|
@ -1666,7 +1667,7 @@ def test_kasp_reload_restart(ns6):
|
|||
|
||||
shutil.copyfile(f"ns6/{zone}2.db.in", f"ns6/{zone}.db")
|
||||
with ns6.watch_log_from_here() as watcher:
|
||||
ns6.rndc("reload", log=False)
|
||||
ns6.rndc("reload")
|
||||
watcher.wait_for_line("all zones loaded")
|
||||
|
||||
newttl = 300
|
||||
|
|
@ -1743,7 +1744,7 @@ def test_kasp_manual_mode(ns3):
|
|||
|
||||
# Force step.
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"dnssec -step {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -step {zone}")
|
||||
watcher.wait_for_line(
|
||||
f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
)
|
||||
|
|
@ -1756,7 +1757,7 @@ def test_kasp_manual_mode(ns3):
|
|||
|
||||
# Load keys.
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"loadkeys {zone}", log=False)
|
||||
ns3.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(blockmsg)
|
||||
|
||||
# Check keys again, make sure no new keys are created.
|
||||
|
|
@ -1767,7 +1768,7 @@ def test_kasp_manual_mode(ns3):
|
|||
|
||||
# Force step.
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"dnssec -step {zone}", log=False)
|
||||
ns3.rndc(f"dnssec -step {zone}")
|
||||
watcher.wait_for_line(
|
||||
f"zone {zone}/IN (signed): zone_rekey done: key {tag}/ECDSAP256SHA256"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
|
||||
def test_dig_tcp_keepalive_handling(named_port, ns2):
|
||||
def get_keepalive_options_received():
|
||||
ns2.rndc("stats", log=False)
|
||||
ns2.rndc("stats")
|
||||
options_received = 0
|
||||
with open("ns2/named.stats", "r", encoding="utf-8") as ns2_stats_file:
|
||||
for line in ns2_stats_file:
|
||||
|
|
@ -55,11 +55,11 @@ def test_dig_tcp_keepalive_handling(named_port, ns2):
|
|||
)
|
||||
|
||||
isctest.log.info("check a re-configured keepalive value")
|
||||
response = ns2.rndc("tcp-timeouts 300 300 300 200", log=False)
|
||||
assert "tcp-initial-timeout=300" in response
|
||||
assert "tcp-idle-timeout=300" in response
|
||||
assert "tcp-keepalive-timeout=300" in response
|
||||
assert "tcp-advertised-timeout=200" in response
|
||||
response = ns2.rndc("tcp-timeouts 300 300 300 200")
|
||||
assert "tcp-initial-timeout=300" in response.out
|
||||
assert "tcp-idle-timeout=300" in response.out
|
||||
assert "tcp-keepalive-timeout=300" in response.out
|
||||
assert "tcp-advertised-timeout=200" in response.out
|
||||
assert (
|
||||
"; TCP-KEEPALIVE: 20.0 secs"
|
||||
in dig("+tcp +keepalive foo.example. @10.53.0.2").out
|
||||
|
|
|
|||
|
|
@ -740,13 +740,12 @@ def test_ksr_common(ns1):
|
|||
f"addzone {zone} "
|
||||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
+ "};"
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test zone is correctly signed
|
||||
# - check rndc dnssec -status output
|
||||
|
|
@ -815,12 +814,11 @@ def test_ksr_lastbundle(ns1):
|
|||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test zone is correctly signed
|
||||
# - check rndc dnssec -status output
|
||||
|
|
@ -894,12 +892,11 @@ def test_ksr_inthemiddle(ns1):
|
|||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test zone is correctly signed
|
||||
# - check rndc dnssec -status output
|
||||
|
|
@ -965,12 +962,11 @@ def check_ksr_rekey_logs_error(server, zone, policy, offset, end):
|
|||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
server.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
server.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test that rekey logs error
|
||||
time_remaining = 10
|
||||
|
|
@ -1088,12 +1084,11 @@ def test_ksr_unlimited(ns1):
|
|||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test zone is correctly signed
|
||||
# - check rndc dnssec -status output
|
||||
|
|
@ -1199,12 +1194,11 @@ def test_ksr_twotone(ns1):
|
|||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test zone is correctly signed
|
||||
# - check rndc dnssec -status output
|
||||
|
|
@ -1278,12 +1272,11 @@ def test_ksr_kskroll(ns1):
|
|||
+ "{ type primary; file "
|
||||
+ f'"{zone}.db"; dnssec-policy {policy}; '
|
||||
+ "};",
|
||||
log=False,
|
||||
)
|
||||
|
||||
# import skr
|
||||
shutil.copyfile(skr_fname, f"ns1/{skr_fname}")
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}", log=False)
|
||||
ns1.rndc(f"skr -import {skr_fname} {zone}")
|
||||
|
||||
# test zone is correctly signed
|
||||
# - check rndc dnssec -status output
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ def check_add_zsk(server, zone, keys, expected, extra_keys, extra, primary=None)
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -220,7 +220,7 @@ def _check_remove_zsk_fail(
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -263,7 +263,7 @@ def check_remove_zsk(
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -299,7 +299,7 @@ def check_add_cdnskey(server, zone, keys, expected, extra_keys, extra, primary=N
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -336,7 +336,7 @@ def _check_remove_cdnskey_fail(
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -379,7 +379,7 @@ def check_remove_cdnskey(
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -415,7 +415,7 @@ def check_add_cds(server, zone, keys, expected, extra_keys, extra, primary=None)
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -452,7 +452,7 @@ def _check_remove_cds_fail(
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
@ -495,7 +495,7 @@ def check_remove_cds(
|
|||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
server.rndc(f"loadkeys {zone}")
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
|
|
|
|||
|
|
@ -114,4 +114,4 @@ def test_nsec3_case(ns3):
|
|||
# Using rndc signing -nsec3param (should fail)
|
||||
isctest.log.info(f"use rndc signing -nsec3param {zone} to change NSEC3 settings")
|
||||
response = ns3.rndc(f"signing -nsec3param 1 1 12 ffff {zone}")
|
||||
assert "zone uses dnssec-policy, use rndc dnssec command instead" in response
|
||||
assert "zone uses dnssec-policy, use rndc dnssec command instead" in response.out
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ def test_nzd2nzf(ns1):
|
|||
isctest.check.refused(res)
|
||||
|
||||
# add new zone into the default NZD using "rndc addzone"
|
||||
ns1.rndc(f"addzone {zone_data}", log=False)
|
||||
ns1.rndc(f"addzone {zone_data}")
|
||||
|
||||
# query for existing zone data
|
||||
res = isctest.query.tcp(msg, ns1.ip)
|
||||
|
|
|
|||
|
|
@ -22,18 +22,20 @@ def test_resolver_cache_reloadfails(ns1, templates):
|
|||
isctest.check.noerror(res)
|
||||
assert res.answer[0].ttl == 300
|
||||
templates.render("ns1/named.conf", {"wrongoption": True})
|
||||
try:
|
||||
# The first reload fails, and the old cache list will be preserved
|
||||
ns1.rndc("reload")
|
||||
except isctest.rndc.RNDCException:
|
||||
templates.render("ns1/named.conf", {"wrongoption": False})
|
||||
# The second reload succeed, and the cache is still there, as preserved
|
||||
# from the old cache list
|
||||
ns1.rndc("reload")
|
||||
time.sleep(3)
|
||||
msg = isctest.query.create("www.example.org.", "A")
|
||||
res = isctest.query.udp(msg, "10.53.0.1")
|
||||
isctest.check.noerror(res)
|
||||
# The ttl being lower than 300 (provided by fake authoritative) proves
|
||||
# the cache is still in use
|
||||
assert res.answer[0].ttl < 300
|
||||
|
||||
# The first reload fails, and the old cache list will be preserved
|
||||
cmd = ns1.rndc("reload", raise_on_exception=False)
|
||||
assert cmd.rc != 0
|
||||
|
||||
templates.render("ns1/named.conf", {"wrongoption": False})
|
||||
# The second reload succeed, and the cache is still there, as preserved
|
||||
# from the old cache list
|
||||
ns1.rndc("reload")
|
||||
time.sleep(3)
|
||||
msg = isctest.query.create("www.example.org.", "A")
|
||||
res = isctest.query.udp(msg, "10.53.0.1")
|
||||
isctest.check.noerror(res)
|
||||
|
||||
# The ttl being lower than 300 (provided by fake authoritative) proves
|
||||
# the cache is still in use
|
||||
assert res.answer[0].ttl < 300
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ def test_zsk_prepub_step3(tld, alg, size, ns3):
|
|||
|
||||
# Force full resign and check all signatures have been replaced.
|
||||
with ns3.watch_log_from_here() as watcher:
|
||||
ns3.rndc(f"sign {zone}", log=False)
|
||||
ns3.rndc(f"sign {zone}")
|
||||
watcher.wait_for_line(f"zone_needdump: zone {zone}/IN (signed): enter")
|
||||
|
||||
step["smooth"] = False
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ def test_rollover_manual(ns3):
|
|||
# Try to schedule a ZSK rollover for an inactive key (should fail).
|
||||
zsk = expected[3].key
|
||||
response = ns3.rndc(f"dnssec -rollover -key {zsk.tag} {zone}")
|
||||
assert "key is not actively signing" in response
|
||||
assert "key is not actively signing" in response.out
|
||||
|
||||
|
||||
def test_rollover_manual_zrrsig_rumoured(ns3):
|
||||
|
|
|
|||
|
|
@ -71,11 +71,8 @@ def do_work(named_proc, resolver_ip, instance, kill_method, n_workers, n_queries
|
|||
|
||||
# helper function, 'command' is the rndc command to run
|
||||
def launch_rndc(command):
|
||||
try:
|
||||
instance.rndc(command, log=False)
|
||||
return 0
|
||||
except isctest.rndc.RNDCException:
|
||||
return -1
|
||||
ret = instance.rndc(command, raise_on_exception=False)
|
||||
return 0 if ret.rc == 0 else -1
|
||||
|
||||
# We're going to execute queries in parallel by means of a thread pool.
|
||||
# dnspython functions block, so we need to circumvent that.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
# information regarding copyright ownership.
|
||||
|
||||
import concurrent.futures
|
||||
import os
|
||||
import time
|
||||
|
||||
import dns.update
|
||||
|
|
@ -27,22 +26,8 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
|
||||
|
||||
def rndc_loop(test_state, server):
|
||||
rndc = os.getenv("RNDC")
|
||||
port = os.getenv("CONTROLPORT")
|
||||
|
||||
cmdline = [
|
||||
rndc,
|
||||
"-c",
|
||||
"../_common/rndc.conf",
|
||||
"-p",
|
||||
port,
|
||||
"-s",
|
||||
server,
|
||||
"reload",
|
||||
]
|
||||
|
||||
while not test_state["finished"]:
|
||||
isctest.run.cmd(cmdline, raise_on_exception=False)
|
||||
server.rndc("reload", raise_on_exception=False)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue