A client with a secret in the store or in a leftover file but no digest gets the digest of that secret instead of stopping the unit. The password reaches authelia's prompt through a pty, not argv. A lost mint race takes the winner's secret. Also name the mint, not the publisher, in the remaining rust docs.
111 lines
4.4 KiB
Nix
111 lines
4.4 KiB
Nix
# `checks.script-test-oidc-client-secrets` — runs
|
|
# ../host-modules/lib/oidc-client-secrets.nix's `mint_client_secret` and
|
|
# `migrate_client_secret` against a stub `bao` that keeps its leaves in files
|
|
# and a stub `authelia` that prints a fixed password and digest. The cases are
|
|
# in ./oidc-client-secrets.sh.
|
|
#
|
|
# What runs is the rendered helper, sourced as the units' scripts include it,
|
|
# after the two helpers it builds on.
|
|
{
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
# `login` answers from `FAKE_BAO_LOGIN_RC`. `kv get` and `kv put -cas=0` act
|
|
# on a file per leaf under `FAKE_BAO_KV`, and answer as bao does: a missing
|
|
# leaf is "No value found at <path>" on stderr, status 2. `FAKE_BAO_DENY_READ`
|
|
# and `FAKE_BAO_DENY_WRITE` answer 403 as a policy that grants neither does.
|
|
# `FAKE_BAO_RACE` has another run create the leaf between this one's read and
|
|
# its write. Every call is logged without the value `put` reads from stdin.
|
|
fakeBao = pkgs.writeShellScriptBin "bao" ''
|
|
echo "$*" >> "$FAKE_BAO_LOG"
|
|
case "$1 $2" in
|
|
"login -method=cert")
|
|
[ "$FAKE_BAO_LOGIN_RC" = 0 ] || { echo "fake bao: certificate refused" >&2; exit 2; }
|
|
printf 's.fake'
|
|
;;
|
|
"kv get")
|
|
[ "''${BAO_TOKEN-}" = s.fake ] || { echo "fake bao: kv without the login's token" >&2; exit 97; }
|
|
[ "$3" = -field=value ] || { echo "fake bao: get without -field=value" >&2; exit 95; }
|
|
leaf="$FAKE_BAO_KV/$(printf '%s' "$4" | tr / _)"
|
|
[ -z "''${FAKE_BAO_DENY_READ-}" ] || { echo "fake bao: permission denied" >&2; exit 2; }
|
|
if [ -n "''${FAKE_BAO_RACE-}" ] && [ ! -e "$FAKE_BAO_KV/.raced" ]; then
|
|
touch "$FAKE_BAO_KV/.raced"
|
|
printf '%s' "$FAKE_BAO_RACE" > "$leaf"
|
|
echo "No value found at secret/data/x" >&2
|
|
exit 2
|
|
fi
|
|
[ -e "$leaf" ] || { echo "No value found at secret/data/x" >&2; exit 2; }
|
|
cat "$leaf"
|
|
echo
|
|
;;
|
|
"kv put")
|
|
[ "''${BAO_TOKEN-}" = s.fake ] || { echo "fake bao: kv without the login's token" >&2; exit 97; }
|
|
[ "$3" = -cas=0 ] || { echo "fake bao: put without -cas=0" >&2; exit 96; }
|
|
[ "$5" = value=- ] || { echo "fake bao: put with the value as an argument" >&2; exit 94; }
|
|
leaf="$FAKE_BAO_KV/$(printf '%s' "$4" | tr / _)"
|
|
[ -z "''${FAKE_BAO_DENY_WRITE-}" ] || { echo "fake bao: permission denied" >&2; exit 2; }
|
|
[ ! -e "$leaf" ] || { echo "fake bao: check-and-set parameter did not match" >&2; exit 2; }
|
|
cat > "$leaf"
|
|
;;
|
|
*)
|
|
echo "fake bao: unexpected call: $*" >&2
|
|
exit 98
|
|
;;
|
|
esac
|
|
'';
|
|
|
|
# With `--random`, prints what `authelia crypto hash generate pbkdf2 --random`
|
|
# prints. Without it, answers the password prompt from stdin the way the CLI
|
|
# does on a terminal: echo, then the digest of what was typed. Prints nothing
|
|
# when `FAKE_AUTHELIA_EMPTY` is set, and fails without a digest when
|
|
# `FAKE_AUTHELIA_NODIGEST` is set. Every call is logged.
|
|
fakeAuthelia = pkgs.writeShellScriptBin "authelia" ''
|
|
echo "$*" >> "$FAKE_AUTHELIA_LOG"
|
|
[ -z "''${FAKE_AUTHELIA_EMPTY-}" ] || exit 0
|
|
case " $* " in
|
|
*" --random "*)
|
|
printf 'Random Password: minted-secret\n\nDigest: $pbkdf2-sha512$fake\n'
|
|
;;
|
|
*)
|
|
[ -z "''${FAKE_AUTHELIA_NODIGEST-}" ] || exit 1
|
|
IFS= read -r typed
|
|
printf 'Enter Password: %s\r\nDigest: digest-of-%s\r\n' "$typed" "$typed"
|
|
;;
|
|
esac
|
|
'';
|
|
|
|
# Runs the command it is given, as util-linux's `script -qec <cmd> /dev/null`
|
|
# does, without needing a pty in the build sandbox. The real pty is checked
|
|
# against the real authelia by hand.
|
|
fakeScript = pkgs.writeShellScriptBin "script" ''
|
|
echo "script $1 $3" >> "$FAKE_AUTHELIA_LOG"
|
|
[ "$1" = -qec ] || exit 99
|
|
exec ${pkgs.bash}/bin/bash -c "$2"
|
|
'';
|
|
in
|
|
pkgs.runCommand "hyperhive-script-test-oidc-client-secrets"
|
|
{
|
|
HELPER = pkgs.writeText "oidc-client-secrets.sh" (
|
|
import ../host-modules/lib/store-seeded-secret.nix { }
|
|
+ import ../host-modules/lib/atomic-write-secret.nix { }
|
|
+ import ../host-modules/lib/oidc-client-secrets.nix { }
|
|
);
|
|
FAKE_BIN = pkgs.symlinkJoin {
|
|
name = "fake-bao-and-authelia";
|
|
paths = [
|
|
fakeBao
|
|
fakeAuthelia
|
|
fakeScript
|
|
];
|
|
};
|
|
nativeBuildInputs = [
|
|
pkgs.coreutils
|
|
pkgs.gnugrep
|
|
pkgs.gnused
|
|
];
|
|
}
|
|
''
|
|
${pkgs.bash}/bin/bash ${./oidc-client-secrets.sh}
|
|
touch "$out"
|
|
''
|