Skip to content

Commit 309a875

Browse files
wass3rwass3rw3rkecrupper
authored
feat(exec): report missing secrets (#595)
* feat(exec): report missing secrets * add tests + format step name also * minor linter fixes * add support for secret plugin --------- Co-authored-by: David May <[email protected]> Co-authored-by: Easton Crupper <[email protected]>
1 parent e402880 commit 309a875

File tree

2 files changed

+458
-0
lines changed

2 files changed

+458
-0
lines changed

action/pipeline/exec.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ func (c *Config) Exec(client compiler.Engine) error {
130130
}
131131
}
132132

133+
// find all secrets that were not provided
134+
missingSecrets := collectMissingSecrets(_pipeline)
135+
133136
// create current directory path for local mount
134137
mount := fmt.Sprintf("%s:%s:rw", base, constants.WorkspaceDefault)
135138

@@ -199,6 +202,9 @@ func (c *Config) Exec(client compiler.Engine) error {
199202
}()
200203

201204
defer func() {
205+
// print any secrets not set to the user
206+
reportMissingSecrets(missingSecrets)
207+
202208
// destroy the build with the executor
203209
err = _executor.DestroyBuild(context.Background())
204210
if err != nil {
@@ -244,6 +250,96 @@ func (c *Config) Exec(client compiler.Engine) error {
244250
return nil
245251
}
246252

253+
// reportMissingSecrets informs the user of any secrets not set.
254+
func reportMissingSecrets(s map[string]string) {
255+
if len(s) > 0 {
256+
logrus.Warn("the following secrets were not set, use --help to learn how to set them:")
257+
258+
for step, secret := range s {
259+
logrus.Warnf("secret %#q not set for step %#q", secret, step)
260+
}
261+
}
262+
}
263+
264+
// collectMissingSecrets searches a given pipeline for used secrets
265+
// and returns a map of secrets not set in the current environment.
266+
// The map key is is the step, stage+step, or secret name formatted
267+
// to match the local exec log output.
268+
func collectMissingSecrets(p *pipeline.Build) map[string]string {
269+
if p == nil {
270+
return make(map[string]string)
271+
}
272+
273+
secrets := map[string]string{}
274+
275+
for _, stage := range p.Stages {
276+
for _, step := range stage.Steps {
277+
for _, secret := range step.Secrets {
278+
stepName := formatStepIdentifier(stage.Name, step.Name, false)
279+
secrets[stepName] = secret.Target
280+
}
281+
}
282+
}
283+
284+
for _, step := range p.Steps {
285+
for _, secret := range step.Secrets {
286+
stepName := formatStepIdentifier("", step.Name, false)
287+
secrets[stepName] = secret.Target
288+
}
289+
}
290+
291+
for _, s := range p.Secrets {
292+
if !s.Origin.Empty() {
293+
for _, secret := range s.Origin.Secrets {
294+
stepName := formatStepIdentifier("", s.Origin.Name, true)
295+
secrets[stepName] = secret.Target
296+
}
297+
}
298+
}
299+
300+
for step, secret := range secrets {
301+
// if the secret was supplied, remove it from the map
302+
// we only care about unset secrets
303+
val, exists := os.LookupEnv(secret)
304+
if exists {
305+
delete(secrets, step)
306+
307+
if val == "" {
308+
logrus.Debugf("secret %#q for step %#q is provided but empty", secret, step)
309+
}
310+
}
311+
}
312+
313+
return secrets
314+
}
315+
316+
// formatStepIdentifier formats a step name to be consistent with what
317+
// the worker logs to make it easier to associate a missing secret
318+
// with a step.
319+
func formatStepIdentifier(stageName, stepName string, isSecret bool) string {
320+
const (
321+
secretPrefix = "[secret: %s]" //nolint:gosec // false positive
322+
stagePrefix = "[stage: %s]"
323+
stepPrefix = "[step: %s]"
324+
)
325+
326+
output := strings.Builder{}
327+
328+
if stageName != "" {
329+
output.WriteString(fmt.Sprintf(stagePrefix, stageName))
330+
}
331+
332+
if stepName != "" {
333+
if isSecret {
334+
output.WriteString(fmt.Sprintf(secretPrefix, stepName))
335+
} else {
336+
output.WriteString(fmt.Sprintf(stepPrefix, stepName))
337+
}
338+
}
339+
340+
return output.String()
341+
}
342+
247343
// skipSteps filters out steps to be removed from the pipeline.
248344
func skipSteps(_pipeline *pipeline.Build, stepsToRemove []string) error {
249345
// filter out steps to be removed

0 commit comments

Comments
 (0)