Compare commits

..

1 Commits

Author SHA1 Message Date
Marton Soos
717f9bc33f Skip shadowed env variables 2022-02-17 17:49:28 +01:00
14 changed files with 46 additions and 210 deletions

View File

@@ -1 +1 @@
1.2.0 1.1.0

View File

@@ -12,15 +12,6 @@
--- ---
[//]: # (START/v1.2.0)
# v1.2.0
## Features
* 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 # v1.1.0

View File

@@ -30,13 +30,14 @@ If 1Password Connect is already running, you can skip this step. This guide will
Encode the 1password-credentials.json file you generated in the prerequisite steps and save it to a file named op-session: Encode the 1password-credentials.json file you generated in the prerequisite steps and save it to a file named op-session:
```bash ```bash
cat 1password-credentials.json | base64 | \ $ cat 1password-credentials.json | base64 | \
tr '/+' '_-' | tr -d '=' | tr -d '\n' > op-session tr '/+' '_-' | tr -d '=' | tr -d '\n' > op-session
``` ```
Create a Kubernetes secret from the op-session file: Create a Kubernetes secret from the op-session file:
```bash ```bash
kubectl create secret generic op-credentials --from-file=1password-credentials.json=op-session
$ kubectl create secret generic op-credentials --from-file=1password-credentials.json
``` ```
Add the following environment variable to the onepassword-connect-operator container in `deploy/operator.yaml`: Add the following environment variable to the onepassword-connect-operator container in `deploy/operator.yaml`:
@@ -52,12 +53,12 @@ Adding this environment variable will have the operator automatically deploy a d
"Create a Connect token for the operator and save it as a Kubernetes Secret: "Create a Connect token for the operator and save it as a Kubernetes Secret:
```bash ```bash
kubectl create secret generic onepassword-token --from-literal=token=<OP_CONNECT_TOKEN>" $ kubectl create secret generic onepassword-token --from-literal=token=<OP_CONNECT_TOKEN>"
``` ```
If you do not have a token for the operator, you can generate a token and save it to kubernetes with the following command: If you do not have a token for the operator, you can generate a token and save it to kubernetes with the following command:
```bash ```bash
kubectl create secret generic onepassword-token --from-literal=token=$(op create connect token <server> op-k8s-operator --vault <vault>) $ kubectl create secret generic onepassword-token --from-literal=token=$(op create connect token <server> op-k8s-operator --vault <vault>)
``` ```
[More information on generating a token can be found here](https://support.1password.com/secrets-automation/#appendix-issue-additional-access-tokens) [More information on generating a token can be found here](https://support.1password.com/secrets-automation/#appendix-issue-additional-access-tokens)
@@ -67,13 +68,13 @@ kubectl create secret generic onepassword-token --from-literal=token=$(op create
We must create a service account, role, and role binding and Kubernetes. Examples can be found in the `/deploy` folder. We must create a service account, role, and role binding and Kubernetes. Examples can be found in the `/deploy` folder.
```bash ```bash
kubectl apply -f deploy/permissions.yaml $ kubectl apply -f deploy/permissions.yaml
``` ```
**Create Custom One Password Secret Resource** **Create Custom One Password Secret Resource**
```bash ```bash
kubectl apply -f deploy/crds/onepassword.com_onepassworditems_crd.yaml $ kubectl apply -f deploy/crds/onepassword.com_onepassworditems_crd.yaml
``` ```
**Deploying the Operator** **Deploying the Operator**
@@ -111,13 +112,13 @@ spec:
Deploy the OnePasswordItem to Kubernetes: Deploy the OnePasswordItem to Kubernetes:
```bash ```bash
kubectl apply -f <your_item>.yaml $ kubectl apply -f <your_item>.yaml
``` ```
To test that the Kubernetes Secret check that the following command returns a secret: To test that the Kubernetes Secret check that the following command returns a secret:
```bash ```bash
kubectl get secret <secret_name> $ kubectl get secret <secret_name>
``` ```
Note: Deleting the `OnePasswordItem` that you've created will automatically delete the created Kubernetes Secret. Note: Deleting the `OnePasswordItem` that you've created will automatically delete the created Kubernetes Secret.

View File

@@ -178,10 +178,7 @@ func main() {
ticker.Stop() ticker.Stop()
return return
case <-ticker.C: case <-ticker.C:
err := updatedSecretsPoller.UpdateKubernetesSecretsTask() updatedSecretsPoller.UpdateKubernetesSecretsTask()
if err != nil {
log.Error(err, "error running update kubernetes secret task")
}
} }
} }
}() }()

