-
Notifications
You must be signed in to change notification settings - Fork 324
Open
Open
Copy link
Labels
devopsDevOps activities (containers, automation, deployment, makefiles, etc)DevOps activities (containers, automation, deployment, makefiles, etc)enhancementNew feature or requestNew feature or requestsecurityImproves securityImproves securitytriageIssues / Features awaiting triageIssues / Features awaiting triage
Milestone
Description
🔐 FEATURE: Enterprise Secrets Management Integration
Summary: Integrate enterprise secrets management solutions (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) into the MCP Gateway Helm chart. This feature enables dynamic secret rotation, eliminates hardcoded secrets, and provides centralized secret lifecycle management for production deployments.
- Add configurable support to the helm chart
- Add optional Vault deployment.
- Optional: add support for Vault to docker-compose.yaml to support development & testing.
Implementation
1. Update values.yaml
with Secrets Management Configuration
# In helm/mcpgateway/values.yaml
# ... existing configuration ...
# ===================================
# Enterprise Secrets Management
# ===================================
secretsManagement:
# Enable external secrets management
enabled: false
# Secret provider: vault, aws, azure, kubernetes
provider: "vault"
# Secret refresh interval (seconds)
refreshInterval: 300
# Enable secret rotation
autoRotation:
enabled: true
checkInterval: 3600 # 1 hour
# HashiCorp Vault Configuration
vault:
enabled: false
address: "https://vault.example.com:8200"
authMethod: "kubernetes" # kubernetes, token, approle
role: "mcpgateway"
mount: "kubernetes"
namespace: "default"
secretPath: "secret/data/mcpgateway"
# TLS Configuration
tls:
enabled: true
caCert: "" # Base64 encoded CA certificate
skipVerify: false
# Token auth (if authMethod: token)
token:
secretName: "vault-token"
secretKey: "token"
# AppRole auth (if authMethod: approle)
appRole:
roleId: ""
secretId:
secretName: "vault-approle"
secretKey: "secret-id"
# AWS Secrets Manager Configuration
aws:
enabled: false
region: "us-east-1"
secretPrefix: "mcpgateway/"
# Authentication via IRSA or explicit credentials
auth:
# Use IRSA (recommended)
useIRSA: true
serviceAccountAnnotations: {}
# Or use explicit credentials
accessKeyId:
secretName: "aws-credentials"
secretKey: "access-key-id"
secretAccessKey:
secretName: "aws-credentials"
secretKey: "secret-access-key"
# Azure Key Vault Configuration
azure:
enabled: false
vaultName: "mcpgateway-keyvault"
tenantId: ""
# Authentication methods
auth:
# Use Managed Identity (recommended)
useManagedIdentity: true
clientId: "" # For user-assigned managed identity
# Or use Service Principal
clientSecret:
secretName: "azure-credentials"
secretKey: "client-secret"
# Secret Mappings - which secrets to fetch
secrets:
# Database credentials
database:
enabled: true
source: "database/creds" # Path in secret store
target: "DATABASE_URL" # Environment variable name
format: "postgresql://{{username}}:{{password}}@{{host}}:{{port}}/{{database}}"
# JWT Secret
jwtSecret:
enabled: true
source: "jwt/secret"
target: "JWT_SECRET"
# OAuth Credentials
oauth:
google:
enabled: false
clientId:
source: "oauth/google/client-id"
target: "GOOGLE_CLIENT_ID"
clientSecret:
source: "oauth/google/client-secret"
target: "GOOGLE_CLIENT_SECRET"
github:
enabled: false
clientId:
source: "oauth/github/client-id"
target: "GITHUB_CLIENT_ID"
clientSecret:
source: "oauth/github/client-secret"
target: "GITHUB_CLIENT_SECRET"
# API Keys
apiKeys:
openai:
enabled: false
source: "api-keys/openai"
target: "OPENAI_API_KEY"
anthropic:
enabled: false
source: "api-keys/anthropic"
target: "ANTHROPIC_API_KEY"
# Custom secrets
custom: []
# - name: "custom-secret"
# source: "path/to/secret"
# target: "CUSTOM_ENV_VAR"
# format: "Bearer {{value}}" # Optional formatting
# External Secrets Operator (if using)
externalSecrets:
# Install External Secrets Operator as dependency
enabled: false
# External Secrets Operator configuration
operator:
installCRDs: true
# Secret Store configuration
secretStore:
name: "mcpgateway-secret-store"
# Refresh interval for ExternalSecret resources
refreshInterval: "1m"
2. Create Secrets Provider Templates
# Create helm/mcpgateway/templates/secrets-provider.yaml
{{- if .Values.secretsManagement.enabled }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mcpgateway.fullname" . }}-secrets-config
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
data:
provider: {{ .Values.secretsManagement.provider | quote }}
refresh-interval: {{ .Values.secretsManagement.refreshInterval | quote }}
auto-rotation-enabled: {{ .Values.secretsManagement.autoRotation.enabled | quote }}
{{- if eq .Values.secretsManagement.provider "vault" }}
vault-address: {{ .Values.secretsManagement.vault.address | quote }}
vault-auth-method: {{ .Values.secretsManagement.vault.authMethod | quote }}
vault-role: {{ .Values.secretsManagement.vault.role | quote }}
vault-mount: {{ .Values.secretsManagement.vault.mount | quote }}
vault-namespace: {{ .Values.secretsManagement.vault.namespace | quote }}
vault-secret-path: {{ .Values.secretsManagement.vault.secretPath | quote }}
{{- end }}
{{- if eq .Values.secretsManagement.provider "aws" }}
aws-region: {{ .Values.secretsManagement.aws.region | quote }}
aws-secret-prefix: {{ .Values.secretsManagement.aws.secretPrefix | quote }}
{{- end }}
{{- if eq .Values.secretsManagement.provider "azure" }}
azure-vault-name: {{ .Values.secretsManagement.azure.vaultName | quote }}
azure-tenant-id: {{ .Values.secretsManagement.azure.tenantId | quote }}
{{- end }}
---
{{- if .Values.externalSecrets.enabled }}
# External Secrets Operator SecretStore
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: {{ include "mcpgateway.fullname" . }}-secret-store
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
spec:
provider:
{{- if eq .Values.secretsManagement.provider "vault" }}
vault:
server: {{ .Values.secretsManagement.vault.address | quote }}
path: {{ .Values.secretsManagement.vault.secretPath | quote }}
version: "v2"
{{- if .Values.secretsManagement.vault.namespace }}
namespace: {{ .Values.secretsManagement.vault.namespace | quote }}
{{- end }}
auth:
{{- if eq .Values.secretsManagement.vault.authMethod "kubernetes" }}
kubernetes:
mountPath: {{ .Values.secretsManagement.vault.mount | quote }}
role: {{ .Values.secretsManagement.vault.role | quote }}
serviceAccountRef:
name: {{ include "mcpgateway.serviceAccountName" . }}
{{- else if eq .Values.secretsManagement.vault.authMethod "token" }}
tokenSecretRef:
name: {{ .Values.secretsManagement.vault.token.secretName | quote }}
key: {{ .Values.secretsManagement.vault.token.secretKey | quote }}
{{- else if eq .Values.secretsManagement.vault.authMethod "approle" }}
appRole:
path: "approle"
roleId: {{ .Values.secretsManagement.vault.appRole.roleId | quote }}
secretRef:
name: {{ .Values.secretsManagement.vault.appRole.secretId.secretName | quote }}
key: {{ .Values.secretsManagement.vault.appRole.secretId.secretKey | quote }}
{{- end }}
{{- if .Values.secretsManagement.vault.tls.enabled }}
caBundle: {{ .Values.secretsManagement.vault.tls.caCert | quote }}
{{- end }}
{{- else if eq .Values.secretsManagement.provider "aws" }}
aws:
service: SecretsManager
region: {{ .Values.secretsManagement.aws.region | quote }}
{{- if not .Values.secretsManagement.aws.auth.useIRSA }}
auth:
secretRef:
accessKeyIDSecretRef:
name: {{ .Values.secretsManagement.aws.auth.accessKeyId.secretName | quote }}
key: {{ .Values.secretsManagement.aws.auth.accessKeyId.secretKey | quote }}
secretAccessKeySecretRef:
name: {{ .Values.secretsManagement.aws.auth.secretAccessKey.secretName | quote }}
key: {{ .Values.secretsManagement.aws.auth.secretAccessKey.secretKey | quote }}
{{- end }}
{{- else if eq .Values.secretsManagement.provider "azure" }}
azurekv:
vaultUrl: "https://{{ .Values.secretsManagement.azure.vaultName }}.vault.azure.net"
tenantId: {{ .Values.secretsManagement.azure.tenantId | quote }}
authType: {{ if .Values.secretsManagement.azure.auth.useManagedIdentity }}"ManagedIdentity"{{ else }}"ServicePrincipal"{{ end }}
{{- if .Values.secretsManagement.azure.auth.useManagedIdentity }}
identityId: {{ .Values.secretsManagement.azure.auth.clientId | quote }}
{{- else }}
authSecretRef:
clientId:
name: {{ .Values.secretsManagement.azure.auth.clientSecret.secretName | quote }}
key: "client-id"
clientSecret:
name: {{ .Values.secretsManagement.azure.auth.clientSecret.secretName | quote }}
key: {{ .Values.secretsManagement.azure.auth.clientSecret.secretKey | quote }}
{{- end }}
{{- end }}
---
# External Secret Resources
{{- if .Values.secretsManagement.secrets.database.enabled }}
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "mcpgateway.fullname" . }}-database-secret
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
spec:
refreshInterval: {{ .Values.externalSecrets.refreshInterval }}
secretStoreRef:
name: {{ include "mcpgateway.fullname" . }}-secret-store
kind: SecretStore
target:
name: {{ include "mcpgateway.fullname" . }}-database-secret
creationPolicy: Owner
data:
- secretKey: database-url
remoteRef:
key: {{ .Values.secretsManagement.secrets.database.source | quote }}
{{- end }}
{{- if .Values.secretsManagement.secrets.jwtSecret.enabled }}
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "mcpgateway.fullname" . }}-jwt-secret
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
spec:
refreshInterval: {{ .Values.externalSecrets.refreshInterval }}
secretStoreRef:
name: {{ include "mcpgateway.fullname" . }}-secret-store
kind: SecretStore
target:
name: {{ include "mcpgateway.fullname" . }}-jwt-secret
creationPolicy: Owner
data:
- secretKey: jwt-secret
remoteRef:
key: {{ .Values.secretsManagement.secrets.jwtSecret.source | quote }}
{{- end }}
{{- range .Values.secretsManagement.secrets.custom }}
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "mcpgateway.fullname" $ }}-{{ .name }}
labels:
{{- include "mcpgateway.labels" $ | nindent 4 }}
spec:
refreshInterval: {{ $.Values.externalSecrets.refreshInterval }}
secretStoreRef:
name: {{ include "mcpgateway.fullname" $ }}-secret-store
kind: SecretStore
target:
name: {{ include "mcpgateway.fullname" $ }}-{{ .name }}
creationPolicy: Owner
data:
- secretKey: value
remoteRef:
key: {{ .source | quote }}
{{- end }}
{{- else }}
# Native secret management init container will handle secrets
{{- end }}
{{- end }}
3. Create Init Container for Secret Injection
# Create helm/mcpgateway/templates/secret-injector-configmap.yaml
{{- if and .Values.secretsManagement.enabled (not .Values.externalSecrets.enabled) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mcpgateway.fullname" . }}-secret-injector
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
data:
secret-injector.py: |
#!/usr/bin/env python3
import os
import sys
import json
import time
import base64
from typing import Dict, Any
# Provider implementations
class VaultProvider:
def __init__(self, config: Dict[str, str]):
import hvac
self.client = hvac.Client(
url=config['vault-address'],
namespace=config.get('vault-namespace')
)
auth_method = config['vault-auth-method']
if auth_method == 'kubernetes':
with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f:
jwt = f.read()
self.client.auth.kubernetes.login(
role=config['vault-role'],
jwt=jwt,
mount_point=config['vault-mount']
)
elif auth_method == 'token':
self.client.token = os.environ.get('VAULT_TOKEN')
def get_secret(self, path: str) -> Dict[str, Any]:
response = self.client.secrets.kv.v2.read_secret_version(
path=path,
mount_point=self.config['vault-secret-path'].split('/')[0]
)
return response['data']['data']
class AWSProvider:
def __init__(self, config: Dict[str, str]):
import boto3
self.client = boto3.client(
'secretsmanager',
region_name=config['aws-region']
)
self.prefix = config['aws-secret-prefix']
def get_secret(self, name: str) -> str:
secret_name = f"{self.prefix}{name}"
response = self.client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])
class AzureProvider:
def __init__(self, config: Dict[str, str]):
from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential
vault_url = f"https://{config['azure-vault-name']}.vault.azure.net"
credential = DefaultAzureCredential()
self.client = SecretClient(vault_url=vault_url, credential=credential)
def get_secret(self, name: str) -> str:
secret = self.client.get_secret(name)
return secret.value
# Main execution
def main():
# Load configuration
config = {}
config_dir = '/etc/mcpgateway/secrets-config'
for filename in os.listdir(config_dir):
with open(os.path.join(config_dir, filename), 'r') as f:
config[filename] = f.read().strip()
# Initialize provider
provider_name = config['provider']
if provider_name == 'vault':
provider = VaultProvider(config)
elif provider_name == 'aws':
provider = AWSProvider(config)
elif provider_name == 'azure':
provider = AzureProvider(config)
else:
raise ValueError(f"Unknown provider: {provider_name}")
# Load secret mappings
with open('/etc/mcpgateway/secret-mappings/mappings.json', 'r') as f:
mappings = json.load(f)
# Fetch and write secrets
env_vars = {}
for mapping in mappings:
if mapping.get('enabled', True):
try:
secret_value = provider.get_secret(mapping['source'])
# Format if needed
if 'format' in mapping:
import re
formatted = mapping['format']
for key, value in secret_value.items():
formatted = formatted.replace(f"{{{{{key}}}}}", str(value))
env_vars[mapping['target']] = formatted
else:
env_vars[mapping['target']] = secret_value
print(f"✓ Fetched secret: {mapping['source']}")
except Exception as e:
print(f"✗ Failed to fetch {mapping['source']}: {e}")
if mapping.get('required', True):
sys.exit(1)
# Write to shared volume
with open('/shared/secrets/env', 'w') as f:
for key, value in env_vars.items():
f.write(f"export {key}='{value}'\n")
print(f"Successfully injected {len(env_vars)} secrets")
if __name__ == '__main__':
main()
{{- end }}
4. Update Deployment to Use Secrets
# Update helm/mcpgateway/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mcpgateway.fullname" . }}
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
spec:
# ... existing spec ...
template:
metadata:
annotations:
{{- if .Values.secretsManagement.enabled }}
checksum/secrets-config: {{ include (print $.Template.BasePath "/secrets-provider.yaml") . | sha256sum }}
{{- end }}
spec:
{{- if .Values.secretsManagement.enabled }}
serviceAccountName: {{ include "mcpgateway.serviceAccountName" . }}
{{- end }}
{{- if and .Values.secretsManagement.enabled (not .Values.externalSecrets.enabled) }}
initContainers:
- name: secret-injector
image: python:3.11-slim
command: ["/bin/bash", "-c"]
args:
- |
pip install hvac boto3 azure-keyvault-secrets azure-identity
python /scripts/secret-injector.py
env:
{{- if eq .Values.secretsManagement.provider "vault" }}
{{- if eq .Values.secretsManagement.vault.authMethod "token" }}
- name: VAULT_TOKEN
valueFrom:
secretKeyRef:
name: {{ .Values.secretsManagement.vault.token.secretName }}
key: {{ .Values.secretsManagement.vault.token.secretKey }}
{{- end }}
{{- end }}
volumeMounts:
- name: secret-injector-script
mountPath: /scripts
- name: secrets-config
mountPath: /etc/mcpgateway/secrets-config
- name: secret-mappings
mountPath: /etc/mcpgateway/secret-mappings
- name: shared-secrets
mountPath: /shared/secrets
{{- end }}
containers:
- name: {{ .Chart.Name }}
# ... existing container spec ...
{{- if .Values.secretsManagement.enabled }}
{{- if .Values.externalSecrets.enabled }}
# Use External Secrets
envFrom:
{{- if .Values.secretsManagement.secrets.database.enabled }}
- secretRef:
name: {{ include "mcpgateway.fullname" . }}-database-secret
{{- end }}
{{- if .Values.secretsManagement.secrets.jwtSecret.enabled }}
- secretRef:
name: {{ include "mcpgateway.fullname" . }}-jwt-secret
{{- end }}
{{- range .Values.secretsManagement.secrets.custom }}
- secretRef:
name: {{ include "mcpgateway.fullname" $ }}-{{ .name }}
{{- end }}
{{- else }}
# Use init container injected secrets
command: ["/bin/bash", "-c"]
args:
- |
source /shared/secrets/env
exec /app/mcpgateway
volumeMounts:
- name: shared-secrets
mountPath: /shared/secrets
readOnly: true
{{- end }}
{{- end }}
volumes:
{{- if and .Values.secretsManagement.enabled (not .Values.externalSecrets.enabled) }}
- name: secret-injector-script
configMap:
name: {{ include "mcpgateway.fullname" . }}-secret-injector
defaultMode: 0755
- name: secrets-config
configMap:
name: {{ include "mcpgateway.fullname" . }}-secrets-config
- name: secret-mappings
configMap:
name: {{ include "mcpgateway.fullname" . }}-secret-mappings
- name: shared-secrets
emptyDir: {}
{{- end }}
5. Create ServiceAccount with Proper Permissions
# Update helm/mcpgateway/templates/serviceaccount.yaml
{{- if and .Values.serviceAccount.create .Values.secretsManagement.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "mcpgateway.serviceAccountName" . }}
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if and .Values.secretsManagement.enabled (eq .Values.secretsManagement.provider "aws") .Values.secretsManagement.aws.auth.useIRSA }}
annotations:
eks.amazonaws.com/role-arn: {{ .Values.secretsManagement.aws.auth.serviceAccountAnnotations.roleArn }}
{{- end }}
{{- if and .Values.secretsManagement.enabled (eq .Values.secretsManagement.provider "azure") .Values.secretsManagement.azure.auth.useManagedIdentity }}
annotations:
azure.workload.identity/client-id: {{ .Values.secretsManagement.azure.auth.clientId }}
{{- end }}
automountServiceAccountToken: true
{{- end }}
6. Add Chart Dependencies
# Update helm/mcpgateway/Chart.yaml
apiVersion: v2
name: mcpgateway
description: Enterprise MCP Gateway with Secrets Management
type: application
version: 0.8.0
appVersion: "0.8.0"
dependencies:
{{- if .Values.externalSecrets.enabled }}
- name: external-secrets
version: "0.9.x"
repository: https://charts.external-secrets.io
condition: externalSecrets.enabled
{{- end }}
7. Create Examples Directory
# Create helm/mcpgateway/examples/secrets-management/vault-example.yaml
secretsManagement:
enabled: true
provider: "vault"
refreshInterval: 300
vault:
enabled: true
address: "https://vault.mycompany.com:8200"
authMethod: "kubernetes"
role: "mcpgateway-prod"
mount: "kubernetes-prod"
namespace: "production"
secretPath: "secret/data/mcpgateway"
tls:
enabled: true
caCert: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
secrets:
database:
enabled: true
source: "database/prod/creds"
target: "DATABASE_URL"
format: "postgresql://{{username}}:{{password}}@prod-db.internal:5432/mcpgateway"
jwtSecret:
enabled: true
source: "security/jwt-secret"
target: "JWT_SECRET"
# Create helm/mcpgateway/examples/secrets-management/aws-example.yaml
secretsManagement:
enabled: true
provider: "aws"
aws:
enabled: true
region: "us-west-2"
secretPrefix: "prod/mcpgateway/"
auth:
useIRSA: true
serviceAccountAnnotations:
roleArn: "arn:aws:iam::123456789012:role/mcpgateway-secrets-reader"
secrets:
database:
enabled: true
source: "rds-credentials"
target: "DATABASE_URL"
8. Create Secret Mappings ConfigMap
# Create helm/mcpgateway/templates/secret-mappings-configmap.yaml
{{- if and .Values.secretsManagement.enabled (not .Values.externalSecrets.enabled) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mcpgateway.fullname" . }}-secret-mappings
labels:
{{- include "mcpgateway.labels" . | nindent 4 }}
data:
mappings.json: |
[
{{- $first := true }}
{{- range $key, $value := .Values.secretsManagement.secrets }}
{{- if and (kindIs "map" $value) $value.enabled }}
{{- if not $first }},{{- end }}
{{- $first = false }}
{
"name": {{ $key | quote }},
"source": {{ $value.source | quote }},
"target": {{ $value.target | quote }}
{{- if $value.format }},
"format": {{ $value.format | quote }}
{{- end }}
{{- if hasKey $value "required" }},
"required": {{ $value.required }}
{{- end }}
}
{{- else if kindIs "map" $value }}
{{- range $subKey, $subValue := $value }}
{{- if and (kindIs "map" $subValue) $subValue.enabled }}
{{- if not $first }},{{- end }}
{{- $first = false }}
{
"name": {{ printf "%s-%s" $key $subKey | quote }},
"source": {{ $subValue.source | quote }},
"target": {{ $subValue.target | quote }}
{{- if $subValue.format }},
"format": {{ $subValue.format | quote }}
{{- end }}
}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- range .Values.secretsManagement.secrets.custom }}
{{- if not $first }},{{- end }}
{{- $first = false }}
{
"name": {{ .name | quote }},
"source": {{ .source | quote }},
"target": {{ .target | quote }}
{{- if .format }},
"format": {{ .format | quote }}
{{- end }}
}
{{- end }}
]
{{- end }}
Testing
1. Test with HashiCorp Vault
# Deploy with Vault integration
helm upgrade --install mcpgateway ./helm/mcpgateway \
-f examples/secrets-management/vault-example.yaml \
--namespace mcpgateway
# Verify secrets are injected
kubectl exec -n mcpgateway deployment/mcpgateway -- env | grep -E "(DATABASE_URL|JWT_SECRET)"
2. Test with AWS Secrets Manager
# Create IRSA role first
eksctl create iamserviceaccount \
--cluster=my-cluster \
--namespace=mcpgateway \
--name=mcpgateway \
--role-name=MCPGatewaySecretsReader \
--attach-policy-arn=arn:aws:iam::aws:policy/SecretsManagerReadWrite \
--approve
# Deploy with AWS integration
helm upgrade --install mcpgateway ./helm/mcpgateway \
-f examples/secrets-management/aws-example.yaml
3. Test Secret Rotation
# Update secret in provider
vault kv put secret/mcpgateway/jwt-secret value="new-secret-value"
# Wait for refresh interval
sleep 300
# Verify pod restarted with new secret
kubectl get pods -n mcpgateway -w
Documentation
README Addition
## Enterprise Secrets Management
MCP Gateway supports integration with enterprise secret management solutions:
- **HashiCorp Vault**: Dynamic secrets with automatic rotation
- **AWS Secrets Manager**: Native AWS integration with IRSA support
- **Azure Key Vault**: Managed identity and service principal auth
- **External Secrets Operator**: Kubernetes-native secret synchronization
### Quick Start
1. **Enable secrets management**:
```yaml
secretsManagement:
enabled: true
provider: "vault" # or "aws", "azure"
-
Configure your provider (see examples directory)
-
Map your secrets:
secrets: database: enabled: true source: "path/to/secret" target: "DATABASE_URL"
Benefits
- No hardcoded secrets: All sensitive data stored in external systems
- Automatic rotation: Secrets refreshed without pod restarts
- Audit trail: Complete visibility of secret access
- Compliance: Meet enterprise security requirements
## Security Benefits
1. **Centralized Management**: Single source of truth for all secrets
2. **Automatic Rotation**: Secrets updated without manual intervention
3. **Audit Compliance**: Full audit trail of secret access
4. **Zero Trust**: No secrets stored in Kubernetes or container images
5. **Fine-grained Access**: Role-based secret access policies
6. **Encryption at Rest**: Enterprise-grade encryption for stored secrets
Metadata
Metadata
Assignees
Labels
devopsDevOps activities (containers, automation, deployment, makefiles, etc)DevOps activities (containers, automation, deployment, makefiles, etc)enhancementNew feature or requestNew feature or requestsecurityImproves securityImproves securitytriageIssues / Features awaiting triageIssues / Features awaiting triage