Subject: Tests: move tang tests to src/pins/tang Origin: v15-2-g3dedc5d Upstream-Author: Sergio Correia Date: Thu Nov 19 11:54:49 2020 -0300 So that we can organize them better. --- a/src/pins/tang/meson.build +++ b/src/pins/tang/meson.build @@ -1,33 +1,3 @@ -actv = find_program( - 'systemd-socket-activate', - 'systemd-activate', - join_paths('/', 'usr', 'lib', 'systemd', 'systemd-activate'), - required: false -) -kgen = find_program( - join_paths(libexecdir, 'tangd-keygen'), - join_paths(get_option('prefix'), get_option('libdir'), 'tangd-keygen'), - join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd-keygen'), - join_paths('/', 'usr', get_option('libdir'), 'tangd-keygen'), - join_paths('/', 'usr', get_option('libexecdir'), 'tangd-keygen'), - required: false -) -updt = find_program( - join_paths(libexecdir, 'tangd-update'), - join_paths(get_option('prefix'), get_option('libdir'), 'tangd-update'), - join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd-update'), - join_paths('/', 'usr', get_option('libdir'), 'tangd-update'), - join_paths('/', 'usr', get_option('libexecdir'), 'tangd-update'), - required: false -) -tang = find_program( - join_paths(libexecdir, 'tangd'), - join_paths(get_option('prefix'), get_option('libdir'), 'tangd'), - join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd'), - join_paths('/', 'usr', get_option('libdir'), 'tangd'), - join_paths('/', 'usr', get_option('libexecdir'), 'tangd'), - required: false -) curl = find_program('curl', required: false) if curl.found() @@ -35,22 +5,7 @@ bins += join_paths(meson.current_source_dir(), 'clevis-encrypt-tang') mans += join_paths(meson.current_source_dir(), 'clevis-encrypt-tang.1') - if actv.found() and kgen.found() and updt.found() and tang.found() - env = environment() - env.set('SD_ACTIVATE', actv.path()) - env.set('TANGD_KEYGEN', kgen.path()) - env.set('TANGD_UPDATE', updt.path()) - env.set('TANGD', tang.path()) - env.prepend('PATH', - join_paths(meson.source_root(), 'src'), - meson.current_source_dir(), - separator: ':' - ) - - test('pin-tang', find_program('./pin-tang'), env: env) - else - warning('Will not run tang tests due to missing dependencies!') - endif + subdir('tests') else warning('Will not install tang pin due to missing dependencies!') endif --- a/src/pins/tang/pin-tang +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -x -# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: -# -# Copyright (c) 2016 Red Hat, Inc. -# Author: Nathaniel McCallum -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -function on_exit() { - if [ "$PID" ]; then kill $PID; wait $PID || true; fi - [ -d "$TMP" ] && rm -rf "$TMP" -} - -trap 'on_exit' EXIT -trap 'exit' ERR - -TMP="$(mktemp -d)" -mkdir -p "$TMP"/db -mkdir -p "$TMP"/cache - -# Generate the server keys -"${TANGD_KEYGEN}" "$TMP"/db sig exc -"${TANGD_UPDATE}" "$TMP"/db "$TMP"/cache - -# Start the server -port="$(shuf -i 1024-65536 -n 1)" - -inetd='--inetd' -[ "${SD_ACTIVATE##*/}" = "systemd-activate" ] && inetd= - -"$SD_ACTIVATE" $inetd -l 127.0.0.1:"$port" -a "$TANGD" "$TMP"/cache & -PID=$! -sleep 0.25 - -thp="$(jose jwk thp -i "$TMP/db/sig.jwk")" -adv="$TMP/cache/default.jws" -url="http://localhost:${port}" - -cfg="$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")" -enc="$(echo -n "hi" | clevis encrypt tang "$cfg")" -dec="$(echo -n "$enc" | clevis decrypt)" -test "$dec" == "hi" - -cfg="$(printf '{"url":"%s","thp":"%s"}' "$url" "$thp")" -enc="$(echo -n "hi" | clevis encrypt tang "$cfg")" -dec="$(echo -n "$enc" | clevis decrypt)" -test "$dec" == "hi" - -kill -9 $PID -! wait $PID -unset PID - -! echo "$enc" | clevis decrypt --- /dev/null +++ b/src/pins/tang/tests/meson.build @@ -0,0 +1,64 @@ +kgen = find_program( + join_paths(libexecdir, 'tangd-keygen'), + join_paths(get_option('prefix'), get_option('libdir'), 'tangd-keygen'), + join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd-keygen'), + join_paths('/', 'usr', get_option('libdir'), 'tangd-keygen'), + join_paths('/', 'usr', get_option('libexecdir'), 'tangd-keygen'), + required: false +) +updt = find_program( + join_paths(libexecdir, 'tangd-update'), + join_paths(get_option('prefix'), get_option('libdir'), 'tangd-update'), + join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd-update'), + join_paths('/', 'usr', get_option('libdir'), 'tangd-update'), + join_paths('/', 'usr', get_option('libexecdir'), 'tangd-update'), + required: false +) +tang = find_program( + join_paths(libexecdir, 'tangd'), + join_paths(get_option('prefix'), get_option('libdir'), 'tangd'), + join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd'), + join_paths('/', 'usr', get_option('libdir'), 'tangd'), + join_paths('/', 'usr', get_option('libexecdir'), 'tangd'), + required: false +) + +socat = find_program('socat', required: false) + +tang_data = configuration_data() +tang_data.set('SOCAT', '') +tang_data.set('TANGD_KEYGEN', '') +tang_data.set('TANGD_UPDATE', '') +tang_data.set('TANGD', '') + +if socat.found() + tang_data.set('SOCAT', socat.path()) +endif + +if kgen.found() + tang_data.set('TANGD_KEYGEN', kgen.path()) +endif + +if tang.found() + tang_data.set('TANGD', tang.path()) +endif + +if updt.found() + tang_data.set('TANGD_UPDATE', updt.path()) +endif + +tang_tests_common = configure_file( + input: 'tang-common-test-functions.in', + output: 'tang-common-test-functions', + configuration: tang_data +) + +env = environment() +env.prepend('PATH', + join_paths(meson.source_root(), 'src'), + join_paths(meson.source_root(), 'src', 'pins', 'tang'), + join_paths(meson.build_root(), 'src', 'pins', 'tang', 'tests'), + separator: ':' +) + +test('pin-tang', find_program('pin-tang'), env: env) --- /dev/null +++ b/src/pins/tang/tests/pin-tang @@ -0,0 +1,55 @@ +#!/bin/bash -xe +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2016 Red Hat, Inc. +# Author: Nathaniel McCallum +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +. tang-common-test-functions + +on_exit() { + exit_status=$? + tang_stop "${TMP}" + [ -d "$TMP" ] && rm -rf "$TMP" + exit "${exit_status}" +} + +trap 'on_exit' EXIT + +TMP="$(mktemp -d)" + +port=$(tang_new_random_port) + +tang_run "${TMP}" "${port}" sig exc + +thp="$(jose jwk thp -i "$TMP/db/sig.jwk")" +adv="${TMP}/adv.jws" +tang_get_adv "${port}" "${adv}" +url="http://localhost:${port}" + +cfg="$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")" +enc="$(echo -n "hi" | clevis encrypt tang "$cfg")" +dec="$(echo -n "$enc" | clevis decrypt)" +test "$dec" == "hi" + +cfg="$(printf '{"url":"%s","thp":"%s"}' "$url" "$thp")" +enc="$(echo -n "hi" | clevis encrypt tang "$cfg")" +dec="$(echo -n "$enc" | clevis decrypt)" +test "$dec" == "hi" + +tang_stop "${TMP}" + +! echo "$enc" | clevis decrypt --- /dev/null +++ b/src/pins/tang/tests/tang-common-test-functions.in @@ -0,0 +1,188 @@ +#!/bin/bash -ex +# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2020 Red Hat, Inc. +# Author: Sergio Correia +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +SOCAT="@SOCAT@" +TANGD_KEYGEN="@TANGD_KEYGEN@" +TANGD_UPDATE="@TANGD_UPDATE@" +TANGD="@TANGD@" + +tang_error() { + echo "${1}" >&2 + exit 1 +} + +tang_skip() { + echo "${1}" >&2 + exit 77 +} + +tang_sanity_check() { + [ -n "${SOCAT}" ] && [ -n "${TANGD_KEYGEN}" ] && \ + [ -n "${TANGD}" ] && return 0 + tang_skip "tang is not enabled/supported. Check if you have met all the requirements" +} + +# Creates a tang adv to be used in the tests. +tang_create_adv() { + local basedir="${1}" + local adv="${2:-/dev/stdout}" + + local SIG="${basedir}/sig.jwk" + jose jwk gen --input='{"alg":"ES512"}' --output="${SIG}" + + local EXC="${basedir}/exc.jwk" + jose jwk gen --input='{"alg":"ECMR"}' --output="${EXC}" + + local TEMPLATE='{"protected":{"cty":"jwk-set+json"}}' + jose jwk pub --set --input="${SIG}" --input="${EXC}" \ + | jose jws sig --detached=- --signature="${TEMPLATE}" \ + --key="${SIG}" --output="${adv}" +} + +# Get a random port to be used with a test tang server. +tang_new_random_port() { + tang_sanity_check + shuf -i 1024-65535 -n 1 +} + +# Removes tang rotated keys from the test server. +tang_remove_rotated_keys() { + tang_sanity_check + local basedir="${1}" + + [ -z "${basedir}" ] && \ + tang_error "tang_remove_rotated_keys: please specify 'basedir'" + + local db="${basedir}/db" + + mkdir -p "${db}" + pushd "${db}" + find . -name ".*.jwk" -exec rm -f {} \; + popd + + [ -n "${TANGD_UPDATE}" ] && "${TANGD_UPDATE}" "${db}" "${basedir}/cache" + return 0 +} + +# Creates new keys for the test tang server. +tang_new_keys() { + tang_sanity_check + local basedir="${1}" + local rotate="${2:-}" + local sig_name="${3:-}" + local exc_name="${4:-}" + + [ -z "${basedir}" ] && tang_error "tang_new_keys: please specify 'basedir'" + + local db="${basedir}/db" + mkdir -p "${db}" + + if [ -n "${rotate}" ]; then + pushd "${db}" + local k + k=$(find . -name "*.jwk" | wc -l) + if [ "${k}" -gt 0 ]; then + for k in *.jwk; do + mv -f -- "${k}" ".${k}" + done + fi + popd + fi + + "${TANGD_KEYGEN}" "${db}" ${sig_name} ${exc_name} + [ -n "${TANGD_UPDATE}" ] && "${TANGD_UPDATE}" "${db}" "${basedir}/cache" + + return 0 +} + +# Wait for the tang server to be operational. +tang_wait_until_ready() { + tang_sanity_check + local port="${1}" + + [ -z "${port}" ] && \ + tang_error "tang_wait_until_ready: please specify 'port'" + + local max_timeout_in_s=5 + local start elapsed + start="${SECONDS}" + while ! curl --output /dev/null --silent --fail \ + "http://localhost:${port}/adv"; do + elapsed=$((SECONDS - start)) + if [ "${elapsed}" -gt "${max_timeout_in_s}" ]; then + tang_error "Timeout (${max_timeout_in_s}s) waiting for tang server" + fi + sleep 0.1 + echo -n . >&2 + done +} + +# Start a test tang server. +tang_run() { + tang_sanity_check + local basedir="${1}" + local port="${2}" + local sig_name="${3:-}" + local exc_name="${4:-}" + + [ -z "${basedir}" ] && tang_error "tang_run: please specify 'basedir'" + [ -z "${port}" ] && tang_error "tang_run: please specify 'port'" + + if ! tang_new_keys "${basedir}" "" "${sig_name}" "${exc_name}"; then + tang_error "Error creating new keys for tang server" + fi + + local KEYS="${basedir}/cache" + [ -z "${TANGD_UPDATE}" ] && KEYS="${basedir}/db" + + local pid pidfile + pidfile="${basedir}/tang.pid" + + "${SOCAT}" -v -v TCP-LISTEN:${port},reuseaddr,fork \ + exec:"${TANGD} ${KEYS}" & + + pid=$! + echo "${pid}" > "${pidfile}" + tang_wait_until_ready "${port}" +} + +# Stop tang server. +tang_stop() { + tang_sanity_check + local basedir="${1}" + [ -z "${basedir}" ] && tang_error "tang_stop: please specify 'basedir'" + + local pidfile="${basedir}/tang.pid" + [ -f "${pidfile}" ] || return 0 + + local pid + pid=$(<"${pidfile}") + kill -9 "${pid}" 2>/dev/null || : +} + +# Get tang advertisement. +tang_get_adv() { + tang_sanity_check + local port="${1}" + local adv="${2:-/dev/stdout}" + + [ -z "${port}" ] && tang_error "tang_get_adv: please specify 'port'" + curl -L -o "${adv}" "http://localhost:${port}/adv" +}