Skip to content

Commit 1fd2d38

Browse files
author
Heming Han
authored
Fix a issue that agent does not clean task execution credentials from credential manager (#2993)
1 parent 9b16cf8 commit 1fd2d38

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

agent/engine/task_manager.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ func (mtask *managedTask) steadyState() bool {
350350
}
351351
}
352352

353-
// cleanupCredentials removes credentials for a stopped task
353+
// cleanupCredentials removes credentials for a stopped task (execution credentials are removed in cleanupTask
354+
// due to its potential usage in the later phase of the task cleanup such as sending logs)
354355
func (mtask *managedTask) cleanupCredentials() {
355356
taskCredentialsID := mtask.GetCredentialsID()
356357
if taskCredentialsID != "" {
@@ -1424,6 +1425,7 @@ func (mtask *managedTask) time() ttime.Time {
14241425
}
14251426

14261427
func (mtask *managedTask) cleanupTask(taskStoppedDuration time.Duration) {
1428+
taskExecutionCredentialsID := mtask.GetExecutionCredentialsID()
14271429
cleanupTimeDuration := mtask.GetKnownStatusTime().Add(taskStoppedDuration).Sub(ttime.Now())
14281430
cleanupTime := make(<-chan time.Time)
14291431
if cleanupTimeDuration < 0 {
@@ -1464,6 +1466,14 @@ func (mtask *managedTask) cleanupTask(taskStoppedDuration time.Duration) {
14641466
mtask.engine.sweepTask(mtask.Task)
14651467
mtask.engine.deleteTask(mtask.Task)
14661468

1469+
// Remove TaskExecutionCredentials from credentialsManager
1470+
if taskExecutionCredentialsID != "" {
1471+
logger.Info("Cleaning up task's execution credentials", logger.Fields{
1472+
field.TaskARN: mtask.Arn,
1473+
})
1474+
mtask.credentialsManager.RemoveCredentials(taskExecutionCredentialsID)
1475+
}
1476+
14671477
// The last thing to do here is to cancel the context, which should cancel
14681478
// all outstanding go routines associated with this managed task.
14691479
mtask.cancel()

agent/engine/task_manager_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
apitaskstatus "github.com/aws/amazon-ecs-agent/agent/api/task/status"
3939
"github.com/aws/amazon-ecs-agent/agent/config"
4040
"github.com/aws/amazon-ecs-agent/agent/credentials"
41+
mock_credentials "github.com/aws/amazon-ecs-agent/agent/credentials/mocks"
4142
"github.com/aws/amazon-ecs-agent/agent/data"
4243
mock_dockerapi "github.com/aws/amazon-ecs-agent/agent/dockerclient/dockerapi/mocks"
4344
"github.com/aws/amazon-ecs-agent/agent/engine/dependencygraph"
@@ -1335,6 +1336,75 @@ func TestTaskWaitForExecutionCredentials(t *testing.T) {
13351336
}
13361337
}
13371338

1339+
func TestCleanupTaskWithExecutionCredentials(t *testing.T) {
1340+
cfg := getTestConfig()
1341+
ctrl := gomock.NewController(t)
1342+
mockTime := mock_ttime.NewMockTime(ctrl)
1343+
mockState := mock_dockerstate.NewMockTaskEngineState(ctrl)
1344+
mockClient := mock_dockerapi.NewMockDockerClient(ctrl)
1345+
mockImageManager := mock_engine.NewMockImageManager(ctrl)
1346+
mockCredentialsManager := mock_credentials.NewMockManager(ctrl)
1347+
mockResource := mock_taskresource.NewMockTaskResource(ctrl)
1348+
defer ctrl.Finish()
1349+
1350+
ctx, cancel := context.WithCancel(context.TODO())
1351+
defer cancel()
1352+
1353+
taskEngine := &DockerTaskEngine{
1354+
ctx: ctx,
1355+
cfg: &cfg,
1356+
dataClient: data.NewNoopClient(),
1357+
state: mockState,
1358+
client: mockClient,
1359+
imageManager: mockImageManager,
1360+
credentialsManager: mockCredentialsManager,
1361+
}
1362+
mTask := &managedTask{
1363+
ctx: ctx,
1364+
cancel: cancel,
1365+
Task: testdata.LoadTask("sleep5"),
1366+
credentialsManager: mockCredentialsManager,
1367+
_time: mockTime,
1368+
engine: taskEngine,
1369+
acsMessages: make(chan acsTransition),
1370+
dockerMessages: make(chan dockerContainerChange),
1371+
resourceStateChangeEvent: make(chan resourceStateChange),
1372+
cfg: taskEngine.cfg,
1373+
}
1374+
1375+
mTask.Task.ResourcesMapUnsafe = make(map[string][]taskresource.TaskResource)
1376+
mTask.Task.SetExecutionRoleCredentialsID("executionRoleCredentialsId")
1377+
mTask.AddResource("mockResource", mockResource)
1378+
mTask.SetKnownStatus(apitaskstatus.TaskStopped)
1379+
mTask.SetSentStatus(apitaskstatus.TaskStopped)
1380+
container := mTask.Containers[0]
1381+
dockerContainer := &apicontainer.DockerContainer{
1382+
DockerName: "dockerContainer",
1383+
}
1384+
1385+
// Expectations for triggering cleanup
1386+
now := mTask.GetKnownStatusTime()
1387+
taskStoppedDuration := 1 * time.Minute
1388+
mockTime.EXPECT().Now().Return(now).AnyTimes()
1389+
cleanupTimeTrigger := make(chan time.Time)
1390+
mockTime.EXPECT().After(gomock.Any()).Return(cleanupTimeTrigger)
1391+
go func() {
1392+
cleanupTimeTrigger <- now
1393+
}()
1394+
1395+
// Expectations to verify the execution credentials get removed
1396+
mockCredentialsManager.EXPECT().RemoveCredentials("executionRoleCredentialsId")
1397+
1398+
// Expectations to verify that the task gets removed
1399+
mockState.EXPECT().ContainerMapByArn(mTask.Arn).Return(map[string]*apicontainer.DockerContainer{container.Name: dockerContainer}, true)
1400+
mockClient.EXPECT().RemoveContainer(gomock.Any(), dockerContainer.DockerName, gomock.Any()).Return(nil)
1401+
mockImageManager.EXPECT().RemoveContainerReferenceFromImageState(container).Return(nil)
1402+
mockState.EXPECT().RemoveTask(mTask.Task)
1403+
mockResource.EXPECT().Cleanup()
1404+
mockResource.EXPECT().GetName()
1405+
mTask.cleanupTask(taskStoppedDuration)
1406+
}
1407+
13381408
func TestCleanupTaskWithInvalidInterval(t *testing.T) {
13391409
ctrl := gomock.NewController(t)
13401410
mockTime := mock_ttime.NewMockTime(ctrl)

0 commit comments

Comments
 (0)