2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 22:45:39 +00:00

[9.18] chg: test: Rewrite keyfromlabel system test to pytest

Backport of MR !9188

Merge branch 'backport-mnowak/pytest_rewrite_keyfromlabel-9.18' into 'bind-9.18'

See merge request isc-projects/bind9!10113
This commit is contained in:
Michal Nowak
2025-02-18 09:47:50 +00:00
8 changed files with 218 additions and 158 deletions

View File

@@ -587,7 +587,7 @@ pylint:
script:
- pylint --rcfile $CI_PROJECT_DIR/.pylintrc $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/|^contrib/)')
# Ignore Pylint wrong-import-position error in system test to enable use of pytest.importorskip
- pylint --rcfile $CI_PROJECT_DIR/.pylintrc --disable=wrong-import-position $(git ls-files 'bin/tests/system/*.py' | grep -vE 'ans\.py')
- pylint --rcfile $CI_PROJECT_DIR/.pylintrc --disable=wrong-import-position $(git ls-files 'bin/tests/system/*.py' | grep -vE '(ans\.py|vulture_ignore_list\.py)')
reuse:
<<: *precheck_job

View File

@@ -13,6 +13,7 @@
import os
from pathlib import Path
import shutil
import ssl
import subprocess
@@ -71,6 +72,16 @@ supported_openssl_version = pytest.mark.skipif(
)
softhsm2_environment = pytest.mark.skipif(
not (
os.getenv("SOFTHSM2_CONF")
and os.getenv("SOFTHSM2_MODULE")
and shutil.which("pkcs11-tool")
and shutil.which("softhsm2-util")
),
reason="SOFTHSM2_CONF and SOFTHSM2_MODULE environmental variables must be set and pkcs11-tool and softhsm2-util tools present",
)
try:
import flaky as flaky_pkg # type: ignore
except ModuleNotFoundError:

View File

