Skip to content

feat: add workload identity federation support for AWS ECS tasks (#496)#674

Open
cy-yun wants to merge 2 commits into
mainfrom
ecs-wif-support
Open

feat: add workload identity federation support for AWS ECS tasks (#496)#674
cy-yun wants to merge 2 commits into
mainfrom
ecs-wif-support

Conversation

@cy-yun

@cy-yun cy-yun commented Jul 7, 2026

Copy link
Copy Markdown

Add support for AWS ECS (Elastic Container Service) credentials in AwsNativeSource

Description

This PR introduces native support for retrieving AWS credentials from the ECS Container Metadata endpoint within AwsNativeSource.

Previously, when running applications inside an Amazon ECS or AWS Fargate container with IAM Roles for Tasks configured, the library could not automatically resolve the temporary container credentials, as it primarily supported EC2 IMDSv2 metadata endpoints, explicit credentials via URLs, or static environment variables (AWS_ACCESS_KEY_ID, etc).

With this change, AwsNativeSource natively honors standard AWS ECS environment variables:

  • AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
  • AWS_CONTAINER_CREDENTIALS_FULL_URI
  • AWS_CONTAINER_AUTHORIZATION_TOKEN
  • AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE

When detected, the library fetches the temporary AccessKeyId, SecretAccessKey, and Token from the ECS metadata server, allowing seamless workload identity federation between AWS ECS/Fargate and Google Cloud.

Changes Made

  • Added AwsNativeSource::getSigningVarsFromEcs to probe and execute HTTP requests to the ECS container metadata endpoint.
  • Included parsing and fallback logic for authorization tokens (AWS_CONTAINER_AUTHORIZATION_TOKEN and AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE).
  • Validated the presence of required JSON response properties to ensure type safety.
  • Injected getSigningVarsFromEcs into the credential resolution fallback chain (after Env variables, but before generic URLs).
  • Added corresponding unit tests in AwsNativeSourceTest for both relative and full URI resolutions, as well as token/file variations.

Additional End-to-End Testing

Because the ECS credential fetcher relies heavily on interacting with AWS's link-local Task Metadata Endpoint, I've also added a standalone end-to-end testing harness alongside our standard unit tests.

This includes:

  • A Local PHP Mock Server (local-ecs-mock-server.php) that explicitly simulates the behavior (and edge cases) of the actual AWS metadata server.
  • Integration into tests.yml which spins up the mock server in the background and runs the SDK against it across every supported version of PHP. This verifies that the GuzzleHttp client handles real TCP socket negotiations, malformed JSON, missing fields, and HTTP 500 errors gracefully in a true runtime environment.

How the Customer Uses It

Customers do not need to change any application code.

When a PHP application using google/auth is deployed on Amazon ECS or AWS Fargate with a Task IAM Role assigned, the flow works automatically:

  1. The customer configures Google Cloud Workload Identity Federation to trust their AWS account/role.
  2. They generate the generic GCP External Account credentials JSON file.
  3. They set the GOOGLE_APPLICATION_CREDENTIALS environment variable to point to this JSON file in their container.
  4. AWS ECS injects the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable into the running container implicitly.
  5. This library detects the variable, automatically queries the ECS metadata endpoint for the container's temporary AWS credentials, signs the GetCallerIdentity request, and exchanges it securely for a Google Cloud token.

End-to-End Testing Report: AWS ECS (Fargate) Workload Identity Federation

In addition to the automated local PHP mock server tests included in this PR, I have successfully conducted a manual end-to-end verification of this feature in a live AWS ECS environment.

Test Environment Setup:

  • AWS Environment: ECS Fargate Cluster running in a private subnet.
  • GCP Environment: Workload Identity Pool configured with an AWS Identity Provider, mapped to a dedicated GCP Service Account (roles/iam.workloadIdentityUser).
  • Container: php:8.1-cli image running a standalone PHP script utilizing the compiled branch of google-auth-library-php.
  • Configuration: Standard client_config.json generated via gcloud iam workload-identity-pools create-cred-config injected via the GOOGLE_APPLICATION_CREDENTIALS environment variable.

Verification Steps & Results:

  1. ECS Metadata Discovery: The SDK successfully discovered the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable automatically injected by the ECS Fargate runtime.
  2. Credential Fetching: The EcsCredentials fetcher successfully communicated with the AWS link-local Task Metadata Endpoint (169.254.170.2) and retrieved the temporary AWS Role credentials (AccessKeyId, SecretAccessKey, Token).
  3. Google STS Token Exchange: The AWS credentials were successfully signed and exchanged at https://sts.googleapis.com/v1/token for a federated identity token.
  4. Service Account Impersonation: The federated token was successfully used to call generateAccessToken on the target GCP Service Account.
  5. Final Validation: The ApplicationDefaultCredentials::getCredentials() call successfully returned a valid, usable GCP access token scoped to https://www.googleapis.com/auth/cloud-platform.

Conclusion:
The AWS ECS credential fetcher operates entirely seamlessly within the existing Application Default Credentials (ADC) pipeline. The container correctly authenticates to GCP purely via its attached AWS ECS Task Role without requiring any static keys.

@cy-yun
cy-yun requested a review from a team as a code owner July 7, 2026 01:38
@cy-yun
cy-yun force-pushed the ecs-wif-support branch 3 times, most recently from 54fe56d to 06f782a Compare July 7, 2026 07:18
@cy-yun
cy-yun force-pushed the ecs-wif-support branch from 2208b96 to 9863020 Compare July 8, 2026 01:04

@bshaffer bshaffer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!

I do have a few questions about the local ecs mock server. Is it testing anything that we aren't already testing with mocks in AwsNativeSourceTest? Or is it testing anything that we couldn't go ahead and test with mocks? Looking at the scenarios, they aren't really complex enough to justify a mock server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants