Entra Agent ID Across Clouds: Part 5, Anti-Patterns
About this series. Five articles on running Microsoft Entra Agent ID against third-party clouds. Each one focuses on one layer of the trust story so you can read whichever part you actually need.
- Entra Agent ID Across Clouds: Part 1, Lower Environment and Secrets
- Entra Agent ID Across Clouds: Part 2, Federation End to End
- Entra Agent ID Across Clouds: Part 3, Managed Identity and Entra Objects
- Entra Agent ID Across Clouds: Part 4, FIC, Cross-Tenant, and OBO
- Entra Agent ID Across Clouds: Part 5, Anti-Patterns (this article)
What this article covers
Parts 1 through 4 built up the two patterns end to end: secret-based for the lower environment, federated for the higher environment, with FIC as the seam and OBO sitting orthogonal to both. This last article is the post-mortem reading list:
- An intermediate variant between the two patterns, and why field experience has not been kind to it.
- Anti-patterns within the secret-based pattern. Failure modes that show up the first time the laptop-shaped stack meets shared infrastructure.
- Anti-patterns within the federated pattern. Failure modes that show up the first time the federated stack meets a real production fleet.
- Summary and takeaways worth pinning to the team wiki when the series falls off the recently-edited list.
If you have skimmed the earlier parts and want one document to send to a teammate before they start an Entra Agent ID rollout, this is the one to send.
An intermediate variant and why it is usually an anti-pattern
Earlier drafts of this series called out an intermediate shape between the secret-based and federated patterns. Field experience has not been kind to it. It is documented here as a variant you may encounter, not as a pattern to adopt.
Caution. Blueprint-secret cloud-federation variant. The sidecar uses the Blueprint client secret to mint an Agent Identity JWT, then hands that JWT to the cloud’s STS as the subject token. The cloud’s credential file disappears, the Blueprint secret stays. People reach for this when they want “no cloud key on disk” without moving to attested compute. The trade is that the Blueprint secret now has a much larger blast radius (it is the root of trust for both clouds), and the operational work to add this variant as an environment is almost exactly the work to set up the federated pattern. If you have the choice, skip the variant and go straight to federated. If you cannot run on attested compute, stay on the secret-based pattern and put your energy into getting to a higher environment.
In plain terms, the variant is a half-step between the two patterns. The cloud side looks federated, but the Azure side has regressed to a secret on disk.
Normal federated pattern
- Sidecar reads an MI JWT from the IMDS endpoint. This is Azure’s signed proof that the workload is running on the managed identity it claims.
- Sidecar presents the MI JWT to Entra as a
client_assertion. Entra validates it against the Blueprint’s Federated Identity Credential and mints an Agent Identity JWT. - Sidecar presents the Agent Identity JWT to the cloud’s STS as the subject token (AWS
AssumeRoleWithWebIdentity, GCPsts.googleapis.com/v1/token, and so on). The cloud returns short-lived credentials.
Trust chain: attested compute → Blueprint → Agent Identity → cloud. Nothing on disk.
The variant
- Sidecar reads the Blueprint
client_secretfrom disk or an environment variable. - Sidecar authenticates to Entra as the Blueprint using that secret. Entra mints an Agent Identity JWT. No MI JWT, no IMDS, no attestation.
- Sidecar presents that Agent Identity JWT to the cloud’s STS, the same way the normal pattern does. The cloud returns short-lived credentials.
Trust chain: client_secret file → Blueprint → Agent Identity → cloud. The disk-resident credential is still there, just one hop earlier in the chain than in the secret-based pattern.
A note on terminology. Subject token is the OAuth 2.0 Token Exchange (RFC 8693) name for the third-party JWT a workload hands to a cloud STS in order to receive cloud credentials in return. AWS and GCP both implement variations of this exchange (AssumeRoleWithWebIdentity and Workload Identity Federation respectively). The cloud STS validates only the JWT in front of it. It has no view into which Entra credential the sidecar used upstream to obtain that JWT, which is precisely what makes the variant deceptive. From the cloud’s perspective, both the normal pattern and the variant look identical.
The rule. Lower environment: secret-based. Higher environment: federated. The variant above exists, but it consumes the same operational budget as federated without delivering its security properties. Use it only when you have a concrete constraint that makes both unavailable.
Anti-patterns within the secret-based pattern
Each of these failure modes is real, recurring, and avoidable. The fix is always cheaper than the breach.
Anti-pattern: baking the cloud credential into the container image. Image layers are visible to anyone with pull access on the registry. A COPY <credential-file> line in a Dockerfile leaks the credential the moment a registry credential leaks. Mount the credential as a volume at runtime, or inject it from a secret store. Never embed it in a layer.
Anti-pattern: rotating one secret but not the other. The Blueprint client secret and the cloud credential have independent rotation schedules and independent risk profiles. Teams that rotate the Blueprint secret on a calendar but leave the cloud credential untouched for a year quietly degrade their security posture to the weaker of the two. Rotate both, together, or accept the older one as your effective security ceiling.
Anti-pattern: shipping the secret-based pattern to production “just for now.” The laptop pattern runs in production. It also carries the full blast radius of both secrets. “Just for now” tends to outlive its sprint. Either commit to the federated pattern before you ship to a higher environment, or accept the risk explicitly and write it into the threat model.
Anti-pattern: leaving the cloud’s credential discovery chain on its default. Many cloud SDKs have an Application Default Credentials chain that ends in a metadata-server probe. On a laptop that probe times out silently and adds tens of seconds to your first call. Always set the SDK’s credential env var explicitly so the lookup short-circuits. The cloud-specific env var name lives in the per-cloud article.
Anti-pattern: committing the cloud credential to git. This sounds obvious until it happens. Add the right *.json / *.env rules to .gitignore from the first commit, and use git secrets or a pre-commit hook to enforce.
Tip. The secret-based pattern is the rung you stand on while moving up. It is rarely the rung you live on once a higher environment is reachable.
Anti-patterns within the federated pattern
Anti-pattern: trying to run the federated pattern on a laptop. Documented at length in Part 2. The laptop has no IMDS. The federation cannot start. The correct response is to stay on the secret-based pattern locally and accept that the federated pattern is a higher-environment construct.
Anti-pattern: using SAMI instead of UAMI. A system-assigned identity gets a new oid for every resource it is attached to. Every redeploy invalidates every trust document that pinned to the old oid. The fleet grinds to a halt quietly, one resource at a time, with no single failure event to attach an alert to. Always use UAMI for federated agents.
Anti-pattern: federating the UAMI directly when per-agent attribution is required. Option 1 (UAMI federates to the cloud) is simpler but flattens every Agent Identity sharing the UAMI into one principal in the cloud’s audit logs. Multi-tenant or multi-role agent platforms need Option 2 from day one to avoid retroactive log-rewriting later.
Anti-pattern: pinning the federation condition to the tenant rather than to the UAMI’s oid. A condition like tid == '<tenant>' accepts any workload in the tenant. An attacker who compromises a different workload in the same tenant inherits the same cloud access. Pin to sub, always. Use tenant conditions only as an additional gate, never as the only one.
Anti-pattern: omitting one of the two audience values from the cloud’s allow-list. The URI form (api://AzureADTokenExchange) is what callers type. The GUID form (fb60f99c-...-936) is what Entra puts on the wire. Listing only one fails for every caller path that emits the other. List both, always. (AWS has an additional twist: it needs an intermediary Entra application whose audience is a workload-scoped URI, because AWS STS does not accept the GUID form at all.)
Anti-pattern: keeping the cloud’s external-credential-config file out of source control because “it looks like a credential.” It is not a credential. It is a configuration file that points the cloud client library at IMDS. Keeping it out of source control creates a hidden manual step that breaks reproducible deploys. Commit it. The real trust lives in the cloud’s federation contract, not in this file.
Anti-pattern: treating the federated pattern as “done” once the federation succeeds. The federated pattern’s threat model assumes the runtime is trustworthy. A compromised container, a stolen image with execution permissions, or a pod with a process-level escape can all use the UAMI from inside the attested boundary. The federated pattern removes credentials from disk. It does not remove the need for runtime hardening.
Anti-pattern: assuming the ACA revision’s identity propagates to sidecars automatically. A revision can have multiple UAMIs attached. The agent container and the sidecar container each pick one based on their own AZURE_CLIENT_ID env var (or the SDK’s discovery rules). Two containers running side by side with no AZURE_CLIENT_ID set may pick different UAMIs and fail in different ways. Pin it explicitly in both containers.
Note. The pattern is the answer to one question.
The secret-based pattern puts trust on disk. The federated pattern puts trust on the runtime attestation surface. Each anti-pattern above is a way of accidentally moving trust to somewhere the pattern did not intend it to live.
Summary and key takeaways
If you take only a handful of points away from this series, take these:
- There are two patterns, mapped to two environments. The secret-based pattern for the lower environment (laptop, dev box, CI). The federated pattern for the higher environment (Azure compute with managed identity). Everything else is variation or anti-pattern.
- The seam between patterns is one configuration block in the sidecar. Everything else is fixed. This is the architectural promise that makes promoting between patterns a one-line code change.
- The federated pattern is two federations in parallel, sharing a runtime trust anchor. It is not “a single secretless thing.” Understanding it as two independent contracts makes both the design and the failure modes legible.
- Your laptop cannot do the federated pattern, and that is by design. Managed identity is bound to attested compute. There is no key to take with you. Plan your inner loop accordingly: stay on the secret-based pattern locally, or move dev into Azure.
- For federated agents, always use UAMI, never SAMI. Pin trust to the workload class, not the instance. This is the rule that lets you operate a fleet without a fleet of trust documents.
- UAMI is a workload identity, not a user. The “user-assigned” name refers to who creates it, not what it represents.
- UAMI, Blueprint, and Agent Identity are three separate objects. Each one does one job. The Agent Identity is what downstream APIs see in their audit logs.
- You can federate either the UAMI or the Agent Identity to the cloud. Option 1 is simpler. Option 2 buys you per-agent attribution in the cloud’s audit logs and atomic per-agent revocation. Start with Option 1. Move to Option 2 when governance requires it.
- OBO is orthogonal to the auth mode. The agent code does not change when the sidecar moves from a secret to a federated assertion.
- The
audclaim on a managed-identity token is a GUID, not the URI you asked for. Configure every audience allow-list with both values. AWS goes one step further and needs an intermediary Entra app to re-shape the audience entirely.
Wrapping up
That is the full picture.
The architecture, in the end, is not complicated. There are two patterns, one shaped for the lower environment where you write code on a laptop, and one shaped for the higher environment where production runs on attested compute. The two are separated by a single seam in the sidecar, and crossing that seam is a matter of changing one block of configuration rather than rewriting the agent. Behind that seam sit three Entra objects, each with a job small enough to describe in a sentence: the UAMI proves what the workload is, the Blueprint defines what the agent is, and the Agent Identity is what the rest of the system actually sees. The Federated Identity Credential is the small piece of wiring that lets these three trust each other without anyone holding a key. On-behalf-of stays politely out of the way until the day a real human steps into the picture, at which point it does its own quiet job alongside the rest. Most of the failure modes in this article are not exotic. They are the ones I keep seeing, in the order I keep seeing them, and once you know they exist they tend to walk past you instead of into you.
One thing this series deliberately steps around is the per-cloud implementation. That is where the next posts go. End-to-end walkthroughs for AWS and GCP are both in the works, grounded in practical experience from working through real-world scenarios.
For new posts, subscribe via the RSS feed or follow along on LinkedIn. Thanks for reading.
Read next
- Digital Identity
Entra Agent ID Across Clouds: Part 4, FIC, Cross-Tenant, and OBO
Fourth article in the five-part series on running Microsoft Entra Agent ID against third-party clouds. Opens up the Federated Identity Credential as a first-class object: single-tenant, cross-tenant SaaS shape, and the orthogonal world of on-behalf-of (OBO) where the agent acts for a signed-in user.
- Digital Identity
Entra Agent ID Across Clouds: Part 3, Managed Identity and Entra Objects
Third article in the five-part series on running Microsoft Entra Agent ID against third-party clouds. Pins down what the UAMI actually is in this architecture, why SAMI breaks federation, the three distinct Entra objects (UAMI, Blueprint, Agent Identity) and the three claims (sub, azp, oid) they each populate, and the production trade-off between federating the UAMI or the Agent Identity to the cloud.
- Digital Identity
Entra Agent ID Across Clouds: Part 2, Federation End to End
Second article in the five-part series on running Microsoft Entra Agent ID against third-party clouds. Walks the federated pattern as two parallel federations sharing one managed-identity JWT, explains why a laptop cannot participate, and shows what actually travels on the wire (including the audience GUID that catches most first deploys).
Worth reading again?
Get the next one in your inbox.