K8s Security Pro
#18 Secrets Management enterprise

External Secrets Operator

Complete External Secrets Operator setup with AWS Secrets Manager: IRSA ServiceAccount, namespace-scoped SecretStore, ClusterSecretStore, individual ExternalSecrets, and bulk dataFrom sync.

CIS Benchmark
5.4.15.4.2
MITRE ATT&CK
T1552.001

Overview

This template provides a complete External Secrets Operator (ESO) configuration for AWS Secrets Manager integration across five resources: an IRSA-enabled ServiceAccount (zero static credentials), a namespace-scoped SecretStore, a ClusterSecretStore, an individual ExternalSecret with templated output, and a bulk dataFrom ExternalSecret for path-prefix syncing.

Security threat addressed: Secrets stored in Git, Helm values, or plain ConfigMaps are exposed to every developer, CI/CD pipeline, and backup system. A single leaked commit exposes every credential ever committed. ESO eliminates this by fetching secrets from dedicated external secret managers.

When to use: Deploy in every cluster that manages secrets. Replace all hardcoded credentials in Git with ExternalSecret resources that reference AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, or HashiCorp Vault.

Threat Model

  • Zero secrets in Git: ExternalSecret resources contain only references (paths), never actual credential values. Git history cannot leak secrets.
  • Automatic rotation: ESO re-fetches secrets on a configurable interval (default: 1h), automatically picking up rotated credentials.
  • Audit trail: AWS CloudTrail logs every secret access, providing a complete audit trail for compliance.
  • IRSA authentication: No static AWS credentials exist anywhere in the cluster; authentication uses short-lived OIDC tokens.

MITRE ATT&CK:

  • T1552.001 — Unsecured Credentials: Credentials in Files: Attackers search filesystems, repos, and config files for hardcoded credentials. ESO removes this vector entirely.

Real-world scenario: A developer accidentally commits a database password to a public Git repository. With ESO, the Git repo contains only key: /production/app/database — the actual password lives exclusively in AWS Secrets Manager with IAM-restricted access and CloudTrail auditing.

YAML Source

# STEP 1: IRSA ServiceAccount for ESO to authenticate to AWS
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-secrets-sa
  namespace: external-secrets
  labels:
    app.kubernetes.io/name: k8s-security
    app.kubernetes.io/part-of: k8s-security-pro
    app.kubernetes.io/managed-by: k8s-security-pro
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/external-secrets-operator-role"
automountServiceAccountToken: false
---
# STEP 2: SecretStore -- Namespace-scoped connection to AWS
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-secrets-manager
  namespace: production
  labels:
    app.kubernetes.io/name: k8s-security
    app.kubernetes.io/part-of: k8s-security-pro
    app.kubernetes.io/managed-by: k8s-security-pro
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
# ... truncated -- get ClusterSecretStore, ExternalSecret with templates,
# and bulk dataFrom sync at k8s-security.pro/pricing

Get the complete template with ClusterSecretStore, templated ExternalSecret (DSN construction), bulk dataFrom path-prefix syncing, and multi-provider support in the Enterprise tier.

Installation

kubectl:

# Install External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
  -n external-secrets --create-namespace

# Apply the configuration
kubectl apply -f 18_external_secrets.yaml

Helm:

helm install k8s-security ./charts/k8s-security -f values-prod.yaml

Kustomize:

kubectl apply -k kustomize/overlays/prod

Verification

# Verify ESO is running
kubectl get pods -n external-secrets

# Check SecretStore connection status
kubectl get secretstore -n production
kubectl describe secretstore aws-secrets-manager -n production

# Check ExternalSecret sync status
kubectl get externalsecret -n production
kubectl describe externalsecret app-database-credentials -n production

# Verify the K8s Secret was created
kubectl get secret app-db-credentials -n production -o jsonpath='{.data}' | jq .

# Check sync conditions
kubectl get externalsecret -n production -o jsonpath='{.items[*].status.conditions}'

CIS Benchmark References

  • 5.4.1 — Prefer using Secrets as files over Secrets as environment variables. ESO creates native K8s Secrets that can be mounted as files.
  • 5.4.2 — Consider external secret storage. ESO directly implements this recommendation by integrating with dedicated secret managers.

MITRE ATT&CK References

  • T1552.001 — Unsecured Credentials: Credentials in Files: Attackers search filesystems, repos, and config files for hardcoded credentials. ESO eliminates this by never storing credential values in Git, Helm charts, or ConfigMaps.

Further Reading

Get Full Access to This Template

This template is included in the Enterprise tier and above.

View Pricing Plans