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  }