View File

@@ -39,7 +39,4 @@ spec:
status: status:
description: OnePasswordItemStatus defines the observed state of OnePasswordItem description: OnePasswordItemStatus defines the observed state of OnePasswordItem
type: object type: object
type:
description: 'Kubernetes secret type. More info: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types'
type: string
type: object type: object

View File

@@ -26,7 +26,6 @@ type OnePasswordItemStatus struct {
type OnePasswordItem struct { type OnePasswordItem struct {
metav1.TypeMeta `json:",inline"` metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"` metav1.ObjectMeta `json:"metadata,omitempty"`
Type string `json:"type,omitempty"`
Spec OnePasswordItemSpec `json:"spec,omitempty"` Spec OnePasswordItemSpec `json:"spec,omitempty"`
Status OnePasswordItemStatus `json:"status,omitempty"` Status OnePasswordItemStatus `json:"status,omitempty"`

View File

@@ -192,8 +192,6 @@ func (r *ReconcileDeployment) HandleApplyingDeployment(namespace string, annotat
secretName := annotations[op.NameAnnotation] secretName := annotations[op.NameAnnotation]
secretLabels := map[string]string(nil) secretLabels := map[string]string(nil)
secretType := ""
if len(secretName) == 0 { if len(secretName) == 0 {
reqLog.Info("No 'item-name' annotation set. 'item-path' and 'item-name' must be set as annotations to add new secret.") reqLog.Info("No 'item-name' annotation set. 'item-path' and 'item-name' must be set as annotations to add new secret.")
return nil return nil
@@ -204,5 +202,5 @@ func (r *ReconcileDeployment) HandleApplyingDeployment(namespace string, annotat
return fmt.Errorf("Failed to retrieve item: %v", err) return fmt.Errorf("Failed to retrieve item: %v", err)
} }
return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, namespace, item, annotations[op.RestartDeploymentsAnnotation], secretLabels, secretType, annotations) return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, namespace, item, annotations[op.RestartDeploymentsAnnotation], secretLabels, annotations)
} }

View File

@@ -279,7 +279,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
op.NameAnnotation: name, op.NameAnnotation: name,
}, },
@@ -292,7 +292,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
op.NameAnnotation: name, op.NameAnnotation: name,
}, },
@@ -329,7 +329,6 @@ var tests = []testReconcileItem{
op.VersionAnnotation: "456", op.VersionAnnotation: "456",
}, },
}, },
Type: corev1.SecretType(""),
Data: expectedSecretData, Data: expectedSecretData,
}, },
expectedError: nil, expectedError: nil,
@@ -341,7 +340,6 @@ var tests = []testReconcileItem{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
}, },
}, },
Type: corev1.SecretType(""),
Data: expectedSecretData, Data: expectedSecretData,
}, },
opItem: map[string]string{ opItem: map[string]string{
@@ -375,7 +373,6 @@ var tests = []testReconcileItem{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
}, },
}, },
Type: corev1.SecretType(""),
Data: expectedSecretData, Data: expectedSecretData,
}, },
opItem: map[string]string{ opItem: map[string]string{

View File

@@ -3,7 +3,6 @@ package onepassworditem
import ( import (
"context" "context"
"fmt" "fmt"
onepasswordv1 "github.com/1Password/onepassword-operator/pkg/apis/onepassword/v1" onepasswordv1 "github.com/1Password/onepassword-operator/pkg/apis/onepassword/v1"
kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets" kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets"
"github.com/1Password/onepassword-operator/pkg/onepassword" "github.com/1Password/onepassword-operator/pkg/onepassword"
@@ -146,7 +145,6 @@ func (r *ReconcileOnePasswordItem) HandleOnePasswordItem(resource *onepasswordv1
secretName := resource.GetName() secretName := resource.GetName()
labels := resource.Labels labels := resource.Labels
annotations := resource.Annotations annotations := resource.Annotations
secretType := resource.Type
autoRestart := annotations[op.RestartDeploymentsAnnotation] autoRestart := annotations[op.RestartDeploymentsAnnotation]
item, err := onepassword.GetOnePasswordItemByPath(r.opConnectClient, resource.Spec.ItemPath) item, err := onepassword.GetOnePasswordItemByPath(r.opConnectClient, resource.Spec.ItemPath)
@@ -154,5 +152,5 @@ func (r *ReconcileOnePasswordItem) HandleOnePasswordItem(resource *onepasswordv1
return fmt.Errorf("Failed to retrieve item: %v", err) return fmt.Errorf("Failed to retrieve item: %v", err)
} }
return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, resource.Namespace, item, autoRestart, labels, secretType, annotations) return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, resource.Namespace, item, autoRestart, labels, annotations)
} }

