# KMS Simplification Migration Guide

**Version**: 0.2.0
**Date**: 2025-10-08
**Status**: Active

## Overview

The KMS service has been simplified from supporting 4 backends (Vault, AWS KMS, Age, Cosmian) to supporting only 2 backends:

- **Age**: Development and local testing
- **Cosmian KMS**: Production deployments

This simplification reduces complexity, removes unnecessary cloud provider dependencies, and provides a clearer separation between development and production use cases.

## What Changed

### Removed

- ❌ HashiCorp Vault backend (`src/vault/`)
- ❌ AWS KMS backend (`src/aws/`)
- ❌ AWS SDK dependencies (`aws-sdk-kms`, `aws-config`, `aws-credential-types`)
- ❌ Envelope encryption helpers (AWS-specific)
- ❌ Complex multi-backend configuration

### Added

- ✅ Age backend for development (`src/age/`)
- ✅ Cosmian KMS backend for production (`src/cosmian/`)
- ✅ Simplified configuration (`provisioning/config/kms.toml`)
- ✅ Clear dev/prod separation
- ✅ Better error messages

### Modified

- 🔄 `KmsBackendConfig` enum (now only Age and Cosmian)
- 🔄 `KmsError` enum (removed Vault/AWS-specific errors)
- 🔄 Service initialization logic
- 🔄 README and documentation
- 🔄 Cargo.toml dependencies

## Why This Change

### Problems with Previous Approach

1. **Unnecessary Complexity**: 4 backends for simple use cases
2. **Cloud Lock-in**: AWS KMS dependency limited flexibility
3. **Operational Overhead**: Vault requires server setup even for dev
4. **Dependency Bloat**: AWS SDK adds significant compile time
5. **Unclear Use Cases**: When to use which backend?

### Benefits of Simplified Approach

1. **Clear Separation**: Age = dev, Cosmian = prod
2. **Faster Compilation**: Removed AWS SDK (saves ~30 s)
3. **Offline Development**: Age works without network
4. **Enterprise Security**: Cosmian provides confidential computing
5. **Easier Maintenance**: 2 backends instead of 4

## Migration Steps

### For Development Environments

If you were using **Vault** or **AWS KMS** for development:

#### Step 1: Install Age

```bash
# macOS
brew install age

# Ubuntu/Debian
apt install age

# From source
go install filippo.io/age/cmd/...@latest
```

#### Step 2: Generate Age Keys

```bash
mkdir -p ~/.config/provisioning/age
age-keygen -o ~/.config/provisioning/age/private_key.txt
age-keygen -y ~/.config/provisioning/age/private_key.txt > ~/.config/provisioning/age/public_key.txt
```

#### Step 3: Update Configuration

Replace your old Vault/AWS config:

**Old (Vault)**:

```toml
[kms]
type = "vault"
address = "http://localhost:8200"
token = "${VAULT_TOKEN}"
mount_point = "transit"
```

**New (Age)**:

```toml
[kms]
environment = "dev"

[kms.age]
public_key_path = "~/.config/provisioning/age/public_key.txt"
private_key_path = "~/.config/provisioning/age/private_key.txt"
```

#### Step 4: Re-encrypt Development Secrets

```bash
# Export old secrets (if using Vault)
vault kv get -format=json secret/dev > dev-secrets.json

# Encrypt with Age
cat dev-secrets.json | age -r $(cat ~/.config/provisioning/age/public_key.txt) > dev-secrets.age

# Test decryption
age -d -i ~/.config/provisioning/age/private_key.txt dev-secrets.age
```

### For Production Environments

If you were using **Vault** or **AWS KMS** for production:

#### Step 1: Set Up Cosmian KMS

Choose one of these options:

**Option A: Cosmian Cloud (Managed)**

```bash
# Sign up at https://cosmian.com
# Get API credentials
export COSMIAN_KMS_URL=https://kms.cosmian.cloud
export COSMIAN_API_KEY=your-api-key
```

**Option B: Self-Hosted Cosmian KMS**

```bash
# Deploy Cosmian KMS server
# See: https://docs.cosmian.com/kms/deployment/

# Configure endpoint
export COSMIAN_KMS_URL=https://kms.example.com
export COSMIAN_API_KEY=your-api-key
```

#### Step 2: Create Master Key in Cosmian

```bash
# Using Cosmian CLI
cosmian-kms create-key \
  --algorithm AES \
  --key-length 256 \
  --key-id provisioning-master-key

# Or via API
curl -X POST $COSMIAN_KMS_URL/api/v1/keys \
  -H "X-API-Key: $COSMIAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "algorithm": "AES",
    "keyLength": 256,
    "keyId": "provisioning-master-key"
  }'
```

#### Step 3: Migrate Production Secrets

**From Vault to Cosmian**:

