Watch
0
0
Fork
You've already forked hyperhive
0

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:
atlas 2026-10-30 16:12:37 +01:00 • committed by mara
commit fcc9c8d0ba

View file

@ -237,7 +237,6 @@ let
publisherCfg.enable
&& publisherCfg.baoClientCertFile != null
&& publisherCfg.baoClientKeyFile != null;
migrateUnit = "${unitName}-client-secrets";
forwarderFetchUnit = "swarm-journal-forwarder-oidc";
# The publisher's store identity, handed into the container as system
# credentials (credential id → host source). The forwarder's fetch presents
@ -580,9 +579,7 @@ let
storeRetry = import ./lib/store-retry.nix { };
# The bridge's own client secret, in the memory-backed runtime directory of
# its unit. While a plaintext file from an earlier release exists the bridge
# keeps using it, since it is the value the digest was made from; the file
# goes once the store holds the same value, and the store's takes over.
# its unit, fetched from the store before each start.
bridgeSecretFile = "/run/swarm-authelia-bridge/client-secret";
bridgeSecretFetch = ''
set -euo pipefail
@ -591,12 +588,9 @@ let
${storeSeededSecret}
${oidcClientSecrets}
legacy=${lib.escapeShellArg "${clientsDir}/${bridgeClientId}.secret"}
store_init
store_login
if [ -s "$legacy" ]; then
value="$(< "$legacy")"
elif client_secret_read ${lib.escapeShellArg (clientLeaf bridgeClientId)}; then
if client_secret_read ${lib.escapeShellArg (clientLeaf bridgeClientId)}; then
value="$CLIENT_SECRET_VALUE"
else
echo "the store holds no readable secret for ${bridgeClientId}" >&2
@ -1094,7 +1088,6 @@ in
++ lib.optionals publishes [
"opentelemetry-collector.service"
"${forwarderFetchUnit}.service"
"${migrateUnit}.service"
"${unitName}-secrets.service"
"swarm-authelia-bridge.service"
];
@ -1133,79 +1126,6 @@ in
serviceConfig.LoadCredential = lib.attrNames storeFiles;
};
# Moves the plaintext files an earlier release left in `clientsDir`
# into the store and removes each once the store holds the same
# value. With no file left it does nothing, store or no store. Nothing
# orders authelia after it: authelia starts from its digests.
systemd.services.${migrateUnit} = lib.mkIf publishes {
description = "move authelia's plaintext OIDC client secrets into the swarm secret store";
wantedBy = [ "multi-user.target" ];
after = [ "${unitName}-secrets.service" ];
path = [
pkgs.coreutils
pkgs.gnugrep
deployCfg.bao.package
];
startLimitBurst = storeRetry.startLimitBurst;
startLimitIntervalSec = storeRetry.startLimitIntervalSec;
serviceConfig = storeRetry.serviceConfig // {
Type = "oneshot";
User = unitName;
Group = socketGroup;
UMask = "0077";
LoadCredential = lib.attrNames storeFiles;
TimeoutStartSec = 120;
RestartPreventExitStatus = 3;
SyslogIdentifier = migrateUnit;
};
environment =
let
store = storeIdentityIn migrateUnit;
in
{
BAO_ADDR = store.addr;
BAO_CLIENT_CERT = store.clientCertFile;
BAO_CLIENT_KEY = store.clientKeyFile;
}
// lib.optionalAttrs (store.caFile != null) { BAO_CACERT = store.caFile; };
script = ''
set -uo pipefail
${storeSeededSecret}
${oidcClientSecrets}
clients=${lib.escapeShellArg clientsDir}
known=${lib.escapeShellArg (lib.concatMapStrings (c: " ${c.id}") secretClients + " ")}
pending=0
for f in "$clients"/*.secret; do
[ -e "$f" ] || continue
id="$(basename "$f" .secret)"
case "$known" in
*" $id "*) pending=1 ;;
*) echo "left $f in place: no client $id is registered here" >&2 ;;
esac
done
if [ "$pending" = 0 ]; then
echo "no plaintext client secret files to move"
exit 0
fi
store_init
store_login
status=0
${lib.concatMapStrings (c: ''
rc=0
migrate_client_secret ${lib.escapeShellArg c.id} ${lib.escapeShellArg (clientLeaf c.id)} || rc=$?
if [ "$rc" != 0 ] && [ "$status" != 1 ]; then
status="$rc"
fi
'') secretClients}
exit "$status"
'';
};
# The authelia binary itself, so an operator who gets a shell
# in here can run `authelia crypto hash generate` to make a
# password for the users file. Without it the container runs
@ -1323,8 +1243,7 @@ in
after = [
"${unitName}-secrets.service"
"${unitName}.service"
]
++ lib.optional publishes "${migrateUnit}.service";
];
wants = [
"${unitName}-secrets.service"
"${unitName}.service"