Vault SSO Stack
The Vault SSO stack provides secure identity-backed secret access using HashiCorp Vault with Single Sign-On (SSO) integration. This stack deploys a complete Vault solution with External Secrets Operator for seamless Kubernetes integration.
Overview
The Vault SSO stack enables organizations to:
- Centralize secret management with HashiCorp Vault
- Implement SSO authentication using OIDC/SAML providers
- Integrate with Kubernetes via External Secrets Operator
- Maintain security best practices with proper authentication and authorization
Key Features
- ✅ Cloud Agnostic - Works on any Kubernetes cluster
- ✅ Complete Solution - Deploys both Vault and External Secrets Operator
- ✅ SSO Integration - Supports OIDC and SAML authentication
- ✅ Kubernetes Native - Uses ExternalSecret CRDs for integration
- ✅ Production Ready - Follows security best practices
Architecture
The Vault SSO stack consists of several components working together:
Component Details
-
Vault Server - Deployed in-cluster using the official HashiCorp Helm chart
- Handles SSO authentication (OIDC/SAML)
- Stores and manages secrets
- Provides REST API and UI
-
External Secrets Operator - Manages Kubernetes secret synchronization
- Connects to Vault via SecretStore
- Creates Kubernetes secrets from Vault data
- Handles automatic refresh and updates
-
SecretStore - Defines the connection to Vault
- Configures authentication method
- Specifies Vault server endpoint
- Sets up access policies
-
ExternalSecret - Defines which secrets to fetch
- Maps Vault paths to Kubernetes secrets
- Configures refresh intervals
- Specifies target namespaces
Prerequisites
Before deploying the Vault SSO stack, ensure you have:
- Kubernetes cluster with Helm support
- SSO provider (OIDC/SAML) configured and accessible
- kubectl configured to access your cluster
- Vault CLI (optional, for administration)
SSO Provider Setup
You'll need to configure your SSO provider (e.g., Google, Okta, Auth0) with:
- Client ID and Client Secret
- Redirect URI:
https://your-vault-domain/ui/vault/auth/oidc/oidc/callback
- Scopes:
openid
,email
,profile
Installation
1. Deploy the Stack
Apply the Vault SSO stack using your preferred method:
# Using kubectl and kustomize
kubectl apply -k kubezero/stacks/vault-sso
# Or using Argo CD (if configured)
kubectl apply -f - <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: vault-sso
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/kubezero
targetRevision: main
path: kubezero/stacks/vault-sso
destination:
server: https://kubernetes.default.svc
namespace: vault
syncPolicy:
automated:
prune: true
selfHeal: true
EOF
2. Initialize Vault
After deployment, Vault needs to be initialized and unsealed:
# Port forward to access Vault
kubectl port-forward -n vault svc/vault 8200:8200
# In another terminal, initialize Vault
export VAULT_ADDR=http://localhost:8200
vault operator init
# Save the output - you'll need the keys and root token
# Unseal Vault (repeat 3 times with different keys)
vault operator unseal
# Login with root token
vault login
3. Configure SSO Authentication
Enable and configure OIDC authentication:
# Enable OIDC auth method
vault auth enable oidc
# Configure OIDC (replace with your provider details)
vault write auth/oidc/config \
oidc_discovery_url="https://accounts.google.com/.well-known/openid_configuration" \
oidc_client_id="your-client-id" \
oidc_client_secret="your-client-secret" \
default_role="default"
# Create OIDC role
vault write auth/oidc/role/default \
bound_audiences="your-client-id" \
allowed_redirect_uris="https://your-vault-domain/ui/vault/auth/oidc/oidc/callback" \
user_claim="email" \
policies="default"
4. Configure External Secrets Integration
Set up Kubernetes authentication for External Secrets Operator:
# Enable Kubernetes auth
vault auth enable kubernetes
# Create a role for External Secrets
vault write auth/kubernetes/role/external-secrets \
bound_service_account_names=external-secrets \
bound_service_account_namespaces=external-secrets \
policies=external-secrets-policy \
ttl=1h
# Create a policy for External Secrets
vault policy write external-secrets-policy -<<EOF
path "secret/data/*" {
capabilities = ["read"]
}
EOF
Configuration
Vault Configuration
The Vault module can be customized by modifying the Helm values in kubezero/modules/vault/helm-chart/helm-chart.yaml
:
valuesInline:
server:
enabled: true
ha:
enabled: true # Enable high availability
replicas: 3
# Customize storage backend
# storage:
# file:
# path: /vault/data
ui:
enabled: true
serviceType: LoadBalancer # For external access
SecretStore Configuration
The SecretStore connects External Secrets Operator to Vault:
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-sso
namespace: external-secrets
spec:
provider:
vault:
server: "http://vault.vault.svc:8200"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "external-secrets"
serviceAccountRef:
name: external-secrets
namespace: external-secrets
ExternalSecret Examples
Basic Secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
namespace: my-app
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-sso
kind: SecretStore
target:
name: database-credentials
data:
- secretKey: username
remoteRef:
key: database/credentials
property: username
- secretKey: password
remoteRef:
key: database/credentials
property: password
Application Secrets
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
namespace: production
spec:
refreshInterval: 30m
secretStoreRef:
name: vault-sso
kind: SecretStore
target:
name: app-secrets
creationPolicy: Owner
data:
- secretKey: api-key
remoteRef:
key: apps/my-app
property: api_key
- secretKey: jwt-secret
remoteRef:
key: apps/my-app
property: jwt_secret
- secretKey: database-url
remoteRef:
key: apps/my-app
property: database_url
Usage
Accessing Vault UI
-
Port forward to access the Vault UI:
kubectl port-forward -n vault svc/vault 8200:8200
-
Open browser and navigate to
http://localhost:8200
-
Login using your SSO provider
Managing Secrets
Via Vault UI
- Navigate to the Secrets tab
- Click Create secret
- Enter the path (e.g.,
secret/apps/my-app
) - Add key-value pairs
- Click Save
Via Vault CLI
# Store a secret
vault kv put secret/apps/my-app \
api_key="your-api-key" \
database_url="postgresql://user:pass@host:5432/db"
# Retrieve a secret
vault kv get secret/apps/my-app
# List secrets
vault kv list secret/apps/
Monitoring
Check the status of External Secrets:
# List ExternalSecrets
kubectl get externalsecrets -A
# Check ExternalSecret status
kubectl describe externalsecret database-credentials -n my-app
# View External Secrets Operator logs
kubectl logs -n external-secrets deployment/external-secrets
Security Considerations
Authentication
- Use strong SSO providers with MFA enabled
- Regularly rotate OIDC client secrets
- Limit redirect URIs to trusted domains
- Use least privilege policies for Vault roles
Authorization
- Create specific policies for different applications
- Use namespace isolation for ExternalSecrets
- Regularly audit Vault access logs
- Implement secret rotation policies
Network Security
- Use TLS for Vault communication
- Restrict network access to Vault services
- Use service mesh for internal communication
- Monitor network traffic for anomalies
Troubleshooting
Common Issues
Vault Unsealed
# Check Vault status
kubectl get pods -n vault
kubectl logs -n vault deployment/vault
# Unseal Vault
vault operator unseal
External Secrets Not Syncing
# Check SecretStore status
kubectl describe secretstore vault-sso -n external-secrets
# Verify Vault connectivity
kubectl exec -n external-secrets deployment/external-secrets -- \
curl -s http://vault.vault.svc:8200/v1/sys/health
# Check ExternalSecret status
kubectl describe externalsecret <name> -n <namespace>
SSO Authentication Issues
-
Verify OIDC configuration:
vault read auth/oidc/config
-
Check redirect URIs match your Vault domain
-
Verify client credentials are correct
-
Check Vault logs for authentication errors
Debug Commands
# Check Vault status
vault status
# List auth methods
vault auth list
# Test OIDC configuration
vault read auth/oidc/config
# Check Kubernetes auth
vault read auth/kubernetes/role/external-secrets
# View Vault policies
vault policy list
vault policy read external-secrets-policy
Best Practices
Secret Management
- Use structured paths (e.g.,
secret/apps/<app-name>
) - Implement secret rotation policies
- Use different namespaces for different environments
- Regularly audit secret access
Access Control
- Create specific roles for each application
- Use namespace-based access control
- Implement time-based access (TTL)
- Regularly review and update policies
Monitoring and Alerting
- Monitor Vault metrics and logs
- Set up alerts for failed authentication
- Track secret access patterns
- Monitor External Secrets sync status