Skip to content

Commit a07a73c

Browse files
committed
fix tmds creds response
1 parent 966c44d commit a07a73c

File tree

11 files changed

+165
-8
lines changed

11 files changed

+165
-8
lines changed

agent/api/task/task.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,10 @@ type Task struct {
245245
// perform some action at the task level, such as pulling image from ECR
246246
ExecutionCredentialsID string `json:"executionCredentialsID"`
247247

248-
// credentialsID is used to set the CredentialsId field for the
248+
// CredentialsID is used to set the CredentialsId field for the
249249
// IAMRoleCredentials object associated with the task. This id can be
250250
// used to look up the credentials for task in the credentials manager
251-
credentialsID string
251+
CredentialsID string `json:"credentialsID"`
252252
credentialsRelativeURIUnsafe string
253253

254254
// ENIs is the list of Elastic Network Interfaces assigned to this task. The
@@ -2805,15 +2805,15 @@ func (task *Task) SetCredentialsID(id string) {
28052805
task.lock.Lock()
28062806
defer task.lock.Unlock()
28072807

2808-
task.credentialsID = id
2808+
task.CredentialsID = id
28092809
}
28102810

28112811
// GetCredentialsID gets the credentials ID for the task
28122812
func (task *Task) GetCredentialsID() string {
28132813
task.lock.RLock()
28142814
defer task.lock.RUnlock()
28152815

2816-
return task.credentialsID
2816+
return task.CredentialsID
28172817
}
28182818

28192819
// SetCredentialsRelativeURI sets the credentials relative uri for the task

agent/engine/data.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ func (engine *DockerTaskEngine) loadTasks() error {
5656
for _, task := range tasks {
5757
engine.state.AddTask(task)
5858

59+
// Register the task role's ID in credentials manager as soon as possible.
60+
// This ensures TMDS can distinguish between invalid credentials requests (400) and
61+
// known credentials that aren't available yet (503) after agent restart.
62+
if credentialsID := task.GetCredentialsID(); credentialsID != "" {
63+
engine.credentialsManager.AddKnownCredentialsID(credentialsID)
64+
}
65+
5966
// TODO: Will need to clean up all of the STOPPED managed daemon tasks
6067
md, ok := task.IsManagedDaemonTask()
6168
if ok {

agent/engine/data_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import (
2727
"github.com/aws/amazon-ecs-agent/ecs-agent/api/attachment"
2828
apicontainerstatus "github.com/aws/amazon-ecs-agent/ecs-agent/api/container/status"
2929
apitaskstatus "github.com/aws/amazon-ecs-agent/ecs-agent/api/task/status"
30+
"github.com/aws/amazon-ecs-agent/ecs-agent/credentials"
31+
mock_credentials "github.com/aws/amazon-ecs-agent/ecs-agent/credentials/mocks"
3032
ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface"
3133

34+
"github.com/golang/mock/gomock"
3235
"github.com/stretchr/testify/assert"
3336
"github.com/stretchr/testify/require"
3437
)
@@ -376,3 +379,40 @@ func TestRemoveENIAttachmentData(t *testing.T) {
376379
require.NoError(t, err)
377380
assert.Len(t, res, 0)
378381
}
382+
383+
func TestLoadTasksRegistersCredentialsIDs(t *testing.T) {
384+
ctrl := gomock.NewController(t)
385+
defer ctrl.Finish()
386+
387+
dataClient := newTestDataClient(t)
388+
mockCredentialsManager := mock_credentials.NewMockManager(ctrl)
389+
390+
// Create a task with credentials ID
391+
testCredentialsID := "test-credentials-id"
392+
taskWithCredentials := &apitask.Task{
393+
Arn: testTaskARN,
394+
Containers: []*apicontainer.Container{testContainer},
395+
}
396+
// Set the credentials ID after task creation
397+
taskWithCredentials.SetCredentialsID(testCredentialsID)
398+
399+
// Save task to data client
400+
require.NoError(t, dataClient.SaveTask(taskWithCredentials))
401+
402+
engine := &DockerTaskEngine{
403+
state: dockerstate.NewTaskEngineState(),
404+
dataClient: dataClient,
405+
credentialsManager: mockCredentialsManager,
406+
}
407+
408+
// Expect credentials ID to be added to known credentials during loadTasks
409+
mockCredentialsManager.EXPECT().AddKnownCredentialsID(testCredentialsID)
410+
411+
// Call loadTasks and verify credentials ID is registered
412+
require.NoError(t, engine.loadTasks())
413+
414+
// Verify task was loaded into state
415+
task, ok := engine.state.TaskByArn(testTaskARN)
416+
assert.True(t, ok)
417+
assert.Equal(t, testCredentialsID, task.GetCredentialsID())
418+
}

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/credentials/interface.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/credentials/manager.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/credentials/mocks/credentials_mocks.go

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v1/credentials_handler.go

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ecs-agent/credentials/interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ type Manager interface {
2020
SetTaskCredentials(*TaskIAMRoleCredentials) error
2121
GetTaskCredentials(string) (TaskIAMRoleCredentials, bool)
2222
RemoveCredentials(string)
23+
IsCredentialsPending(string) bool
24+
AddKnownCredentialsID(string)
2325
}

ecs-agent/credentials/manager.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ func (roleCredentials *IAMRoleCredentials) GenerateCredentialsEndpointRelativeUR
8686
// the credentials endpoint
8787
type credentialsManager struct {
8888
// idToTaskCredentials maps credentials id to its corresponding TaskIAMRoleCredentials object
89+
// this map contains credentials id for which agent received the actual credentials from ACS already
8990
idToTaskCredentials map[string]TaskIAMRoleCredentials
91+
// knownCredentialsIDs tracks all credentials IDs we know about
92+
knownCredentialsIDs map[string]bool
9093
taskCredentialsLock sync.RWMutex
9194
}
9295

@@ -108,6 +111,7 @@ func IAMRoleCredentialsFromACS(roleCredentials *ecsacs.IAMRoleCredentials, roleT
108111
func NewManager() Manager {
109112
return &credentialsManager{
110113
idToTaskCredentials: make(map[string]TaskIAMRoleCredentials),
114+
knownCredentialsIDs: make(map[string]bool),
111115
}
112116
}
113117

@@ -132,6 +136,8 @@ func (manager *credentialsManager) SetTaskCredentials(taskCredentials *TaskIAMRo
132136
IAMRoleCredentials: taskCredentials.GetIAMRoleCredentials(),
133137
}
134138

139+
manager.knownCredentialsIDs[credentials.CredentialsID] = true
140+
135141
return nil
136142
}
137143

@@ -157,4 +163,26 @@ func (manager *credentialsManager) RemoveCredentials(id string) {
157163
defer manager.taskCredentialsLock.Unlock()
158164

159165
delete(manager.idToTaskCredentials, id)
166+
delete(manager.knownCredentialsIDs, id)
167+
}
168+
169+
// IsCredentialsPending returns true if credentials ID is known but has not yet arrived from ACS.
170+
func (manager *credentialsManager) IsCredentialsPending(id string) bool {
171+
manager.taskCredentialsLock.RLock()
172+
defer manager.taskCredentialsLock.RUnlock()
173+
174+
_, isKnown := manager.knownCredentialsIDs[id]
175+
_, hasCredentials := manager.idToTaskCredentials[id]
176+
177+
return isKnown && !hasCredentials
178+
}
179+
180+
// AddKnownCredentialsID adds a credentials ID to the known set
181+
// This is useful when agent needs to track known credentials IDs
182+
// for which the credentials themselves have not arrived from ACS.
183+
func (manager *credentialsManager) AddKnownCredentialsID(id string) {
184+
manager.taskCredentialsLock.Lock()
185+
defer manager.taskCredentialsLock.Unlock()
186+
187+
manager.knownCredentialsIDs[id] = true
160188
}

ecs-agent/credentials/mocks/credentials_mocks.go

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)