github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/creds/kubernetes/secrets.go (about) 1 package kubernetes 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 "time" 8 9 "code.cloudfoundry.org/lager" 10 "github.com/pf-qiu/concourse/v6/atc/creds" 11 12 v1 "k8s.io/api/core/v1" 13 k8serr "k8s.io/apimachinery/pkg/api/errors" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "k8s.io/client-go/kubernetes" 16 ) 17 18 type Secrets struct { 19 logger lager.Logger 20 21 client kubernetes.Interface 22 namespacePrefix string 23 } 24 25 // NewSecretLookupPaths defines how variables will be searched in the underlying secret manager 26 func (secrets Secrets) NewSecretLookupPaths(teamName string, pipelineName string, allowRootPath bool) []creds.SecretLookupPath { 27 lookupPaths := []creds.SecretLookupPath{} 28 if len(pipelineName) > 0 { 29 lookupPaths = append(lookupPaths, creds.NewSecretLookupWithPrefix(secrets.namespacePrefix+teamName+"/"+pipelineName+".")) 30 } 31 lookupPaths = append(lookupPaths, creds.NewSecretLookupWithPrefix(secrets.namespacePrefix+teamName+"/")) 32 if allowRootPath { 33 lookupPaths = append(lookupPaths, creds.NewSecretLookupWithPrefix(secrets.namespacePrefix+"/")) 34 } 35 return lookupPaths 36 } 37 38 // Get retrieves the value and expiration of an individual secret 39 func (secrets Secrets) Get(secretPath string) (interface{}, *time.Time, bool, error) { 40 parts := strings.Split(secretPath, "/") 41 if len(parts) != 2 { 42 return nil, nil, false, fmt.Errorf("unable to split kubernetes secret path into [namespace]/[secret]: %s", secretPath) 43 } 44 45 var namespace = parts[0] 46 var secretName = parts[1] 47 48 secret, found, err := secrets.findSecret(namespace, secretName) 49 if err != nil { 50 secrets.logger.Error("failed-to-fetch-secret", err, lager.Data{ 51 "namespace": namespace, 52 "secret-name": secretName, 53 }) 54 return nil, nil, false, err 55 } 56 57 if found { 58 return secrets.getValueFromSecret(secret) 59 } 60 61 secrets.logger.Info("secret-not-found", lager.Data{ 62 "namespace": namespace, 63 "secret-name": secretName, 64 }) 65 66 return nil, nil, false, nil 67 } 68 69 func (secrets Secrets) getValueFromSecret(secret *v1.Secret) (interface{}, *time.Time, bool, error) { 70 val, found := secret.Data["value"] 71 if found { 72 return string(val), nil, true, nil 73 } 74 75 // TODO: make this smarter since we now have access to ref.Fields 76 stringified := map[string]interface{}{} 77 for k, v := range secret.Data { 78 stringified[k] = string(v) 79 } 80 81 return stringified, nil, true, nil 82 } 83 84 func (secrets Secrets) findSecret(namespace, name string) (*v1.Secret, bool, error) { 85 var secret *v1.Secret 86 var err error 87 88 secret, err = secrets.client.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) 89 90 if err != nil && k8serr.IsNotFound(err) { 91 return nil, false, nil 92 } else if err != nil { 93 return nil, false, err 94 } else { 95 return secret, true, err 96 } 97 }