fix(secrets-cli): degrade on malformed master-key source + topology note

This commit is contained in:
Joseph Doherty
2026-07-19 09:08:24 -04:00
parent 83af2b2eaf
commit 9bc1e5852e
2 changed files with 36 additions and 0 deletions
@@ -53,6 +53,11 @@ public sealed class SecretsSessionFactory
// Mirrors the DI extensions' store selection: a configured SQL-Server hub wins, EXCEPT when its
// connection string is an unresolved '${secret:}' reference (the app resolves that from its own
// bootstrapped store at startup; the CLI has no such resolver), in which case fall back to SQLite.
//
// The CLI deliberately treats a configured Secrets:SqlServer section as the authoritative target
// regardless of the app's replication topology: in hub-replication mode the SQL-Server hub is the
// shared source of truth, so editing it here is correct — the change converges to each node's local
// store via the sync sweep, rather than being written to one node's local SQLite and racing the hub.
private static (ISecretStore Store, ISecretsStoreMigrator Migrator, string StoreKind) BuildStore(
StoreTarget target, List<string> warnings)
{
@@ -99,6 +104,16 @@ public sealed class SecretsSessionFactory
return (provider, new AesGcmEnvelopeCipher(provider));
}
catch (ArgumentOutOfRangeException ex)
{
// MasterKeyProviderFactory.Create throws this when MasterKeySource is out of range — a
// malformed config value. This is operator-facing lockout tooling, so degrade rather than
// crash; name the invalid value so the operator can see what to fix.
warnings.Add(
$"Master-key source '{target.Secrets.MasterKey.Source}' is not a recognized value — " +
$"session is degraded (metadata only): {ex.Message}");
return (null, null);
}
catch (MasterKeyUnavailableException ex)
{
// Thrown by every provider (Environment/File/Dpapi) and the base length check when the key