Design Document: Central Secret Store
Overview
The Central Secret Store system provides centralized, automated secret management and distribution across the Kubernetes platform using External Secrets Operator (ESO). The system maintains a single source of truth for all platform credentials while automatically distributing appropriately formatted secrets to namespaces based on their requirements.
Architecture
The system follows a hub-and-spoke architecture where:
- Central Hub: A dedicated
central-secret-storenamespace contains master secrets - Distribution Layer: External Secrets Operator with ClusterExternalSecret resources
- Target Spokes: Application namespaces receive formatted secrets based on labels
- Access Control: RBAC ensures secure access to central credentials
graph TB subgraph "Central Secret Store Namespace" CS[Central Secrets] ESO[External Secrets Operator] end subgraph "Distribution Layer" CES1[ClusterExternalSecret: Docker Registry] CES2[ClusterExternalSecret: Git Credentials] CES3[ClusterExternalSecret: OAuth] end subgraph "Target Namespaces" NS1[Application Namespace] NS2[Kargo Namespace] NS3[ArgoCD Namespace] end CS --> ESO ESO --> CES1 ESO --> CES2 ESO --> CES3 CES1 --> NS1 CES1 --> NS2 CES2 --> NS2 CES2 --> NS3 CES3 --> NS1
Components and Interfaces
ClusterSecretStore
The ClusterSecretStore provides the connection between ESO and the central secret storage:
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: central-secret-store
spec:
provider:
kubernetes:
server:
caProvider:
type: ConfigMap
name: kube-root-ca.crt
key: ca.crt
namespace: kube-system
auth:
serviceAccount:
name: external-secrets
namespace: external-secrets-system
remoteNamespace: central-secret-storeClusterExternalSecret Resources
Each credential type has its own ClusterExternalSecret that defines:
- Namespace Selection: Which namespaces receive the secret
- Secret Template: How the secret should be formatted
- Data Mapping: Which central secret properties to use
Namespace Labeling System
Namespaces use labels to indicate which secrets they need:
secrets/gh-docker-registry: "true"- Docker registry credentialssecrets/gh-git-credentials: "true"- Git access credentialssecrets/gh-oauth-credentials: "true"- OAuth application credentials
Secret Format Templates
Different applications require different secret formats for the same underlying credentials:
Docker Registry Format (kubernetes.io/dockerconfigjson):
template:
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: |
{
"auths": {
"ghcr.io": {
"username": "{{ .username }}",
"password": "{{ .token }}",
"auth": "{{ printf \"%s:%s\" .username .token | b64enc }}"
}
}
}Kargo Format (Opaque with specific labels):
template:
type: Opaque
metadata:
labels:
kargo.akuity.io/cred-type: image
data:
username: "{{ .username }}"
password: "{{ .token }}"
repoURL: "{{ .repoURL }}"Data Models
Central Secret Structure
Master secrets in the central store follow this structure:
apiVersion: v1
kind: Secret
metadata:
name: github-pat
namespace: central-secret-store
type: Opaque
data:
username: <base64-encoded-username>
token: <base64-encoded-token>Distributed Secret Metadata
All distributed secrets include consistent metadata:
metadata:
labels:
managed-by: external-secrets
source: central-secret-store
secret-type: <credential-type>
kargo.akuity.io/cred-type: <kargo-type> # When applicable
argocd.argoproj.io/secret-type: <argocd-type> # When applicableCorrectness Properties
A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.
Property 1: Secret Propagation Consistency
For any central secret update, all dependent namespace secrets should be updated within the refresh interval Validates: Requirements 1.2
Property 2: Namespace-Based Secret Provisioning
For any namespace with appropriate labels, the system should automatically provision all required secrets matching those labels Validates: Requirements 2.1, 2.2
Property 3: Dynamic Label-Based Distribution
For any namespace label change, the system should add or remove secrets to match the new label configuration Validates: Requirements 2.3, 2.5
Property 4: Multi-Pattern Selector Support
For any valid namespace selector pattern (label-based, name-based, expression-based), the system should correctly identify and target matching namespaces Validates: Requirements 2.4
Property 5: Secret Format and Template Correctness
For any secret template configuration, the generated secrets should match the specified Kubernetes secret type and contain all required fields in the correct format Validates: Requirements 3.1, 3.2, 3.3, 3.4
Property 6: Multi-Format Generation from Single Source
For any source credential, the system should be able to generate multiple different secret formats simultaneously without data corruption Validates: Requirements 3.2
Property 7: Credential Type Support
For any supported credential type (Docker registry, Git, OAuth, TLS), the system should successfully authenticate and authorize operations using the distributed credentials Validates: Requirements 4.1, 4.2, 4.3, 4.4
Property 8: Namespace Access Control Enforcement
For any namespace and secret combination, the system should only distribute secrets to namespaces that have appropriate authorization labels or selectors Validates: Requirements 5.1, 5.2
Property 9: Audit Trail Completeness
For any secret operation (create, update, delete, access), the system should generate corresponding audit log entries with sufficient detail for security analysis Validates: Requirements 1.4, 5.4
Property 10: Security Policy Dynamic Updates
For any security policy change, the system should update access controls and secret distribution within the refresh interval without manual intervention Validates: Requirements 5.5
Error Handling
Central Store Unavailability
- Graceful Degradation: Continue operating with cached secrets when central store is unavailable
- Retry Logic: Implement exponential backoff for reconnection attempts
- Status Reporting: Provide clear status indicators for central store connectivity
Secret Validation Failures
- Pre-Distribution Validation: Validate secret templates before creating ExternalSecrets
- Format Verification: Ensure generated secrets match expected Kubernetes secret types
- Error Propagation: Surface validation errors through ESO status conditions
Namespace Targeting Errors
- Selector Validation: Validate namespace selectors before applying ClusterExternalSecrets
- Orphaned Secret Cleanup: Remove secrets from namespaces that no longer match selectors
- Conflict Resolution: Handle cases where multiple ClusterExternalSecrets target the same namespace/secret name
RBAC and Permission Issues
- Permission Validation: Verify ESO service account has required permissions before secret operations
- Access Denied Handling: Provide clear error messages for permission failures
- Least Privilege Enforcement: Ensure RBAC rules follow principle of least privilege
Testing Strategy
Unit Testing Approach
- Template Validation: Test secret template rendering with various input combinations
- Selector Logic: Test namespace selector matching logic with edge cases
- Format Conversion: Test conversion between different secret formats
- RBAC Validation: Test permission checking logic
Property-Based Testing Configuration
- Minimum 100 iterations per property test due to randomization
- ESO Integration: Use actual External Secrets Operator for realistic testing
- Namespace Simulation: Generate random namespace configurations for comprehensive testing
- Secret Generation: Test with randomly generated credential data
Integration Testing Focus
- ESO Integration: Verify ClusterExternalSecret resources work correctly with ESO
- Kubernetes API: Test secret creation and updates through Kubernetes API
- Cross-Namespace Distribution: Verify secrets are correctly distributed across namespaces
- Label-Based Targeting: Test namespace selector functionality
Acceptance Testing Scope
- End-to-End Workflows: Test complete secret distribution workflows
- Application Integration: Verify applications can successfully use distributed secrets
- Security Validation: Confirm access controls work as expected
- Operational Scenarios: Test backup/restore, upgrades, and failure scenarios
Property Test Tags: Each property test must reference its design document property using the format: Feature: central-secret-store, Property {number}: {property_text}