github.com/argoproj/argo-cd/v2@v2.10.5/util/db/secrets.go (about)

     1  package db
     2  
     3  import (
     4  	"fmt"
     5  	"hash/fnv"
     6  	"net/netip"
     7  	"net/url"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	"context"
    13  
    14  	log "github.com/sirupsen/logrus"
    15  	apiv1 "k8s.io/api/core/v1"
    16  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    17  	"k8s.io/apimachinery/pkg/fields"
    18  	"k8s.io/apimachinery/pkg/labels"
    19  	"k8s.io/apimachinery/pkg/selection"
    20  	informerv1 "k8s.io/client-go/informers/core/v1"
    21  	"k8s.io/client-go/tools/cache"
    22  
    23  	"github.com/argoproj/argo-cd/v2/common"
    24  )
    25  
    26  func (db *db) listSecretsByType(types ...string) ([]*apiv1.Secret, error) {
    27  	labelSelector := labels.NewSelector()
    28  	req, err := labels.NewRequirement(common.LabelKeySecretType, selection.Equals, types)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	labelSelector = labelSelector.Add(*req)
    33  
    34  	secretsLister, err := db.settingsMgr.GetSecretsLister()
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	secrets, err := secretsLister.Secrets(db.ns).List(labelSelector)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	return secrets, nil
    43  }
    44  
    45  func boolOrFalse(secret *apiv1.Secret, key string) (bool, error) {
    46  	val, present := secret.Data[key]
    47  	if !present {
    48  		return false, nil
    49  	}
    50  
    51  	return strconv.ParseBool(string(val))
    52  }
    53  
    54  func intOrZero(secret *apiv1.Secret, key string) (int64, error) {
    55  	val, present := secret.Data[key]
    56  	if !present {
    57  		return 0, nil
    58  	}
    59  
    60  	return strconv.ParseInt(string(val), 10, 64)
    61  }
    62  
    63  func updateSecretBool(secret *apiv1.Secret, key string, value bool) {
    64  	if _, present := secret.Data[key]; present || value {
    65  		secret.Data[key] = []byte(strconv.FormatBool(value))
    66  	}
    67  }
    68  
    69  func updateSecretInt(secret *apiv1.Secret, key string, value int64) {
    70  	if _, present := secret.Data[key]; present || value != 0 {
    71  		secret.Data[key] = []byte(strconv.FormatInt(value, 10))
    72  	}
    73  }
    74  
    75  func updateSecretString(secret *apiv1.Secret, key, value string) {
    76  	if _, present := secret.Data[key]; present || len(value) > 0 {
    77  		secret.Data[key] = []byte(value)
    78  	}
    79  }
    80  
    81  func (db *db) createSecret(ctx context.Context, secret *apiv1.Secret) (*apiv1.Secret, error) {
    82  	return db.kubeclientset.CoreV1().Secrets(db.ns).Create(ctx, secret, metav1.CreateOptions{})
    83  }
    84  
    85  func addSecretMetadata(secret *apiv1.Secret, secretType string) {
    86  	if secret.Annotations == nil {
    87  		secret.Annotations = map[string]string{}
    88  	}
    89  	secret.Annotations[common.AnnotationKeyManagedBy] = common.AnnotationValueManagedByArgoCD
    90  
    91  	if secret.Labels == nil {
    92  		secret.Labels = map[string]string{}
    93  	}
    94  	secret.Labels[common.LabelKeySecretType] = secretType
    95  }
    96  
    97  func (db *db) deleteSecret(ctx context.Context, secret *apiv1.Secret) error {
    98  	var err error
    99  
   100  	canDelete := secret.Annotations != nil && secret.Annotations[common.AnnotationKeyManagedBy] == common.AnnotationValueManagedByArgoCD
   101  	if canDelete {
   102  		err = db.kubeclientset.CoreV1().Secrets(db.ns).Delete(ctx, secret.Name, metav1.DeleteOptions{})
   103  	} else {
   104  		delete(secret.Labels, common.LabelKeySecretType)
   105  		_, err = db.kubeclientset.CoreV1().Secrets(db.ns).Update(ctx, secret, metav1.UpdateOptions{})
   106  	}
   107  
   108  	return err
   109  }
   110  
   111  func (db *db) watchSecrets(ctx context.Context,
   112  	secretType string,
   113  	handleAddEvent func(secret *apiv1.Secret),
   114  	handleModEvent func(oldSecret *apiv1.Secret, newSecret *apiv1.Secret),
   115  	handleDeleteEvent func(secret *apiv1.Secret)) {
   116  
   117  	secretListOptions := func(options *metav1.ListOptions) {
   118  		labelSelector := fields.ParseSelectorOrDie(common.LabelKeySecretType + "=" + secretType)
   119  		options.LabelSelector = labelSelector.String()
   120  	}
   121  	secretEventHandler := cache.ResourceEventHandlerFuncs{
   122  		AddFunc: func(obj interface{}) {
   123  			if secretObj, ok := obj.(*apiv1.Secret); ok {
   124  				handleAddEvent(secretObj)
   125  			}
   126  		},
   127  		DeleteFunc: func(obj interface{}) {
   128  			if secretObj, ok := obj.(*apiv1.Secret); ok {
   129  				handleDeleteEvent(secretObj)
   130  			}
   131  		},
   132  		UpdateFunc: func(oldObj, newObj interface{}) {
   133  			if oldSecretObj, ok := oldObj.(*apiv1.Secret); ok {
   134  				if newSecretObj, ok := newObj.(*apiv1.Secret); ok {
   135  					handleModEvent(oldSecretObj, newSecretObj)
   136  				}
   137  			}
   138  		},
   139  	}
   140  
   141  	indexers := cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}
   142  	clusterSecretInformer := informerv1.NewFilteredSecretInformer(db.kubeclientset, db.ns, 3*time.Minute, indexers, secretListOptions)
   143  	_, err := clusterSecretInformer.AddEventHandler(secretEventHandler)
   144  	if err != nil {
   145  		log.Error(err)
   146  	}
   147  
   148  	log.Info("Starting secretInformer for", secretType)
   149  	go func() {
   150  		clusterSecretInformer.Run(ctx.Done())
   151  		log.Info("secretInformer for", secretType, "cancelled")
   152  	}()
   153  	<-ctx.Done()
   154  }
   155  
   156  // URIToSecretName hashes an uri address to the secret name using a formula.
   157  // Part of the uri address is incorporated for debugging purposes
   158  func URIToSecretName(uriType, uri string) (string, error) {
   159  	parsedURI, err := url.ParseRequestURI(uri)
   160  	if err != nil {
   161  		return "", err
   162  	}
   163  	host := parsedURI.Host
   164  	if strings.HasPrefix(host, "[") {
   165  		last := strings.Index(host, "]")
   166  		if last >= 0 {
   167  			addr, err := netip.ParseAddr(host[1:last])
   168  			if err != nil {
   169  				return "", err
   170  			}
   171  			host = strings.ReplaceAll(addr.String(), ":", "-")
   172  		}
   173  	} else {
   174  		last := strings.Index(host, ":")
   175  		if last >= 0 {
   176  			host = host[0:last]
   177  		}
   178  	}
   179  	h := fnv.New32a()
   180  	_, _ = h.Write([]byte(uri))
   181  	host = strings.ToLower(host)
   182  	return fmt.Sprintf("%s-%s-%v", uriType, host, h.Sum32()), nil
   183  }