External Secrets Operator
Complete External Secrets Operator setup with AWS Secrets Manager: IRSA ServiceAccount, namespace-scoped SecretStore, ClusterSecretStore, individual ExternalSecrets, and bulk dataFrom sync.
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
- Kubernetes Supply Chain Security: From Image Scanning to SLSA — Understand how external secrets management fits into the broader supply chain security strategy.
Get Full Access to This Template
This template is included in the Enterprise tier and above.
View Pricing Plans