askill
external-secrets

external-secretsSafety 95Repository

External Secrets Operator (ESO) — SecretStore, ClusterSecretStore, ExternalSecret, PushSecret, templating, and multi-tenant patterns. Use when syncing secrets from AWS Secrets Manager or Vault into K8s. NOT for sealed-secrets or SOPS.

3 stars
1.2k downloads
Updated 3/14/2026

Package Files

Loading files...
SKILL.md

External Secrets Operator

Sync secrets from external providers (AWS, Vault) into Kubernetes Secrets using CRDs.

Docs: https://external-secrets.io/latest/

Installation

helm repo add external-secrets https://charts.external-secrets.io

helm install external-secrets external-secrets/external-secrets \
  -n external-secrets --create-namespace \
  --set installCRDs=true

CRDs require server-side apply (they exceed 256KB):

kubectl apply --server-side -f \
  "https://raw.githubusercontent.com/external-secrets/external-secrets/v0.14.3/deploy/crds/bundle.yaml"

Verify:

kubectl -n external-secrets get pods
kubectl get crd externalsecrets.external-secrets.io

Core Concepts

SecretStore vs ClusterSecretStore

SecretStoreClusterSecretStore
ScopeSingle namespaceCluster-wide
Auth secretsSame namespace onlyAny namespace via namespace field
Use whenTeam-owned, namespace isolationShared platform credentials

Provider Configurations

AWS Secrets Manager

SecretStore (namespace-scoped)

apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: aws-secrets
  namespace: my-app
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-creds
            key: access-key
          secretAccessKeySecretRef:
            name: aws-creds
            key: secret-key

IRSA (preferred on EKS)

Omit the auth block entirely and set role:

spec:
  provider:
    aws:
      service: SecretsManager  # or ParameterStore
      region: us-east-1
      role: arn:aws:iam::123456789:role/eso-role

AWS Parameter Store

Same provider block, just change the service:

spec:
  provider:
    aws:
      service: ParameterStore
      region: us-east-1

HashiCorp Vault (On-Prem)

ClusterSecretStore with Kubernetes Auth

apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "external-secrets"
          serviceAccountRef:
            name: my-sa

AppRole Auth

spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      version: "v2"
      auth:
        appRole:
          path: "approle"
          roleRef:
            name: vault-approle
            key: role-id
          secretRef:
            name: vault-approle
            key: secret-id

Token Auth (dev/simple setups)

spec:
  provider:
    vault:
      server: "https://vault.example.com"
      path: "secret"
      version: "v2"
      auth:
        tokenSecretRef:
          name: vault-token
          key: token

Vault gotchas:

  • KV v2 path: the actual API path is <mount>/data/<key> — ESO handles this when version: "v2" is set. Don't add /data/ yourself
  • Vault namespaces (Enterprise): set spec.provider.vault.namespace
  • TLS: use spec.provider.vault.caBundle or caProvider for self-signed certs

ExternalSecret

Individual Keys (data)

apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets
    kind: SecretStore
  target:
    name: app-secrets
    creationPolicy: Owner
  data:
    - secretKey: db-password        # Key in K8s Secret
      remoteRef:
        key: prod/database          # Key in provider
        property: password          # JSON property (if structured)
    - secretKey: api-key
      remoteRef:
        key: prod/api-keys
        property: stripe

Full Secret Sync (dataFrom)

spec:
  dataFrom:
    # Extract all keys from a single secret
    - extract:
        key: prod/database
    # Find multiple secrets by name/tags
    - find:
        name:
          regexp: "prod/.*"
        # AWS tags filter:
        # tags:
        #   environment: production

Both Together

spec:
  data:
    - secretKey: extra-key
      remoteRef:
        key: prod/extra
  dataFrom:
    - extract:
        key: prod/database

Templating

Transform secret data before storing in Kubernetes:

spec:
  target:
    template:
      engineVersion: v2
      type: Opaque  # or kubernetes.io/tls, kubernetes.io/dockerconfigjson
      data:
        DATABASE_URL: |
          postgresql://{{ .username }}:{{ .password }}@{{ .host }}:5432/{{ .dbname }}
        decoded: "{{ .encoded_value | b64dec }}"
        .dockerconfigjson: |
          {"auths":{"registry.example.com":{"username":"{{ .user }}","password":"{{ .pass }}"}}}
  data:
    - secretKey: username
      remoteRef:
        key: db-creds
        property: username
    - secretKey: password
      remoteRef:
        key: db-creds
        property: password
    - secretKey: host
      remoteRef:
        key: db-creds
        property: host
    - secretKey: dbname
      remoteRef:
        key: db-creds
        property: dbname

Template functions: standard Go template functions plus b64enc, b64dec, upper, lower, replace, trim, now, hasPrefix, hasSuffix.

Helm escaping: wrap ESO templates in backticks when deploying via Helm:

password: "{{ `{{ .mysecret }}` }}"

Troubleshooting

Check Status

kubectl get secretstores -A
kubectl get clustersecretstores
kubectl get externalsecrets -A
kubectl describe externalsecret <name> -n <ns>

Common Issues

SymptomCauseFix
SecretSyncedErrorProvider auth failedCheck credentials in referenced Secret
SecretStore NotReadyConnection/auth issuekubectl describe secretstore <name>
Secret not updatingrefreshInterval too long or CreatedOnce policyCheck refreshInterval and refreshPolicy
InvalidStoreRefWrong store name/kindVerify secretStoreRef matches existing store
CRD install failsOver 256KB limitUse kubectl apply --server-side
RBAC errorsMissing permissionsEnsure ESO SA has access to auth secrets

Diagnostic Script

Run scripts/eso-diagnostics.sh for comprehensive health checks.

Reference Docs

References

Related Skills

  • helm — Helm secrets handling patterns and ESO integration in charts
  • argocd — GitOps deployment of ExternalSecret/SecretStore resources
  • crossplane — Crossplane provider credentials via ESO
  • cert-manager — Store CA private keys in external secret managers

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

92/100Analyzed 2/23/2026

Highly comprehensive and actionable skill for External Secrets Operator. Covers installation, provider configurations (AWS Secrets Manager, Parameter Store, Vault with multiple auth methods), ExternalSecret resources with data/dataFrom/templating, and troubleshooting. Well-structured with YAML examples, comparison tables, and clear explanations. Bonus points for 'when to use' guidance, tags for discoverability, and reference to external docs. Minor gap on PushSecret details but otherwise excellent reference content.

95
90
90
85
92

Metadata

Licenseunknown
Version-
Updated3/14/2026
Publishertylertitsworth

Tags

apici-cddatabasesecurity