azure managed identity review - tfsugjp/skills GitHub Wiki
Add an azure-managed-identity-review plugin whose skill reviews an Azure managed identity across every resource, app setting, code path, and federated identity credential (FIC) that shares it. It reports grants missing for each consumer's audience and grants leaked to consumers that should not hold them, from Bicep, Terraform, and the live subscription. The review is read-only; fixes are proposed as IaC changes.
| Type | Issue |
|---|---|
| Parent | Issue #91 |
| Sub-issue | Issue #92 |
| Sub-issue | Issue #93 |
| Sub-issue | Issue #94 |
| Sub-issue | Issue #95 |
- A user-assigned identity is often created for one resource (for example a storage account's customer-managed key in Key Vault) and reused by others (a Function App, a GitHub Actions workflow through an FIC).
- Grants made for the first purpose do not cover the other consumers' audiences (Service Bus, SQL, Cosmos DB data plane, custom
api://apps), and every grant on the identity is usable by every consumer and every trusted external workload. - Local E2E runs under the developer's own credentials (
DefaultAzureCredential,local.settings.jsonwithout__credential), so missing grants show up only after deployment.
- Placement: new plugin
plugins/azure-managed-identity-review/with one skill and one script,scripts/msi_review.py(Python 3.9+, standard library only). -
static <path>: compiles Bicep entry files with the Bicep CLI, reads ARM JSON (nested deployments, ARM expressions,--parameters), parses Terraform (*.tf, orterraform show -jsonwith--tf-plan-json), and scans source code andlocal.settings.jsonfor credentials, token scopes, and service hosts (--map <dir>=<resource>). -
live --subscription <id>: read-onlyazcalls only (Resource Graph throughaz restwith a UTF-8 body file, role assignments without Microsoft Graph lookups, FICs, masked app settings, Cosmos DB data-plane assignments).--static <path>adds drift findings;--record/--replaystore masked output. - Model: identities, consumers (including CMK, Key Vault reference, image pull, and kubelet slots), targets with the identity actually used (connection
__clientId,AZURE_CLIENT_ID, a custom client ID setting, or the system-assigned default), grants, and FICs. Role IDs and names are verified withaz role definition list. - Coverage: a grant covers a target at the target resource or a broader scope that contains it (resource groups compared when known, unresolved scopes never count; Key Vault secret and key operations need different roles); a grant on a child (container, queue, secret, Foundry project) counts only when the consumer's endpoint points into it. Target names come from endpoints, Key Vault references, registry login servers, and CMK vault URIs; Event Hubs and Service Bus are told apart by resource type.
- Rules: MIR000 unresolved reference, MIR001 shared identity, MIR002 target without a covering grant, MIR003 broad, privileged, or single-consumer grant on a shared identity, MIR004 FIC on a shared identity or non-standard FIC, MIR005 missing, unintended, or unmatched client ID, MIR006 non-RBAC grant to verify, MIR007 local development masks gaps, MIR008 drift between Azure and IaC.
- Output: Markdown report per identity (consumers and their uses, grants and who needs them, FICs, findings with fixes) or
--json;--resourcereviews a resource's identities and all their other consumers. Exit code 0, 1 (warnings or errors), or 2 (input error).
- Static inventory for Bicep/ARM and Terraform (#92).
- Read-only live collector with record and replay (#93).
- Rules MIR000-MIR008 with fixtures and unit tests (#94).
- SKILL.md, references, plugin manifests, marketplaces, and repository docs (#95).
-
python3 scripts/validate_marketplaces.pysucceeds. - The unit tests pass locally and in the existing Ubuntu CI job: the canonical scenario in compiled ARM, Terraform, and Bicep with code; identity selection; non-RBAC targets; a clean configuration; unresolved references; Terraform plan JSON; recorded live output with drift; and a positive fixture for every rule.
- A read-only live run against a real subscription confirms the
azarguments, masking, and identity inference.