mirror of
				https://github.com/1Password/onepassword-operator.git
				synced 2025-10-30 19:29:40 +00:00 
			
		
		
		
	Compare commits
	
		
			12 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 58b4ff8ecf | ||
|   | d93fecdc76 | ||
|   | 486465247d | ||
|   | 79868ae374 | ||
|   | 6286f7e306 | ||
|   | 0b5efc8690 | ||
|   | a760e524ea | ||
|   | 19f774bb2d | ||
|   | 32643651d9 | ||
|   | ba8d3fa698 | ||
|   | c57aa22a9c | ||
|   | 48944b0d56 | 
							
								
								
									
										104
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,96 +1,128 @@ | ||||
| [//]: # (START/LATEST) | ||||
| [//]: # "START/LATEST" | ||||
|  | ||||
| # Latest | ||||
|  | ||||
| ## Features | ||||
|   * A user-friendly description of a new feature. {issue-number} | ||||
|  | ||||
| - A user-friendly description of a new feature. {issue-number} | ||||
|  | ||||
| ## Fixes | ||||
|  * A user-friendly description of a fix. {issue-number} | ||||
|  | ||||
| - A user-friendly description of a fix. {issue-number} | ||||
|  | ||||
| ## Security | ||||
|  * A user-friendly description of a security fix. {issue-number} | ||||
|  | ||||
| - A user-friendly description of a security fix. {issue-number} | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v1.3.0) | ||||
| [//]: # "START/v1.4.0" | ||||
|  | ||||
| # v1.4.0 | ||||
|  | ||||
| ## Features | ||||
|  | ||||
| - The operator now declares the an OwnerReference for the secrets it manages. This should stop secrets from getting pruned by tools like Argo CD. {#51,#84,#96} | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # "START/v1.3.0" | ||||
|  | ||||
| # v1.3.0 | ||||
|  | ||||
| ## Features | ||||
|   * Added support for loading secrets from files stored in 1Password. {#47} | ||||
|  | ||||
| - Added support for loading secrets from files stored in 1Password. {#47} | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v1.2.0) | ||||
| [//]: # "START/v1.2.0" | ||||
|  | ||||
| # v1.2.0 | ||||
|  | ||||
| ## Features | ||||
|   * Support secrets provisioned through FromEnv. {#74} | ||||
|   * Support configuration of Kubernetes Secret type. {#87} | ||||
|   * Improved logging. (#72) | ||||
|  | ||||
| - Support secrets provisioned through FromEnv. {#74} | ||||
| - Support configuration of Kubernetes Secret type. {#87} | ||||
| - Improved logging. (#72) | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v1.1.0) | ||||
| [//]: # "START/v1.1.0" | ||||
|  | ||||
| # v1.1.0 | ||||
|  | ||||
| ## Fixes | ||||
|  * Fix normalization for keys in a Secret's `data` section to allow upper- and lower-case alphanumeric characters. {#66} | ||||
|  | ||||
| - Fix normalization for keys in a Secret's `data` section to allow upper- and lower-case alphanumeric characters. {#66} | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v1.0.2) | ||||
| [//]: # "START/v1.0.2" | ||||
|  | ||||
| # v1.0.2 | ||||
|  | ||||
| ## Fixes | ||||
|  * Name normalizer added to handle non-conforming item names. | ||||
|  | ||||
| - Name normalizer added to handle non-conforming item names. | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v1.0.1) | ||||
| [//]: # "START/v1.0.1" | ||||
|  | ||||
| # v1.0.1 | ||||
|  | ||||
| ## Features | ||||
| * This release also contains an arm64 Docker image. {#20} | ||||
| * Docker images are also pushed to the :latest and :<major>.<minor> tags. | ||||
|  | ||||
| - This release also contains an arm64 Docker image. {#20} | ||||
| - Docker images are also pushed to the :latest and :<major>.<minor> tags. | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v1.0.0) | ||||
| [//]: # "START/v1.0.0" | ||||
|  | ||||
| # v1.0.0 | ||||
|  | ||||
| ## Features: | ||||
| * Option to automatically deploy 1Password Connect via the operator | ||||
| * Ignore restart annotation when looking for 1Password annotations | ||||
| * Release Automation | ||||
| * Upgrading apiextensions.k8s.io/v1beta apiversion from the operator custom resource | ||||
| * Adding configuration for auto rolling restart on deployments | ||||
| * Configure Auto Restarts for a OnePasswordItem Custom Resource | ||||
| * Update Connect Dependencies to latest | ||||
| * Add Github action for building and testing operator | ||||
|  | ||||
| - Option to automatically deploy 1Password Connect via the operator | ||||
| - Ignore restart annotation when looking for 1Password annotations | ||||
| - Release Automation | ||||
| - Upgrading apiextensions.k8s.io/v1beta apiversion from the operator custom resource | ||||
| - Adding configuration for auto rolling restart on deployments | ||||
| - Configure Auto Restarts for a OnePasswordItem Custom Resource | ||||
| - Update Connect Dependencies to latest | ||||
| - Add Github action for building and testing operator | ||||
|  | ||||
| ## Fixes: | ||||
| * Fix spec field example for OnePasswordItem in readme | ||||
| * Casing of annotations are now consistent | ||||
|  | ||||
| - Fix spec field example for OnePasswordItem in readme | ||||
| - Casing of annotations are now consistent | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v0.0.2) | ||||
| [//]: # "START/v0.0.2" | ||||
|  | ||||
| # v0.0.2 | ||||
|  | ||||
| ## Features: | ||||
| * Items can now be accessed by either `vaults/<vault_id>/items/<item_id>` or `vaults/<vault_title>/items/<item_title>` | ||||
|  | ||||
| - Items can now be accessed by either `vaults/<vault_id>/items/<item_id>` or `vaults/<vault_title>/items/<item_title>` | ||||
|  | ||||
| --- | ||||
|  | ||||
| [//]: # (START/v0.0.1) | ||||
| [//]: # "START/v0.0.1" | ||||
|  | ||||
| # v0.0.1 | ||||
|  | ||||
| Initial 1Password Operator release | ||||
|  | ||||
| ## Features | ||||
| * watches for deployment creations with `onepassword` annotations and creates an associated kubernetes secret | ||||
| * watches for `onepasswordsecret` crd creations and creates an associated kubernetes secrets | ||||
| * watches for changes to 1Password secrets associated with kubernetes secrets and updates the kubernetes secret with changes | ||||
| * restart pods when secret has been updated | ||||
| * cleanup of kubernetes secrets when deployment or `onepasswordsecret` is deleted | ||||
|  | ||||
| - watches for deployment creations with `onepassword` annotations and creates an associated kubernetes secret | ||||
| - watches for `onepasswordsecret` crd creations and creates an associated kubernetes secrets | ||||
| - watches for changes to 1Password secrets associated with kubernetes secrets and updates the kubernetes secret with changes | ||||
| - restart pods when secret has been updated | ||||
| - cleanup of kubernetes secrets when deployment or `onepasswordsecret` is deleted | ||||
|  | ||||
| --- | ||||
|   | ||||
| @@ -14,9 +14,11 @@ import ( | ||||
| 	appsv1 "k8s.io/api/apps/v1" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	ctrl "sigs.k8s.io/controller-runtime" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/client/apiutil" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/controller" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/handler" | ||||
| 	logf "sigs.k8s.io/controller-runtime/pkg/log" | ||||
| @@ -114,7 +116,7 @@ func (r *ReconcileDeployment) Reconcile(request reconcile.Request) (reconcile.Re | ||||
| 			} | ||||
| 		} | ||||
| 		// Handles creation or updating secrets for deployment if needed | ||||
| 		if err := r.HandleApplyingDeployment(deployment.Namespace, annotations, request); err != nil { | ||||
| 		if err := r.HandleApplyingDeployment(deployment, deployment.Namespace, annotations, request); err != nil { | ||||
| 			return reconcile.Result{}, err | ||||
| 		} | ||||
| 		return reconcile.Result{}, nil | ||||
| @@ -187,7 +189,7 @@ func (r *ReconcileDeployment) removeOnePasswordFinalizerFromDeployment(deploymen | ||||
| 	return r.kubeClient.Update(context.Background(), deployment) | ||||
| } | ||||
|  | ||||
| func (r *ReconcileDeployment) HandleApplyingDeployment(namespace string, annotations map[string]string, request reconcile.Request) error { | ||||
| func (r *ReconcileDeployment) HandleApplyingDeployment(deployment *appsv1.Deployment, namespace string, annotations map[string]string, request reconcile.Request) error { | ||||
| 	reqLog := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) | ||||
|  | ||||
| 	secretName := annotations[op.NameAnnotation] | ||||
| @@ -204,5 +206,17 @@ func (r *ReconcileDeployment) HandleApplyingDeployment(namespace string, annotat | ||||
| 		return fmt.Errorf("Failed to retrieve item: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, namespace, item, annotations[op.RestartDeploymentsAnnotation], secretLabels, secretType, annotations) | ||||
| 	// Create owner reference. | ||||
| 	gvk, err := apiutil.GVKForObject(deployment, r.scheme) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not to retrieve group version kind: %v", err) | ||||
| 	} | ||||
| 	ownerRef := &metav1.OwnerReference{ | ||||
| 		APIVersion: gvk.GroupVersion().String(), | ||||
| 		Kind:       gvk.Kind, | ||||
| 		Name:       deployment.GetName(), | ||||
| 		UID:        deployment.GetUID(), | ||||
| 	} | ||||
|  | ||||
| 	return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, namespace, item, annotations[op.RestartDeploymentsAnnotation], secretLabels, secretType, annotations, ownerRef) | ||||
| } | ||||
|   | ||||
| @@ -14,9 +14,11 @@ import ( | ||||
|  | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	ctrl "sigs.k8s.io/controller-runtime" | ||||
| 	kubeClient "sigs.k8s.io/controller-runtime/pkg/client" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/client/apiutil" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/controller" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/handler" | ||||
| 	logf "sigs.k8s.io/controller-runtime/pkg/log" | ||||
| @@ -154,5 +156,17 @@ func (r *ReconcileOnePasswordItem) HandleOnePasswordItem(resource *onepasswordv1 | ||||
| 		return fmt.Errorf("Failed to retrieve item: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, resource.Namespace, item, autoRestart, labels, secretType, annotations) | ||||
| 	// Create owner reference. | ||||
| 	gvk, err := apiutil.GVKForObject(resource, r.scheme) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not to retrieve group version kind: %v", err) | ||||
| 	} | ||||
| 	ownerRef := &metav1.OwnerReference{ | ||||
| 		APIVersion: gvk.GroupVersion().String(), | ||||
| 		Kind:       gvk.Kind, | ||||
| 		Name:       resource.GetName(), | ||||
| 		UID:        resource.GetUID(), | ||||
| 	} | ||||
|  | ||||
| 	return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, resource.Namespace, item, autoRestart, labels, secretType, annotations, ownerRef) | ||||
| } | ||||
|   | ||||
| @@ -101,7 +101,7 @@ var tests = []testReconcileItem{ | ||||
| 		}, | ||||
| 	}, | ||||
| 	{ | ||||
| 		testName: "Test Do not update if OnePassword Version has not changed", | ||||
| 		testName: "Test Do not update if OnePassword Version or VaultPath has not changed", | ||||
| 		customResource: &onepasswordv1.OnePasswordItem{ | ||||
| 			TypeMeta: metav1.TypeMeta{ | ||||
| 				Kind:       onePasswordItemKind, | ||||
|   | ||||
| @@ -35,7 +35,7 @@ var ErrCannotUpdateSecretType = errs.New("Cannot change secret type. Secret type | ||||
|  | ||||
| var log = logf.Log | ||||
|  | ||||
| func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretName, namespace string, item *onepassword.Item, autoRestart string, labels map[string]string, secretType string, secretAnnotations map[string]string) error { | ||||
| func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretName, namespace string, item *onepassword.Item, autoRestart string, labels map[string]string, secretType string, secretAnnotations map[string]string, ownerRef *metav1.OwnerReference) error { | ||||
|  | ||||
| 	itemVersion := fmt.Sprint(item.Version) | ||||
|  | ||||
| @@ -57,7 +57,7 @@ func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretNa | ||||
| 	} | ||||
|  | ||||
| 	// "Opaque" and "" secret types are treated the same by Kubernetes. | ||||
| 	secret := BuildKubernetesSecretFromOnePasswordItem(secretName, namespace, secretAnnotations, labels, secretType, *item) | ||||
| 	secret := BuildKubernetesSecretFromOnePasswordItem(secretName, namespace, secretAnnotations, labels, secretType, *item, ownerRef) | ||||
|  | ||||
| 	currentSecret := &corev1.Secret{} | ||||
| 	err := kubeClient.Get(context.Background(), types.NamespacedName{Name: secret.Name, Namespace: secret.Namespace}, currentSecret) | ||||
| @@ -87,13 +87,19 @@ func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretNa | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func BuildKubernetesSecretFromOnePasswordItem(name, namespace string, annotations map[string]string, labels map[string]string, secretType string, item onepassword.Item) *corev1.Secret { | ||||
| func BuildKubernetesSecretFromOnePasswordItem(name, namespace string, annotations map[string]string, labels map[string]string, secretType string, item onepassword.Item, ownerRef *metav1.OwnerReference) *corev1.Secret { | ||||
| 	var ownerRefs []metav1.OwnerReference | ||||
| 	if ownerRef != nil { | ||||
| 		ownerRefs = []metav1.OwnerReference{*ownerRef} | ||||
| 	} | ||||
|  | ||||
| 	return &corev1.Secret{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Name:            formatSecretName(name), | ||||
| 			Namespace:       namespace, | ||||
| 			Annotations:     annotations, | ||||
| 			Labels:          labels, | ||||
| 			OwnerReferences: ownerRefs, | ||||
| 		}, | ||||
| 		Data: BuildKubernetesSecretData(item.Fields, item.Files), | ||||
| 		Type: corev1.SecretType(secretType), | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
|  | ||||
| 	"github.com/1Password/connect-sdk-go/onepassword" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	kubeValidate "k8s.io/apimachinery/pkg/util/validation" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| @@ -37,7 +38,7 @@ func TestCreateKubernetesSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	} | ||||
| 	secretType := "" | ||||
|  | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations) | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations, nil) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Unexpected error: %v", err) | ||||
| 	} | ||||
| @@ -55,6 +56,54 @@ func TestCreateKubernetesSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestKubernetesSecretFromOnePasswordItemOwnerReferences(t *testing.T) { | ||||
| 	secretName := "test-secret-name" | ||||
| 	namespace := "test" | ||||
|  | ||||
| 	item := onepassword.Item{} | ||||
| 	item.Fields = generateFields(5) | ||||
| 	item.Version = 123 | ||||
| 	item.Vault.ID = "hfnjvi6aymbsnfc2xeeoheizda" | ||||
| 	item.ID = "h46bb3jddvay7nxopfhvlwg35q" | ||||
|  | ||||
| 	kubeClient := fake.NewFakeClient() | ||||
| 	secretLabels := map[string]string{} | ||||
| 	secretAnnotations := map[string]string{ | ||||
| 		"testAnnotation": "exists", | ||||
| 	} | ||||
| 	secretType := "" | ||||
|  | ||||
| 	ownerRef := &metav1.OwnerReference{ | ||||
| 		Kind:       "Deployment", | ||||
| 		APIVersion: "apps/v1", | ||||
| 		Name:       "test-deployment", | ||||
| 		UID:        types.UID("test-uid"), | ||||
| 	} | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations, ownerRef) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Unexpected error: %v", err) | ||||
| 	} | ||||
| 	createdSecret := &corev1.Secret{} | ||||
| 	err = kubeClient.Get(context.Background(), types.NamespacedName{Name: secretName, Namespace: namespace}, createdSecret) | ||||
|  | ||||
| 	// Check owner references. | ||||
| 	gotOwnerRefs := createdSecret.ObjectMeta.OwnerReferences | ||||
| 	if len(gotOwnerRefs) != 1 { | ||||
| 		t.Errorf("Expected owner references length: 1 but got: %d", len(gotOwnerRefs)) | ||||
| 	} | ||||
|  | ||||
| 	expOwnerRef := metav1.OwnerReference{ | ||||
| 		Kind:       "Deployment", | ||||
| 		APIVersion: "apps/v1", | ||||
| 		Name:       "test-deployment", | ||||
| 		UID:        types.UID("test-uid"), | ||||
| 	} | ||||
| 	gotOwnerRef := gotOwnerRefs[0] | ||||
| 	if gotOwnerRef != expOwnerRef { | ||||
| 		t.Errorf("Expected owner reference value: %v but got: %v", expOwnerRef, gotOwnerRef) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	secretName := "test-secret-update" | ||||
| 	namespace := "test" | ||||
| @@ -70,7 +119,7 @@ func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	secretAnnotations := map[string]string{} | ||||
| 	secretType := "" | ||||
|  | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations) | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations, nil) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Unexpected error: %v", err) | ||||
| @@ -82,7 +131,7 @@ func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	newItem.Version = 456 | ||||
| 	newItem.Vault.ID = "hfnjvi6aymbsnfc2xeeoheizda" | ||||
| 	newItem.ID = "h46bb3jddvay7nxopfhvlwg35q" | ||||
| 	err = CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &newItem, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations) | ||||
| 	err = CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &newItem, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations, nil) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Unexpected error: %v", err) | ||||
| 	} | ||||
| @@ -118,7 +167,7 @@ func TestBuildKubernetesSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	labels := map[string]string{} | ||||
| 	secretType := "" | ||||
|  | ||||
| 	kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, secretType, item) | ||||
| 	kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, secretType, item, nil) | ||||
| 	if kubeSecret.Name != strings.ToLower(name) { | ||||
| 		t.Errorf("Expected name value: %v but got: %v", name, kubeSecret.Name) | ||||
| 	} | ||||
| @@ -153,7 +202,7 @@ func TestBuildKubernetesSecretFixesInvalidLabels(t *testing.T) { | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, secretType, item) | ||||
| 	kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, secretType, item, nil) | ||||
|  | ||||
| 	// Assert Secret's meta.name was fixed | ||||
| 	if kubeSecret.Name != expectedName { | ||||
| @@ -188,7 +237,7 @@ func TestCreateKubernetesTLSSecretFromOnePasswordItem(t *testing.T) { | ||||
| 	} | ||||
| 	secretType := "kubernetes.io/tls" | ||||
|  | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations) | ||||
| 	err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations, nil) | ||||
| 	if err != nil { | ||||
| 		t.Errorf("Unexpected error: %v", err) | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,8 @@ import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
|  | ||||
| 	v1 "github.com/1Password/onepassword-operator/pkg/apis/onepassword/v1" | ||||
|  | ||||
| 	kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets" | ||||
| 	"github.com/1Password/onepassword-operator/pkg/utils" | ||||
|  | ||||
| @@ -116,23 +118,30 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]* | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		item, err := GetOnePasswordItemByPath(h.opConnectClient, secret.Annotations[ItemPathAnnotation]) | ||||
| 		OnePasswordItemPath := h.getPathFromOnePasswordItem(secret) | ||||
|  | ||||
| 		item, err := GetOnePasswordItemByPath(h.opConnectClient, OnePasswordItemPath) | ||||
| 		if err != nil { | ||||
| 			log.Error(err, "failed to retrieve 1Password item at path \"%s\" for secret \"%s\"", secret.Annotations[ItemPathAnnotation], secret.Name) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		itemVersion := fmt.Sprint(item.Version) | ||||
| 		if currentVersion != itemVersion { | ||||
| 		itemPathString := fmt.Sprintf("vaults/%v/items/%v", item.Vault.ID, item.ID) | ||||
|  | ||||
| 		if currentVersion != itemVersion || secret.Annotations[ItemPathAnnotation] != itemPathString { | ||||
| 			if isItemLockedForForcedRestarts(item) { | ||||
| 				log.Info(fmt.Sprintf("Secret '%v' has been updated in 1Password but is set to be ignored. Updates to an ignored secret will not trigger an update to a kubernetes secret or a rolling restart.", secret.GetName())) | ||||
| 				secret.Annotations[VersionAnnotation] = itemVersion | ||||
| 				secret.Annotations[ItemPathAnnotation] = itemPathString | ||||
| 				h.client.Update(context.Background(), &secret) | ||||
| 				continue | ||||
| 			} | ||||
| 			log.Info(fmt.Sprintf("Updating kubernetes secret '%v'", secret.GetName())) | ||||
| 			secret.Annotations[VersionAnnotation] = itemVersion | ||||
| 			updatedSecret := kubeSecrets.BuildKubernetesSecretFromOnePasswordItem(secret.Name, secret.Namespace, secret.Annotations, secret.Labels, string(secret.Type), *item) | ||||
| 			secret.Annotations[ItemPathAnnotation] = itemPathString | ||||
| 			updatedSecret := kubeSecrets.BuildKubernetesSecretFromOnePasswordItem(secret.Name, secret.Namespace, secret.Annotations, secret.Labels, string(secret.Type), *item, nil) | ||||
| 			log.Info(fmt.Sprintf("New secret path: %v and version: %v", updatedSecret.Annotations[ItemPathAnnotation], updatedSecret.Annotations[VersionAnnotation])) | ||||
| 			h.client.Update(context.Background(), updatedSecret) | ||||
| 			if updatedSecrets[secret.Namespace] == nil { | ||||
| 				updatedSecrets[secret.Namespace] = make(map[string]*corev1.Secret) | ||||
| @@ -177,6 +186,22 @@ func (h *SecretUpdateHandler) getIsSetForAutoRestartByNamespaceMap() (map[string | ||||
| 	return namespacesMap, nil | ||||
| } | ||||
|  | ||||
| func (h *SecretUpdateHandler) getPathFromOnePasswordItem(secret corev1.Secret) string { | ||||
| 	onePasswordItem := &v1.OnePasswordItem{} | ||||
|  | ||||
| 	// Search for our original OnePasswordItem if it exists | ||||
| 	err := h.client.Get(context.TODO(), client.ObjectKey{ | ||||
| 		Namespace: secret.Namespace, | ||||
| 		Name:      secret.Name}, onePasswordItem) | ||||
|  | ||||
| 	if err == nil { | ||||
| 		return onePasswordItem.Spec.ItemPath | ||||
| 	} | ||||
|  | ||||
| 	// If we can't find the OnePassword Item we'll just return the annotation from the secret item. | ||||
| 	return secret.Annotations[ItemPathAnnotation] | ||||
| } | ||||
|  | ||||
| func isSecretSetForAutoRestart(secret *corev1.Secret, deployment *appsv1.Deployment, setForAutoRestartByNamespace map[string]bool) bool { | ||||
| 	restartDeployment := secret.Annotations[RestartDeploymentsAnnotation] | ||||
| 	//If annotation for auto restarts for deployment is not set. Check for the annotation on its namepsace | ||||
|   | ||||
		Reference in New Issue
	
	Block a user