github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/creds/secret_var_lookup_rules.go (about) 1 package creds 2 3 import ( 4 "bytes" 5 "errors" 6 "io/ioutil" 7 "text/template" 8 "text/template/parse" 9 ) 10 11 // SecretLookupPath transforms variable name into full secret path 12 type SecretLookupPath interface { 13 VariableToSecretPath(string) (string, error) 14 } 15 16 // SecretLookupWithPrefix is an implementation which returns [prefix][separator][varName] 17 type SecretLookupWithPrefix struct { 18 Prefix string 19 } 20 21 func NewSecretLookupWithPrefix(prefix string) SecretLookupPath { 22 return &SecretLookupWithPrefix{ 23 Prefix: prefix, 24 } 25 } 26 27 func (sl SecretLookupWithPrefix) VariableToSecretPath(path string) (string, error) { 28 return sl.Prefix + path, nil 29 } 30 31 // SecretLookupWithTemplate uses the given template to construct a lookup path specific 32 // to a team and (optionally) pipeline 33 type SecretTemplate struct { 34 *template.Template 35 pipelineDependent bool 36 } 37 38 type SecretLookupWithTemplate struct { 39 PathTemplate *SecretTemplate 40 TeamName string 41 PipelineName string 42 } 43 44 func BuildSecretTemplate(name, tmpl string) (*SecretTemplate, error) { 45 t, err := template.New(name).Option("missingkey=error").Parse(tmpl) 46 if err != nil { 47 return nil, err 48 } 49 50 if parse.IsEmptyTree(t.Root) { 51 return nil, errors.New("secret template should not be empty") 52 } 53 54 // Validate that the template only consumes the expected keys 55 dummy := struct{ Team, Pipeline, Secret string }{"team", "pipeline", "secret"} 56 if err = t.Execute(ioutil.Discard, &dummy); err != nil { 57 return nil, err 58 } 59 60 // Detect whether this template requires "Pipeline", and therefore 61 // should only be expanded when there is a pipeline context 62 pipelineDependent := false 63 dummyNoPipeline := struct{ Team, Secret string }{"team", "secret"} 64 if t.Execute(ioutil.Discard, &dummyNoPipeline) != nil { 65 pipelineDependent = true 66 } 67 68 return &SecretTemplate{t, pipelineDependent}, nil 69 } 70 71 func NewSecretLookupWithTemplate(pathTemplate *SecretTemplate, teamName string, pipelineName string) SecretLookupPath { 72 if pathTemplate.pipelineDependent && len(pipelineName) == 0 { 73 return nil 74 } 75 76 return &SecretLookupWithTemplate{ 77 PathTemplate: pathTemplate, 78 TeamName: teamName, 79 PipelineName: pipelineName, 80 } 81 } 82 83 func (sl SecretLookupWithTemplate) VariableToSecretPath(path string) (string, error) { 84 var buf bytes.Buffer 85 data := struct { 86 Team string 87 Pipeline string 88 Secret string 89 }{ 90 sl.TeamName, 91 sl.PipelineName, 92 path, 93 } 94 95 err := sl.PathTemplate.Execute(&buf, &data) 96 return buf.String(), err 97 }