Identity Lifecycle and Deprovisioning¶
This guide covers the resource chain Entrabot provisions in Entra, the runtime identity states the MCP server moves through, and how to inspect, rotate, and tear down that chain.
Provisioning order¶
Provisioning creates four resources, in order:
- Blueprint application — the Agent Identity Blueprint app registration.
- BlueprintPrincipal — created explicitly as its own step; it is not auto-created alongside the Blueprint application.
- Agent Identity — a service principal scoped to the Blueprint.
- Agent User — a real Entra user account linked to the Agent Identity,
which is what gives the agent Teams presence and an
idtyp=usertoken.
See the
create_entra_agent_ids.py reference
for the script that runs this chain.
Runtime identity states¶
The MCP server's identity state machine is not a strict linear progression — it defines a specific set of allowed transitions:
| From | Allowed transitions to |
|---|---|
UNAUTHENTICATED |
DELEGATED, AGENT_USER |
DELEGATED |
PROVISIONING, UNAUTHENTICATED |
PROVISIONING |
AGENT_USER, ERROR, DELEGATED |
AGENT_USER |
ERROR, UNAUTHENTICATED |
ERROR |
DELEGATED, UNAUTHENTICATED |
Every transition is validated against this table and applied atomically. If the transition fails partway through, it rolls back cleanly and does not leave partial session state behind.
To inspect the current state and health of the chain — Blueprint, Agent Identity, Agent User, sponsors, permissions, certificates, licenses, and storage configuration — run:
macOS/Linux:
Windows (PowerShell):
See the
show_agent_status.py reference.
Certificate lifecycle¶
Windows operators rotate the Blueprint certificate with:
This wraps rotate_cert_windows.py: it captures the current certificate's
public DER before generating a new one (the only chance to do so for
non-exportable TPM-backed keys), PATCHes the new public certificate onto the
Blueprint app, and updates both thumbprints it tracks: the x5t#S256
(SHA-256) used in JWT assertion headers, and the 40-character SHA-1
thumbprint Windows CNG uses to locate the private key in the certificate
store. It then runs a smoke test against the new certificate, and rolls back
the PATCH plus local state if the smoke test fails. See the
deploy-windows.ps1 reference
and the
rotate_cert_windows.py reference.
macOS and Linux operators use two diagnostic scripts rather than an
automated rotation flow: find_local_blueprint_cert.py recovers a
registered certificate thumbprint matching the local private key when local
state is missing it, and verify_blueprint_cert.py checks whether a cached
thumbprint is still registered on the Blueprint app. If either script
reports a stale or missing certificate, re-run setup to regenerate and
re-register it. See the auth-and-certs reference pages for
find_local_blueprint_cert.py
and
verify_blueprint_cert.py.
Targeted deprovisioning¶
To remove a single Agent User chain, first run a dry run — the target UPN is required:
macOS/Linux:
.venv/bin/python3 scripts/deprovision_entra_agent_identity.py --agent-user-upn agent@tenant.onmicrosoft.com --dry-run
Windows (PowerShell):
.\.venv\Scripts\python.exe scripts\deprovision_entra_agent_identity.py --agent-user-upn agent@tenant.onmicrosoft.com --dry-run
Review the output, then run the same command without --dry-run to perform
the deletion:
macOS/Linux:
.venv/bin/python3 scripts/deprovision_entra_agent_identity.py --agent-user-upn agent@tenant.onmicrosoft.com
Windows (PowerShell):
.\.venv\Scripts\python.exe scripts\deprovision_entra_agent_identity.py --agent-user-upn agent@tenant.onmicrosoft.com
Before deleting anything, the script checks whether another Agent Identity references the same Blueprint. If one does, the script aborts without deleting the Agent User's licenses, the Agent User, the Agent Identity, or the Blueprint — nothing is removed, so other chains sharing that Blueprint are left intact. Otherwise, it removes, in order: the Agent User's directly assigned licenses, the Agent User itself, the Agent Identity service principal, and finally the Blueprint application.
The script does not touch local on-disk state or Azure Blob storage — those
are handled separately. See the
deprovision_entra_agent_identity.py reference.
For cloud storage cleanup, see the
deprovision_blob_storage.py reference
and the Storage Configuration guide.