# Configuration Encryption Guide

**Version**: 1.0.0
**Last Updated**: 2025-10-08
**Status**: Production Ready

## Overview

The Provisioning Platform includes a comprehensive configuration encryption system that provides:

- **Transparent Encryption/Decryption**: Configs are automatically decrypted on load
- **Multiple KMS Backends**: Age, AWS KMS, HashiCorp Vault, Cosmian KMS
- **Memory-Only Decryption**: Secrets never written to disk in plaintext
- **SOPS Integration**: Industry-standard encryption with SOPS
- **Sensitive Data Detection**: Automatic scanning for unencrypted sensitive data

## Table of Contents

1. [Prerequisites](#prerequisites)
2. [Quick Start](#quick-start)
3. [Configuration Encryption](#configuration-encryption)
4. [KMS Backends](#kms-backends)
5. [CLI Commands](#cli-commands)
6. [Integration with Config Loader](#integration-with-config-loader)
7. [Best Practices](#best-practices)
8. [Troubleshooting](#troubleshooting)

---

## Prerequisites

### Required Tools

1. **SOPS** (v3.10.2+)

   ```bash
   # macOS
   brew install sops

   # Linux
   wget https://github.com/mozilla/sops/releases/download/v3.10.2/sops-v3.10.2.linux.amd64
   sudo mv sops-v3.10.2.linux.amd64 /usr/local/bin/sops
   sudo chmod +x /usr/local/bin/sops
   ```

2. **Age** (for Age backend - recommended)

   ```bash
   # macOS
   brew install age

   # Linux
   apt install age
   ```

3. **AWS CLI** (for AWS KMS backend - optional)

   ```bash
   brew install awscli
   ```

### Verify Installation

```bash
# Check SOPS
sops --version

# Check Age
age --version

# Check AWS CLI (optional)
aws --version
```plaintext

---

## Quick Start

### 1. Initialize Encryption

Generate Age keys and create SOPS configuration:

```bash
provisioning config init-encryption --kms age
```plaintext

This will:

- Generate Age key pair in `~/.config/sops/age/keys.txt`
- Display your public key (recipient)
- Create `.sops.yaml` in your project

### 2. Set Environment Variables

Add to your shell profile (`~/.zshrc` or `~/.bashrc`):

```bash
# Age encryption
export SOPS_AGE_RECIPIENTS="age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"
export PROVISIONING_KAGE="$HOME/.config/sops/age/keys.txt"
```plaintext

Replace the recipient with your actual public key.

### 3. Validate Setup

```bash
provisioning config validate-encryption
```plaintext

Expected output:

```plaintext
✅ Encryption configuration is valid
   SOPS installed: true
   Age backend: true
   KMS enabled: false
   Errors: 0
   Warnings: 0
```plaintext

### 4. Encrypt Your First Config

```bash
# Create a config with sensitive data
cat > workspace/config/secure.yaml <<EOF
database:
  host: localhost
  password: supersecret123
  api_key: key_abc123
EOF

# Encrypt it
provisioning config encrypt workspace/config/secure.yaml --in-place

# Verify it's encrypted
provisioning config is-encrypted workspace/config/secure.yaml
```plaintext

---

## Configuration Encryption

### File Naming Conventions

Encrypted files should follow these patterns:

- `*.enc.yaml` - Encrypted YAML files
- `*.enc.yml` - Encrypted YAML files (alternative)
- `*.enc.toml` - Encrypted TOML files
- `secure.yaml` - Files in workspace/config/

The `.sops.yaml` configuration automatically applies encryption rules based on file paths.

### Encrypt a Configuration File

#### Basic Encryption

```bash
# Encrypt and create new file
provisioning config encrypt secrets.yaml

# Output: secrets.yaml.enc
```plaintext

#### In-Place Encryption

```bash
# Encrypt and replace original
provisioning config encrypt secrets.yaml --in-place
```plaintext

#### Specify Output Path

```bash
# Encrypt to specific location
provisioning config encrypt secrets.yaml --output workspace/config/secure.enc.yaml
```plaintext

#### Choose KMS Backend

```bash
# Use Age (default)
provisioning config encrypt secrets.yaml --kms age

# Use AWS KMS
provisioning config encrypt secrets.yaml --kms aws-kms

# Use Vault
provisioning config encrypt secrets.yaml --kms vault
```plaintext

### Decrypt a Configuration File

```bash
# Decrypt to new file
provisioning config decrypt secrets.enc.yaml

# Decrypt in-place
provisioning config decrypt secrets.enc.yaml --in-place

# Decrypt to specific location
provisioning config decrypt secrets.enc.yaml --output plaintext.yaml
```plaintext

### Edit Encrypted Files

The system provides a secure editing workflow:

```bash
# Edit encrypted file (auto decrypt -> edit -> re-encrypt)
provisioning config edit-secure workspace/config/secure.enc.yaml
```plaintext

This will:

1. Decrypt the file temporarily
2. Open in your `$EDITOR` (vim/nano/etc)
3. Re-encrypt when you save and close
4. Remove temporary decrypted file

### Check Encryption Status

```bash
# Check if file is encrypted
provisioning config is-encrypted workspace/config/secure.yaml

# Get detailed encryption info
provisioning config encryption-info workspace/config/secure.yaml
```plaintext

---

## KMS Backends

### Age (Recommended for Development)

**Pros**:

- Simple file-based keys
- No external dependencies
- Fast and secure
- Works offline

**Setup**:

```bash
# Initialize
provisioning config init-encryption --kms age

# Set environment variables
export SOPS_AGE_RECIPIENTS="age1..."  # Your public key
export PROVISIONING_KAGE="$HOME/.config/sops/age/keys.txt"
```plaintext

**Encrypt/Decrypt**:

```bash
provisioning config encrypt secrets.yaml --kms age
provisioning config decrypt secrets.enc.yaml
```plaintext

### AWS KMS (Production)

**Pros**:

- Centralized key management
- Audit logging
- IAM integration
- Key rotation

**Setup**:

1. Create KMS key in AWS Console
2. Configure AWS credentials:

   ```bash
   aws configure
   ```

1. Update `.sops.yaml`:

   ```yaml
   creation_rules:
     - path_regex: .*\.enc\.yaml$
       kms: "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
   ```

**Encrypt/Decrypt**:

```bash
provisioning config encrypt secrets.yaml --kms aws-kms
provisioning config decrypt secrets.enc.yaml
```plaintext

### HashiCorp Vault (Enterprise)

**Pros**:

- Dynamic secrets
- Centralized secret management
- Audit logging
- Policy-based access

**Setup**:

1. Configure Vault address and token:

   ```bash
   export VAULT_ADDR="https://vault.example.com:8200"
   export VAULT_TOKEN="s.xxxxxxxxxxxxxx"
   ```

1. Update configuration:

   ```toml
   # workspace/config/provisioning.yaml
   kms:
     enabled: true
     mode: "remote"
     vault:
       address: "https://vault.example.com:8200"
       transit_key: "provisioning"
   ```

**Encrypt/Decrypt**:

```bash
provisioning config encrypt secrets.yaml --kms vault
provisioning config decrypt secrets.enc.yaml
```plaintext

### Cosmian KMS (Confidential Computing)

**Pros**:

- Confidential computing support
- Zero-knowledge architecture
- Post-quantum ready
- Cloud-agnostic

**Setup**:

1. Deploy Cosmian KMS server
2. Update configuration:

   ```toml
   kms:
     enabled: true
     mode: "remote"
     remote:
       endpoint: "https://kms.example.com:9998"
       auth_method: "certificate"
       client_cert: "/path/to/client.crt"
       client_key: "/path/to/client.key"
   ```

**Encrypt/Decrypt**:

```bash
provisioning config encrypt secrets.yaml --kms cosmian
provisioning config decrypt secrets.enc.yaml
```plaintext

---

## CLI Commands

### Configuration Encryption Commands

| Command | Description |
|---------|-------------|
| `config encrypt <file>` | Encrypt configuration file |
| `config decrypt <file>` | Decrypt configuration file |
| `config edit-secure <file>` | Edit encrypted file securely |
| `config rotate-keys <file> <key>` | Rotate encryption keys |
| `config is-encrypted <file>` | Check if file is encrypted |
| `config encryption-info <file>` | Show encryption details |
| `config validate-encryption` | Validate encryption setup |
| `config scan-sensitive <dir>` | Find unencrypted sensitive configs |
| `config encrypt-all <dir>` | Encrypt all sensitive configs |
| `config init-encryption` | Initialize encryption (generate keys) |

### Examples

```bash
# Encrypt workspace config
provisioning config encrypt workspace/config/secure.yaml --in-place

# Edit encrypted file
provisioning config edit-secure workspace/config/secure.yaml

# Scan for unencrypted sensitive configs
provisioning config scan-sensitive workspace/config --recursive

# Encrypt all sensitive configs in workspace
provisioning config encrypt-all workspace/config --kms age --recursive

# Check encryption status
provisioning config is-encrypted workspace/config/secure.yaml

# Get detailed info
provisioning config encryption-info workspace/config/secure.yaml

# Validate setup
provisioning config validate-encryption
```plaintext

---

## Integration with Config Loader

### Automatic Decryption

The config loader automatically detects and decrypts encrypted files:

```nushell
# Load encrypted config (automatically decrypted in memory)
use lib_provisioning/config/loader.nu

let config = (load-provisioning-config --debug)
```plaintext

**Key Features**:

- **Transparent**: No code changes needed
- **Memory-Only**: Decrypted content never written to disk
- **Fallback**: If decryption fails, attempts to load as plain file
- **Debug Support**: Shows decryption status with `--debug` flag

### Manual Loading

```nushell
use lib_provisioning/config/encryption.nu

# Load encrypted config
let secure_config = (load-encrypted-config "workspace/config/secure.enc.yaml")

# Memory-only decryption (no file created)
let decrypted_content = (decrypt-config-memory "workspace/config/secure.enc.yaml")
```plaintext

### Configuration Hierarchy with Encryption

The system supports encrypted files at any level:

```plaintext
1. workspace/{name}/config/provisioning.yaml        ← Can be encrypted
2. workspace/{name}/config/providers/*.toml         ← Can be encrypted
3. workspace/{name}/config/platform/*.toml          ← Can be encrypted
4. ~/.../provisioning/ws_{name}.yaml                ← Can be encrypted
5. Environment variables (PROVISIONING_*)           ← Plain text
```plaintext

---

## Best Practices

### 1. Encrypt All Sensitive Data

**Always encrypt configs containing**:

- Passwords
- API keys
- Secret keys
- Private keys
- Tokens
- Credentials

**Scan for unencrypted sensitive data**:

```bash
provisioning config scan-sensitive workspace --recursive
```plaintext

### 2. Use Appropriate KMS Backend

| Environment | Recommended Backend |
|-------------|---------------------|
| Development | Age (file-based) |
| Staging | AWS KMS or Vault |
| Production | AWS KMS or Vault |
| CI/CD | AWS KMS with IAM roles |

### 3. Key Management

**Age Keys**:

- Store private keys securely: `~/.config/sops/age/keys.txt`
- Set file permissions: `chmod 600 ~/.config/sops/age/keys.txt`
- Backup keys securely (encrypted backup)
- Never commit private keys to git

**AWS KMS**:

- Use separate keys per environment
- Enable key rotation
- Use IAM policies for access control
- Monitor usage with CloudTrail

**Vault**:

- Use transit engine for encryption
- Enable audit logging
- Implement least-privilege policies
- Regular policy reviews

### 4. File Organization

```plaintext
workspace/
└── config/
    ├── provisioning.yaml         # Plain (no secrets)
    ├── secure.yaml                # Encrypted (SOPS auto-detects)
    ├── providers/
    │   ├── aws.toml               # Plain (no secrets)
    │   └── aws-credentials.enc.toml  # Encrypted
    └── platform/
        └── database.enc.yaml      # Encrypted
```plaintext

### 5. Git Integration

**Add to `.gitignore`**:

```gitignore
# Unencrypted sensitive files
**/secrets.yaml
**/credentials.yaml
**/*.dec.yaml
**/*.dec.toml

# Temporary decrypted files
*.tmp.yaml
*.tmp.toml
```plaintext

**Commit encrypted files**:

```bash
# Encrypted files are safe to commit
git add workspace/config/secure.enc.yaml
git commit -m "Add encrypted configuration"
```plaintext

### 6. Rotation Strategy

**Regular Key Rotation**:

```bash
# Generate new Age key
age-keygen -o ~/.config/sops/age/keys-new.txt

# Update .sops.yaml with new recipient

# Rotate keys for file
provisioning config rotate-keys workspace/config/secure.yaml <new-key-id>
```plaintext

**Frequency**:

- Development: Annually
- Production: Quarterly
- After team member departure: Immediately

### 7. Audit and Monitoring

**Track encryption status**:

```bash
# Regular scans
provisioning config scan-sensitive workspace --recursive

# Validate encryption setup
provisioning config validate-encryption
```plaintext

**Monitor access** (with Vault/AWS KMS):

- Enable audit logging
- Review access patterns
- Alert on anomalies

---

## Troubleshooting

### SOPS Not Found

**Error**:

```plaintext
SOPS binary not found
```plaintext

**Solution**:

```bash
# Install SOPS
brew install sops

# Verify
sops --version
```plaintext

### Age Key Not Found

**Error**:

```plaintext
Age key file not found: ~/.config/sops/age/keys.txt
```plaintext

**Solution**:

```bash
# Generate new key
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt

# Set environment variable
export PROVISIONING_KAGE="$HOME/.config/sops/age/keys.txt"
```plaintext

### SOPS_AGE_RECIPIENTS Not Set

**Error**:

```plaintext
no AGE_RECIPIENTS for file.yaml
```plaintext

**Solution**:

```bash
# Extract public key from private key
grep "public key:" ~/.config/sops/age/keys.txt

# Set environment variable
export SOPS_AGE_RECIPIENTS="age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"
```plaintext

### Decryption Failed

**Error**:

```plaintext
Failed to decrypt configuration file
```plaintext

**Solutions**:

1. **Wrong key**:

   ```bash
   # Verify you have the correct private key
   provisioning config validate-encryption
   ```

1. **File corrupted**:

   ```bash
   # Check file integrity
   sops --decrypt workspace/config/secure.yaml
   ```

2. **Wrong backend**:

   ```bash
   # Check SOPS metadata in file
   head -20 workspace/config/secure.yaml
   ```

### AWS KMS Access Denied

**Error**:

```plaintext
AccessDeniedException: User is not authorized to perform: kms:Decrypt
```plaintext

**Solution**:

```bash
# Check AWS credentials
aws sts get-caller-identity

# Verify KMS key policy allows your IAM user/role
aws kms describe-key --key-id <key-arn>
```plaintext

### Vault Connection Failed

**Error**:

```plaintext
Vault encryption failed: connection refused
```plaintext

**Solution**:

```bash
# Verify Vault address
echo $VAULT_ADDR

# Check connectivity
curl -k $VAULT_ADDR/v1/sys/health

# Verify token
vault token lookup
```plaintext

---

## Security Considerations

### Threat Model

**Protected Against**:

- ✅ Plaintext secrets in git
- ✅ Accidental secret exposure
- ✅ Unauthorized file access
- ✅ Key compromise (with rotation)

**Not Protected Against**:

- ❌ Memory dumps during decryption
- ❌ Root/admin access to running process
- ❌ Compromised Age/KMS keys
- ❌ Social engineering

### Security Best Practices

1. **Principle of Least Privilege**: Only grant decryption access to those who need it
2. **Key Separation**: Use different keys for different environments
3. **Regular Audits**: Review who has access to keys
4. **Secure Key Storage**: Never store private keys in git
5. **Rotation**: Regularly rotate encryption keys
6. **Monitoring**: Monitor decryption operations (with AWS KMS/Vault)

---

## Additional Resources

- **SOPS Documentation**: <https://github.com/mozilla/sops>
- **Age Encryption**: <https://age-encryption.org/>
- **AWS KMS**: <https://aws.amazon.com/kms/>
- **HashiCorp Vault**: <https://www.vaultproject.io/>
- **Cosmian KMS**: <https://www.cosmian.com/>

---

## Support

For issues or questions:

- Check troubleshooting section above
- Run: `provisioning config validate-encryption`
- Review logs with `--debug` flag

---

## Quick Reference

### Setup (One-time)

```bash
# 1. Initialize encryption
provisioning config init-encryption --kms age

# 2. Set environment variables (add to ~/.zshrc or ~/.bashrc)
export SOPS_AGE_RECIPIENTS="age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"
export PROVISIONING_KAGE="$HOME/.config/sops/age/keys.txt"

# 3. Validate setup
provisioning config validate-encryption
```plaintext

### Common Commands

| Task | Command |
|------|---------|
| **Encrypt file** | `provisioning config encrypt secrets.yaml --in-place` |
| **Decrypt file** | `provisioning config decrypt secrets.enc.yaml` |
| **Edit encrypted** | `provisioning config edit-secure secrets.enc.yaml` |
| **Check if encrypted** | `provisioning config is-encrypted secrets.yaml` |
| **Scan for unencrypted** | `provisioning config scan-sensitive workspace --recursive` |
| **Encrypt all sensitive** | `provisioning config encrypt-all workspace/config --kms age` |
| **Validate setup** | `provisioning config validate-encryption` |
| **Show encryption info** | `provisioning config encryption-info secrets.yaml` |

### File Naming Conventions

Automatically encrypted by SOPS:

- `workspace/*/config/secure.yaml` ← Auto-encrypted
- `*.enc.yaml` ← Auto-encrypted
- `*.enc.yml` ← Auto-encrypted
- `*.enc.toml` ← Auto-encrypted
- `workspace/*/config/providers/*credentials*.toml` ← Auto-encrypted

### Quick Workflow

```bash
# Create config with secrets
cat > workspace/config/secure.yaml <<EOF
database:
  password: supersecret
api_key: secret_key_123
EOF

# Encrypt in-place
provisioning config encrypt workspace/config/secure.yaml --in-place

# Verify encrypted
provisioning config is-encrypted workspace/config/secure.yaml

# Edit securely (decrypt -> edit -> re-encrypt)
provisioning config edit-secure workspace/config/secure.yaml

# Configs are auto-decrypted when loaded
provisioning env  # Automatically decrypts secure.yaml
```plaintext

### KMS Backends

| Backend | Use Case | Setup Command |
|---------|----------|---------------|
| **Age** | Development, simple setup | `provisioning config init-encryption --kms age` |
| **AWS KMS** | Production, AWS environments | Configure in `.sops.yaml` |
| **Vault** | Enterprise, dynamic secrets | Set `VAULT_ADDR` and `VAULT_TOKEN` |
| **Cosmian** | Confidential computing | Configure in `config.toml` |

### Security Checklist

- ✅ Encrypt all files with passwords, API keys, secrets
- ✅ Never commit unencrypted secrets to git
- ✅ Set file permissions: `chmod 600 ~/.config/sops/age/keys.txt`
- ✅ Add plaintext files to `.gitignore`: `*.dec.yaml`, `secrets.yaml`
- ✅ Regular key rotation (quarterly for production)
- ✅ Separate keys per environment (dev/staging/prod)
- ✅ Backup Age keys securely (encrypted backup)

### Troubleshooting

| Problem | Solution |
|---------|----------|
| `SOPS binary not found` | `brew install sops` |
| `Age key file not found` | `provisioning config init-encryption --kms age` |
| `SOPS_AGE_RECIPIENTS not set` | `export SOPS_AGE_RECIPIENTS="age1..."` |
| `Decryption failed` | Check key file: `provisioning config validate-encryption` |
| `AWS KMS Access Denied` | Verify IAM permissions: `aws sts get-caller-identity` |

### Testing

```bash
# Run all encryption tests
nu provisioning/core/nulib/lib_provisioning/config/encryption_tests.nu

# Run specific test
nu provisioning/core/nulib/lib_provisioning/config/encryption_tests.nu --test roundtrip

# Test full workflow
nu provisioning/core/nulib/lib_provisioning/config/encryption_tests.nu test-full-encryption-workflow

# Test KMS backend
use lib_provisioning/kms/client.nu
kms-test --backend age
```plaintext

### Integration

Configs are **automatically decrypted** when loaded:

```nushell
# Nushell code - encryption is transparent
use lib_provisioning/config/loader.nu

# Auto-decrypts encrypted files in memory
let config = (load-provisioning-config)

# Access secrets normally
let db_password = ($config | get database.password)
```plaintext

### Emergency Key Recovery

If you lose your Age key:

1. **Check backups**: `~/.config/sops/age/keys.txt.backup`
2. **Check other systems**: Keys might be on other dev machines
3. **Contact team**: Team members with access can re-encrypt for you
4. **Rotate secrets**: If keys are lost, rotate all secrets

### Advanced

#### Multiple Recipients (Team Access)

```yaml
# .sops.yaml
creation_rules:
  - path_regex: .*\.enc\.yaml$
    age: >-
      age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p,
      age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8q
```plaintext

#### Key Rotation

```bash
# Generate new key
age-keygen -o ~/.config/sops/age/keys-new.txt

# Update .sops.yaml with new recipient

# Rotate keys for file
provisioning config rotate-keys workspace/config/secure.yaml <new-key-id>
```plaintext

#### Scan and Encrypt All

```bash
# Find all unencrypted sensitive configs
provisioning config scan-sensitive workspace --recursive

# Encrypt them all
provisioning config encrypt-all workspace --kms age --recursive

# Verify
provisioning config scan-sensitive workspace --recursive
```plaintext

### Documentation

- **Full Guide**: `docs/user/CONFIG_ENCRYPTION_GUIDE.md`
- **SOPS Docs**: <https://github.com/mozilla/sops>
- **Age Docs**: <https://age-encryption.org/>

---

**Last Updated**: 2025-10-08
**Version**: 1.0.0