```bash
# Export secrets from Vault
vault kv get -format=json secret/prod > prod-secrets.json

# Import to Cosmian
# (Use temporary Age encryption for transfer)
cat prod-secrets.json | \
  age -r $(cat ~/.config/provisioning/age/public_key.txt) | \
  base64 > prod-secrets.enc

# On production server with Cosmian
cat prod-secrets.enc | \
  base64 -d | \
  age -d -i ~/.config/provisioning/age/private_key.txt | \
  # Re-encrypt with Cosmian
  curl -X POST $COSMIAN_KMS_URL/api/v1/encrypt \
    -H "X-API-Key: $COSMIAN_API_KEY" \
    -d @-
```

**From AWS KMS to Cosmian**:

```bash
# Decrypt with AWS KMS
aws kms decrypt \
  --ciphertext-blob fileb://encrypted-data \
  --output text \
  --query Plaintext | \
  base64 -d > plaintext-data

# Encrypt with Cosmian
curl -X POST $COSMIAN_KMS_URL/api/v1/encrypt \
  -H "X-API-Key: $COSMIAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"keyId\":\"provisioning-master-key\",\"data\":\"$(base64 plaintext-data)\"}"
```

#### Step 4: Update Production Configuration

**Old (AWS KMS)**:

```toml
[kms]
type = "aws-kms"
region = "us-east-1"
key_id = "arn:aws:kms:us-east-1:123456789012:key/..."
```

**New (Cosmian)**:

```toml
[kms]
environment = "prod"

[kms.cosmian]
server_url = "${COSMIAN_KMS_URL}"
api_key = "${COSMIAN_API_KEY}"
default_key_id = "provisioning-master-key"
tls_verify = true
use_confidential_computing = false  # Enable if using SGX/SEV
```

#### Step 5: Test Production Setup

```bash
# Set environment
export PROVISIONING_ENV=prod
export COSMIAN_KMS_URL=https://kms.example.com
export COSMIAN_API_KEY=your-api-key

# Start KMS service
cargo run --bin kms-service

# Test encryption
curl -X POST http://localhost:8082/api/v1/kms/encrypt \
  -H "Content-Type: application/json" \
  -d '{"plaintext":"SGVsbG8=","context":"env=prod"}'

# Test decryption
curl -X POST http://localhost:8082/api/v1/kms/decrypt \
  -H "Content-Type: application/json" \
  -d '{"ciphertext":"...","context":"env=prod"}'
```

## Configuration Comparison

### Before (4 Backends)

```toml
# Development could use any backend
[kms]
type = "vault"  # or "aws-kms"
address = "http://localhost:8200"
token = "${VAULT_TOKEN}"

# Production used Vault or AWS
[kms]
type = "aws-kms"
region = "us-east-1"
key_id = "arn:aws:kms:..."
```

### After (2 Backends)

```toml
# Clear environment-based selection
[kms]
dev_backend = "age"
prod_backend = "cosmian"
environment = "${PROVISIONING_ENV:-dev}"

# Age for development
[kms.age]
public_key_path = "~/.config/provisioning/age/public_key.txt"
private_key_path = "~/.config/provisioning/age/private_key.txt"

# Cosmian for production
[kms.cosmian]
server_url = "${COSMIAN_KMS_URL}"
api_key = "${COSMIAN_API_KEY}"
default_key_id = "provisioning-master-key"
tls_verify = true
```

## Breaking Changes

### API Changes

#### Removed Functions

- `generate_data_key()` - Now only available with Cosmian backend
- `envelope_encrypt()` - AWS-specific, removed
- `envelope_decrypt()` - AWS-specific, removed
- `rotate_key()` - Now handled server-side by Cosmian

#### Changed Error Types

**Before**:

```rust
KmsError::VaultError(String)
KmsError::AwsKmsError(String)
```

**After**:

```rust
KmsError::AgeError(String)
KmsError::CosmianError(String)
```

#### Updated Configuration Enum

**Before**:

```rust
enum KmsBackendConfig {
    Vault { address, token, mount_point, ... },
    AwsKms { region, key_id, assume_role },
}
```

**After**:

```rust
enum KmsBackendConfig {
    Age { public_key_path, private_key_path },
    Cosmian { server_url, api_key, default_key_id, tls_verify },
}
```

## Code Migration

### Rust Code

**Before (AWS KMS)**:

```rust
use kms_service::{KmsService, KmsBackendConfig};

let config = KmsBackendConfig::AwsKms {
    region: "us-east-1".to_string(),
    key_id: "arn:aws:kms:...".to_string(),
    assume_role: None,
};

let kms = KmsService::new(config).await?;
```

**After (Cosmian)**:

```rust
use kms_service::{KmsService, KmsBackendConfig};

let config = KmsBackendConfig::Cosmian {
    server_url: env::var("COSMIAN_KMS_URL")?,
    api_key: env::var("COSMIAN_API_KEY")?,
    default_key_id: "provisioning-master-key".to_string(),
    tls_verify: true,
};

let kms = KmsService::new(config).await?;
```

### Nushell Code

**Before (Vault)**:

```nushell
# Set Vault environment
$env.VAULT_ADDR = "http://localhost:8200"
$env.VAULT_TOKEN = "root"

# Use KMS
kms encrypt "secret-data"
```

**After (Age for dev)**:

```nushell
# Set environment
$env.PROVISIONING_ENV = "dev"

# Age keys automatically loaded from config
kms encrypt "secret-data"
```

