github.com/banzaicloud/operator-tools@v0.28.10/pkg/secret/secret.go (about) 1 // Copyright © 2020 Banzai Cloud 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package secret 16 17 import ( 18 "context" 19 "fmt" 20 21 "emperror.dev/errors" 22 corev1 "k8s.io/api/core/v1" 23 "k8s.io/apimachinery/pkg/types" 24 "sigs.k8s.io/controller-runtime/pkg/client" 25 ) 26 27 type SecretLoader interface { 28 Load(secret *Secret) (string, error) 29 } 30 31 func NewSecretLoader(client client.Reader, namespace, mountPath string, secrets *MountSecrets) SecretLoader { 32 return &secretLoader{ 33 client: client, 34 mountPath: mountPath, 35 namespace: namespace, 36 secrets: secrets, 37 } 38 } 39 40 type MountSecrets []MountSecret 41 42 func (m *MountSecrets) Append(namespace string, secret *corev1.SecretKeySelector, mappedKey string, value []byte) { 43 *m = append(*m, MountSecret{ 44 Name: secret.Name, 45 Key: secret.Key, 46 MappedKey: mappedKey, 47 Namespace: namespace, 48 Value: value, 49 }) 50 } 51 52 type MountSecret struct { 53 Namespace string 54 Name string 55 Key string 56 MappedKey string 57 Value []byte 58 } 59 60 type secretLoader struct { 61 // secretLoader is limited to a single namespace, to avoid hijacking other namespace's secrets 62 namespace string 63 mountPath string 64 client client.Reader 65 secrets *MountSecrets 66 } 67 68 func (k *secretLoader) Load(secret *Secret) (string, error) { 69 if secret.Value != "" { 70 return secret.Value, nil 71 } 72 73 if secret.MountFrom != nil && secret.MountFrom.SecretKeyRef != nil { 74 mappedKey := fmt.Sprintf("%s-%s-%s", k.namespace, secret.MountFrom.SecretKeyRef.Name, secret.MountFrom.SecretKeyRef.Key) 75 secretItem := &corev1.Secret{} 76 err := k.client.Get(context.TODO(), types.NamespacedName{ 77 Name: secret.MountFrom.SecretKeyRef.Name, 78 Namespace: k.namespace}, secretItem) 79 if err != nil { 80 return "", errors.WrapIfWithDetails( 81 err, "failed to load secret", "secret", secret.MountFrom.SecretKeyRef.Name, "namespace", k.namespace) 82 } 83 k.secrets.Append(k.namespace, secret.MountFrom.SecretKeyRef, mappedKey, secretItem.Data[secret.MountFrom.SecretKeyRef.Key]) 84 return k.mountPath + "/" + mappedKey, nil 85 } 86 87 if secret.ValueFrom != nil && secret.ValueFrom.SecretKeyRef != nil { 88 k8sSecret := &corev1.Secret{} 89 err := k.client.Get(context.TODO(), types.NamespacedName{ 90 Name: secret.ValueFrom.SecretKeyRef.Name, 91 Namespace: k.namespace}, k8sSecret) 92 if err != nil { 93 return "", errors.WrapIff(err, "failed to get kubernetes secret %s:%s", 94 k.namespace, 95 secret.ValueFrom.SecretKeyRef.Name) 96 } 97 value, ok := k8sSecret.Data[secret.ValueFrom.SecretKeyRef.Key] 98 if !ok { 99 return "", errors.Errorf("key %q not found in secret %q in namespace %q", 100 secret.ValueFrom.SecretKeyRef.Key, 101 secret.ValueFrom.SecretKeyRef.Name, 102 k.namespace) 103 } 104 return string(value), nil 105 } 106 107 return "", errors.New("No secret Value or ValueFrom defined for field") 108 }