@@ -27,6 +27,12 @@ import (
27
27
"github.com/urfave/cli"
28
28
)
29
29
30
+ const (
31
+ // EcsCliResourcePrefix is prepended to the names of resources created through the ecs-cli
32
+ // TODO: move to more generic package for use in other parts of the ecs-cli
33
+ EcsCliResourcePrefix = "amazon-ecs-cli-setup-"
34
+ )
35
+
30
36
// CredsOutputEntry contains the credential ARN and associated container names
31
37
// TODO: use & move to output_reader once implemented?
32
38
type CredsOutputEntry struct {
@@ -53,60 +59,49 @@ func Up(c *cli.Context) {
53
59
}
54
60
55
61
commandConfig := getNewCommandConfig (c )
62
+ updateAllowed := c .Bool (flags .UpdateExistingSecretsFlag )
63
+
64
+ smClient := secretsClient .NewSecretsManagerClient (commandConfig )
56
65
57
- _ , err = getOrCreateRegistryCredentials (credsInput .RegistryCredentials , commandConfig , c )
66
+ _ , err = getOrCreateRegistryCredentials (credsInput .RegistryCredentials , smClient , updateAllowed )
58
67
if err != nil {
59
68
log .Fatal ("Error executing 'up': " , err )
60
69
}
61
70
62
- //TODO: create role, produce output
71
+ //TODO: use getOrCreate...() result to create role, produce output
63
72
}
64
73
65
- func getOrCreateRegistryCredentials (entryMap readers.RegistryCreds , cmdConfig * config. CommandConfig , c * cli. Context ) (* map [string ]CredsOutputEntry , error ) {
74
+ func getOrCreateRegistryCredentials (entryMap readers.RegistryCreds , smClient secretsClient. SMClient , updateAllowed bool ) (map [string ]CredsOutputEntry , error ) {
66
75
registryResults := make (map [string ]CredsOutputEntry )
67
- updateAllowed := c .Bool (flags .UpdateExistingSecretsFlag )
68
-
69
- smClient := secretsClient .NewSecretsManagerClient (cmdConfig )
70
76
71
77
for registryName , credentialEntry := range entryMap {
72
- hasCredPair := hasCredPair (credentialEntry )
73
- hasSecretARN := false
74
- if credentialEntry .SecretManagerARN != "" {
75
- hasSecretARN = true
76
- }
77
-
78
78
log .Infof ("Processing credentials for registry %s..." , registryName )
79
79
80
- if hasCredPair && hasSecretARN {
81
- arn , err := updateOrWarnForExistingSecret (credentialEntry , updateAllowed , smClient )
80
+ arn := credentialEntry .SecretManagerARN
81
+ if arn == "" {
82
+ newSecretArn , err := findOrCreateRegistrySecret (registryName , credentialEntry , smClient )
82
83
if err != nil {
83
84
return nil , err
84
85
}
85
- registryResults [registryName ] = buildOutputEntry (arn , credentialEntry .ContainerNames )
86
-
87
- } else if hasSecretARN {
88
- registryResults [registryName ] = buildOutputEntry (credentialEntry .SecretManagerARN , credentialEntry .ContainerNames )
89
- log .Infof ("Using existing secret %s." , registryName )
90
-
91
- } else {
92
- arn , err := createNewRegistrySecret (registryName , credentialEntry , smClient )
93
- if err != nil {
86
+ arn = newSecretArn
87
+ } else if credentialEntry .HasCredPair () {
88
+ if err := updateOrWarnForExistingSecret (credentialEntry , updateAllowed , smClient ); err != nil {
94
89
return nil , err
95
90
}
96
- registryResults [registryName ] = buildOutputEntry (arn , credentialEntry .ContainerNames )
91
+ } else {
92
+ log .Infof ("Using existing secret %s." , arn )
97
93
}
94
+ registryResults [registryName ] = buildOutputEntry (arn , credentialEntry .ContainerNames )
98
95
}
99
96
100
- log .Infof ("\n up results: %v" , registryResults )
101
-
102
- return & registryResults , nil
97
+ return registryResults , nil
103
98
}
104
99
105
- func createNewRegistrySecret (registryName string , credEntry readers.RegistryCredEntry , smClient secretsClient.SMClient ) (string , error ) {
100
+ func findOrCreateRegistrySecret (registryName string , credEntry readers.RegistryCredEntry , smClient secretsClient.SMClient ) (string , error ) {
106
101
107
102
secretName := generateSecretName (registryName )
108
103
109
- existingSecret , _ := smClient .DescribeSecret (secretName )
104
+ existingSecret , _ := smClient .DescribeSecret (* secretName )
110
105
if existingSecret != nil {
111
106
log .Infof ("Existing credential secret found, using %s" , * existingSecret .ARN )
112
107
@@ -116,9 +111,9 @@ func createNewRegistrySecret(registryName string, credEntry readers.RegistryCred
116
111
secretString := generateSecretString (credEntry .Username , credEntry .Password )
117
112
118
113
createSecretRequest := secretsmanager.CreateSecretInput {
119
- Name : aws . String ( secretName ) ,
120
- SecretString : aws . String ( secretString ) ,
121
- Description : aws . String ( fmt . Sprintf ( "Created with the ECS CLI for use with registry %s" , registryName ) ),
114
+ Name : secretName ,
115
+ SecretString : secretString ,
116
+ Description : generateSecretDescription ( registryName ),
122
117
}
123
118
if credEntry .KmsKeyID != "" {
124
119
createSecretRequest .SetKmsKeyId (credEntry .KmsKeyID )
@@ -133,28 +128,27 @@ func createNewRegistrySecret(registryName string, credEntry readers.RegistryCred
133
128
return * output .ARN , nil
134
129
}
135
130
136
- func updateOrWarnForExistingSecret (credEntry readers.RegistryCredEntry , updateAllowed bool , smClient secretsClient.SMClient ) ( string , error ) {
131
+ func updateOrWarnForExistingSecret (credEntry readers.RegistryCredEntry , updateAllowed bool , smClient secretsClient.SMClient ) error {
137
132
secretArn := credEntry .SecretManagerARN
138
133
139
134
if updateAllowed {
140
135
updatedSecretString := generateSecretString (credEntry .Username , credEntry .Password )
141
136
putSecretValueRequest := secretsmanager.PutSecretValueInput {
142
137
SecretId : aws .String (secretArn ),
143
- SecretString : aws . String ( updatedSecretString ) ,
138
+ SecretString : updatedSecretString ,
144
139
}
145
140
146
141
_ , err := smClient .PutSecretValue (putSecretValueRequest )
147
142
if err != nil {
148
- return "" , err
143
+ return err
149
144
}
150
145
151
146
log .Infof ("Updated existing secret %s with new value" , secretArn )
152
147
153
148
} else {
154
149
log .Warnf ("'username' and 'password' found but ignored for existing secret %s. To update existing secrets with new values, use '--update-existing-secrets' flag." , secretArn )
155
150
}
156
-
157
- return secretArn , nil
151
+ return nil
158
152
}
159
153
160
154
func validateCredsInput (input readers.ECSRegCredsInput ) error {
@@ -166,28 +160,24 @@ func validateCredsInput(input readers.ECSRegCredsInput) error {
166
160
return errors .New ("provided credentials must contain at least one registry" )
167
161
}
168
162
163
+ namedContainers := make (map [string ]bool )
164
+
169
165
for registryName , credentialEntry := range inputRegCreds {
170
- if ! hasRequiredFields ( credentialEntry ) {
166
+ if ! credentialEntry . HasRequiredFields ( ) {
171
167
return fmt .Errorf ("missing required field(s) for registry %s; registry credentials should contain existing secret ARN or username + password" , registryName )
172
168
}
169
+ if len (credentialEntry .ContainerNames ) > 0 {
170
+ for _ , container := range credentialEntry .ContainerNames {
171
+ if namedContainers [container ] {
172
+ return fmt .Errorf ("container '%s' appears in more than one registry; container names must be unique across a set of registry credentials" , container )
173
+ }
174
+ namedContainers [container ] = true
175
+ }
176
+ }
173
177
}
174
178
return nil
175
179
}
176
180
177
- func hasRequiredFields (entry readers.RegistryCredEntry ) bool {
178
- if (entry .SecretManagerARN != "" ) || hasCredPair (entry ) {
179
- return true
180
- }
181
- return false
182
- }
183
-
184
- func hasCredPair (entry readers.RegistryCredEntry ) bool {
185
- if entry .Username != "" && entry .Password != "" {
186
- return true
187
- }
188
- return false
189
- }
190
-
191
181
func getNewCommandConfig (c * cli.Context ) * config.CommandConfig {
192
182
rdwr , err := config .NewReadWriter ()
193
183
if err != nil {
@@ -201,12 +191,16 @@ func getNewCommandConfig(c *cli.Context) *config.CommandConfig {
201
191
return commandConfig
202
192
}
203
193
204
- func generateSecretName (regName string ) string {
205
- return "amazon-ecs-cli-setup-" + regName
194
+ func generateSecretName (regName string ) * string {
195
+ return aws .String (EcsCliResourcePrefix + regName )
196
+ }
197
+
198
+ func generateSecretString (username , password string ) * string {
199
+ return aws .String (`{"username":"` + username + `"},{"password":"` + password + `"}` )
206
200
}
207
201
208
- func generateSecretString ( username , password string ) string {
209
- return `{"username":"` + username + `"},{"password":"` + password + `"}`
202
+ func generateSecretDescription ( regName string ) * string {
203
+ return aws . String ( fmt . Sprintf ( "Created with the ECS CLI for use with registry %s" , regName ))
210
204
}
211
205
212
206
func buildOutputEntry (arn string , containers []string ) CredsOutputEntry {
0 commit comments