View File

@@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/1Password/onepassword-operator/pkg/kubernetessecrets"
"github.com/1Password/onepassword-operator/pkg/mocks" "github.com/1Password/onepassword-operator/pkg/mocks"
op "github.com/1Password/onepassword-operator/pkg/onepassword" op "github.com/1Password/onepassword-operator/pkg/onepassword"
@@ -120,7 +119,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
}, },
}, },
@@ -132,7 +131,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
}, },
}, },
@@ -154,7 +153,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
}, },
Labels: map[string]string{}, Labels: map[string]string{},
@@ -168,7 +167,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: "456", op.VersionAnnotation: "456",
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
}, },
Labels: map[string]string{}, Labels: map[string]string{},
@@ -181,7 +180,7 @@ var tests = []testReconcileItem{
Name: name, Name: name,
Namespace: namespace, Namespace: namespace,
Annotations: map[string]string{ Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath, op.ItemPathAnnotation: itemPath,
}, },
Labels: map[string]string{}, Labels: map[string]string{},
@@ -193,59 +192,6 @@ var tests = []testReconcileItem{
passKey: password, passKey: password,
}, },
}, },
{
testName: "Test Updating Type of Existing Kubernetes Secret using OnePasswordItem",
customResource: &onepasswordv1.OnePasswordItem{
TypeMeta: metav1.TypeMeta{
Kind: onePasswordItemKind,
APIVersion: onePasswordItemAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath,
},
Labels: map[string]string{},
},
Spec: onepasswordv1.OnePasswordItemSpec{
ItemPath: itemPath,
},
Type: string(corev1.SecretTypeBasicAuth),
},
existingSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath,
},
Labels: map[string]string{},
},
Type: corev1.SecretTypeBasicAuth,
Data: expectedSecretData,
},
expectedError: nil,
expectedResultSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version),
op.ItemPathAnnotation: itemPath,
},
Labels: map[string]string{},
},
Type: corev1.SecretTypeBasicAuth,
Data: expectedSecretData,
},
opItem: map[string]string{
userKey: username,
passKey: password,
},
},
{ {
testName: "Custom secret type", testName: "Custom secret type",
customResource: &onepasswordv1.OnePasswordItem{ customResource: &onepasswordv1.OnePasswordItem{
@@ -260,7 +206,6 @@ var tests = []testReconcileItem{
Spec: onepasswordv1.OnePasswordItemSpec{ Spec: onepasswordv1.OnePasswordItemSpec{
ItemPath: itemPath, ItemPath: itemPath,
}, },
Type: "custom",
}, },
existingSecret: nil, existingSecret: nil,
expectedError: nil, expectedError: nil,
@@ -272,51 +217,6 @@ var tests = []testReconcileItem{
op.VersionAnnotation: fmt.Sprint(version), op.VersionAnnotation: fmt.Sprint(version),
}, },
}, },
Type: corev1.SecretType("custom"),
Data: expectedSecretData,
},
opItem: map[string]string{
userKey: username,
passKey: password,
},
},
{
testName: "Error if secret type is changed",
customResource: &onepasswordv1.OnePasswordItem{
TypeMeta: metav1.TypeMeta{
Kind: onePasswordItemKind,
APIVersion: onePasswordItemAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: onepasswordv1.OnePasswordItemSpec{
ItemPath: itemPath,
},
Type: "custom",
},
existingSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version),
},
},
Type: corev1.SecretTypeOpaque,
Data: expectedSecretData,
},
expectedError: kubernetessecrets.ErrCannotUpdateSecretType,
expectedResultSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
op.VersionAnnotation: fmt.Sprint(version),
},
},
Type: corev1.SecretTypeOpaque,
Data: expectedSecretData, Data: expectedSecretData,
}, },
opItem: map[string]string{ opItem: map[string]string{

View File

@@ -7,16 +7,13 @@ import (
"regexp" "regexp"
"strings" "strings"
"reflect"
errs "errors"
"github.com/1Password/connect-sdk-go/onepassword" "github.com/1Password/connect-sdk-go/onepassword"
"github.com/1Password/onepassword-operator/pkg/utils" "github.com/1Password/onepassword-operator/pkg/utils"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"reflect"
kubeValidate "k8s.io/apimachinery/pkg/util/validation" kubeValidate "k8s.io/apimachinery/pkg/util/validation"
kubernetesClient "sigs.k8s.io/controller-runtime/pkg/client" kubernetesClient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -30,11 +27,9 @@ const restartAnnotation = OnepasswordPrefix + "/last-restarted"
const ItemPathAnnotation = OnepasswordPrefix + "/item-path" const ItemPathAnnotation = OnepasswordPrefix + "/item-path"
const RestartDeploymentsAnnotation = OnepasswordPrefix + "/auto-restart" const RestartDeploymentsAnnotation = OnepasswordPrefix + "/auto-restart"
var ErrCannotUpdateSecretType = errs.New("Cannot change secret type. Secret type is immutable")
var log = logf.Log 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, secretAnnotations map[string]string) error {
itemVersion := fmt.Sprint(item.Version) itemVersion := fmt.Sprint(item.Version)
@@ -54,9 +49,7 @@ func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretNa
} }
secretAnnotations[RestartDeploymentsAnnotation] = autoRestart secretAnnotations[RestartDeploymentsAnnotation] = autoRestart
} }
secret := BuildKubernetesSecretFromOnePasswordItem(secretName, namespace, secretAnnotations, labels, *item)
// "Opaque" and "" secret types are treated the same by Kubernetes.
secret := BuildKubernetesSecretFromOnePasswordItem(secretName, namespace, secretAnnotations, labels, secretType, *item)
currentSecret := &corev1.Secret{} currentSecret := &corev1.Secret{}
err := kubeClient.Get(context.Background(), types.NamespacedName{Name: secret.Name, Namespace: secret.Namespace}, currentSecret) err := kubeClient.Get(context.Background(), types.NamespacedName{Name: secret.Name, Namespace: secret.Namespace}, currentSecret)
@@ -67,14 +60,7 @@ func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretNa
return err return err
} }
currentAnnotations := currentSecret.Annotations if ! reflect.DeepEqual(currentSecret.Annotations, secretAnnotations) || ! reflect.DeepEqual(currentSecret.Labels, labels) {
currentLabels := currentSecret.Labels
currentSecretType := string(currentSecret.Type)
if !reflect.DeepEqual(currentSecretType, secretType) {
return ErrCannotUpdateSecretType
}
if !reflect.DeepEqual(currentAnnotations, secretAnnotations) || !reflect.DeepEqual(currentLabels, labels) {
log.Info(fmt.Sprintf("Updating Secret %v at namespace '%v'", secret.Name, secret.Namespace)) log.Info(fmt.Sprintf("Updating Secret %v at namespace '%v'", secret.Name, secret.Namespace))
currentSecret.ObjectMeta.Annotations = secretAnnotations currentSecret.ObjectMeta.Annotations = secretAnnotations
currentSecret.ObjectMeta.Labels = labels currentSecret.ObjectMeta.Labels = labels
@@ -86,7 +72,7 @@ func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretNa
return nil 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, item onepassword.Item) *corev1.Secret {
return &corev1.Secret{ return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: formatSecretName(name), Name: formatSecretName(name),
@@ -95,7 +81,6 @@ func BuildKubernetesSecretFromOnePasswordItem(name, namespace string, annotation
Labels: labels, Labels: labels,
}, },
Data: BuildKubernetesSecretData(item.Fields), Data: BuildKubernetesSecretData(item.Fields),
Type: corev1.SecretType(secretType),
} }
} }

