fix(secret-rotator): revoke old HA token over a new-token session #321
@@ -173,18 +173,28 @@ fn rotate_ha_token() -> Result<String, Box<dyn Error>> {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
// Only now is the old token expendable — the replacement is stored.
|
||||
match ha.revoke(&old_id) {
|
||||
// Revoke over a FRESH connection authenticated with the NEW token, not the
|
||||
// one we've been using. HA binds the WebSocket session to the refresh token
|
||||
// behind its access token, so deleting the OLD token over the OLD token's
|
||||
// own session tears that session down before the delete-ack can be read —
|
||||
// the delete succeeds server-side but surfaces as "connection closed by
|
||||
// HA", a false failure. Reconnecting with the new token keeps the session
|
||||
// alive through the revoke. (Verified live: the old flow reported failure
|
||||
// while the old token was in fact already gone.)
|
||||
drop(ha);
|
||||
let mut ha2 = ha::Ha::connect(&ha_url, &fresh)?;
|
||||
match ha2.revoke(&old_id) {
|
||||
Ok(()) => Ok(format!(
|
||||
"rotated {bao_path}#{field}: minted '{unique_name}', revoked old '{old_name}' ({old_id}) — value not logged"
|
||||
)),
|
||||
Err(e) => {
|
||||
// Not fatal: the new token is already live and stored. But an old
|
||||
// token that was meant to be retired and is still valid is a real
|
||||
// finding, so say so loudly.
|
||||
eprintln!("warning: new token is live, but the OLD token '{old_name}' ({old_id}) REMAINS VALID: {e}");
|
||||
// Reaching here means the new token is live and stored but the old
|
||||
// one may genuinely still be valid. Now that the session is NOT the
|
||||
// one being deleted, this is a real finding rather than the
|
||||
// self-inflicted false negative above — surface it loudly.
|
||||
eprintln!("warning: new token is live and stored, but revoking the OLD token '{old_name}' ({old_id}) failed and it MAY REMAIN VALID: {e}");
|
||||
Ok(format!(
|
||||
"rotated {bao_path}#{field}: minted '{client_name}'; old token NOT revoked (see warning)"
|
||||
"rotated {bao_path}#{field}: minted '{unique_name}'; old token '{old_name}' ({old_id}) NOT confirmed revoked (see warning)"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user