rotate_cert_windows.py¶
Transactional Windows Blueprint certificate rotation with full rollback,
extracted from deploy-windows.ps1 so the rollback contract is testable. Windows
only.
Part of the auth-and-certs command reference.
Purpose¶
Performs an all-or-nothing rotation of the Blueprint certificate: it registers
the new certificate on the Blueprint app, smoke-tests token acquisition, and
either commits (removing the old certificate) or rolls everything back. It is a
module invoked by deploy-windows.ps1, not a
standalone CLI entry point. See
Windows Platform APIs → Two thumbprints, two purposes
and Token flows.
Requirements¶
- Windows, driven by
deploy-windows.ps1. - The wrapper must, before generating the new certificate, capture the old certificate's public DER — for a non-exportable TPM key this is the only chance to grab the old public material for rollback.
- The wrapper supplies: the old DER, the new certificate's SHA-1 thumbprint,
x5t#S256, and public DER (fromgenerate_windows_cert.py), plus callables for the GraphPATCH, the smoke test, deletion of the old certificate, and a Graph token provider, together with the.envpath, MSAL cache path, and Blueprint object ID.
Usage¶
Invoked through the deploy wrapper rather than run directly:
Options¶
Not a CLI. The rotation is driven by the parameters the wrapper passes to the
rotate function.
Effects¶
The rotation runs as an ordered transaction:
- Read the original
x5t#S256and SHA-1 thumbprints from.env. - Acquire a Graph token.
PATCHthe new certificate DER onto the Blueprint'skeyCredentials.- Rewrite the
BLUEPRINT_CERT_*lines in.envto the new thumbprints (the single source of truth for the next run). - Run the smoke test (acquire a fresh Agent User token end to end).
- On the outcome:
- Smoke passes → delete the old certificate from
Cert:\CurrentUser\Myby its SHA-1 thumbprint. The old certificate is removed only after the new one is proven to work. - Smoke fails → roll back in order: re-
PATCHthe old DER onto the Blueprint, restore the original thumbprints in.env, and delete the MSAL cache so the next call does not present a token signed by the now-invalid new key.
Exit behavior¶
Outcomes surface as typed errors that the wrapper maps to process exit codes:
- Success — returns without error; the new certificate is live and the old one removed.
RotationFailed— the initialPATCHfailed; no rollback was needed and the old certificate is untouched.RotationRolledBack— thePATCHsucceeded but the smoke test failed; the original certificate and.envthumbprints were restored, and the MSAL cache was deleted (not restored) so a fresh cache is built on the next token acquisition.ManualInterventionRequired— both the initialPATCHand the rollbackPATCHfailed;.envand the MSAL cache are deliberately left untouched for manual triage, since the old DER is the only public material matching a working private key.
Security¶
Private keys never leave the certificate store; only public DER is exchanged.
Invalidating the MSAL cache on rollback prevents a stale-signed token from
looping on 401 after the new key is removed.
Common failures¶
- Rollback after smoke failure — expected and safe; the previous certificate is restored automatically.
ManualInterventionRequired— re-PATCHthe old DER manually; do not touch.env/MSAL until the Blueprint is consistent again.
Related commands¶
generate_windows_cert.py— produces the new certificate material this rotation consumes.deploy-windows.ps1— the wrapper that drives this module.setup-windows.ps1— first-time Windows provisioning.