keep authelia's keys in bao, seeded from the existing key files
This commit is contained in:
parent
a70b25847e
commit
99fab06348
1 changed files with 557 additions and 89 deletions
86
nix/host-modules/lib/store-seeded-secret.nix
Normal file
86
nix/host-modules/lib/store-seeded-secret.nix
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Shared shell steps for a unit that keeps a secret it once generated on disk
|
||||
# in the swarm secret store instead. The store's value wins; a store holding
|
||||
# none is seeded from the old file, so the secret keeps its value; a new value
|
||||
# is minted only when there is no file either.
|
||||
#
|
||||
# `store_seeded` prints the value and never rotates one: the store is written
|
||||
# with `-cas=0`, so only a leaf that holds nothing takes a value, and a lost
|
||||
# race reads the winner's back.
|
||||
#
|
||||
# Pure function — NOT a NixOS module. Call it from a module's `let`:
|
||||
#
|
||||
# storeSeededSecret = import ./lib/store-seeded-secret.nix { };
|
||||
# script = ''
|
||||
# ${storeSeededSecret}
|
||||
# store_init
|
||||
# store_login
|
||||
# key="$(store_seeded secret/swarm/services/foo/key /var/lib/foo/key mint_key)" || exit 1
|
||||
# '';
|
||||
#
|
||||
# Needs `bao` and `coreutils` on the caller's `path` and the `BAO_*` client
|
||||
# environment set. Takes the EXIT trap, to remove its scratch file.
|
||||
{ }:
|
||||
''
|
||||
# Bounded, so a store that drops packets cannot hold the caller past its
|
||||
# start timeout; one that refuses answers at once.
|
||||
store_bao() {
|
||||
timeout 15 bao "$@"
|
||||
}
|
||||
|
||||
store_init() {
|
||||
STORE_ERR="$(mktemp)"
|
||||
STORE_UP=0
|
||||
trap 'rm -f "$STORE_ERR"' EXIT
|
||||
}
|
||||
|
||||
# Sets STORE_UP. A store that cannot be logged in to leaves every secret to
|
||||
# its file.
|
||||
store_login() {
|
||||
local token
|
||||
if token="$(store_bao login -method=cert -token-only 2>"$STORE_ERR")"; then
|
||||
BAO_TOKEN="$token"
|
||||
export BAO_TOKEN
|
||||
STORE_UP=1
|
||||
else
|
||||
cat "$STORE_ERR" >&2
|
||||
echo "could not log in to the swarm secret store; secrets keep the value of their files." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# <leaf> <earlier file> <mint command…>. The value on stdout; status 1 when
|
||||
# neither the store nor the file can give one.
|
||||
store_seeded() {
|
||||
local leaf="$1" earlier="$2" value candidate
|
||||
shift 2
|
||||
if [ "$STORE_UP" = 1 ]; then
|
||||
if value="$(store_bao kv get -field=value "$leaf" 2>"$STORE_ERR")" && [ -n "$value" ]; then
|
||||
printf '%s' "$value"
|
||||
return 0
|
||||
fi
|
||||
if [ -s "$earlier" ]; then
|
||||
candidate="$(< "$earlier")"
|
||||
echo "storing the value of $earlier in $leaf." >&2
|
||||
else
|
||||
candidate="$("$@")"
|
||||
echo "no earlier value; minting $leaf." >&2
|
||||
fi
|
||||
if ! printf '%s' "$candidate" | store_bao kv put -cas=0 "$leaf" value=- >/dev/null 2>"$STORE_ERR"; then
|
||||
echo "could not create $leaf; reading it back in case another run created it." >&2
|
||||
cat "$STORE_ERR" >&2
|
||||
fi
|
||||
if value="$(store_bao kv get -field=value "$leaf" 2>"$STORE_ERR")" && [ -n "$value" ]; then
|
||||
printf '%s' "$value"
|
||||
return 0
|
||||
fi
|
||||
cat "$STORE_ERR" >&2
|
||||
echo "the store did not return $leaf." >&2
|
||||
fi
|
||||
if [ -s "$earlier" ]; then
|
||||
echo "using the value of $earlier for $leaf." >&2
|
||||
printf '%s' "$(< "$earlier")"
|
||||
return 0
|
||||
fi
|
||||
echo "no value for $leaf in the store or at $earlier." >&2
|
||||
return 1
|
||||
}
|
||||
''
|
||||
Loading…
Reference in a new issue