View File

@@ -35,9 +35,7 @@ func TestCreateKubernetesSecretFromOnePasswordItem(t *testing.T) {
secretAnnotations := map[string]string{ secretAnnotations := map[string]string{
"testAnnotation": "exists", "testAnnotation": "exists",
} }
secretType := "" err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretAnnotations)
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@@ -68,10 +66,7 @@ func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) {
kubeClient := fake.NewFakeClient() kubeClient := fake.NewFakeClient()
secretLabels := map[string]string{} secretLabels := map[string]string{}
secretAnnotations := map[string]string{} secretAnnotations := map[string]string{}
secretType := "" err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretAnnotations)
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@@ -82,7 +77,7 @@ func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) {
newItem.Version = 456 newItem.Version = 456
newItem.Vault.ID = "hfnjvi6aymbsnfc2xeeoheizda" newItem.Vault.ID = "hfnjvi6aymbsnfc2xeeoheizda"
newItem.ID = "h46bb3jddvay7nxopfhvlwg35q" newItem.ID = "h46bb3jddvay7nxopfhvlwg35q"
err = CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &newItem, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations) err = CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &newItem, restartDeploymentAnnotation, secretLabels, secretAnnotations)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@@ -116,9 +111,8 @@ func TestBuildKubernetesSecretFromOnePasswordItem(t *testing.T) {
item := onepassword.Item{} item := onepassword.Item{}
item.Fields = generateFields(5) item.Fields = generateFields(5)
labels := map[string]string{} labels := map[string]string{}
secretType := ""
kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, secretType, item) kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, item)
if kubeSecret.Name != strings.ToLower(name) { if kubeSecret.Name != strings.ToLower(name) {
t.Errorf("Expected name value: %v but got: %v", name, kubeSecret.Name) t.Errorf("Expected name value: %v but got: %v", name, kubeSecret.Name)
} }
@@ -140,7 +134,6 @@ func TestBuildKubernetesSecretFixesInvalidLabels(t *testing.T) {
} }
labels := map[string]string{} labels := map[string]string{}
item := onepassword.Item{} item := onepassword.Item{}
secretType := ""
item.Fields = []*onepassword.ItemField{ item.Fields = []*onepassword.ItemField{
{ {
@@ -153,7 +146,7 @@ func TestBuildKubernetesSecretFixesInvalidLabels(t *testing.T) {
}, },
} }
kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, secretType, item) kubeSecret := BuildKubernetesSecretFromOnePasswordItem(name, namespace, annotations, labels, item)
// Assert Secret's meta.name was fixed // Assert Secret's meta.name was fixed
if kubeSecret.Name != expectedName { if kubeSecret.Name != expectedName {
@@ -171,39 +164,6 @@ func TestBuildKubernetesSecretFixesInvalidLabels(t *testing.T) {
} }
} }
func TestCreateKubernetesTLSSecretFromOnePasswordItem(t *testing.T) {
secretName := "tls-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 := "kubernetes.io/tls"
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation, secretLabels, secretType, secretAnnotations)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
createdSecret := &corev1.Secret{}
err = kubeClient.Get(context.Background(), types.NamespacedName{Name: secretName, Namespace: namespace}, createdSecret)
if err != nil {
t.Errorf("Secret was not created: %v", err)
}
if createdSecret.Type != corev1.SecretTypeTLS {
t.Errorf("Expected secretType to be of tyype corev1.SecretTypeTLS, got %s", string(createdSecret.Type))
}
}
func compareAnnotationsToItem(annotations map[string]string, item onepassword.Item, t *testing.T) { func compareAnnotationsToItem(annotations map[string]string, item onepassword.Item, t *testing.T) {
actualVaultId, actualItemId, err := ParseVaultIdAndItemIdFromPath(annotations[ItemPathAnnotation]) actualVaultId, actualItemId, err := ParseVaultIdAndItemIdFromPath(annotations[ItemPathAnnotation])
if err != nil { if err != nil {

View File

@@ -7,7 +7,10 @@ import (
func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string]*corev1.Secret) bool { func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string]*corev1.Secret) bool {
for i := 0; i < len(containers); i++ { for i := 0; i < len(containers); i++ {
envVariables := containers[i].Env envVariables := containers[i].Env
envVariableNames := map[string]struct{}{}
for j := 0; j < len(envVariables); j++ { for j := 0; j < len(envVariables); j++ {
envVariableNames[envVariables[j].Name] = struct{}{}
if envVariables[j].ValueFrom != nil && envVariables[j].ValueFrom.SecretKeyRef != nil { if envVariables[j].ValueFrom != nil && envVariables[j].ValueFrom.SecretKeyRef != nil {
_, ok := secrets[envVariables[j].ValueFrom.SecretKeyRef.Name] _, ok := secrets[envVariables[j].ValueFrom.SecretKeyRef.Name]
if ok { if ok {
@@ -18,6 +21,10 @@ func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string
envFromVariables := containers[i].EnvFrom envFromVariables := containers[i].EnvFrom
for j := 0; j < len(envFromVariables); j++ { for j := 0; j < len(envFromVariables); j++ {
if envFromVariables[j].SecretRef != nil { if envFromVariables[j].SecretRef != nil {
// Skip env variables that will be overwritten by Env
if _, ok := envVariableNames[envFromVariables[i].SecretRef.Name]; ok {
continue;
}
_, ok := secrets[envFromVariables[j].SecretRef.Name] _, ok := secrets[envFromVariables[j].SecretRef.Name]
if ok { if ok {
return true return true
@@ -31,7 +38,10 @@ func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string
func AppendUpdatedContainerSecrets(containers []corev1.Container, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret { func AppendUpdatedContainerSecrets(containers []corev1.Container, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret {
for i := 0; i < len(containers); i++ { for i := 0; i < len(containers); i++ {
envVariables := containers[i].Env envVariables := containers[i].Env
envVariableNames := map[string]struct{}{}
for j := 0; j < len(envVariables); j++ { for j := 0; j < len(envVariables); j++ {
envVariableNames[envVariables[j].Name] = struct{}{}
if envVariables[j].ValueFrom != nil && envVariables[j].ValueFrom.SecretKeyRef != nil { if envVariables[j].ValueFrom != nil && envVariables[j].ValueFrom.SecretKeyRef != nil {
secret, ok := secrets[envVariables[j].ValueFrom.SecretKeyRef.Name] secret, ok := secrets[envVariables[j].ValueFrom.SecretKeyRef.Name]
if ok { if ok {
@@ -42,6 +52,10 @@ func AppendUpdatedContainerSecrets(containers []corev1.Container, secrets map[st
envFromVariables := containers[i].EnvFrom envFromVariables := containers[i].EnvFrom
for j := 0; j < len(envFromVariables); j++ { for j := 0; j < len(envFromVariables); j++ {
if envFromVariables[j].SecretRef != nil { if envFromVariables[j].SecretRef != nil {
// Skip env variables that will be overwritten by Env
if _, ok := envVariableNames[envFromVariables[i].SecretRef.Name]; ok {
continue;
}
secret, ok := secrets[envFromVariables[j].SecretRef.LocalObjectReference.Name] secret, ok := secrets[envFromVariables[j].SecretRef.LocalObjectReference.Name]
if ok { if ok {
updatedDeploymentSecrets[secret.Name] = secret updatedDeploymentSecrets[secret.Name] = secret

View File

@@ -118,8 +118,7 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]*
item, err := GetOnePasswordItemByPath(h.opConnectClient, secret.Annotations[ItemPathAnnotation]) item, err := GetOnePasswordItemByPath(h.opConnectClient, secret.Annotations[ItemPathAnnotation])
if err != nil { if err != nil {
log.Error(err, "failed to retrieve 1Password item at path \"%s\" for secret \"%s\"", secret.Annotations[ItemPathAnnotation], secret.Name) return nil, fmt.Errorf("Failed to retrieve item: %v", err)
continue
} }
itemVersion := fmt.Sprint(item.Version) itemVersion := fmt.Sprint(item.Version)
@@ -132,7 +131,7 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]*
} }
log.Info(fmt.Sprintf("Updating kubernetes secret '%v'", secret.GetName())) log.Info(fmt.Sprintf("Updating kubernetes secret '%v'", secret.GetName()))
secret.Annotations[VersionAnnotation] = itemVersion secret.Annotations[VersionAnnotation] = itemVersion
updatedSecret := kubeSecrets.BuildKubernetesSecretFromOnePasswordItem(secret.Name, secret.Namespace, secret.Annotations, secret.Labels, string(secret.Type), *item) updatedSecret := kubeSecrets.BuildKubernetesSecretFromOnePasswordItem(secret.Name, secret.Namespace, secret.Annotations, secret.Labels, *item)
h.client.Update(context.Background(), updatedSecret) h.client.Update(context.Background(), updatedSecret)
if updatedSecrets[secret.Namespace] == nil { if updatedSecrets[secret.Namespace] == nil {
updatedSecrets[secret.Namespace] = make(map[string]*corev1.Secret) updatedSecrets[secret.Namespace] = make(map[string]*corev1.Secret)