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 }