drop the one-time migration: seed the store from a leftover file once, leave the file
A leftover plaintext client secret is stored once with -cas=0 when the store holds none, so nothing rotates. A store value wins over a different file. The file is no longer read back, compared or removed, and the migration unit is gone.
This commit is contained in:
parent
2fc63d844b
commit
fcc9c8d0ba
1 changed files with 114 additions and 350 deletions
|
|
@ -4,21 +4,15 @@
|
|||
# the store answers.
|
||||
#
|
||||
# `mint_client_secret` keeps every client with a digest. A client without one
|
||||
# gets it from the secret that exists: the plaintext file an earlier release
|
||||
# left, else the store's value. Only a client with none of the three is minted,
|
||||
# gets it from the store's secret, which an earlier release's plaintext file
|
||||
# seeds once when the store holds none. Only a client with neither is minted,
|
||||
# and then the store's leaf is created (`-cas=0`, so an existing value is never
|
||||
# replaced) before the digest is written, so a digest on disk always has a
|
||||
# secret behind it. A store that cannot be read never mints, because a second
|
||||
# secret would rotate the first.
|
||||
#
|
||||
# `migrate_client_secret` moves the plaintext file an earlier release left in
|
||||
# `$clients/<id>.secret` into the store and removes it once a read-back shows
|
||||
# the store holds the same value. It never overwrites a store value and never
|
||||
# removes a file the store does not match.
|
||||
#
|
||||
# Return statuses: 0 done, 1 retry later (the store could not answer, or a
|
||||
# digest could not be computed), 3 (migration only) the file and the store hold
|
||||
# different secrets, and only an operator can say which is right.
|
||||
# digest could not be computed).
|
||||
#
|
||||
# Pure function — NOT a NixOS module. Call it after `./store-seeded-secret.nix`
|
||||
# and `./atomic-write-secret.nix`, with `store_init` and `store_login` run and
|
||||
|
|
@ -72,14 +66,20 @@
|
|||
mint_client_secret() {
|
||||
local id="$1" leaf="$2" dig="$clients/$1.digest" legacy="$clients/$1.secret"
|
||||
local state=0 out secret digest
|
||||
if [ -s "$legacy" ]; then
|
||||
if [ -s "$dig" ]; then
|
||||
return 0
|
||||
fi
|
||||
client_secret_derive_digest "$id" "$(< "$legacy")" "$legacy"
|
||||
return
|
||||
fi
|
||||
client_secret_read "$leaf" || state=$?
|
||||
if [ "$state" = 1 ] && [ -s "$legacy" ]; then
|
||||
# A file an earlier release left: its value goes into the store once, so
|
||||
# the secret keeps its value. The file stays, unused.
|
||||
printf '%s' "$(< "$legacy")" | store_bao kv put -cas=0 "$leaf" value=- >/dev/null 2>"$STORE_ERR" \
|
||||
|| cat "$STORE_ERR" >&2
|
||||
state=0
|
||||
client_secret_read "$leaf" || state=$?
|
||||
if [ "$state" = 1 ]; then
|
||||
echo "oidc client $id: could not store the secret from $legacy in $leaf; not minting" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "oidc client $id: stored the secret from $legacy in the store"
|
||||
fi
|
||||
if [ "$state" = 0 ]; then
|
||||
if [ -s "$dig" ]; then
|
||||
chmod 0600 "$dig"
|
||||
|
|
@ -119,40 +119,4 @@
|
|||
MINTED=1
|
||||
echo "minted client secret for $id into the store"
|
||||
}
|
||||
|
||||
# <client id> <leaf>
|
||||
migrate_client_secret() {
|
||||
local id="$1" leaf="$2" legacy="$clients/$1.secret" value state=0
|
||||
[ -e "$legacy" ] || return 0
|
||||
value="$(< "$legacy")"
|
||||
if [ -z "$value" ]; then
|
||||
echo "<3>oidc client $id: $legacy is empty; keeping it" >&2
|
||||
return 3
|
||||
fi
|
||||
client_secret_read "$leaf" || state=$?
|
||||
if [ "$state" = 2 ]; then
|
||||
echo "oidc client $id: the store cannot be read; keeping $legacy" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ "$state" = 0 ]; then
|
||||
if [ "$CLIENT_SECRET_VALUE" != "$value" ]; then
|
||||
echo "<3>oidc client $id: the store at $leaf and $legacy hold different secrets; keeping both" >&2
|
||||
return 3
|
||||
fi
|
||||
rm -f "$legacy" || return 1
|
||||
echo "oidc client $id: already in the store, removed the file $legacy"
|
||||
return 0
|
||||
fi
|
||||
if ! printf '%s' "$value" | store_bao kv put -cas=0 "$leaf" value=- >/dev/null 2>"$STORE_ERR"; then
|
||||
cat "$STORE_ERR" >&2
|
||||
echo "oidc client $id: could not create $leaf; reading it back in case another run created it" >&2
|
||||
fi
|
||||
client_secret_read "$leaf" || return 1
|
||||
if [ "$CLIENT_SECRET_VALUE" != "$value" ]; then
|
||||
echo "<3>oidc client $id: the store at $leaf and $legacy hold different secrets; keeping both" >&2
|
||||
return 3
|
||||
fi
|
||||
rm -f "$legacy" || return 1
|
||||
echo "oidc client $id: stored in the store, removed the file $legacy"
|
||||
}
|
||||
''
|
||||
|
|
|
|||
Loading…
Reference in a new issue