Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3b67629

Browse files
committed
Improve messaging and validation for registry creds
1 parent 2a55895 commit 3b67629

File tree

8 files changed

+59
-36
lines changed

8 files changed

+59
-36
lines changed

ecs-cli/modules/cli/compose/project/project.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ type Project interface {
5353

5454
// ecsProject struct is an implementation of Project.
5555
type ecsProject struct {
56-
containerConfigs []adapter.ContainerConfig
57-
volumes *adapter.Volumes
58-
ecsContext *context.ECSContext
59-
privateRegistryContext *regcredio.ECSRegistryCredsOutput // TODO: rename to 'ecsRegistryCreds'
56+
containerConfigs []adapter.ContainerConfig
57+
volumes *adapter.Volumes
58+
ecsContext *context.ECSContext
59+
ecsRegistryCreds *regcredio.ECSRegistryCredsOutput
6060

6161
// TODO: track a map of entities [taskDefinition -> Entity]
6262
// 1 task definition for every disjoint set of containers in the compose file
@@ -126,7 +126,7 @@ func (p *ecsProject) Parse() error {
126126
return err
127127
}
128128

129-
if err := p.parsePrivateRegistryContext(); err != nil {
129+
if err := p.parseECSRegistryCreds(); err != nil {
130130
return err
131131
}
132132

@@ -180,15 +180,15 @@ func (p *ecsProject) parseECSParams() error {
180180
return nil
181181
}
182182

183-
func (p *ecsProject) parsePrivateRegistryContext() error {
183+
func (p *ecsProject) parseECSRegistryCreds() error {
184184
logrus.Debug("Parsing the ecs-registry-creds yaml...")
185185
registryCredsFileName := p.ecsContext.CLIContext.GlobalString(flags.RegistryCredsFileNameFlag)
186186
regCreds, err := regcredio.ReadCredsOutput(registryCredsFileName)
187187
if err != nil {
188188
return err
189189
}
190190

191-
p.privateRegistryContext = regCreds
191+
p.ecsRegistryCreds = regCreds
192192

193193
return nil
194194
}
@@ -212,7 +212,7 @@ func (p *ecsProject) transformTaskDefinition() error {
212212
Volumes: p.VolumeConfigs(),
213213
ContainerConfigs: p.ContainerConfigs(), // TODO Change to pointer on project?
214214
ECSParams: ecsContext.ECSParams,
215-
PrivRegistryContext: p.privateRegistryContext,
215+
ECSRegistryCreds: p.ecsRegistryCreds,
216216
}
217217

218218
taskDefinition, err := utils.ConvertToTaskDefinition(convertParams)

ecs-cli/modules/cli/compose/project/project_test.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ func setupTestProject(t *testing.T) *ecsProject {
296296
}
297297

298298
func setupTestProjectWithEcsParams(t *testing.T, ecsParamsFileName string) *ecsProject {
299-
return setupTestProjectWithPrivateRegistryContext(t, ecsParamsFileName, "")
299+
return setupTestProjectWithECSRegistryCreds(t, ecsParamsFileName, "")
300300
}
301301

302302
// TODO: refactor into all-purpose 'setupTestProject' func
303-
func setupTestProjectWithPrivateRegistryContext(t *testing.T, ecsParamsFileName, credFileName string) *ecsProject {
303+
func setupTestProjectWithECSRegistryCreds(t *testing.T, ecsParamsFileName, credFileName string) *ecsProject {
304304
envLookup, err := utils.GetDefaultEnvironmentLookup()
305305
assert.NoError(t, err, "Unexpected error setting up environment lookup")
306306

@@ -326,7 +326,7 @@ func setupTestProjectWithPrivateRegistryContext(t *testing.T, ecsParamsFileName,
326326
}
327327
}
328328

329-
func TestParsePrivateRegistryContext(t *testing.T) {
329+
func TestParseECSRegistryCreds(t *testing.T) {
330330
credsInputString := `version: "1"
331331
registry_credential_outputs:
332332
task_execution_role: someTestRole
@@ -349,16 +349,16 @@ registry_credential_outputs:
349349
credFileName := tmpfile.Name()
350350
defer os.Remove(credFileName)
351351

352-
project := setupTestProjectWithPrivateRegistryContext(t, "", credFileName)
352+
project := setupTestProjectWithECSRegistryCreds(t, "", credFileName)
353353

354354
_, err = tmpfile.Write(content)
355355
assert.NoError(t, err, "Could not write data to ecs registry creds tempfile")
356356

357-
if err := project.parsePrivateRegistryContext(); err != nil {
357+
if err := project.parseECSRegistryCreds(); err != nil {
358358
t.Fatalf("Unexpected error parsing the "+regcredio.ECSCredFileBaseName+" data [%s]: %v", credsInputString, err)
359359
}
360360

361-
ecsRegCreds := project.privateRegistryContext
361+
ecsRegCreds := project.ecsRegistryCreds
362362
assert.NotNil(t, ecsRegCreds, "Expected "+regcredio.ECSCredFileBaseName+" to be set on project")
363363
assert.Equal(t, "1", ecsRegCreds.Version, "Expected Version to match")
364364

@@ -380,10 +380,10 @@ registry_credential_outputs:
380380
assert.ElementsMatch(t, []string{"test"}, secondOutputEntry.ContainerNames)
381381
}
382382

383-
func TestParsePrivateRegistryContext_NoFile(t *testing.T) {
383+
func TestParseECSRegistryCreds_NoFile(t *testing.T) {
384384
project := setupTestProject(t)
385-
err := project.parsePrivateRegistryContext()
385+
err := project.parseECSRegistryCreds()
386386
if assert.NoError(t, err) {
387-
assert.Nil(t, project.privateRegistryContext)
387+
assert.Nil(t, project.ecsRegistryCreds)
388388
}
389389
}

ecs-cli/modules/cli/regcreds/regcreds_app.go

+15-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ import (
3131
"github.com/urfave/cli"
3232
)
3333

34+
const (
35+
maxContainersPerTaskDef = 10
36+
)
37+
3438
// Up creates or updates registry credential secrets and an ECS task execution role needed to use them in a task def
3539
func Up(c *cli.Context) {
3640
args := c.Args()
@@ -105,6 +109,8 @@ func Up(c *cli.Context) {
105109
} else {
106110
log.Info("Skipping generation of registry credentials output file.")
107111
}
112+
113+
log.Info("\nIf your input file contains sensitive information, make sure that you delete it after use.")
108114
}
109115

110116
func getOrCreateRegistryCredentials(entryMap regcredio.RegistryCreds, smClient secretsClient.SMClient, updateAllowed bool) (map[string]regcredio.CredsOutputEntry, error) {
@@ -208,6 +214,9 @@ func validateCredsInput(input regcredio.ECSRegCredsInput, kmsClient kms.Client)
208214
if len(inputRegCreds) == 0 {
209215
return nil, errors.New("provided credentials must contain at least one registry")
210216
}
217+
if len(inputRegCreds) > maxContainersPerTaskDef {
218+
return nil, errors.New("no more than" + string(maxContainersPerTaskDef) + "registry credential entries can be created at one time")
219+
}
211220

212221
namedContainers := make(map[string]bool)
213222
outputRegCreds := make(map[string]regcredio.RegistryCredEntry)
@@ -219,13 +228,16 @@ func validateCredsInput(input regcredio.ECSRegCredsInput, kmsClient kms.Client)
219228
if len(credentialEntry.ContainerNames) > 0 {
220229
for _, container := range credentialEntry.ContainerNames {
221230
if namedContainers[container] {
222-
return nil, fmt.Errorf("container '%s' appears in more than one registry; container names must be unique across a set of registry credentials", container)
231+
return nil, fmt.Errorf("container '%s' appears in more than one registry; container names must be unique across given registry credentials", container)
223232
}
224233
namedContainers[container] = true
225234
}
226235
}
236+
if len(credentialEntry.ContainerNames) == 0 {
237+
log.Warnf("No container names given for registry '%s'; output cannot be incorporated into a task definition when running 'compose' command", registryName)
238+
}
227239
if credentialEntry.SecretManagerARN != "" && !isARN(credentialEntry.SecretManagerARN) {
228-
return nil, fmt.Errorf("invalid secret_manager_arn for registry %s", registryName)
240+
return nil, fmt.Errorf("invalid secrets_manager_arn for registry %s", registryName)
229241
}
230242
// if key specified as ID or alias, validate & get ARN
231243
if credentialEntry.KmsKeyID != "" {
@@ -241,7 +253,7 @@ func validateCredsInput(input regcredio.ECSRegCredsInput, kmsClient kms.Client)
241253
keyRegion := strings.Split(credentialEntry.KmsKeyID, ":")[3]
242254

243255
if secretRegion != keyRegion {
244-
return nil, fmt.Errorf("region of 'secret_manager_arn'(%s) and 'kms_key_id'(%s) for registry %s do not match; secret and encryption key must be in same region", secretRegion, keyRegion, registryName)
256+
return nil, fmt.Errorf("region of 'secrets_manager_arn'(%s) and 'kms_key_id'(%s) for registry %s do not match; secret and encryption key must be in same region", secretRegion, keyRegion, registryName)
245257
}
246258
}
247259
outputRegCreds[registryName] = credentialEntry

ecs-cli/modules/commands/regcreds/regcreds_command.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ func RegistryCredsCommand() cli.Command {
3636
func upCommand() cli.Command {
3737
return cli.Command{
3838
Name: "up",
39-
Usage: "Generates AWS Secrets Manager secrets and an IAM Task Execution Role for use in an ECS Task Definition.",
39+
Usage: "Uses a YAML input file to generate AWS Secrets Manager secrets and an IAM Task Execution Role for use in an ECS Task Definition.",
4040
Action: regcreds.Up,
41-
Flags: regcredsUpFlags(),
41+
Flags: flags.AppendFlags(flags.OptionalRegionAndProfileFlags(), regcredsUpFlags()),
4242
OnUsageError: flags.UsageErrorFactory("up"),
4343
}
4444
}

ecs-cli/modules/utils/compose/convert_task_definition.go

+16-5
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type ConvertTaskDefParams struct {
4646
Volumes *adapter.Volumes
4747
ContainerConfigs []adapter.ContainerConfig
4848
ECSParams *ECSParams
49-
PrivRegistryContext *regcredio.ECSRegistryCredsOutput
49+
ECSRegistryCreds *regcredio.ECSRegistryCredsOutput
5050
}
5151

5252
// ConvertToTaskDefinition transforms the yaml configs to its ecs equivalent (task definition)
@@ -99,15 +99,15 @@ func ConvertToTaskDefinition(params ConvertTaskDefParams) (*ecs.TaskDefinition,
9999
executionRoleArn := taskDefParams.executionRoleArn
100100

101101
// Check for and apply provided ecs-registry-creds values
102-
if params.PrivRegistryContext != nil {
103-
err := addRegistryCredsToContainerDefs(containerDefinitions, params.PrivRegistryContext.CredentialResources.ContainerCredentials)
102+
if params.ECSRegistryCreds != nil {
103+
err := addRegistryCredsToContainerDefs(containerDefinitions, params.ECSRegistryCreds.CredentialResources.ContainerCredentials)
104104
if err != nil {
105105
return nil, err
106106
}
107107

108108
// if provided, add or replace existing executionRoleArn with value from cred file
109-
if params.PrivRegistryContext.CredentialResources.TaskExecutionRole != "" {
110-
newExecutionRole := params.PrivRegistryContext.CredentialResources.TaskExecutionRole
109+
if params.ECSRegistryCreds.CredentialResources.TaskExecutionRole != "" {
110+
newExecutionRole := params.ECSRegistryCreds.CredentialResources.TaskExecutionRole
111111

112112
if executionRoleArn != "" {
113113
// TODO: refactor 'showResourceOverrideMsg()' to take in override src and use here
@@ -464,7 +464,18 @@ func addRegistryCredsToContainerDefs(containerDefs []*ecs.ContainerDefinition, c
464464
CredentialsParameter: aws.String(foundCredParam),
465465
}
466466
containerDef.RepositoryCredentials = &containerRepoCreds
467+
468+
// remove container entry from cred map
469+
delete(credsMap, containerName)
470+
}
471+
}
472+
// if credMap contains container names not present in our container definitions, log a warning
473+
if len(credsMap) > 0 {
474+
unusedContainers := make([]string, 0, len(credsMap))
475+
for container := range credsMap {
476+
unusedContainers = append(unusedContainers, container)
467477
}
478+
log.Warnf("Containers listed with registry credentials but not used: %v", unusedContainers)
468479
}
469480
}
470481
return nil

ecs-cli/modules/utils/compose/convert_task_definition_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,7 @@ task_definition:
15231523
// helper functions //
15241524
//////////////////////
15251525

1526-
func TestConvertToTaskDefinitionWithPrivRegContext(t *testing.T) {
1526+
func TestConvertToTaskDefinitionWithECSRegistryCreds(t *testing.T) {
15271527
containerConfigs := testContainerConfigs([]string{"mysql", "wordpress"})
15281528
credsFileString := `version: "1"
15291529
registry_credential_outputs:
@@ -1557,7 +1557,7 @@ registry_credential_outputs:
15571557
assert.Equal(t, "arn:aws:secretsmanager::secret:amazon-ecs-cli-setup-my.example.registry.net", aws.StringValue(mysqlContainer.RepositoryCredentials.CredentialsParameter))
15581558
}
15591559

1560-
func TestConvertToTaskDefinitionWithPrivRegContext_EmptyContainerCredMap(t *testing.T) {
1560+
func TestConvertToTaskDefinitionWithECSRegistryCreds_EmptyContainerCredMap(t *testing.T) {
15611561
containerConfigs := testContainerConfigs([]string{"mysql", "wordpress"})
15621562
credsNoContainersFileString := `version: "1"
15631563
registry_credential_outputs:
@@ -1589,7 +1589,7 @@ registry_credential_outputs:
15891589
assert.Empty(t, mysqlContainer.RepositoryCredentials)
15901590
}
15911591

1592-
func TestConvertToTaskDefinitionWithPrivRegContext_OverrideECSParamsValues(t *testing.T) {
1592+
func TestConvertToTaskDefinitionWithECSRegistryCreds_OverrideECSParamsValues(t *testing.T) {
15931593
containerConfigs := testContainerConfigs([]string{"mysql", "wordpress"})
15941594

15951595
// set up reg cred file
@@ -1654,7 +1654,7 @@ task_definition:
16541654
assert.Equal(t, "arn:aws:secretsmanager::secret:amazon-ecs-cli-setup-my.example.registry.net", aws.StringValue(mysqlContainer.RepositoryCredentials.CredentialsParameter))
16551655
}
16561656

1657-
func TestConvertToTaskDefinitionWithPrivRegContext_ErrorOnDuplicateContainers(t *testing.T) {
1657+
func TestConvertToTaskDefinitionWithECSRegistryCreds_ErrorOnDuplicateContainers(t *testing.T) {
16581658
containerConfigs := testContainerConfigs([]string{"mysql", "wordpress"})
16591659
credsDuplicateContainersFileString := `version: "1"
16601660
registry_credential_outputs:
@@ -1698,7 +1698,7 @@ func convertToTaskDefinitionForTest(t *testing.T, containerConfigs []adapter.Con
16981698
Volumes: volumeConfigs,
16991699
ContainerConfigs: containerConfigs,
17001700
ECSParams: ecsParams,
1701-
PrivRegistryContext: ecsRegCreds,
1701+
ECSRegistryCreds: ecsRegCreds,
17021702
}
17031703

17041704
taskDefinition, err := ConvertToTaskDefinition(testParams)

ecs-cli/modules/utils/regcredio/creds_readers_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ registry_credentials:
3232
- nginx-custom
3333
- logging
3434
other-registry.net:
35-
secret_manager_arn: aws:arn:secretsmanager:secret/repocreds-776ytg
35+
secrets_manager_arn: aws:arn:secretsmanager:secret/repocreds-776ytg
3636
container_names:
3737
- metrics`
3838

@@ -93,7 +93,7 @@ func TestReadCredsInputWithEnvVarsFromShell(t *testing.T) {
9393
inputFileString := `version: 1
9494
registry_credentials:
9595
myrepo.someregistry.io:
96-
secret_manager_arn: ${MY_SECRET_ARN}
96+
secrets_manager_arn: ${MY_SECRET_ARN}
9797
username: ${MY_REG_USRNAME}
9898
password: ${MY_REG_PASSWORD}
9999
kms_key_id: ${MY_KEY_ARN}
@@ -135,7 +135,7 @@ func TestReadCredsInput_ErrorBadYaml(t *testing.T) {
135135
badCredEntryFileString := `version: 1
136136
registry_credentials:
137137
myrepo.someregistry.io:
138-
secret_manager_arn: arn:aws:secretmanager:some-secret
138+
secrets_manager_arn: arn:aws:secretmanager:some-secret
139139
container_names:
140140
- test`
141141

ecs-cli/modules/utils/regcredio/types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type RegistryCreds map[string]RegistryCredEntry
2626

2727
// RegistryCredEntry contains info needed to create an AWS Secrets Manager secret and match it to an ECS container(s)
2828
type RegistryCredEntry struct {
29-
SecretManagerARN string `yaml:"secret_manager_arn"`
29+
SecretManagerARN string `yaml:"secrets_manager_arn"`
3030
Username string `yaml:"username"`
3131
Password string `yaml:"password"`
3232
KmsKeyID string `yaml:"kms_key_id"`

0 commit comments

Comments
 (0)