mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-30 07:37:36 +00:00
Each left a host misconfigured or without its daemon after an upgrade or install. Keep fips-dns working on a renamed TUN and respect a disabled fips-dns. fips-dns-setup waited for an interface named fips0 before trying any resolver backend, so on a host whose config sets tun.name to anything else it timed out after 30 seconds and exited 1. Debian's postinst starts fips-dns on upgrade and fails the configure when it does not come up, so upgrading such a host left the package half-configured with apt exiting 100. postinst also re-enabled fips-dns.service on every configure, undoing an operator's disable on each upgrade or reinstall. fips-dns-setup now reads the interface name from the daemon config (tun.name under the top-level tun: block, falling back to fips0) and waits for it only in the resolvectl backend, the one backend that uses the interface; that backend records the interface in its state file and fips-dns-teardown reverts it from there. postinst enables fips-dns only on first install, or when the package is installed again after a remove that disabled it while it was enabled: prerm's remove records under /var/lib/fips whether fips-dns was enabled, postinst consumes the record, and purge removes it. An older package's remove left no record, and its postinst enabled fips-dns on every configure, so preinst treats an install from config-files state with no record as enabled at remove; otherwise removing 0.5.3 and installing this package would leave .fips names unresolved. Tests: a dns-resolver scenario with the TUN renamed to mesh0, a container-free test of the name lookup run with the other static checks in both CI runners, and two Debian upgrade scenarios covering the renamed-TUN upgrade, a disable surviving a reinstall, and enablement across remove and reinstall, including a remove that left no record. Leave the running daemon alone on a FreeBSD package upgrade. On an upgrade the old package's pre-deinstall stopped fips and fips_dns, and the new package's post-install started them again when enabled. pkg 2.8.4 ends a process that a package script starts once pkg returns, even under daemon(8), so the started daemon was gone by the time pkg exited: every upgrade left the node with no daemon and without its .fips resolver drop-in until the operator ran service fips restart. pre-deinstall now stops the services and tears down the drop-in only on removal, and post-install no longer starts anything. The running daemon keeps its replaced binary until the operator restarts it, and the package prints an upgrade message saying to run service fips restart (which also starts a daemon that is not running) and service fips_dns restart if it is used. Upgrades from a package before this one still run that package's pre-deinstall, which stops the daemon, so they still need the restart; the README says so. packaging/freebsd/test-upgrade.sh upgrades over a running, enabled daemon to a package built from the same binaries at version 99.0.0 and checks that a daemon is still running up to 10 seconds after pkg returns, that the restart instruction was printed, and that the restart moves the daemon onto the new binary with one process. The FreeBSD Package workflow runs it in its VM after the log rotation check. Repoint an existing Windows service registration at the installed fips.exe. When the fips service already existed, --install-service opened it and set only its description, then reported success. A service registered from another folder, by hand or by an older install, therefore kept starting that folder's fips.exe after install-service.ps1 had copied the new release into Program Files. On ERROR_SERVICE_EXISTS, --install-service now reads the existing configuration and rewrites it with this executable and --service, keeping the service's start type and account, prints the old and new binary paths when they differ, and says "updated" rather than "installed". The service commands it, install-service.ps1 and the ZIP README print are now sc.exe: in PowerShell a bare sc is the Set-Content alias. The Windows Package workflow gains a step that registers the service from C:\fips-old, runs install-service.ps1 under Windows PowerShell, and requires the registration to name Program Files' fips.exe with --service, and the ZIP check now fails on a README line that names a bare sc.
129 lines
4.1 KiB
Bash
Executable File
129 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Tests for tun_name() in packaging/common/fips-dns-setup, which reads the
|
|
# TUN interface name the daemon will create from the top-level `tun:` block of
|
|
# its config and falls back to the daemon's default, fips0.
|
|
#
|
|
# The script is sourced in a subshell, with FIPS_CONFIG pointing at a fixture,
|
|
# and only tun_name is called. Sourcing must not run the script's main path,
|
|
# which waits for the interface and configures the host's resolver. As a guard
|
|
# against a script whose main path does run, every command that path could use
|
|
# to touch the host (ip, systemctl, resolvectl, nmcli, and sleep, so a wait
|
|
# ends at once) is replaced by a stub on PATH that only reports it was called.
|
|
# No containers, no root; about a second.
|
|
#
|
|
# Run:
|
|
# ./tun-name-test.sh
|
|
# Exits 0 only if every case passes; non-zero if any case fails.
|
|
|
|
set -uo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
SETUP="$REPO_ROOT/packaging/common/fips-dns-setup"
|
|
SHIPPED_YAML="$REPO_ROOT/packaging/common/fips.yaml"
|
|
|
|
FAILURES=0
|
|
WORK=$(mktemp -d)
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
|
|
mkdir -p "$WORK/bin"
|
|
for cmd in ip systemctl resolvectl nmcli; do
|
|
printf '#!/bin/sh\necho "STUB-CALLED: %s $*" >&2\nexit 1\n' "$cmd" >"$WORK/bin/$cmd"
|
|
chmod +x "$WORK/bin/$cmd"
|
|
done
|
|
printf '#!/bin/sh\nexit 0\n' >"$WORK/bin/sleep"
|
|
chmod +x "$WORK/bin/sleep"
|
|
|
|
# Print what tun_name returns for the config at $1, or a line starting with
|
|
# "ERROR:" saying why it could not be called. $0 inside the subshell is "_", so
|
|
# the script's main guard sees it is being sourced.
|
|
lookup() {
|
|
local config="$1" out rc=0
|
|
# shellcheck disable=SC2016 # expanded by the subshell, not here
|
|
out=$(PATH="$WORK/bin:$PATH" FIPS_CONFIG="$config" timeout 10 bash -c '
|
|
source "$1" >"$2/source.out" 2>&1 || exit 3
|
|
declare -F tun_name >/dev/null || exit 4
|
|
tun_name
|
|
' _ "$SETUP" "$WORK" 2>&1) || rc=$?
|
|
case "$rc" in
|
|
0) printf '%s\n' "$out" ;;
|
|
4) echo "ERROR: fips-dns-setup defines no tun_name function" ;;
|
|
124) echo "ERROR: sourcing fips-dns-setup did not return within 10s" ;;
|
|
*) echo "ERROR: sourcing fips-dns-setup exited $rc, so it ran its main path: $(tr '\n' ' ' <"$WORK/source.out")" ;;
|
|
esac
|
|
return 0
|
|
}
|
|
|
|
# expect <case name> <wanted name> <config path>
|
|
expect() {
|
|
local name="$1" want="$2" config="$3" got
|
|
got=$(lookup "$config")
|
|
if [ "$got" = "$want" ]; then
|
|
echo "PASS $name (got $got)"
|
|
else
|
|
echo "FAIL $name (want '$want', got '$got')"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# fixture <file name> <yaml text>: writes a config fixture and prints its path.
|
|
fixture() {
|
|
printf '%s\n' "$2" >"$WORK/$1"
|
|
echo "$WORK/$1"
|
|
return 0
|
|
}
|
|
|
|
expect "shipped_config_gives_fips0" fips0 "$SHIPPED_YAML"
|
|
|
|
expect "plain_name_under_tun_is_read" mesh0 "$(fixture plain.yaml 'tun:
|
|
enabled: true
|
|
name: mesh0
|
|
mtu: 1280')"
|
|
|
|
expect "double_quoted_name_is_unquoted" mesh0 "$(fixture dq.yaml 'tun:
|
|
name: "mesh0"')"
|
|
|
|
expect "single_quoted_name_with_trailing_comment_is_unquoted" mesh0 "$(fixture sq.yaml "tun:
|
|
name: 'mesh0' # renamed for the lab")"
|
|
|
|
expect "commented_tun_line_and_four_space_indent_are_read" mesh1 "$(fixture indent.yaml 'tun: # the TUN device
|
|
enabled: true
|
|
name: mesh1')"
|
|
|
|
expect "name_under_another_top_level_block_is_ignored" fips0 "$(fixture other.yaml 'node:
|
|
name: notatun
|
|
tun:
|
|
enabled: true
|
|
dns:
|
|
name: alsonot')"
|
|
|
|
expect "name_nested_below_tun_is_not_the_tun_name" mesh2 "$(fixture nested.yaml 'tun:
|
|
extra:
|
|
name: deeper
|
|
name: mesh2')"
|
|
|
|
expect "name_after_the_tun_block_ends_is_ignored" fips0 "$(fixture after.yaml 'tun:
|
|
enabled: true
|
|
# a comment between blocks
|
|
peers:
|
|
- name: peer0')"
|
|
|
|
expect "commented_out_name_is_ignored" fips0 "$(fixture commented.yaml 'tun:
|
|
# name: mesh9
|
|
enabled: true')"
|
|
|
|
expect "config_without_tun_block_gives_fips0" fips0 "$(fixture notun.yaml 'node:
|
|
identity:
|
|
persistent: true')"
|
|
|
|
expect "missing_config_gives_fips0" fips0 "$WORK/does-not-exist.yaml"
|
|
|
|
echo
|
|
if [ "$FAILURES" -eq 0 ]; then
|
|
echo "tun-name: all cases passed"
|
|
exit 0
|
|
fi
|
|
echo "tun-name: $FAILURES case(s) failed"
|
|
exit 1
|