Add external secret for renovate
This commit is contained in:
parent
c04dffe516
commit
733d0c1425
158
charts/external-secrets/INDEX.md
Normal file
158
charts/external-secrets/INDEX.md
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# External Secrets Documentation Index
|
||||||
|
|
||||||
|
This folder contains comprehensive documentation and templates for using External Secrets Operator (ESO) across your repositories.
|
||||||
|
|
||||||
|
## 📚 Documentation Files
|
||||||
|
|
||||||
|
### [USAGE.md](./USAGE.md)
|
||||||
|
**Complete usage guide for External Secrets Operator**
|
||||||
|
|
||||||
|
Covers:
|
||||||
|
- Overview and architecture
|
||||||
|
- Getting started with ESO
|
||||||
|
- How to structure your `secrets-reponame` folders
|
||||||
|
- SecretStore configuration (Vault, Kubernetes, etc.)
|
||||||
|
- Creating ExternalSecret resources
|
||||||
|
- Real-world examples (Django, PostgreSQL, TLS)
|
||||||
|
- Troubleshooting guide
|
||||||
|
- Best practices
|
||||||
|
|
||||||
|
**Start here** if you want to understand how External Secrets works and how to use it in your repository.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂️ Templates & Examples
|
||||||
|
|
||||||
|
Located in the `templates-examples/` folder. Copy these to your repository's `secrets-<reponame>/` folder and customize them.
|
||||||
|
|
||||||
|
### SecretStore Templates
|
||||||
|
|
||||||
|
- **[secretstore-vault.yaml](./templates-examples/secretstore-vault.yaml)**
|
||||||
|
- Connect to a Vault backend
|
||||||
|
- Use this for most applications that use Vault
|
||||||
|
|
||||||
|
- **[secretstore-kubernetes.yaml](./templates-examples/secretstore-kubernetes.yaml)**
|
||||||
|
- Sync secrets from another Kubernetes namespace
|
||||||
|
- Use this if your secrets are already in Kubernetes
|
||||||
|
|
||||||
|
- **[clustersecretstore-vault.yaml](./templates-examples/clustersecretstore-vault.yaml)**
|
||||||
|
- Cluster-wide Vault connection (managed by infrastructure team)
|
||||||
|
- Use this for shared secrets available across the cluster
|
||||||
|
|
||||||
|
### ExternalSecret Templates
|
||||||
|
|
||||||
|
- **[externalsecret-basic.yaml](./templates-examples/externalsecret-basic.yaml)**
|
||||||
|
- Sync individual secret properties from Vault
|
||||||
|
- Most common use case
|
||||||
|
- Recommended for most applications
|
||||||
|
|
||||||
|
- **[externalsecret-extract.yaml](./templates-examples/externalsecret-extract.yaml)**
|
||||||
|
- Sync entire secret objects from Vault
|
||||||
|
- Use when you have a secret with many properties
|
||||||
|
|
||||||
|
- **[externalsecret-advanced.yaml](./templates-examples/externalsecret-advanced.yaml)**
|
||||||
|
- Advanced templating and transformations
|
||||||
|
- Build configuration files from secret values
|
||||||
|
- Use for complex secret combinations
|
||||||
|
|
||||||
|
### Application Integration Templates
|
||||||
|
|
||||||
|
- **[deployment-example.yaml](./templates-examples/deployment-example.yaml)**
|
||||||
|
- Show how to use synced secrets in your Deployment
|
||||||
|
- Three different methods to reference secrets:
|
||||||
|
- Environment variables via `envFrom`
|
||||||
|
- Individual environment variables
|
||||||
|
- Mount as files
|
||||||
|
|
||||||
|
### Getting Started
|
||||||
|
|
||||||
|
- **[QUICKSTART.md](./templates-examples/QUICKSTART.md)**
|
||||||
|
- Step-by-step guide to get started quickly
|
||||||
|
- Copy-paste commands
|
||||||
|
- Verification steps
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start Workflow
|
||||||
|
|
||||||
|
1. **Read [USAGE.md](./USAGE.md)** to understand the concepts
|
||||||
|
2. **Copy templates** from `templates-examples/` to your repository's `secrets-<reponame>/` folder
|
||||||
|
3. **Customize the templates** with your values:
|
||||||
|
- Namespace
|
||||||
|
- Vault URLs and paths
|
||||||
|
- Secret property names
|
||||||
|
- Refresh intervals
|
||||||
|
4. **Follow [QUICKSTART.md](./templates-examples/QUICKSTART.md)** to apply and verify
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Common Use Cases
|
||||||
|
|
||||||
|
### I want to sync database credentials
|
||||||
|
→ Copy [secretstore-vault.yaml](./templates-examples/secretstore-vault.yaml) and [externalsecret-basic.yaml](./templates-examples/externalsecret-basic.yaml)
|
||||||
|
|
||||||
|
### I want to sync TLS certificates
|
||||||
|
→ Copy [externalsecret-basic.yaml](./templates-examples/externalsecret-basic.yaml) and set `refreshInterval: 720h` (30 days)
|
||||||
|
|
||||||
|
### I want to sync multiple related secrets as a config file
|
||||||
|
→ Copy [externalsecret-advanced.yaml](./templates-examples/externalsecret-advanced.yaml)
|
||||||
|
|
||||||
|
### I want to use a cluster-wide SecretStore
|
||||||
|
→ Work with the infrastructure team to set up [clustersecretstore-vault.yaml](./templates-examples/clustersecretstore-vault.yaml)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Expected Repository Structure
|
||||||
|
|
||||||
|
After following this guide, your repository should have:
|
||||||
|
|
||||||
|
```
|
||||||
|
my-app-repo/
|
||||||
|
├── src/
|
||||||
|
├── k8s/
|
||||||
|
│ ├── base/
|
||||||
|
│ ├── overlays/
|
||||||
|
│ └── secrets-my-app/ ← Your secrets folder
|
||||||
|
│ ├── secretstore.yaml ← Copied and customized
|
||||||
|
│ ├── externalsecret.yaml ← Copied and customized
|
||||||
|
│ └── deployment.yaml ← References the secret
|
||||||
|
├── argocd-app.yaml ← Points to k8s/
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 Links
|
||||||
|
|
||||||
|
- [Official External Secrets Documentation](https://external-secrets.io/)
|
||||||
|
- [Vault Backend Provider](https://external-secrets.io/latest/provider/vault/)
|
||||||
|
- [Kubernetes Backend Provider](https://external-secrets.io/latest/provider/kubernetes/)
|
||||||
|
- [API Reference](https://external-secrets.io/latest/api/secretstore/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ FAQ
|
||||||
|
|
||||||
|
**Q: Can I version control my SecretStore and ExternalSecret files?**
|
||||||
|
A: Yes! These files should be in your repository's Git. Only the actual secret values stay in Vault/backend.
|
||||||
|
|
||||||
|
**Q: How often are secrets synced?**
|
||||||
|
A: Controlled by `refreshInterval` in the ExternalSecret (default 1h). You can trigger immediate sync using kubectl annotations.
|
||||||
|
|
||||||
|
**Q: What happens if the secret backend is unavailable?**
|
||||||
|
A: The operator will continue using the last synced secret. Check logs and operator status.
|
||||||
|
|
||||||
|
**Q: Can multiple applications use the same SecretStore?**
|
||||||
|
A: Yes, if they're in the same namespace. Or use a ClusterSecretStore for cluster-wide access.
|
||||||
|
|
||||||
|
**Q: How do I rotate secrets?**
|
||||||
|
A: Update the secret in your backend (Vault, etc.). The operator will automatically sync it based on `refreshInterval`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Getting Help
|
||||||
|
|
||||||
|
1. Check [USAGE.md](./USAGE.md) > Troubleshooting section
|
||||||
|
2. Review your ExternalSecret status: `kubectl describe externalsecret <name> -n <namespace>`
|
||||||
|
3. Check operator logs: `kubectl logs -n external-secrets deployment/external-secrets`
|
||||||
|
4. Contact your infrastructure team for Vault or cluster-wide SecretStore issues
|
||||||
462
charts/external-secrets/USAGE.md
Normal file
462
charts/external-secrets/USAGE.md
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
# External Secrets - Usage Guide
|
||||||
|
|
||||||
|
This guide explains how to use External Secrets Operator (ESO) to manage secrets across your Kubernetes cluster and sync them from various secret backends (Vault, Kubernetes secrets, etc.) into your applications.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Architecture](#architecture)
|
||||||
|
- [Getting Started](#getting-started)
|
||||||
|
- [Using External Secrets in Your Repository](#using-external-secrets-in-your-repository)
|
||||||
|
- [SecretStore Configuration](#secretstore-configuration)
|
||||||
|
- [Creating External Secrets](#creating-external-secrets)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
External Secrets Operator allows you to use external secret management systems (Vault, AWS Secrets Manager, Azure Key Vault, etc.) as a source of truth for secrets in your Kubernetes cluster. It automatically syncs secrets from these backends into native Kubernetes Secrets.
|
||||||
|
|
||||||
|
**Key Benefits:**
|
||||||
|
- Centralized secret management
|
||||||
|
- Automatic synchronization
|
||||||
|
- No need to store secrets in Git
|
||||||
|
- Support for multiple secret backends
|
||||||
|
- Templating and transformation capabilities
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ External Secret Operator (ESO) │
|
||||||
|
│ (installed in external-secrets namespace) │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────┼───────────────────┐
|
||||||
|
↓ ↓ ↓
|
||||||
|
┌─────────┐ ┌─────────┐ ┌──────────┐
|
||||||
|
│ Vault │ │ AWS │ │ Kubernetes
|
||||||
|
│ Secrets │ │ SecretsM│ │ Secrets
|
||||||
|
└─────────┘ └─────────┘ └──────────┘
|
||||||
|
↑ ↑ ↑
|
||||||
|
└───────────────────┼───────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────┐
|
||||||
|
│ SecretStore (or ClusterStore) │
|
||||||
|
│ (defines backend connection) │
|
||||||
|
└───────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────┐
|
||||||
|
│ ExternalSecret │
|
||||||
|
│ (defines what to sync & where) │
|
||||||
|
└───────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────┐
|
||||||
|
│ Kubernetes Secret │
|
||||||
|
│ (synced and kept in sync) │
|
||||||
|
└───────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌───────────────────────────────────┐
|
||||||
|
│ Your Application Pods │
|
||||||
|
│ (consumes the secrets) │
|
||||||
|
└───────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
External Secrets Operator is already installed in your cluster via the Helm chart in this repo. Verify the installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get deployments -n external-secrets
|
||||||
|
kubectl get crd | grep external-secrets
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see:
|
||||||
|
- Deployment: `external-secrets`
|
||||||
|
- Deployment: `external-secrets-webhook`
|
||||||
|
- CRDs: `secretstores.external-secrets.io`, `externalsecrets.external-secrets.io`, etc.
|
||||||
|
|
||||||
|
## Using External Secrets in Your Repository
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
For each repository that needs to manage secrets with External Secrets, create a `secrets-reponame` folder in your Kubernetes manifests:
|
||||||
|
|
||||||
|
```
|
||||||
|
my-app-repo/
|
||||||
|
├── src/
|
||||||
|
├── k8s/
|
||||||
|
│ ├── base/
|
||||||
|
│ ├── overlays/
|
||||||
|
│ └── secrets-my-app/ ← Create this folder
|
||||||
|
│ ├── secretstore.yaml
|
||||||
|
│ ├── externalsecret.yaml
|
||||||
|
│ └── values.yaml (optional, for kustomize/helm values)
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Folder Contents
|
||||||
|
|
||||||
|
The `secrets-reponame` folder should contain:
|
||||||
|
|
||||||
|
1. **secretstore.yaml** - Defines how to connect to your secret backend (Vault, AWS, etc.)
|
||||||
|
2. **externalsecret.yaml** - Defines which secrets to sync from the backend into Kubernetes
|
||||||
|
|
||||||
|
## SecretStore Configuration
|
||||||
|
|
||||||
|
A `SecretStore` is a namespaced resource that defines the connection to your secret backend. Create `secretstore.yaml` in your `secrets-reponame` folder:
|
||||||
|
|
||||||
|
### Example: Vault Backend
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: SecretStore
|
||||||
|
metadata:
|
||||||
|
name: vault-secretstore
|
||||||
|
namespace: default # Change to your app's namespace
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: "https://vault.example.com:8200"
|
||||||
|
path: "secret"
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: "kubernetes"
|
||||||
|
role: "my-app-role" # Define this in Vault
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Kubernetes Secrets Backend
|
||||||
|
|
||||||
|
If you want to sync secrets from another namespace or use Kubernetes as the backend:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: SecretStore
|
||||||
|
metadata:
|
||||||
|
name: k8s-secretstore
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
kubernetes:
|
||||||
|
remoteNamespace: "secrets-management"
|
||||||
|
auth:
|
||||||
|
serviceAccount:
|
||||||
|
name: external-secrets-reader
|
||||||
|
```
|
||||||
|
|
||||||
|
### ClusterSecretStore (Cluster-Wide)
|
||||||
|
|
||||||
|
If you want the SecretStore to be available cluster-wide, use `ClusterSecretStore` instead:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
metadata:
|
||||||
|
name: vault-cluster-store
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: "https://vault.example.com:8200"
|
||||||
|
path: "secret"
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: "kubernetes"
|
||||||
|
role: "my-app-role"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating External Secrets
|
||||||
|
|
||||||
|
An `ExternalSecret` is a Kubernetes custom resource that defines:
|
||||||
|
- Which `SecretStore` to use
|
||||||
|
- Which secrets to fetch from the backend
|
||||||
|
- How to transform them
|
||||||
|
- Where to create the resulting Kubernetes Secret
|
||||||
|
|
||||||
|
### Basic Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: app-secrets
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h # Sync every hour
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secretstore
|
||||||
|
kind: SecretStore
|
||||||
|
target:
|
||||||
|
name: app-secrets # Name of the Kubernetes Secret to create
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
data:
|
||||||
|
DATABASE_URL: "{{ .db_url }}"
|
||||||
|
API_KEY: "{{ .api_key }}"
|
||||||
|
data:
|
||||||
|
- secretKey: db_url
|
||||||
|
remoteRef:
|
||||||
|
key: my-app/database # Key in Vault
|
||||||
|
property: url # Property within that key
|
||||||
|
- secretKey: api_key
|
||||||
|
remoteRef:
|
||||||
|
key: my-app/api # Key in Vault
|
||||||
|
property: token
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced: Multiple Secrets
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: multi-secrets
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
refreshInterval: 30m
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secretstore
|
||||||
|
kind: SecretStore
|
||||||
|
target:
|
||||||
|
name: multi-secrets
|
||||||
|
creationPolicy: Owner
|
||||||
|
dataFrom:
|
||||||
|
- extract:
|
||||||
|
key: my-app/all-secrets # Fetch entire secret object
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Django Application
|
||||||
|
|
||||||
|
**Directory:** `my-django-app/k8s/secrets-django/`
|
||||||
|
|
||||||
|
**secretstore.yaml:**
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: SecretStore
|
||||||
|
metadata:
|
||||||
|
name: django-vault
|
||||||
|
namespace: django
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: "https://vault.example.com:8200"
|
||||||
|
path: "secret"
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: "kubernetes"
|
||||||
|
role: "django-app"
|
||||||
|
```
|
||||||
|
|
||||||
|
**externalsecret.yaml:**
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: django-env
|
||||||
|
namespace: django
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: django-vault
|
||||||
|
kind: SecretStore
|
||||||
|
target:
|
||||||
|
name: django-env
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
data:
|
||||||
|
SECRET_KEY: "{{ .secret_key }}"
|
||||||
|
DATABASE_URL: "{{ .database_url }}"
|
||||||
|
ALLOWED_HOSTS: "{{ .allowed_hosts }}"
|
||||||
|
data:
|
||||||
|
- secretKey: secret_key
|
||||||
|
remoteRef:
|
||||||
|
key: django/prod
|
||||||
|
property: secret_key
|
||||||
|
- secretKey: database_url
|
||||||
|
remoteRef:
|
||||||
|
key: django/prod
|
||||||
|
property: database_url
|
||||||
|
- secretKey: allowed_hosts
|
||||||
|
remoteRef:
|
||||||
|
key: django/prod
|
||||||
|
property: allowed_hosts
|
||||||
|
```
|
||||||
|
|
||||||
|
**Deployment usage:**
|
||||||
|
```yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: django-app
|
||||||
|
namespace: django
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: django
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: django-env # Reference the synced secret
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: PostgreSQL Database Credentials
|
||||||
|
|
||||||
|
**secretstore.yaml:**
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: SecretStore
|
||||||
|
metadata:
|
||||||
|
name: postgres-vault
|
||||||
|
namespace: databases
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: "https://vault.example.com:8200"
|
||||||
|
path: "secret"
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: "kubernetes"
|
||||||
|
role: "postgres"
|
||||||
|
```
|
||||||
|
|
||||||
|
**externalsecret.yaml:**
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: postgres-credentials
|
||||||
|
namespace: databases
|
||||||
|
spec:
|
||||||
|
refreshInterval: 24h
|
||||||
|
secretStoreRef:
|
||||||
|
name: postgres-vault
|
||||||
|
kind: SecretStore
|
||||||
|
target:
|
||||||
|
name: postgres-credentials
|
||||||
|
creationPolicy: Owner
|
||||||
|
data:
|
||||||
|
- secretKey: username
|
||||||
|
remoteRef:
|
||||||
|
key: postgres/primary
|
||||||
|
property: username
|
||||||
|
- secretKey: password
|
||||||
|
remoteRef:
|
||||||
|
key: postgres/primary
|
||||||
|
property: password
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: TLS Certificates
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: tls-certs
|
||||||
|
namespace: ingress-nginx
|
||||||
|
spec:
|
||||||
|
refreshInterval: 720h # 30 days
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-cluster-store
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
target:
|
||||||
|
name: app-tls
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
data:
|
||||||
|
tls.crt: "{{ .cert }}"
|
||||||
|
tls.key: "{{ .key }}"
|
||||||
|
data:
|
||||||
|
- secretKey: cert
|
||||||
|
remoteRef:
|
||||||
|
key: tls/app
|
||||||
|
property: certificate
|
||||||
|
- secretKey: key
|
||||||
|
remoteRef:
|
||||||
|
key: tls/app
|
||||||
|
property: key
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check ExternalSecret Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get ExternalSecret status
|
||||||
|
kubectl get externalsecret -n <namespace>
|
||||||
|
kubectl describe externalsecret <name> -n <namespace>
|
||||||
|
|
||||||
|
# Check if the synced Kubernetes Secret exists
|
||||||
|
kubectl get secret <target-name> -n <namespace>
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Operator Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check External Secrets Operator logs
|
||||||
|
kubectl logs -n external-secrets deployment/external-secrets
|
||||||
|
|
||||||
|
# Check webhook logs (if using webhook)
|
||||||
|
kubectl logs -n external-secrets deployment/external-secrets-webhook
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### 1. ExternalSecret shows "Error" status
|
||||||
|
- Check SecretStore connection details (URL, path, role)
|
||||||
|
- Verify Vault authentication is configured correctly
|
||||||
|
- Check role exists in Vault and has proper permissions
|
||||||
|
- Review operator logs for detailed error messages
|
||||||
|
|
||||||
|
#### 2. Secret is not being created
|
||||||
|
- Ensure `refreshInterval` has passed or manually trigger a sync
|
||||||
|
- Verify the target name is correct
|
||||||
|
- Check RBAC permissions for the operator
|
||||||
|
|
||||||
|
#### 3. Secret content is empty
|
||||||
|
- Verify the remote key path is correct in Vault
|
||||||
|
- Ensure the property name exists in the secret
|
||||||
|
- Check that the ExternalSecret template is valid
|
||||||
|
|
||||||
|
#### 4. Authentication failures
|
||||||
|
- Verify the ServiceAccount has the `external-secrets` name or matches the configured account
|
||||||
|
- Check Vault auth method configuration
|
||||||
|
- Ensure Kubernetes auth role is properly configured in Vault
|
||||||
|
|
||||||
|
### Force Refresh
|
||||||
|
|
||||||
|
To trigger an immediate refresh of an ExternalSecret:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl annotate externalsecret <name> \
|
||||||
|
-n <namespace> \
|
||||||
|
force-sync="$(date +%s)" \
|
||||||
|
--overwrite
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Use ClusterSecretStore** for widely-shared secrets (databases, certs)
|
||||||
|
2. **Use namespaced SecretStore** for app-specific secrets
|
||||||
|
3. **Set appropriate refreshInterval** - shorter for sensitive data, longer for stable secrets
|
||||||
|
4. **Use templating** for complex secret transformations
|
||||||
|
5. **Enable RBAC** to restrict which services can access which secrets
|
||||||
|
6. **Monitor** ExternalSecret status regularly
|
||||||
|
7. **Version control** the SecretStore and ExternalSecret manifests (not the actual secrets)
|
||||||
|
8. **Rotate secrets** in your backend independently of the operator
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Official External Secrets Documentation](https://external-secrets.io/)
|
||||||
|
- [Supported Secret Backends](https://external-secrets.io/latest/introduction/overview/#features)
|
||||||
|
- [API Reference](https://external-secrets.io/latest/api/secretstore/)
|
||||||
|
- [Vault Integration](https://external-secrets.io/latest/provider/vault/)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues specific to this cluster's External Secrets setup, check the main README or contact the infrastructure team.
|
||||||
101
charts/external-secrets/templates-examples/QUICKSTART.md
Normal file
101
charts/external-secrets/templates-examples/QUICKSTART.md
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# Quick Start: Copy to your repository
|
||||||
|
#
|
||||||
|
# This file shows the minimal steps to get external-secrets working
|
||||||
|
# in your application repository.
|
||||||
|
|
||||||
|
## Step 1: Create the folder structure
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p k8s/secrets-<your-app-name>
|
||||||
|
cd k8s/secrets-<your-app-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Copy template files
|
||||||
|
|
||||||
|
Copy the following template files to your `secrets-<your-app-name>/` folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Choose based on your secret backend:
|
||||||
|
# For Vault:
|
||||||
|
cp secretstore-vault.yaml ./
|
||||||
|
|
||||||
|
# For Kubernetes secrets:
|
||||||
|
cp secretstore-kubernetes.yaml ./
|
||||||
|
|
||||||
|
# Choose based on what you want to sync:
|
||||||
|
# For individual secret properties:
|
||||||
|
cp externalsecret-basic.yaml ./
|
||||||
|
|
||||||
|
# For entire secret objects:
|
||||||
|
cp externalsecret-extract.yaml ./
|
||||||
|
|
||||||
|
# For advanced templating:
|
||||||
|
cp externalsecret-advanced.yaml ./
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 3: Customize the files
|
||||||
|
|
||||||
|
Edit each file and replace the CHANGE markers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit secretstore
|
||||||
|
vim secretstore-vault.yaml
|
||||||
|
|
||||||
|
# Edit externalsecret
|
||||||
|
vim externalsecret-basic.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Key things to customize:
|
||||||
|
- Namespace (where your app runs)
|
||||||
|
- Vault server URL
|
||||||
|
- Vault secret paths
|
||||||
|
- Secret property names
|
||||||
|
- Refresh interval
|
||||||
|
|
||||||
|
## Step 4: Apply to your cluster
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f k8s/secrets-<your-app-name>/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 5: Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if the ExternalSecret synced successfully
|
||||||
|
kubectl get externalsecret -n <your-namespace>
|
||||||
|
|
||||||
|
# Check if the secret was created
|
||||||
|
kubectl get secret app-secrets -n <your-namespace>
|
||||||
|
|
||||||
|
# View the secret contents (be careful with sensitive data!)
|
||||||
|
kubectl get secret app-secrets -n <your-namespace> -o jsonpath='{.data}' | jq .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 6: Use in your Deployment
|
||||||
|
|
||||||
|
Reference the synced secret in your Deployment/StatefulSet/DaemonSet:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: app-secrets
|
||||||
|
```
|
||||||
|
|
||||||
|
See `deployment-example.yaml` for more usage patterns.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If the ExternalSecret doesn't sync:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
kubectl describe externalsecret app-secrets -n <your-namespace>
|
||||||
|
|
||||||
|
# Check operator logs
|
||||||
|
kubectl logs -n external-secrets deployment/external-secrets
|
||||||
|
|
||||||
|
# Verify SecretStore is reachable
|
||||||
|
kubectl describe secretstore vault-secretstore -n <your-namespace>
|
||||||
|
```
|
||||||
|
|
||||||
|
See `USAGE.md` in the external-secrets chart for detailed troubleshooting.
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
# Template ClusterSecretStore - Vault (Cluster-Wide)
|
||||||
|
#
|
||||||
|
# Use ClusterSecretStore if you want the store to be available cluster-wide.
|
||||||
|
# This is useful for shared secrets like TLS certificates or database credentials.
|
||||||
|
#
|
||||||
|
# Note: This should typically be created and managed by the infrastructure team,
|
||||||
|
# not individual applications.
|
||||||
|
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
metadata:
|
||||||
|
name: vault-cluster-store
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: "https://vault.example.com:8200" # CHANGE: Your Vault server URL
|
||||||
|
path: "secret" # CHANGE: Your secret path in Vault
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: "kubernetes"
|
||||||
|
role: "cluster-app-role" # CHANGE: Your cluster-wide Vault role
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
# Template: Deployment Using ExternalSecret
|
||||||
|
#
|
||||||
|
# This shows how to reference and use the synced Kubernetes Secret in a Deployment.
|
||||||
|
# Copy and customize this template in your application's k8s manifests.
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: my-app
|
||||||
|
namespace: default # CHANGE: Your application's namespace
|
||||||
|
labels:
|
||||||
|
app: my-app
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: my-app
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: my-app
|
||||||
|
spec:
|
||||||
|
serviceAccountName: my-app
|
||||||
|
|
||||||
|
containers:
|
||||||
|
- name: app
|
||||||
|
image: my-app:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
|
||||||
|
# Method 1: Import all secret keys as environment variables
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: app-secrets # CHANGE: Name of the ExternalSecret's target
|
||||||
|
|
||||||
|
# Method 2: Individual secret values as environment variables
|
||||||
|
env:
|
||||||
|
- name: DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: app-secrets # CHANGE: Name of the ExternalSecret's target
|
||||||
|
key: DATABASE_URL
|
||||||
|
|
||||||
|
- name: API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: app-secrets # CHANGE: Name of the ExternalSecret's target
|
||||||
|
key: API_KEY
|
||||||
|
|
||||||
|
# Method 3: Mount secret as files (useful for config files)
|
||||||
|
volumeMounts:
|
||||||
|
- name: app-secrets
|
||||||
|
mountPath: /etc/app/secrets
|
||||||
|
readOnly: true
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- containerPort: 8000
|
||||||
|
name: http
|
||||||
|
|
||||||
|
# Volume for mounting secrets
|
||||||
|
volumes:
|
||||||
|
- name: app-secrets
|
||||||
|
secret:
|
||||||
|
secretName: app-secrets # CHANGE: Name of the ExternalSecret's target
|
||||||
|
defaultMode: 0400 # Read-only for owner only
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
# Template ExternalSecret - With Advanced Templating
|
||||||
|
#
|
||||||
|
# This template demonstrates more advanced features:
|
||||||
|
# - Multiple secrets from different sources
|
||||||
|
# - Template transformations
|
||||||
|
# - Custom keys in the resulting Secret
|
||||||
|
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: app-secrets-advanced
|
||||||
|
namespace: default # CHANGE: Your application's namespace
|
||||||
|
spec:
|
||||||
|
refreshInterval: 30m
|
||||||
|
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secretstore
|
||||||
|
kind: SecretStore
|
||||||
|
|
||||||
|
target:
|
||||||
|
name: app-secrets-advanced
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
# Build a custom configuration file from secret values
|
||||||
|
data:
|
||||||
|
config.yaml: |
|
||||||
|
database:
|
||||||
|
host: "{{ .db_host }}"
|
||||||
|
port: {{ .db_port }}
|
||||||
|
username: "{{ .db_user }}"
|
||||||
|
password: "{{ .db_password }}"
|
||||||
|
api:
|
||||||
|
key: "{{ .api_key }}"
|
||||||
|
secret: "{{ .api_secret }}"
|
||||||
|
.env: |
|
||||||
|
DATABASE_URL=postgresql://{{ .db_user }}:{{ .db_password }}@{{ .db_host }}:{{ .db_port }}/myapp
|
||||||
|
API_KEY={{ .api_key }}
|
||||||
|
|
||||||
|
data:
|
||||||
|
# Database credentials
|
||||||
|
- secretKey: db_host
|
||||||
|
remoteRef:
|
||||||
|
key: databases/postgres # CHANGE
|
||||||
|
property: host
|
||||||
|
|
||||||
|
- secretKey: db_port
|
||||||
|
remoteRef:
|
||||||
|
key: databases/postgres # CHANGE
|
||||||
|
property: port
|
||||||
|
|
||||||
|
- secretKey: db_user
|
||||||
|
remoteRef:
|
||||||
|
key: databases/postgres # CHANGE
|
||||||
|
property: username
|
||||||
|
|
||||||
|
- secretKey: db_password
|
||||||
|
remoteRef:
|
||||||
|
key: databases/postgres # CHANGE
|
||||||
|
property: password
|
||||||
|
|
||||||
|
# API credentials
|
||||||
|
- secretKey: api_key
|
||||||
|
remoteRef:
|
||||||
|
key: my-app/api-keys # CHANGE
|
||||||
|
property: key
|
||||||
|
|
||||||
|
- secretKey: api_secret
|
||||||
|
remoteRef:
|
||||||
|
key: my-app/api-keys # CHANGE
|
||||||
|
property: secret
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
# Template ExternalSecret - Basic Configuration
|
||||||
|
#
|
||||||
|
# This template syncs secrets from Vault into a Kubernetes Secret.
|
||||||
|
# Copy this file to your `secrets-<repo-name>/` folder and customize.
|
||||||
|
#
|
||||||
|
# The secrets defined here will be synced into a Kubernetes Secret named "app-secrets"
|
||||||
|
# that your pods can mount or reference via environment variables.
|
||||||
|
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: app-secrets
|
||||||
|
namespace: default # CHANGE: Your application's namespace
|
||||||
|
spec:
|
||||||
|
# How often to sync secrets (shorter = more frequent updates)
|
||||||
|
refreshInterval: 1h
|
||||||
|
|
||||||
|
# Reference to the SecretStore (should be in the same namespace)
|
||||||
|
# or ClusterSecretStore (available cluster-wide)
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secretstore # CHANGE: Name of your SecretStore
|
||||||
|
kind: SecretStore # CHANGE: Use "ClusterSecretStore" if using cluster-wide store
|
||||||
|
|
||||||
|
# Target: where to create the synced Kubernetes Secret
|
||||||
|
target:
|
||||||
|
name: app-secrets # CHANGE: Name of the Secret to create
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
engineVersion: v2
|
||||||
|
# Template the secret data (optional transformation)
|
||||||
|
data:
|
||||||
|
DATABASE_URL: "{{ .db_url }}"
|
||||||
|
API_KEY: "{{ .api_key }}"
|
||||||
|
|
||||||
|
# Source: which secrets to fetch from the backend
|
||||||
|
data:
|
||||||
|
- secretKey: db_url # Name used in template and Secret
|
||||||
|
remoteRef:
|
||||||
|
key: my-app/database # CHANGE: Path in Vault
|
||||||
|
property: url # CHANGE: Property within that Vault key
|
||||||
|
|
||||||
|
- secretKey: api_key # Name used in template and Secret
|
||||||
|
remoteRef:
|
||||||
|
key: my-app/api # CHANGE: Path in Vault
|
||||||
|
property: token # CHANGE: Property within that Vault key
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
# Template ExternalSecret - Full Secret Object
|
||||||
|
#
|
||||||
|
# This template syncs an entire secret object from Vault.
|
||||||
|
# Use this when you have a secret object with multiple properties
|
||||||
|
# and want to import all of them at once.
|
||||||
|
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: app-all-secrets
|
||||||
|
namespace: default # CHANGE: Your application's namespace
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secretstore # CHANGE: Name of your SecretStore
|
||||||
|
kind: SecretStore
|
||||||
|
|
||||||
|
target:
|
||||||
|
name: app-all-secrets
|
||||||
|
creationPolicy: Owner
|
||||||
|
|
||||||
|
# Use dataFrom to import an entire secret object
|
||||||
|
dataFrom:
|
||||||
|
- extract:
|
||||||
|
key: my-app/all-secrets # CHANGE: Path to the secret object in Vault
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
# Template SecretStore - Kubernetes Backend
|
||||||
|
#
|
||||||
|
# Use this if you want to sync secrets from another Kubernetes namespace
|
||||||
|
# or use Kubernetes as your secret backend.
|
||||||
|
#
|
||||||
|
# Copy this file to your `secrets-<repo-name>/` folder and customize.
|
||||||
|
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: SecretStore
|
||||||
|
metadata:
|
||||||
|
name: k8s-secretstore
|
||||||
|
namespace: default # CHANGE: Your application's namespace
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
kubernetes:
|
||||||
|
remoteNamespace: "secrets-management" # CHANGE: Namespace containing source secrets
|
||||||
|
auth:
|
||||||
|
serviceAccount:
|
||||||
|
name: external-secrets-reader # CHANGE: ServiceAccount name for reading
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
# Template SecretStore - Vault Backend
|
||||||
|
#
|
||||||
|
# Copy this file to your `secrets-<repo-name>/` folder and customize the values.
|
||||||
|
# Replace:
|
||||||
|
# - vault.example.com with your actual Vault server
|
||||||
|
# - my-app-role with the role configured in Vault
|
||||||
|
# - default with your application's namespace
|
||||||
|
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: SecretStore
|
||||||
|
metadata:
|
||||||
|
name: vault-secretstore
|
||||||
|
namespace: default # CHANGE: Your application's namespace
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: "https://vault.example.com:8200" # CHANGE: Your Vault server URL
|
||||||
|
path: "secret" # CHANGE: Your secret path in Vault
|
||||||
|
auth:
|
||||||
|
kubernetes:
|
||||||
|
mountPath: "kubernetes"
|
||||||
|
role: "my-app-role" # CHANGE: Your Vault auth role
|
||||||
@ -10,4 +10,13 @@ externalSecrets:
|
|||||||
data:
|
data:
|
||||||
- secretKey: oidc.keycloak.clientSecret
|
- secretKey: oidc.keycloak.clientSecret
|
||||||
remoteKey: infra/argocd
|
remoteKey: infra/argocd
|
||||||
property: client_secret
|
property: client_secret
|
||||||
|
|
||||||
|
- name: renovate-secret
|
||||||
|
namespace: infra
|
||||||
|
targetName: renovate-secret
|
||||||
|
creationPolicy: Merge
|
||||||
|
data:
|
||||||
|
- secretKey: gitea.token
|
||||||
|
remoteKey: infra/renovate
|
||||||
|
property: gitea_token
|
||||||
Loading…
x
Reference in New Issue
Block a user