prvng_core/services/kms/README.md

15 KiB

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
```plaintext

## 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}}"
```plaintext

## 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
```plaintext

**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!
```plaintext

**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"
```plaintext

**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"
```plaintext

**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
```plaintext

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]+",
]
```plaintext

### 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
```plaintext

**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)
```plaintext

## 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"
```plaintext

### 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"
```plaintext

### 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
```plaintext

## 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
```plaintext

### 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"
```plaintext

### API Key

```toml
[kms.remote.auth]
method = "api_key"
api_key = "sops://kms/api_key"  # Secret reference!
```plaintext

### Basic Authentication

```toml
[kms.remote.auth]
method = "basic"
username = "provisioning"
password_secret = "vault://kms/password"  # Secret reference!
```plaintext

### IAM (AWS)

```toml
[kms.remote.auth]
method = "iam"
iam_role_arn = "arn:aws:iam::123456789012:role/kms-role"
```plaintext

## 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)
    # ...
}
```plaintext

### 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
        }
    }
}
```plaintext

## 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"
```plaintext

**After (Config-based):**

```toml
[kms.remote]
endpoint = "https://kms.example.com"

[kms.remote.auth]
method = "mtls"
```plaintext

### 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..."]
```plaintext

## 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
```plaintext

### 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
```plaintext

### 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
```plaintext

## Troubleshooting

### Issue: Permission Denied on Key File

**Error:**

```plaintext
Permission denied: /path/to/age.txt
```plaintext

**Solution:**

```bash
chmod 0600 /path/to/age.txt
```plaintext

Or update config:

```toml
[kms.local.age]
key_permissions = "0600"

[kms.security]
enforce_key_permissions = true
```plaintext

### Issue: Remote KMS Connection Failed

**Error:**

```plaintext
Connection timeout: https://kms.example.com
```plaintext

**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
```plaintext

**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 | Nickel 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.