External Secrets Operator

Here is my attemp to have External Secrets Operator minimal possible setup

We will deploy only wanted pieces

So far, minimally required are following CRDS:

  • secretstore - holds credentials for keyvault
  • externalsecret - will produce kubernetes secrets filled with values from keyvault

We gonna need to create secret that will hold keyvault credentials

apiVersion: v1
kind: Secret
metadata:
  name: azure-secret-sp
type: Opaque
stringData:
  ClientID: "00000000-0000-0000-0000-000000000000"
  ClientSecret: "00000000-0000-0000-0000-000000000000" # instead consider federated credentials

and SecretStore that will use this secret and connect to KeyVault

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: example
spec:
  provider:
    azurekv:
      tenantId: "00000000-0000-0000-0000-000000000000"
      vaultUrl: "https://example.vault.azure.net"
      authSecretRef:
        clientId:
          name: azure-secret-sp
          key: ClientID
        clientSecret:
          name: azure-secret-sp
          key: ClientSecret

and finally secrets controller (we do not need everything elase, also note how we are disabling few things via arguments)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-secrets
  labels:
    app: external-secrets
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: external-secrets
  template:
    metadata:
      labels:
        app: external-secrets
    spec:
      serviceAccountName: external-secrets
      automountServiceAccountToken: true
      containers:
        - name: external-secrets
          image: oci.external-secrets.io/external-secrets/external-secrets:v0.10.5
          imagePullPolicy: IfNotPresent
          args:
            - --enable-push-secret-reconciler=false
            - --enable-cluster-store-reconciler=false
            - --enable-cluster-external-secret-reconciler=false
          ports:
            - name: metrics
              containerPort: 8080
              protocol: TCP
          resources:
            requests:
              cpu: 10m
              memory: 64Mi
            limits:
              cpu: 500m
              memory: 128Mi
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            runAsUser: 1000
            seccompProfile:
              type: RuntimeDefault

here is kustomization

apiVersion: kustomize.config.k8s.io/v1beta1
resources:
  # crd: secretstore - holds credentials for keyvault
  - https://raw.githubusercontent.com/external-secrets/external-secrets/refs/tags/v0.11.0/config/crds/bases/external-secrets.io_secretstores.yaml
  # crd: externalsecret - will produce kubernetes secrets filled with values from keyvault
  - https://raw.githubusercontent.com/external-secrets/external-secrets/refs/tags/v0.11.0/config/crds/bases/external-secrets.io_externalsecrets.yaml
  # external secrets controller
  - service-account.yml
  - cluster-role-binding.yml
  - deployment.yml
  # azure key vault
  - secret.yml
  - secret-store.yml
  # sync key vault secret into kubernetes secret
  - example.external-secret.yml

and its usage example:

kind create cluster
kubectl wait --for=condition=Ready node --all --timeout=90s

kubectl apply -k .
kubectl rollout status deployment external-secrets --timeout=10m

kubectl logs -l app=external-secrets --tail=5 | jq .msg

kubectl get secrets secret-to-be-created
kubectl get secrets secret-to-be-created -o json | jq -r '.data["secret-key-to-be-managed"]' | base64 -d
# should output: "bar"

kind delete cluster