## Rollback Plan

If you need to rollback to Vault/AWS KMS:

```bash
# Checkout previous version
git checkout tags/v0.1.0

# Rebuild with old dependencies
cd provisioning/platform/kms-service
cargo clean
cargo build --release

# Restore old configuration
cp provisioning/config/kms.toml.backup provisioning/config/kms.toml
```

## Testing the Migration

### Development Testing

```bash
# 1. Generate Age keys
age-keygen -o /tmp/test_private.txt
age-keygen -y /tmp/test_private.txt > /tmp/test_public.txt

# 2. Test encryption
echo "test-data" | age -r $(cat /tmp/test_public.txt) > /tmp/encrypted

# 3. Test decryption
age -d -i /tmp/test_private.txt /tmp/encrypted

# 4. Start KMS service with test keys
export PROVISIONING_ENV=dev
# Update config to point to /tmp keys
cargo run --bin kms-service
```

### Production Testing

```bash
# 1. Set up test Cosmian instance
export COSMIAN_KMS_URL=https://kms-staging.example.com
export COSMIAN_API_KEY=test-api-key

# 2. Create test key
cosmian-kms create-key --key-id test-key --algorithm AES --key-length 256

# 3. Test encryption
curl -X POST $COSMIAN_KMS_URL/api/v1/encrypt \
  -H "X-API-Key: $COSMIAN_API_KEY" \
  -d '{"keyId":"test-key","data":"dGVzdA=="}'

# 4. Start KMS service
export PROVISIONING_ENV=prod
cargo run --bin kms-service
```

## Troubleshooting

### Age Keys Not Found

```bash
# Check keys exist
ls -la ~/.config/provisioning/age/

# Regenerate if missing
age-keygen -o ~/.config/provisioning/age/private_key.txt
age-keygen -y ~/.config/provisioning/age/private_key.txt > ~/.config/provisioning/age/public_key.txt
```

### Cosmian Connection Failed

```bash
# Check network connectivity
curl -v $COSMIAN_KMS_URL/api/v1/health

# Verify API key
curl $COSMIAN_KMS_URL/api/v1/version \
  -H "X-API-Key: $COSMIAN_API_KEY"

# Check TLS certificate
openssl s_client -connect kms.example.com:443
```

### Compilation Errors

```bash
# Clean and rebuild
cd provisioning/platform/kms-service
cargo clean
cargo update
cargo build --release
```

## Support

- **Documentation**: See README.md
- **Issues**: Report on project issue tracker
- **Cosmian Support**: <https://docs.cosmian.com/support/>

## Timeline

- **2025-10-08**: Migration guide published
- **2025-10-15**: Deprecation notices for Vault/AWS
- **2025-11-01**: Old backends removed from codebase
- **2025-11-15**: Migration complete, old configs unsupported

## FAQs

**Q: Can I still use Vault if I really need to?**
A: No, Vault support has been removed. Use Age for dev or Cosmian for prod.

**Q: What about AWS KMS for existing deployments?**
A: Migrate to Cosmian KMS. The API is similar, and migration tools are provided.

**Q: Is Age secure enough for production?**
A: No. Age is designed for development only. Use Cosmian KMS for production.

**Q: Does Cosmian support confidential computing?**
A: Yes, Cosmian KMS supports SGX and SEV for confidential computing workloads.

**Q: How much does Cosmian cost?**
A: Cosmian offers both cloud and self-hosted options. Contact Cosmian for pricing.

**Q: Can I use my own KMS backend?**
A: Not currently supported. Only Age and Cosmian are available.

## Checklist

Use this checklist to track your migration:

### Development Migration

- [ ] Install Age (`brew install age` or equivalent)
- [ ] Generate Age keys (`age-keygen`)
- [ ] Update `provisioning/config/kms.toml` to use Age backend
- [ ] Export secrets from Vault/AWS (if applicable)
- [ ] Re-encrypt secrets with Age
- [ ] Test KMS service startup
- [ ] Test encrypt/decrypt operations
- [ ] Update CI/CD pipelines (if applicable)
- [ ] Update documentation

### Production Migration

- [ ] Set up Cosmian KMS server (cloud or self-hosted)
- [ ] Create master key in Cosmian
- [ ] Export production secrets from Vault/AWS
- [ ] Re-encrypt secrets with Cosmian
- [ ] Update `provisioning/config/kms.toml` to use Cosmian backend
- [ ] Set environment variables (`COSMIAN_KMS_URL`, `COSMIAN_API_KEY`)
- [ ] Test KMS service startup in staging
- [ ] Test encrypt/decrypt operations in staging
- [ ] Load test Cosmian integration
- [ ] Update production deployment configs
- [ ] Deploy to production
- [ ] Verify all secrets accessible
- [ ] Decommission old KMS infrastructure

## Conclusion

The KMS simplification reduces complexity while providing better separation between development and production use cases. Age offers a fast, offline solution for development, while Cosmian KMS provides enterprise-grade security for production deployments.

For questions or issues, please refer to the documentation or open an issue.
