Home› Blog› GCP Architecture Series #43 — Workload Identity Federation for AWS…
GCP Architecture GCP Architecture Series

GCP Architecture Series #43 — Workload Identity Federation for AWS

Three posts have been spent removing the service account key. Federation removes the service account too: an AWS workload presents the credentials it already has, and Google verifies them by calling AWS. Nothing is issued, nothing is stored — and the identity that results is not backed by any directory, which is where the risk moves to.

Verified against current vendor documentation on 25 September 2026. Pricing, limits and API behaviour were checked against the official docs on that date. Cloud services change fast — if you are reading this much later, treat the specifics as a starting point and re-check the linked sources.

Business Challenge

#40 removed the key and #41 removed the need to hold one. This removes the Google Cloud identity as a thing you provision at all.

1
"We will need a role and a trust policy on the AWS side"

Not for this mechanism. Your workloads use AWS temporary security credentials — IAM roles or instance profiles — and Google Cloud verifies them using the AWS GetCallerIdentity API. You do not need to make any configuration changes in your AWS account for this option.

Correct approach

Configure the pool and provider on the Google side and leave AWS alone. The trust is established by Google asking AWS who the caller is, not by AWS being told to trust Google.

2
"So the workload impersonates a service account"

It can, but that is no longer the recommendation. Google recommends that you grant direct resource access to the principal — and in that case, the principal is the federated user. Impersonation is the fallback for APIs with limitations.

Correct approach

Grant the role to the federated principal on the resource. Reach for a service account only when a specific API forces it.

3
"We will map the role name, it is stable enough"

AWS role names are reusable, and federation has no directory to tell two of them apart. Delete an identity and recreate one sharing its attributes, and the old and new will be indistinguishable to Workload Identity Federation — so a binding that was meant to only refer to the old one might apply to the new one too.

Correct approach

Map attributes that cannot be reused over time. This is the single most important decision in the configuration and it is made once, invisibly, in a mapping expression.

4
"One pool, several providers, it is tidier"

It is also how subjects collide. Google's guidance is explicit: use a single provider per workload identity pool to avoid subject collisions.

Correct approach

One pool per provider, in a dedicated project, with an organization policy constraint stopping pools being created elsewhere.

Architecture

The AWS mechanism is unusual among federations because the verification runs in the opposite direction from the one you expect.

Diagram: how Google Cloud verifies an AWS credential using GetCallerIdentity without AWS-side configuration, how an attribute mapping turns an ARN into a subject and custom attributes, direct resource access compared with service account impersonation, and why a claims-based identity makes recreated identities indistinguishable
Google asks AWS who the caller is. Everything after that is a mapping expression, and the mapping is the security boundary.

What arrives, and what you do with it

The AWS assertion carries three things: account (the AWS account number), arn (the ARN of the external entity) and userid. An attribute mapping turns those into a Google Cloud identity. The documented mapping for an EC2 instance with an attached role is:

MappingProduces
google.subject=assertion.arn The subject — a unique identifier for the user, used in IAM principal:// role bindings, and appearing in Cloud Logging logs.
attribute.account=assertion.account The AWS account ID as a custom attribute.
attribute.aws_role=assertion.arn.extract(...) Introduces a custom attribute aws_role and assigns it the AWS role name.
attribute.aws_ec2_instance=... The EC2 instance ID, pulled out of the same ARN.

From a single ARN like arn:aws:sts::000000000000:assumed-role/ec2-my-role/i-00000000000000000, the mapping produces four separately grantable facts. You can then bind a role to every workload in that AWS role, or to one specific EC2 instance, using a principalSet:// identifier that names the attribute and its value — the same principal type from #31, pointed at a pool rather than a project.

Two ways to use the result

Direct resource accessService account impersonation
Who the principal is The federated user itself. The Google Cloud service account.
Where the grant lives On the resource, naming the federated principal. On the resource, naming the service account.
Status Recommended. For APIs with documented limitations.

Direct access is the more interesting of the two, because it means an AWS workload appears in a Google Cloud allow policy as itself. No service account exists to be audited, disabled, or accidentally granted Editor. The #39 checklist does not apply, because there is nothing there to check.

The attribute condition fails closed, and that is worth noting after #36

