mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 22:15:20 +00:00
Rewrite keyfromlabel system test to pytest
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
# information regarding copyright ownership.
|
# information regarding copyright ownership.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -58,6 +59,16 @@ with_json_c = 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:
|
try:
|
||||||
import flaky as flaky_pkg # type: ignore
|
import flaky as flaky_pkg # type: ignore
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
|
@@ -28,6 +28,7 @@ def cmd(
|
|||||||
log_stderr=True,
|
log_stderr=True,
|
||||||
input_text: Optional[bytes] = None,
|
input_text: Optional[bytes] = None,
|
||||||
raise_on_exception=True,
|
raise_on_exception=True,
|
||||||
|
env: Optional[dict] = None,
|
||||||
):
|
):
|
||||||
"""Execute a command with given args as subprocess."""
|
"""Execute a command with given args as subprocess."""
|
||||||
isctest.log.debug(f"command: {' '.join(args)}")
|
isctest.log.debug(f"command: {' '.join(args)}")
|
||||||
@@ -43,6 +44,9 @@ def cmd(
|
|||||||
f"~~~ cmd stderr ~~~\n{procdata.stderr.decode('utf-8')}\n~~~~~~~~~~~~~~~~~~"
|
f"~~~ cmd stderr ~~~\n{procdata.stderr.decode('utf-8')}\n~~~~~~~~~~~~~~~~~~"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if env is None:
|
||||||
|
env = dict(os.environ)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
args,
|
args,
|
||||||
@@ -52,6 +56,7 @@ def cmd(
|
|||||||
check=True,
|
check=True,
|
||||||
cwd=cwd,
|
cwd=cwd,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
|
env=env,
|
||||||
)
|
)
|
||||||
print_debug_logs(proc)
|
print_debug_logs(proc)
|
||||||
return 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 -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 -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
|
|
188
bin/tests/system/keyfromlabel/tests_keyfromlabel.py
Normal file
188
bin/tests/system/keyfromlabel/tests_keyfromlabel.py
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# 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"],
|
||||||
|
"-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"],
|
||||||
|
"-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 function (cipher-suites/tests_cipher_suites.py:31)
|
||||||
transfers_complete # unused variable (cipher-suites/tests_cipher_suites.py:86)
|
transfers_complete # unused variable (cipher-suites/tests_cipher_suites.py:86)
|
||||||
|
token_init_and_cleanup # unused function (keyfromlabel/tests_keyfromlabel.py:43)
|
||||||
|
Reference in New Issue
Block a user