@@ -30,6 +30,7 @@ def cmd(
log_stderr=True,
input_text: Optional[bytes] = None,
raise_on_exception=True,
env: Optional[dict] = None,
):
"""Execute a command with given args as subprocess."""
isctest.log.debug(f"command: {' '.join(args)}")
@@ -45,6 +46,9 @@ def cmd(
f"~~~ cmd stderr ~~~\n{procdata.stderr.decode('utf-8')}\n~~~~~~~~~~~~~~~~~~"
)
if env is None:
env = dict(os.environ)
try:
proc = subprocess.run(
args,
@@ -54,6 +58,7 @@ def cmd(
check=True,
cwd=cwd,
timeout=timeout,
env=env,
)
print_debug_logs(proc)
return proc

View File

@@ -1,23 +0,0 @@
#!/bin/sh
#
# 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.
# shellcheck source=conf.sh
. ../conf.sh
set -e
softhsm2-util --delete-token --token "softhsm2-keyfromlabel" >/dev/null 2>&1 || echo_i "softhsm2-keyfromlabel token not found for cleaning"
softhsm2-util --init-token --free --pin 1234 --so-pin 1234 --label "softhsm2-keyfromlabel" | awk '/^The token has been initialized and is reassigned to slot/ { print $NF }'
printf '%s' "${HSMPIN:-1234}" >pin
PWD=$(pwd)

View File

@@ -1,91 +0,0 @@
#!/bin/sh
#
# 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.
set -e
# shellcheck source=conf.sh
. ../conf.sh
PWD=$(pwd)
keygen() {
type="$1"
bits="$2"
zone="$3"
id="$4"
label="${id}-${zone}"
p11id=$(echo "${label}" | openssl sha1 -r | awk '{print $1}')
pkcs11-tool --module $SOFTHSM2_MODULE --token-label "softhsm2-keyfromlabel" -l -k --key-type $type:$bits --label "${label}" --id "${p11id}" --pin $(cat $PWD/pin) >pkcs11-tool.out.$zone.$id || return 1
}
keyfromlabel() {
alg="$1"
zone="$2"
id="$3"
shift 3
$KEYFRLAB -E pkcs11 -a $alg -l "token=softhsm2-keyfromlabel;object=${id}-${zone};pin-source=$PWD/pin" "$@" $zone >>keyfromlabel.out.$zone.$id 2>>/dev/null || return 1
cat keyfromlabel.out.$zone.$id
}
infile="template.db.in"
for algtypebits in rsasha256:rsa:2048 rsasha512:rsa:2048 \
ecdsap256sha256:EC:prime256v1 ecdsap384sha384:EC:prime384v1; do # Edwards curves are not yet supported by OpenSC
# ed25519:EC:edwards25519 ed448:EC:edwards448
alg=$(echo "$algtypebits" | cut -f 1 -d :)
type=$(echo "$algtypebits" | cut -f 2 -d :)
bits=$(echo "$algtypebits" | cut -f 3 -d :)
if $SHELL ../testcrypto.sh $alg; then
zone="$alg.example"
zonefile="zone.$alg.example.db"
ret=0
echo_i "Generate keys $alg $type:$bits for zone $zone"
keygen $type $bits $zone keyfromlabel-zsk || ret=1
keygen $type $bits $zone keyfromlabel-ksk || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
# Skip dnssec-keyfromlabel if key generation failed.
test $ret -eq 0 || continue
echo_i "Get ZSK $alg $zone $type:$bits"
ret=0
zsk=$(keyfromlabel $alg $zone keyfromlabel-zsk)
test -z "$zsk" && ret=1
test "$ret" -eq 0 || echo_i "failed (zsk=$zsk)"
status=$((status + ret))
echo_i "Get KSK $alg $zone $type:$bits"
ret=0
ksk=$(keyfromlabel $alg $zone keyfromlabel-ksk -f KSK)
test -z "$ksk" && ret=1
test "$ret" -eq 0 || echo_i "failed (ksk=$ksk)"
status=$((status + ret))
# Skip signing if dnssec-keyfromlabel failed.
test $ret -eq 0 || continue
echo_i "Sign zone with $ksk $zsk"
ret=0
cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile"
$SIGNER -E pkcs11 -S -a -g -o "$zone" "$zonefile" >signer.out.$zone || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
fi
done
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View File

@@ -0,0 +1,199 @@
# 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 hashlib
import os
import re
import shutil
import pytest
import isctest.mark
pytestmark = [
isctest.mark.supported_openssl_version,
isctest.mark.softhsm2_environment,
pytest.mark.extra_artifacts(
[
"*.example.db",
"*.example.db.signed",
"K*",
"dsset-*",
"keyfromlabel.out.*",
"pin",
"pkcs11-tool.out.*",
"signer.out.*",
],
),
]
EMPTY_OPENSSL_CONF_ENV = {**os.environ, "OPENSSL_CONF": ""}
HSMPIN = "1234"
@pytest.fixture(autouse=True)
def token_init_and_cleanup():
# Create pin file for the $KEYFRLAB command
with open("pin", "w", encoding="utf-8") as pinfile:
pinfile.write(HSMPIN)
token_init_command = [
"softhsm2-util",
"--init-token",
"--free",
"--pin",
HSMPIN,
"--so-pin",
HSMPIN,
"--label",
"softhsm2-keyfromlabel",
]
token_cleanup_command = [
"softhsm2-util",
"--delete-token",
"--token",
"softhsm2-keyfromlabel",
]
isctest.run.cmd(
token_cleanup_command,
env=EMPTY_OPENSSL_CONF_ENV,
log_stderr=False,
raise_on_exception=False,
)
try:
output = isctest.run.cmd(
token_init_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True
).stdout.decode("utf-8")
assert "The token has been initialized and is reassigned to slot" in output
yield
finally:
output = isctest.run.cmd(
token_cleanup_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True
).stdout.decode("utf-8")
assert re.search("Found token (.*) with matching token label", output)
assert re.search("The token (.*) has been deleted", output)
# pylint: disable-msg=too-many-locals
@pytest.mark.parametrize(
"alg_name,alg_type,alg_bits",
[
("rsasha256", "rsa", "2048"),
("rsasha512", "rsa", "2048"),
("ecdsap256sha256", "EC", "prime256v1"),
("ecdsap384sha384", "EC", "prime384v1"),
# Edwards curves are not yet supported by OpenSC
# ("ed25519","EC","edwards25519"),
# ("ed448","EC","edwards448")
],
)
def test_keyfromlabel(alg_name, alg_type, alg_bits):
def keygen(alg_type, alg_bits, zone, key_id):
label = f"{key_id}-{zone}"
p11_id = hashlib.sha1(label.encode("utf-8")).hexdigest()
pkcs11_command = [
"pkcs11-tool",
"--module",
os.environ.get("SOFTHSM2_MODULE"),
"--token-label",
"softhsm2-keyfromlabel",
"-l",
"-k",
"--key-type",
f"{alg_type}:{alg_bits}",
"--label",
label,
"--id",
p11_id,
"--pin",
HSMPIN,
]
output = isctest.run.cmd(
pkcs11_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True
).stdout.decode("utf-8")
assert "Key pair generated" in output
def keyfromlabel(alg_name, zone, key_id, key_flag):
key_flag = key_flag.split() if key_flag else []
keyfrlab_command = [
os.environ["KEYFRLAB"],
"-E",
"pkcs11",
"-a",
alg_name,
"-l",
f"pkcs11:token=softhsm2-keyfromlabel;object={key_id}-{zone};pin-source=pin",
*key_flag,
zone,
]
output = isctest.run.cmd(keyfrlab_command, log_stdout=True)
output_decoded = output.stdout.decode("utf-8").rstrip() + ".key"
assert os.path.exists(output_decoded)
return output_decoded
if (
isctest.run.cmd(
[os.environ["SHELL"], "../testcrypto.sh", alg_name],
raise_on_exception=False,
).returncode
!= 0
):
pytest.skip(f"{alg_name} is not supported")
# Generate keys for the $zone zone
zone = f"{alg_name}.example"
keygen(alg_type, alg_bits, zone, "keyfromlabel-zsk")
keygen(alg_type, alg_bits, zone, "keyfromlabel-ksk")
# Get ZSK
zsk_file = keyfromlabel(alg_name, zone, "keyfromlabel-zsk", "")
# Get KSK
ksk_file = keyfromlabel(alg_name, zone, "keyfromlabel-ksk", "-f KSK")
# Sign zone with KSK and ZSK
zone_file = f"zone.{alg_name}.example.db"
with open(zone_file, "w", encoding="utf-8") as outfile:
for f in ["template.db.in", ksk_file, zsk_file]:
with open(f, "r", encoding="utf-8") as fd:
shutil.copyfileobj(fd, outfile)
signer_command = [
os.environ["SIGNER"],
"-E",
"pkcs11",
"-S",
"-a",
"-g",
"-o",
zone,
zone_file,
]
isctest.run.cmd(signer_command, log_stdout=True)
assert os.path.exists(f"{zone_file}.signed")

View File

@@ -1,32 +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 pytest
import isctest.mark
pytestmark = pytest.mark.extra_artifacts(
[
"*.example.db",
"*.example.db.signed",
"K*",
"dsset-*",
"keyfromlabel.out.*",
"pin",
"pkcs11-tool.out.*",
"signer.out.*",
]
)
@isctest.mark.supported_openssl_version
def test_keyfromlabel(run_tests_sh):
run_tests_sh()

View File

@@ -1,21 +1,12 @@
#!/bin/sh -e
#
# 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
# 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.
. ../conf.sh
if [ -n "${SOFTHSM2_MODULE}" ] && command -v pkcs11-tool >/dev/null && command -v softhsm2-util >/dev/null; then
exit 0
fi
echo_i "skip: softhsm2-util or pkcs11-tool not available"
exit 255
token_init_and_cleanup # unused function (keyfromlabel/tests_keyfromlabel.py:43)