github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/k8s/secrets.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2021-Present The Jackal Authors
     3  
     4  // Package k8s provides a client for interacting with a Kubernetes cluster.
     5  package k8s
     6  
     7  import (
     8  	"context"
     9  	"crypto/tls"
    10  	"fmt"
    11  
    12  	"github.com/defenseunicorns/pkg/helpers"
    13  	corev1 "k8s.io/api/core/v1"
    14  	"k8s.io/apimachinery/pkg/api/errors"
    15  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  )
    17  
    18  // GetSecret returns a Kubernetes secret.
    19  func (k *K8s) GetSecret(namespace, name string) (*corev1.Secret, error) {
    20  	return k.Clientset.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
    21  }
    22  
    23  // GetSecretsWithLabel returns a list of Kubernetes secrets with the given label.
    24  func (k *K8s) GetSecretsWithLabel(namespace, labelSelector string) (*corev1.SecretList, error) {
    25  	listOptions := metav1.ListOptions{LabelSelector: labelSelector}
    26  	return k.Clientset.CoreV1().Secrets(namespace).List(context.TODO(), listOptions)
    27  }
    28  
    29  // GenerateSecret returns a Kubernetes secret object without applying it to the cluster.
    30  func (k *K8s) GenerateSecret(namespace, name string, secretType corev1.SecretType) *corev1.Secret {
    31  	secret := &corev1.Secret{
    32  		TypeMeta: metav1.TypeMeta{
    33  			APIVersion: corev1.SchemeGroupVersion.String(),
    34  			Kind:       "Secret",
    35  		},
    36  		ObjectMeta: metav1.ObjectMeta{
    37  			Name:      name,
    38  			Namespace: namespace,
    39  		},
    40  		Type: secretType,
    41  		Data: map[string][]byte{},
    42  	}
    43  
    44  	// Merge in common labels so that later modifications to the secret can't mutate them
    45  	secret.ObjectMeta.Labels = helpers.MergeMap[string](k.Labels, secret.ObjectMeta.Labels)
    46  
    47  	return secret
    48  }
    49  
    50  // GenerateTLSSecret returns a Kubernetes secret object without applying it to the cluster.
    51  func (k *K8s) GenerateTLSSecret(namespace, name string, conf GeneratedPKI) (*corev1.Secret, error) {
    52  	if _, err := tls.X509KeyPair(conf.Cert, conf.Key); err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	secretTLS := k.GenerateSecret(namespace, name, corev1.SecretTypeTLS)
    57  	secretTLS.Data[corev1.TLSCertKey] = conf.Cert
    58  	secretTLS.Data[corev1.TLSPrivateKeyKey] = conf.Key
    59  
    60  	return secretTLS, nil
    61  }
    62  
    63  // CreateOrUpdateTLSSecret creates or updates a Kubernetes secret with a new TLS secret.
    64  func (k *K8s) CreateOrUpdateTLSSecret(namespace, name string, conf GeneratedPKI) (*corev1.Secret, error) {
    65  	secret, err := k.GenerateTLSSecret(namespace, name, conf)
    66  	if err != nil {
    67  		return secret, err
    68  	}
    69  
    70  	return k.CreateOrUpdateSecret(secret)
    71  }
    72  
    73  // DeleteSecret deletes a Kubernetes secret.
    74  func (k *K8s) DeleteSecret(secret *corev1.Secret) error {
    75  	namespaceSecrets := k.Clientset.CoreV1().Secrets(secret.Namespace)
    76  
    77  	err := namespaceSecrets.Delete(context.TODO(), secret.Name, metav1.DeleteOptions{})
    78  	if err != nil && !errors.IsNotFound(err) {
    79  		return fmt.Errorf("error deleting the secret: %w", err)
    80  	}
    81  
    82  	return nil
    83  }
    84  
    85  // CreateOrUpdateSecret creates or updates a Kubernetes secret.
    86  func (k *K8s) CreateOrUpdateSecret(secret *corev1.Secret) (createdSecret *corev1.Secret, err error) {
    87  
    88  	namespaceSecrets := k.Clientset.CoreV1().Secrets(secret.Namespace)
    89  
    90  	if _, err = k.GetSecret(secret.Namespace, secret.Name); err != nil {
    91  		// create the given secret
    92  		if createdSecret, err = namespaceSecrets.Create(context.TODO(), secret, metav1.CreateOptions{}); err != nil {
    93  			return createdSecret, fmt.Errorf("unable to create the secret: %w", err)
    94  		}
    95  	} else {
    96  		// update the given secret
    97  		if createdSecret, err = namespaceSecrets.Update(context.TODO(), secret, metav1.UpdateOptions{}); err != nil {
    98  			return createdSecret, fmt.Errorf("unable to update the secret: %w", err)
    99  		}
   100  	}
   101  
   102  	return createdSecret, nil
   103  }