-
Notifications
You must be signed in to change notification settings - Fork 264
Support AWS ECS task role credentials in ExternalAccount::AwsCredentials #567
Description
Summary
Google::Auth::ExternalAccount::AwsCredentials#fetch_security_credentials currently resolves AWS credentials from only two sources:
- Environment variables (
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) - EC2 instance metadata (IMDS)
When running on AWS ECS (Fargate or EC2 launch type), credentials are provided via the ECS credential provider, which uses AWS_CONTAINER_CREDENTIALS_RELATIVE_URI or AWS_CONTAINER_CREDENTIALS_FULL_URI environment variables to point to a local metadata endpoint. This endpoint is not the EC2 IMDS endpoint and has a different API format, so the existing EC2 metadata fallback does not work.
Expected behavior
fetch_security_credentials should check for ECS task role credentials (via AWS_CONTAINER_CREDENTIALS_RELATIVE_URI / AWS_CONTAINER_CREDENTIALS_FULL_URI) between the environment variable check and the EC2 metadata fallback.
Resolution order should be:
- ENV vars (
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) — current behavior - ECS task role via
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI— new - EC2 instance metadata via
credential_source.url— current fallback
Current workaround
We are using prepend to monkey-patch fetch_security_credentials with ECS support:
module AwsEcsCredentialSupport
private
def fetch_security_credentials
env_key = ENV[Google::Auth::CredentialsLoader::AWS_ACCESS_KEY_ID_VAR]
env_secret = ENV[Google::Auth::CredentialsLoader::AWS_SECRET_ACCESS_KEY_VAR]
if env_key && env_secret
return {
access_key_id: env_key,
secret_access_key: env_secret,
session_token: ENV[Google::Auth::CredentialsLoader::AWS_SESSION_TOKEN_VAR]
}
end
if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"] || ENV["AWS_CONTAINER_CREDENTIALS_FULL_URI"]
creds = Aws::ECSCredentials.new.credentials
if creds.access_key_id && creds.secret_access_key
return {
access_key_id: creds.access_key_id,
secret_access_key: creds.secret_access_key,
session_token: creds.session_token
}
end
end
super
end
end
Google::Auth::ExternalAccount::AwsCredentials.prepend(AwsEcsCredentialSupport)Related issues in other languages
- Java: [google-auth-library-java] Workload Identity Federation should support ECS Fargate container credentials google-cloud-java#12605, [google-auth-library-java] Workload identity federation doesn't support full aws credential sources. google-cloud-java#12595
- Python: https://github.com/googleapis/google-auth-library-python/issues/1099
There is also a third-party Python package aws-ecs-gcp-workload-identity-federation that works around this limitation.
Use case
We use GCP Workload Identity Federation to allow AWS ECS tasks to access Google Cloud resources (BigQuery) without long-lived service account keys. The ECS tasks run on Fargate, where the only credential source available is the ECS task role metadata endpoint.