# KMS (Key Management Service) Configuration **Version:** 1.0.0 **Status:** Independent configuration system for local and remote KMS **Location:** `/provisioning/core/services/kms/` ## Overview The KMS configuration system provides a comprehensive, independent configuration for managing encryption keys and secrets. It supports three operational modes: 1. **Local Mode** - Uses local encryption tools (age, SOPS, Vault) 2. **Remote Mode** - Connects to external KMS servers (Cosmian KMS, AWS KMS, etc.) 3. **Hybrid Mode** - Combines both with automatic fallback ## Directory Structure ``` provisioning/core/services/kms/ ├── config.defaults.toml # System defaults for all KMS settings ├── config.schema.toml # Validation rules and constraints ├── config.remote.example.toml # Production remote KMS examples ├── config.local.example.toml # Local encryption examples ├── lib.nu # KMS library functions (existing) └── README.md # This file ``` ## Configuration Files ### 1. config.defaults.toml Primary configuration file containing all KMS settings with sensible defaults. **Key Sections:** - `[kms]` - Core settings (enabled, mode, version) - `[kms.paths]` - Path configuration with interpolation support - `[kms.local]` - Local encryption provider settings - `[kms.remote]` - Remote KMS server configuration - `[kms.hybrid]` - Hybrid mode settings - `[kms.policies]` - Key rotation and backup policies - `[kms.encryption]` - Encryption algorithms and KDF settings - `[kms.security]` - Security enforcement rules ### 2. config.schema.toml Validation schema defining: - Type constraints for all fields - Value ranges and patterns - Cross-field validation rules - Security requirements ### 3. Example Configurations - **config.remote.example.toml** - Remote KMS deployment scenarios - **config.local.example.toml** - Local encryption configurations (age, SOPS, Vault) ## Path Interpolation All paths support interpolation variables for flexibility and portability: ### Available Interpolation Variables | Variable | Description | Example | |----------|-------------|---------| | `{{workspace.path}}` | Current workspace root | `/workspace/my-project` | | `{{kms.paths.base}}` | KMS base directory | `{{workspace.path}}/.kms` | | `{{env.HOME}}` | User home directory | `/home/user` | | `{{env.VAR}}` | Any environment variable | `{{env.CONFIG_DIR}}` | | `{{now.date}}` | Current date | `2025-10-06` | | `{{git.branch}}` | Current git branch | `main` | ### Path Examples ```toml # Workspace-relative paths (recommended) [kms.paths] base = "{{workspace.path}}/.kms" keys_dir = "{{kms.paths.base}}/keys" # Absolute paths [kms.local] key_path = "/etc/provisioning/kms/age.txt" # Home directory paths [kms.remote.auth] token_path = "{{env.HOME}}/.config/provisioning/kms-token" # Environment variable paths [kms.local.vault] token_path = "{{env.VAULT_TOKEN_PATH}}" ``` ## Security Considerations ### 1. Key File Permissions **CRITICAL:** Key files MUST have restricted permissions (0600 or 0400). ```toml [kms.local.age] key_permissions = "0600" # Read/write for owner only [kms.security] enforce_key_permissions = true # Enforces permission checks ``` **Best Practice:** - Production keys: `0400` (read-only) - Development keys: `0600` (read/write for owner) - Never use: `0644`, `0755`, or world-readable permissions ### 2. Secret References (NOT Plaintext!) **NEVER store secrets directly in configuration files.** Use secret references instead: ```toml # ✅ CORRECT - Secret reference [kms.remote.auth] password_secret = "sops://kms/remote/password" api_key = "vault://kms/api/key" # ❌ WRONG - Plaintext secret [kms.remote.auth] password = "my-secret-password" # NEVER DO THIS! ``` **Supported Secret References:** - `sops://path/to/secret` - SOPS encrypted secret - `vault://path/to/secret` - HashiCorp Vault secret - `kms://path/to/secret` - KMS-encrypted secret - `age://path/to/secret` - Age-encrypted secret ### 3. TLS/mTLS Configuration Always use TLS 1.3 for remote KMS connections: ```toml [kms.remote.tls] enabled = true verify = true # Always verify certificates min_version = "1.3" # TLS 1.3 minimum ca_cert_path = "/etc/kms/ca.crt" # For mTLS authentication [kms.remote.auth] method = "mtls" client_cert_path = "/etc/kms/client.crt" client_key_path = "/etc/kms/client.key" ``` **Security Rules:** - Never disable TLS verification in production - Use mTLS when available for mutual authentication - Store certificates outside version control - Rotate certificates regularly ### 4. Audit Logging Enable audit logging for production environments: ```toml [kms.policies] audit_log_enabled = true audit_log_path = "{{kms.paths.base}}/audit.log" audit_log_format = "json" ``` **Logged Operations:** - Encryption/decryption requests - Key rotation events - Authentication attempts - Configuration changes ### 5. Debug Mode Warning **NEVER enable debug mode in production!** ```toml [kms.operations] debug = false # Debug exposes sensitive data in logs! verbose = false ``` Debug mode includes: - Plaintext key material in logs - Full request/response bodies - Authentication credentials - Decrypted secrets ### 6. Secret Scanning Enable secret scanning to prevent accidental exposure: ```toml [kms.security] secret_scanning_enabled = true disallow_plaintext_secrets = true secret_patterns = [ "(?i)password\\s*=\\s*['\"]?[^'\"\\s]+", "(?i)api[_-]?key\\s*=\\s*['\"]?[^'\"\\s]+", "(?i)token\\s*=\\s*['\"]?[^'\"\\s]+", ] ``` ### 7. Key Backup and Rotation Implement key rotation and backup policies: ```toml [kms.policies] auto_rotate = true rotation_days = 90 # Rotate every 90 days backup_enabled = true backup_path = "{{kms.paths.base}}/backups" backup_retention_count = 5 # Keep last 5 backups ``` **Backup Best Practices:** - Store backups in secure, encrypted storage - Test restore procedures regularly - Document key recovery process - Separate backup storage from primary keys ## Configuration Loading The KMS configuration is loaded via config accessor functions in `/provisioning/core/nulib/lib_provisioning/config/accessor.nu`. ### Available Accessor Functions #### Core Settings - `get-kms-enabled` - Check if KMS is enabled - `get-kms-mode` - Get operating mode (local/remote/hybrid) - `get-kms-version` - Get KMS config version #### Path Accessors - `get-kms-base-path` - Get base KMS directory - `get-kms-keys-dir` - Get keys directory - `get-kms-cache-dir` - Get cache directory - `get-kms-config-dir` - Get config directory #### Local Configuration - `get-kms-local-enabled` - Check if local mode enabled - `get-kms-local-provider` - Get provider (age/sops/vault) - `get-kms-local-key-path` - Get key file path - `get-kms-age-generate-on-init` - Check auto-generate setting #### Remote Configuration - `get-kms-remote-enabled` - Check if remote mode enabled - `get-kms-remote-endpoint` - Get KMS server URL - `get-kms-remote-auth-method` - Get auth method - `get-kms-remote-timeout` - Get connection timeout #### Full Config Helper - `get-kms-config-full` - Get complete KMS config as record ### Usage Examples ```nushell # Check if KMS is enabled let kms_enabled = (get-kms-enabled) # Get operating mode let mode = (get-kms-mode) # Get full configuration let kms_config = (get-kms-config-full) # Get local key path with interpolation resolved let key_path = (get-kms-local-key-path) ``` ## Operational Modes ### 1. Local Mode (Default) Uses local encryption tools without external dependencies. **Use Cases:** - Development environments - Offline operations - Simple encryption needs - No cloud KMS access **Supported Providers:** - **age** - Simple, modern encryption (recommended) - **sops** - Secret Operations with multiple backends - **vault** - HashiCorp Vault Transit engine **Example:** ```toml [kms] enabled = true mode = "local" [kms.local] enabled = true provider = "age" key_path = "{{kms.paths.keys_dir}}/age.txt" ``` ### 2. Remote Mode Connects to external KMS server for centralized key management. **Use Cases:** - Production environments - Centralized key management - Compliance requirements - Multi-region deployments **Supported Integrations:** - Cosmian KMS - AWS KMS - HashiCorp Vault (remote) - Custom KMS servers **Example:** ```toml [kms] enabled = true mode = "remote" [kms.remote] enabled = true endpoint = "https://kms.production.example.com" [kms.remote.auth] method = "mtls" client_cert_path = "/etc/kms/client.crt" client_key_path = "/etc/kms/client.key" ``` ### 3. Hybrid Mode Combines local and remote with automatic fallback. **Use Cases:** - High availability requirements - Gradual migration from local to remote - Offline operation support - Disaster recovery **Example:** ```toml [kms] enabled = true mode = "hybrid" [kms.local] enabled = true provider = "age" [kms.remote] enabled = true endpoint = "https://kms.example.com" [kms.hybrid] enabled = true fallback_to_local = true sync_keys = false ``` ## Authentication Methods ### Token-based Authentication ```toml [kms.remote.auth] method = "token" token_path = "{{kms.paths.config_dir}}/token" refresh_token = true token_expiry_seconds = 3600 ``` ### mTLS (Mutual TLS) ```toml [kms.remote.auth] method = "mtls" client_cert_path = "/etc/kms/client.crt" client_key_path = "/etc/kms/client.key" [kms.remote.tls] ca_cert_path = "/etc/kms/ca.crt" ``` ### API Key ```toml [kms.remote.auth] method = "api_key" api_key = "sops://kms/api_key" # Secret reference! ``` ### Basic Authentication ```toml [kms.remote.auth] method = "basic" username = "provisioning" password_secret = "vault://kms/password" # Secret reference! ``` ### IAM (AWS) ```toml [kms.remote.auth] method = "iam" iam_role_arn = "arn:aws:iam::123456789012:role/kms-role" ``` ## Integration with Existing KMS Library The existing KMS library (`lib.nu`) can be updated to use the new configuration: ### Current Implementation ```nushell # Old: Hardcoded config lookup def get_kms_config [] { let server_url = (get-kms-server) # ... } ``` ### Updated Implementation ```nushell # New: Use new config accessors def get_kms_config [] { let mode = (get-kms-mode) match $mode { "local" => { { provider: (get-kms-local-provider) key_path: (get-kms-local-key-path) # ... } } "remote" => { { endpoint: (get-kms-remote-endpoint) auth_method: (get-kms-remote-auth-method) # ... } } "hybrid" => { # Both local and remote config } } } ``` ## Validation Configuration is validated against the schema: ### Validation Rules 1. **Mode Consistency** - `local` mode requires `kms.local.enabled = true` - `remote` mode requires `kms.remote.enabled = true` - `hybrid` mode requires both enabled 2. **Auth Method Requirements** - `mtls` requires `client_cert_path` and `client_key_path` - `token` requires `token_path` - `api_key` requires `api_key` - `basic` requires `username` and `password_secret` 3. **Security Enforcement** - Password must be secret reference (not plaintext) - Key permissions must be 0600 or 0400 - TLS verification required for production 4. **Resource Constraints** - Timeout: 1-300 seconds - Retry attempts: 0-10 - Cache TTL: 60-3600 seconds - File size: 1-1024 MB ## Migration Guide ### From Environment Variables to Config **Before (ENV-based):** ```bash export PROVISIONING_KMS_SERVER="https://kms.example.com" export PROVISIONING_KMS_AUTH="certificate" ``` **After (Config-based):** ```toml [kms.remote] endpoint = "https://kms.example.com" [kms.remote.auth] method = "mtls" ``` ### From SOPS to KMS Config The new KMS config is independent from SOPS but still supports SOPS as a provider: ```toml [kms.local] provider = "sops" sops_config = "{{workspace.path}}/.sops.yaml" [kms.local.sops] age_recipients = ["age1xxx...", "age1yyy..."] ``` ## Best Practices ### 1. Development Environment ```toml [kms] mode = "local" [kms.local] provider = "age" key_path = "/tmp/dev-age.txt" [kms.operations] verbose = true debug = false # Never true, even in dev! [kms.policies] backup_enabled = false audit_log_enabled = false ``` ### 2. Production Environment ```toml [kms] mode = "remote" [kms.remote] endpoint = "https://kms.prod.example.com" timeout_seconds = 30 retry_attempts = 3 [kms.remote.auth] method = "mtls" client_cert_path = "/etc/kms/client.crt" client_key_path = "/etc/kms/client.key" [kms.remote.tls] verify = true min_version = "1.3" [kms.policies] auto_rotate = true rotation_days = 90 backup_enabled = true audit_log_enabled = true [kms.security] enforce_key_permissions = true disallow_plaintext_secrets = true [kms.operations] verbose = false debug = false ``` ### 3. Hybrid/HA Environment ```toml [kms] mode = "hybrid" [kms.local] enabled = true provider = "age" [kms.remote] enabled = true endpoint = "https://kms.example.com" [kms.hybrid] enabled = true fallback_to_local = true sync_keys = false ``` ## Troubleshooting ### Issue: Permission Denied on Key File **Error:** ``` Permission denied: /path/to/age.txt ``` **Solution:** ```bash chmod 0600 /path/to/age.txt ``` Or update config: ```toml [kms.local.age] key_permissions = "0600" [kms.security] enforce_key_permissions = true ``` ### Issue: Remote KMS Connection Failed **Error:** ``` Connection timeout: https://kms.example.com ``` **Solutions:** 1. Check network connectivity 2. Verify TLS certificates 3. Increase timeout: ```toml [kms.remote] timeout_seconds = 60 retry_attempts = 5 ``` ### Issue: Secret Reference Not Found **Error:** ``` Secret not found: sops://kms/password ``` **Solution:** 1. Verify secret exists in SOPS/Vault 2. Check secret path format 3. Ensure SOPS/Vault is properly configured ## Version Compatibility | KMS Config Version | Nushell Version | KCL Version | Notes | |-------------------|-----------------|-------------|-------| | 1.0.0 | 0.107.1+ | 0.11.3+ | Initial release | ## Related Documentation - **Config System**: `/provisioning/config/README.md` - **SOPS Integration**: `/provisioning/core/nulib/lib_provisioning/secrets/` - **Environment Setup**: `/docs/environment-setup.md` - **Security Guide**: `/docs/security/secrets-management.md` ## Support For issues or questions: 1. Check this README 2. Review example configurations 3. Consult validation schema 4. Check audit logs (if enabled) ## License Part of the provisioning project. See project LICENSE.