1Password/onepassword-operator

Operator breaks ArgoCD/GitOps integration by incorrectly copying all labels to secrets

codeshrew opened this issue · 1 comments

Your environment

Operator Version: 1password/onepassword-operator:1.1.0

Connect Server Version: 1password/connect-api:1.5.1

Kubernetes Version: v1.21.5-eks-bc4871b

1Password Operator version used:

operator:
  create: true

What happened?

GitOps tools, such as ArgoCD and Flux manage resources in Kubernetes by tracking desired state (in git repos) and resolving actual state (in the Kubernetes cluster) to match that desired state. They will both create and delete (or prune) resources to make the actual state match the desired state.

To do this properly, they need to track which resources they own so they don't prune resources that are not managed by them. ArgoCD accomplishes this through Labels such as argocd.argoproj.io/instance: example-argocd-project.

The 1Password Operator copies all Labels from the OnePasswordItem to the Secret. This creates issues for systems such as ArgoCD which use labels to track whether or not they "own" a particular resource. More specifically, this label: argocd.argoproj.io/instance: example-argocd-project in the following resources let ArgoCD know that it is the owner of these. The breaking side of this issue comes in when an ArgoCD project is set to prune resources that no longer appear in the associated git repo (this is default and desired behavior).

What did you expect to happen?

When the 1Password Operator creates a Secret from a OnePasswordItem, it should not copy any labels from the OnePasswordItem to the Secret.

You can see other systems that integrate well with a GitOps flow that follow this behavior, such as SealedSecrets.

Note that there are no labels.

apiVersion: v1
data:
  test: REDACTED
kind: Secret
metadata:
  annotations:
    operator.1password.io/item-path: vaults/<vault_id_or_title>/items/<item_id_or_title>
    operator.1password.io/item-version: "2"
  name: test
  namespace: example
type: Opaque

Steps to reproduce

  1. Add OnePasswordItem to git repo for the example-argocd-project. Git commit and push.
  2. ArgoCD sees the new resource and creates it in the example namespace in the cluster
  3. 1Password Operator sees the new OnePasswordItem in the example namespace and creates the Secret in the same namespace copying all the labels to the Secret
  4. ArgoCD will see the Secret created by the 1Password Operator, it checks the labels to see if it owns this resource. It sees the argocd.argoproj.io/instance: example-argocd-project label which tells it that it does own it
  5. ArgoCD checks to see if this Secret exists in the git repo for the project to decide if it should prune it
  6. The Secret does not exist in the project (since it was created in the cluster by the 1Password Operator), so ArgoCD believes it should prune this resource that it owns.
  7. The Secret is deleted by ArgoCD
  8. The 1Password Operator shows errors in its log about this deleted secret already existing: {"level":"info","ts":1648753133.12132,"msg":"Secret with name test and version 2 already exists"}

Given this OnePasswordItem:

apiVersion: onepassword.com/v1
kind: OnePasswordItem
metadata:
  name: test
spec:
  itemPath: "vaults/<vault_id_or_title>/items/<item_id_or_title>"

The operator creates a Secret like the following, in which it has copied all the Labels from the OnePasswordItem.

apiVersion: v1
data:
  test: REDACTED
kind: Secret
metadata:
  annotations:
    operator.1password.io/item-path: vaults/<vault_id_or_title>/items/<item_id_or_title>
    operator.1password.io/item-version: "2"
  creationTimestamp: "2022-04-01T17:18:07Z"
  labels:
    argocd.argoproj.io/instance: example-argocd-project
    tags.datadoghq.com/env: dev
  name: test
  namespace: example
type: Opaque

Current Workaround

A workaround is to not use the custom resource of OnePasswordItem but to instead use the annotations on Deployments method as documented in the 1Password Operator README.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-example
  annotations:
    operator.1password.io/item-path: "vaults/<vault_id_or_title>/items/<item_id_or_title>"
    operator.1password.io/item-name: "<secret_name>"

Hi guys, awesome add.
When do we expect this to be added to the latest 1password/connect helm chart available?