From 4ce2f35248123ff2366c8c365ad6a94945578d66 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 18 Dec 2016 17:42:17 +0100 Subject: tests: cache the apt-key homedir used for Release signing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Importing a new secret key into gpg(2) can be increadibly slow which prolongs the test runs significantly – by caching the homedir we gain a significant speedbonus as reimporting already present keys seems like a far less costly operation. Git-Dch: Ignore --- cmdline/apt-key.in | 31 ++++++++++++++++++++----------- test/integration/framework | 29 ++++++++++++++++++++++++++--- test/integration/run-tests | 10 ++++++++++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index c9ff4b3f4..76fa37123 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -1,7 +1,7 @@ #!/bin/sh set -e -unset GREP_OPTIONS +unset GREP_OPTIONS GPGHOMEDIR CURRENTTRAP export IFS="$(printf "\n\b")" MASTER_KEYRING='&keyring-master-filename;' @@ -526,6 +526,11 @@ while [ -n "$1" ]; do # … other more complicated ones pipe gpg into gpg. aptkey_execute() { echo >&2 'EXEC:' "$@"; sh "$@"; } ;; + --homedir) + # force usage of a specific homedir instead of creating a temporary + shift + GPGHOMEDIR="$1" + ;; --*) echo >&2 "Unknown option: $1" usage @@ -593,9 +598,13 @@ cleanup_gpg_home() { rm -rf "$GPGHOMEDIR" } +# gpg needs (in different versions more or less) files to function correctly, +# so we give it its own homedir and generate some valid content for it later on create_gpg_home() { - # gpg needs (in different versions more or less) files to function correctly, - # so we give it its own homedir and generate some valid content for it later on + # for cases in which we want to cache a homedir due to expensive setup + if [ -n "$GPGHOMEDIR" ]; then + return + fi if [ -n "$TMPDIR" ]; then # tmpdir is a directory and current user has rwx access to it # same tests as in apt-pkg/contrib/fileutl.cc GetTempDir() @@ -603,7 +612,7 @@ create_gpg_home() { unset TMPDIR fi fi - GPGHOMEDIR="$(mktemp -d)" + GPGHOMEDIR="$(mktemp --directory --tmpdir 'apt-key-gpghome.XXXXXXXXXX')" CURRENTTRAP="${CURRENTTRAP} cleanup_gpg_home;" trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM if [ -z "$GPGHOMEDIR" ]; then @@ -644,6 +653,13 @@ EOF create_gpg_home + # now tell gpg that it shouldn't try to maintain this trustdb file + echo "#!/bin/sh +exec '$(escape_shell "${GPG_EXE}")' --ignore-time-conflict --no-options --no-default-keyring \\ +--homedir '$(escape_shell "${GPGHOMEDIR}")' --no-auto-check-trustdb --trust-model always \"\$@\"" > "${GPGHOMEDIR}/gpg.0.sh" + GPG_SH="${GPGHOMEDIR}/gpg.0.sh" + GPG="$GPG_SH" + # create the trustdb with an (empty) dummy keyring # older gpgs required it, newer gpgs even warn that it isn't needed, # but require it nonetheless for some commands, so we just play safe @@ -655,13 +671,6 @@ EOF false fi - # now tell gpg that it shouldn't try to maintain this trustdb file - echo "#!/bin/sh -exec '$(escape_shell "${GPG_EXE}")' --ignore-time-conflict --no-options --no-default-keyring \\ ---homedir '$(escape_shell "${GPGHOMEDIR}")' --no-auto-check-trustdb --trust-model always \"\$@\"" > "${GPGHOMEDIR}/gpg.0.sh" - GPG_SH="${GPGHOMEDIR}/gpg.0.sh" - GPG="$GPG_SH" - # We don't usually need a secret keyring, of course, but # for advanced operations, we might really need a secret keyring after all if [ -n "$FORCED_SECRET_KEYRING" ] && [ -r "$FORCED_SECRET_KEYRING" ]; then diff --git a/test/integration/framework b/test/integration/framework index 05c8fcd2a..a0e9e759c 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1157,6 +1157,30 @@ setupaptarchive() { fi } +killgpgagent() { + if [ -z "${TMPWORKINGDIRECTORY}" ]; then return; fi + local GPGHOME="${TMPWORKINGDIRECTORY}/signinghome" + if [ -e "${GPGHOME}" ]; then return; fi + # ensure the agent dies quickly as different versions have different suicide heuristics + GNUPGHOME="${GPGHOME}" gpgconf --kill gpg-agent >/dev/null 2>&1 || true + rm -rf "$GPGHOME" +} +dosigning() { + local KEY="$1" + shift + local GPGHOME="${TMPWORKINGDIRECTORY}/signinghome" + if [ -n "$APT_TEST_SIGNINGHOME" ]; then + GPGHOME="$APT_TEST_SIGNINGHOME" + else + if [ ! -e "$GPGHOME" ]; then + mkdir -p --mode=700 "${GPGHOME}" + addtrap 'prefix' 'killgpgagent;' + fi + fi + testsuccess aptkey --quiet --keyring ${KEY}.pub --secret-keyring ${KEY}.sec --readonly \ + --homedir "${GPGHOME}" adv --batch --yes --digest-algo "${APT_TESTS_DIGEST_ALGO:-SHA512}" \ + "$@" +} signreleasefiles() { local SIGNERS="${1:-Joe Sixpack}" local REPODIR="${2:-aptarchive}" @@ -1208,21 +1232,20 @@ signreleasefiles() { mv "${KEY}.new.pub" "${KEY}.pub" mv "${KEY}.new.sec" "${KEY}.sec" fi - local GPG="aptkey --quiet --keyring ${KEY}.pub --secret-keyring ${KEY}.sec --readonly adv --batch --yes --digest-algo ${APT_TESTS_DIGEST_ALGO:-SHA512}" for RELEASE in $(find "${REPODIR}/" -name Release); do # we might have set a specific date for the Release file, so copy it local DATE="$(stat --format "%y" "${RELEASE}")" if [ "$APT_DONT_SIGN" = 'Release.gpg' ]; then rm -f "${RELEASE}.gpg" else - testsuccess $GPG "$@" $SIGUSERS --armor --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" + dosigning "$KEY" "$@" $SIGUSERS --armor --detach-sign --sign --output "${RELEASE}.gpg" "${RELEASE}" touch -d "$DATE" "${RELEASE}.gpg" fi local INRELEASE="${RELEASE%/*}/InRelease" if [ "$APT_DONT_SIGN" = 'InRelease' ]; then rm -f "$INRELEASE" else - testsuccess $GPG "$@" $SIGUSERS --clearsign --output "$INRELEASE" "$RELEASE" + dosigning "$KEY" "$@" $SIGUSERS --clearsign --output "$INRELEASE" "$RELEASE" touch -d "$DATE" "${INRELEASE}" fi done diff --git a/test/integration/run-tests b/test/integration/run-tests index 7c0b74ce2..3dcacc7bd 100755 --- a/test/integration/run-tests +++ b/test/integration/run-tests @@ -107,6 +107,16 @@ if [ -n "$APT_TEST_JOBS" ]; then fi exec $parallel -j "$APT_TEST_JOBS" "./$(basename "$0")" -- $(echo "$TESTLIST") fi + +APT_TEST_SIGNINGHOME="$(mktemp --directory --tmpdir 'apt-key-signinghome.XXXXXXXXXX')" +removesigninghome() { + if [ -z "$APT_TEST_SIGNINGHOME" ]; then return; fi + GNUPGHOME="${APT_TEST_SIGNINGHOME}" gpgconf --kill gpg-agent >/dev/null 2>&1 || true + rm -rf -- "$APT_TEST_SIGNINGHOME" +} +trap "removesigninghome; exit 0" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM +export APT_TEST_SIGNINGHOME + TOTAL="$(echo "$TESTLIST" | wc -l)" if [ "$MSGLEVEL" -le 1 ]; then printf "${CTEST}Running testcases${CRESET}: " -- cgit v1.2.3