mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 05:28:00 +00:00
Rewrite keyfromlabel system test to pytest
(cherry picked from commit 409f394d6eb5352f1f7ca38af43b166bc4a1a3bd)
This commit is contained in:
parent
8713e2f61c
commit
5d615b4797
@ -13,6 +13,7 @@
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
@ -76,6 +77,16 @@ dnsrps_enabled = 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:
|
||||
|
@ -28,6 +28,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)}")
|
||||
@ -43,6 +44,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,
|
||||
@ -52,6 +56,7 @@ def cmd(
|
||||
check=True,
|
||||
cwd=cwd,
|
||||
timeout=timeout,
|
||||
env=env,
|
||||
)
|
||||
print_debug_logs(proc)
|
||||
return proc
|
||||
|
@ -1,31 +0,0 @@
|
||||
#!/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
|
||||
# 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
|
||||
|
||||
[ -n "${SOFTHSM2_CONF}" ] || {
|
||||
echo_i "skip: softhsm2 configuration not available"
|
||||
exit 255
|
||||
}
|
||||
|
||||
[ -f "$SOFTHSM2_MODULE" ] || {
|
||||
echo_i "skip: softhsm2 module not available"
|
||||
exit 1
|
||||
}
|
||||
|
||||
for _bin in softhsm2-util pkcs11-tool; do
|
||||
command -v "$_bin" >/dev/null || {
|
||||
echo_i "skip: $_bin not available"
|
||||
exit 1
|
||||
}
|
||||
done
|
@ -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
|
||||
|
||||
OPENSSL_CONF= softhsm2-util --delete-token --token "softhsm2-keyfromlabel" >/dev/null 2>&1 || true
|
||||
OPENSSL_CONF= 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)
|
@ -1,94 +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}')
|
||||
OPENSSL_CONF= 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 $ENGINE_ARG -a $alg -l "pkcs11:token=softhsm2-keyfromlabel;object=${id}-${zone};pin-source=$PWD/pin" "$@" $zone >>keyfromlabel.out.$zone.$id || return 1
|
||||
cat keyfromlabel.out.$zone.$id
|
||||
}
|
||||
|
||||
status=0
|
||||
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 :)
|
||||
alg_upper=$(echo "$alg" | tr '[:lower:]' '[:upper:]')
|
||||
supported=$(eval "echo \$${alg_upper}_SUPPORTED")
|
||||
|
||||
if [ "${supported}" = 1 ]; 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 $ENGINE_ARG -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
|
190
bin/tests/system/keyfromlabel/tests_keyfromlabel.py
Normal file
190
bin/tests/system/keyfromlabel/tests_keyfromlabel.py
Normal file
@ -0,0 +1,190 @@
|
||||
# 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.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"],
|
||||
*os.environ.get("ENGINE_ARG", "").split(),
|
||||
"-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 f"{alg_name.upper()}_SUPPORTED" not in os.environ:
|
||||
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"],
|
||||
*os.environ.get("ENGINE_ARG", "").split(),
|
||||
"-S",
|
||||
"-a",
|
||||
"-g",
|
||||
"-o",
|
||||
zone,
|
||||
zone_file,
|
||||
]
|
||||
isctest.run.cmd(signer_command, log_stdout=True)
|
||||
|
||||
assert os.path.exists(f"{zone_file}.signed")
|
@ -1,29 +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
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*.example.db",
|
||||
"*.example.db.signed",
|
||||
"K*",
|
||||
"dsset-*",
|
||||
"keyfromlabel.out.*",
|
||||
"pin",
|
||||
"pkcs11-tool.out.*",
|
||||
"signer.out.*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_keyfromlabel(run_tests_sh):
|
||||
run_tests_sh()
|
@ -11,3 +11,4 @@
|
||||
|
||||
transfers_complete # unused function (cipher-suites/tests_cipher_suites.py:31)
|
||||
transfers_complete # unused variable (cipher-suites/tests_cipher_suites.py:86)
|
||||
token_init_and_cleanup # unused function (keyfromlabel/tests_keyfromlabel.py:43)
|
||||
|
Loading…
x
Reference in New Issue
Block a user