Keeper Kubernetes Secrets Injector

Automatically inject secrets from Keeper Secrets Manager into your Kubernetes pods at runtime.
Features
- Multiple injection modes - Files (tmpfs), environment variables, or Kubernetes Secrets
- Pod-scoped lifetime - Secrets removed when pod terminates (default mode)
- Automatic sync from Keeper - Sidecar detects changes in Keeper and updates pods without restarts
- Simple configuration - Just two annotations to get started
- Title-based lookup - Reference secrets by name, not UIDs
- Keeper Notation - Use
keeper://UID/field/password for precise extraction (via the per-secret keeper.security/secret-<name> annotation or a notation: field in keeper.security/config; the singular keeper.security/secret treats its value as a literal record title)
- File Attachments - Download files from Keeper records
- Folder Support - Fetch all secrets from a Keeper folder
- Production-ready - HA, metrics, leader election
Installation
Option 1: Helm (OCI Registry) - Recommended
# Works for both new installation and upgrades
helm upgrade --install keeper-injector oci://registry-1.docker.io/keeper/keeper-injector \
--namespace keeper-security \
--create-namespace
Option 2: Helm (Repository)
helm repo add keeper https://keeper-security.github.io/helm-charts
helm repo update
helm upgrade --install keeper-injector keeper/keeper-injector \
--namespace keeper-security \
--create-namespace
Option 3: kubectl (Direct YAML)
kubectl apply -f https://github.com/Keeper-Security/keeper-k8s-injector/releases/latest/download/install.yaml
Quick Start
1. Create KSM Auth Secret
Option 1: Base64 Config (Recommended)
From Keeper: Vault → Secrets Manager → Select Application → Devices → Add Device → Base64
kubectl create secret generic keeper-auth \
--from-literal=config='<paste-base64-config-here>' \
--namespace default
Option 2: Config File
kubectl create secret generic keeper-auth \
--from-file=config=ksm-config.json \
--namespace default
2. Create a Test Pod
⚠️ Important: Replace "YOUR-SECRET-TITLE" with an actual secret title from your Keeper Secrets Manager application.
Create test pod:
cat > test-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: test-secrets
annotations:
keeper.security/inject: "true"
keeper.security/ksm-config: "keeper-auth"
keeper.security/secret: "YOUR-SECRET-TITLE"
spec:
containers:
- name: busybox
image: busybox:latest
command: ["sleep", "3600"]
EOF
Deploy and verify:
kubectl apply -f test-pod.yaml
# pod/test-secrets created
kubectl wait --for=condition=Ready pod/test-secrets --timeout=60s
# pod/test-secrets condition met
kubectl exec test-secrets -- cat /keeper/secrets/YOUR-SECRET-TITLE.json
# {
# "login": "admin",
# "password": "my-secure-password-123",
# "hostname": "db.example.com"
# }
kubectl delete pod test-secrets
Examples
Try these working examples to see the injector in action:
Try It Now
# Clone the repo
git clone https://github.com/Keeper-Security/keeper-k8s-injector.git
cd keeper-k8s-injector
# Run the hello-secrets example
kubectl apply -f examples/01-hello-secrets/
kubectl port-forward svc/hello-secrets 8080:80
# Open http://localhost:8080
Documentation
📖 View Full Documentation - Complete guide with tutorials and reference
Quick Links:
Annotation Examples
Multiple Secrets
keeper.security/secrets: "database-creds, api-keys, tls-cert"
Custom Paths
keeper.security/secret-db: "/app/config/database.json"
keeper.security/secret-api: "/etc/myapp/api.json"
With Rotation
The sidecar refreshes secret files in place on the configured interval. The optional
keeper.security/signal annotation is not yet implemented (planned) — it is accepted but
currently a no-op (no signal is delivered to the app container on refresh), so have your app
re-read the secret files to pick up changes.
keeper.security/refresh-interval: "5m"
keeper.security/signal: "SIGHUP" # planned; currently a no-op
Keeper Notation (Specific Fields)
keeper.security/secret-password: "keeper://QabbPIdM8Unw4hwVM-F8VQ/field/password:/app/secrets/db-pass"
File Attachments
keeper.security/file-cert: "Database Credentials:cert.pem:/app/certs/server.pem"
Keeper notation also works for file attachments:
keeper.security/file-cert: "keeper://Database Credentials/file/cert.pem:/app/certs/server.pem"
Comparison with External Secrets Operator (ESO)
| Feature |
Keeper Injector |
External Secrets Operator |
| Creates K8s Secrets |
Optional |
Yes (always) |
| Secret storage |
Pod tmpfs (default) |
etcd |
| Secrets in etcd backups |
Optional |
Yes |
| Configuration |
Annotations |
CRDs |
| Sync from Keeper |
Sidecar polling |
Controller polling |
| Pod isolation |
Yes (default) |
Shared secrets |
Use Keeper Injector when: Security is paramount, you need secrets out of etcd, or require per-pod isolation.
Use ESO when: You need all secrets as K8s Secret objects, or prefer CRD-based GitOps workflows.
Docker Images
| Image |
Description |
keeper/injector-webhook |
Mutating admission webhook |
keeper/injector-sidecar |
Sidecar container for secret fetching |
Images are available on Docker Hub with multi-arch support (amd64, arm64).
Requirements
- Kubernetes 1.21+ (tested with 1.21-1.34)
- Keeper Secrets Manager application
TLS certificates are auto-generated. cert-manager is optional.
Links
Contributing
Contributions are welcome! Please open an issue or pull request.
License
MIT License - see LICENSE for details.
Support