Repository navigation
fix(ecs): vend task-role sessions from the ECS credentials endpoint - #2621
Merged
Merged
Conversation
GET /_fakecloud/ecs/creds/{task_id} returned static placeholder
credentials. It now returns a session for the task's taskRoleArn, named
after the task ID (assumed-role/<role>/<task-id>), minted and registered
like an AssumeRole session so it verifies under --verify-sigv4 and is
evaluated as the role under --iam. Sets are cached per task until near
expiry, then rotated, and revoked once the task stops. Stopped, unknown
and role-less tasks get the ECS agent's HTTP 400 InvalidIdInRequest.
RunTask overrides.taskRoleArn/executionRoleArn now replace the task
definition's roles for the task. RegisterTaskDefinition, RunTask role
overrides and CloudFormation AWS::ECS::TaskDefinition share
validate_task_role: the trust policy must name ecs-tasks.amazonaws.com,
and under --iam strict another account's role is refused, both with
ECS's ClientException message.
The --imds-link-local listener on 169.254.170.2 also serves task
credentials at the agent's /v2/credentials/<task-id>.
Closes #2601
- Hold the ECS read lock through the revocation sweep so a task started mid-sweep is not revoked against a stale snapshot. - Check another account's task role against its own trust policy. - Document the endpoint's new behavior in every SDK.
With persistence on, IAM state keeps the sessions handed to tasks while the per-task cache that revokes them starts empty, and the restart stops every restored task. Revoke the sessions of stopped tasks on startup.
A task stopping (and being swept) between the running check and the mint could still be handed a fresh session until the next sweep.
ECS accepts a bare role name for taskRoleArn; its session was minted (and looked for after a restart) in the server's default account rather than the task's. Resolve it to the full role ARN in the task's account and partition, which is also what the endpoint now reports as RoleArn.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #2601.
GET /_fakecloud/ecs/creds/{task_id}(newfakecloud-serverecs_credsmodule) returns an STS session for the task'staskRoleArn, session name = task id (assumed-role/<role>/<task-id>), minted via the samemint_session_credentialspath as Lambda (feat(lambda): give function containers the AWS environment #2562), so it verifies under--verify-sigv4and acts as the role under--iam.WorkloadCredentialCache, shared rotation logic) and re-minted near expiry; revoked when the task stops (1s sweep, task lookup held through the mint so a stopping task can't get a fresh session); sessions left over from before a restart are revoked at startup.{"code":"InvalidIdInRequest","message":"CredentialsV2Request: Credentials not found","HTTPErrorCode":400}; empty id ->NoIdInRequest. The fallback to a made-up default role is gone.taskRoleArnresolves in the task's account.RunTaskoverrides.taskRoleArn/executionRoleArnnow actually apply (they were validated but ignored).fakecloud_ecs::validate_task_roleshared by RegisterTaskDefinition, RunTask overrides and CFNAWS::ECS::TaskDefinition: trust policy must nameecs-tasks.amazonaws.com(looked up in the role's owning account); cross-account role refused under--iam strict, logged under soft; error is ECS'sClientException("ECS was unable to assume the role '...'").--imds-link-local's169.254.170.2listener also serves the agent path/v2/credentials/<task-id>.Known pre-existing limitation (documented, not changed here): the injected
AWS_CONTAINER_CREDENTIALS_FULL_URIhost ishost.docker.internal(or the in-cluster URL), which AWS SDKs reject for plain HTTP (only loopback /169.254.170.2allowed). HTTP clients get the credentials; SDK default chains inside the container don't.docs/services/ecs.mdno longer claims it works out of the box.Surfaces:
docs/services/ecs.md,docs/reference/introspection.md,docs/guides/instance-credentials.md,docs/reference/configuration.md,--imds-link-localhelp text,AGENTS.mdservice notes, doc comments in all seven SDKs (no code change).Test plan
ecs_task_role_credentials.rs(3): running task under--verify-sigv4+--iam strict->GetCallerIdentity=assumed-role/app-task-role/<task-id>, allowed SQS call works, disallowed denied, container fetched creds itself (wget), after StopTask endpoint 400 and old keys stop authenticating; role-less and unknown task -> agent error; RegisterTaskDefinition rejects untrusted and cross-account roles.ecs_task_role_secrets.rsandiam_pass_role.rsfor the new behavior;ecs,ecs_enforce,cloudformation_ecs,cloudformation_ecs_backing,ecs_metadata_endpoint,instance_credentials,imdse2e pass.Summary by cubic
GET /_fakecloud/ecs/creds/{task_id}now vends a real STS session for the task'staskRoleArn(session name = task ID) instead of static credentials, minted and registered like an AssumeRole session so it verifies under--verify-sigv4and acts as the role under--iam. Closes #2601.New Features
InvalidIdInRequestresponse, and the fallback to a made-up default role is gone.RunTaskoverrides.taskRoleArn/executionRoleArnnow apply, and bare role names resolve in the task's account.AWS::ECS::TaskDefinitionshare role validation: the trust policy must nameecs-tasks.amazonaws.com, cross-account roles are refused under--iam strict, both with ECS'sClientException.--imds-link-local's169.254.170.2listener also serves the agent path/v2/credentials/<task-id>.Migration
AWS_CONTAINER_CREDENTIALS_FULL_URIhost (host.docker.internalor the in-cluster URL) is still rejected by AWS SDKs for plain HTTP; HTTP clients get credentials, SDK default chains in containers don't, and the docs no longer claim it works out of the box.Written for commit 749baf3. Summary will update on new commits.