An attribute condition is a CEL expression that can check assertion attributes and target attributes. Its evaluation rule is stated plainly: if the condition evaluates to true for a given credential, the credential is accepted — otherwise, the credential is rejected. Compare #36, where a denial condition that cannot be evaluated applies the deny. Both fail safe, but by opposite routes: the deny rule fires when it cannot decide, and the federation condition refuses when it cannot confirm. Same instinct, mirrored, because one is subtracting access and the other is admitting an identity.

Why This Architecture Holds Up

The sentence that governs everything else is this: Workload Identity Federation does not maintain a directory of user accounts; instead, it implements claims-based identities. The consequence is stated just as directly — when two tokens are issued by the same identity provider and their claims map to the same google.subject value, the two tokens are assumed to identify the same user.

There is no lookup. Identity is the mapped claim. Which produces an exact inversion of something established four posts ago.

Delete it, then recreate it with the same nameResult
A Google Cloud service account (#39) Inherits nothing. Bindings use an immutable unique ID, so the old grants do not apply.
A federated external identity Inherits everything. The old and new are indistinguishable, so a binding meant for the old one may apply to the new one.

Same scenario, opposite outcome, and the reason is ownership of the identifier. Google mints the unique ID behind a service account and can guarantee it is never reissued. It has no such control over an AWS ARN or an email address in somebody else's directory, so it cannot promise the identifier means one thing forever — and it tells you so rather than pretending.

That pushes the guarantee onto the mapping expression, which is why the best-practice list reads the way it does. Use attributes that cannot be reused over time. Use attributes the user cannot modify, because bad actors might be able to gain unauthorized access to other resources by deliberately modifying their user attributes to match existing IAM bindings. Do not let the mappings themselves be changed. Each of those is a sentence about a CEL expression that somebody writes once during setup and nobody reviews again.

What to do with this

  1. Map on something non-reusable. A role name can be deleted and recreated; treat that as the default assumption rather than the edge case.
  2. Treat the attribute mapping as production security config. It is the entire trust relationship, expressed in one field.
  3. Prefer direct resource access. It is the recommendation, and it removes the service account from the design entirely.
  4. One provider per pool, in a dedicated project, with pool creation elsewhere blocked by organization policy.
  5. Remember the AWS side is untouched. Nothing in your AWS account records that this trust exists, so the documentation for it has to live somewhere you will look.
  6. Check what the subject will be before granting anything — it is what appears in Cloud Logging, so it is what an investigation will have to work from.

Key Architecture Decisions

DecisionChoose thisBecause
An AWS workload needs Google Cloud access Federation, not a key Google verifies the AWS credentials it already has.
Configuration on the AWS side None required Verification runs through GetCallerIdentity.
How the workload gets permissions Direct resource access It is the recommendation; the principal is the federated user.
Service account impersonation Only for limited APIs It is the documented fallback, not the default.
What to map to google.subject Something non-reusable Recreated identities are otherwise indistinguishable.
Attributes a user can edit Never map them They can be modified to match an existing binding.
Pool and provider layout One provider per pool It is how subject collisions are avoided.
Where pools live A dedicated project Creation elsewhere can be blocked by org policy.
Granting a whole AWS role principalSet:// on attribute.aws_role The mapping makes the role name separately grantable.

Closing Thought

Federation is usually sold as the end of a credential problem, and for the workload it is: nothing is issued, nothing is stored, nothing expires into an outage. But the problem has not disappeared so much as changed form. A service account key was a secret you had to protect. A federated identity is an assertion you have to be able to trust, and trusting it means trusting that the attribute you mapped means the same thing next year as it does today.

Google is unusually candid about this. It does not claim to maintain a directory; it says outright that identity here is whatever the claims map to, and then spends a best-practices page explaining what that costs. The whole list — immutable attributes, non-reusable attributes, unmodifiable mappings, one provider per pool — is really one instruction repeated: the identifier is now yours to choose, and nobody downstream can tell a good choice from a bad one. A service account key at least announced itself as dangerous by being a file. A mapping expression looks like configuration.

Next in this series

#44 takes federation to the place it is most used and most misconfigured: OIDC providers and CI systems — GitHub Actions, Terraform Cloud, and why a single shared issuer URL makes the attribute condition non-optional.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent