# KMS Simplification Migration Guide\n\n**Version**: 0.2.0\n**Date**: 2025-10-08\n**Status**: Active\n\n## Overview\n\nThe KMS service has been simplified from supporting 4 backends (Vault, AWS KMS, Age, Cosmian) to supporting only 2 backends:\n\n- **Age**: Development and local testing\n- **Cosmian KMS**: Production deployments\n\nThis simplification reduces complexity, removes unnecessary cloud provider dependencies, and provides a clearer separation between development and\nproduction use cases.\n\n## What Changed\n\n### Removed\n\n- ❌ HashiCorp Vault backend (`src/vault/`)\n- ❌ AWS KMS backend (`src/aws/`)\n- ❌ AWS SDK dependencies (`aws-sdk-kms`, `aws-config`, `aws-credential-types`)\n- ❌ Envelope encryption helpers (AWS-specific)\n- ❌ Complex multi-backend configuration\n\n### Added\n\n- ✅ Age backend for development (`src/age/`)\n- ✅ Cosmian KMS backend for production (`src/cosmian/`)\n- ✅ Simplified configuration (`provisioning/config/kms.toml`)\n- ✅ Clear dev/prod separation\n- ✅ Better error messages\n\n### Modified\n\n- 🔄 `KmsBackendConfig` enum (now only Age and Cosmian)\n- 🔄 `KmsError` enum (removed Vault/AWS-specific errors)\n- 🔄 Service initialization logic\n- 🔄 README and documentation\n- 🔄 Cargo.toml dependencies\n\n## Why This Change\n\n### Problems with Previous Approach\n\n1. **Unnecessary Complexity**: 4 backends for simple use cases\n2. **Cloud Lock-in**: AWS KMS dependency limited flexibility\n3. **Operational Overhead**: Vault requires server setup even for dev\n4. **Dependency Bloat**: AWS SDK adds significant compile time\n5. **Unclear Use Cases**: When to use which backend?\n\n### Benefits of Simplified Approach\n\n1. **Clear Separation**: Age = dev, Cosmian = prod\n2. **Faster Compilation**: Removed AWS SDK (saves ~30 s)\n3. **Offline Development**: Age works without network\n4. **Enterprise Security**: Cosmian provides confidential computing\n5. **Easier Maintenance**: 2 backends instead of 4\n\n## Migration Steps\n\n### For Development Environments\n\nIf you were using **Vault** or **AWS KMS** for development:\n\n#### Step 1: Install Age\n\n```\n# macOS\nbrew install age\n\n# Ubuntu/Debian\napt install age\n\n# From source\ngo install filippo.io/age/cmd/...@latest\n```\n\n#### Step 2: Generate Age Keys\n\n```\nmkdir -p ~/.config/provisioning/age\nage-keygen -o ~/.config/provisioning/age/private_key.txt\nage-keygen -y ~/.config/provisioning/age/private_key.txt > ~/.config/provisioning/age/public_key.txt\n```\n\n#### Step 3: Update Configuration\n\nReplace your old Vault/AWS config:\n\n**Old (Vault)**:\n\n```\n[kms]\ntype = "vault"\naddress = "http://localhost:8200"\ntoken = "${VAULT_TOKEN}"\nmount_point = "transit"\n```\n\n**New (Age)**:\n\n```\n[kms]\nenvironment = "dev"\n\n[kms.age]\npublic_key_path = "~/.config/provisioning/age/public_key.txt"\nprivate_key_path = "~/.config/provisioning/age/private_key.txt"\n```\n\n#### Step 4: Re-encrypt Development Secrets\n\n```\n# Export old secrets (if using Vault)\nvault kv get -format=json secret/dev > dev-secrets.json\n\n# Encrypt with Age\ncat dev-secrets.json | age -r $(cat ~/.config/provisioning/age/public_key.txt) > dev-secrets.age\n\n# Test decryption\nage -d -i ~/.config/provisioning/age/private_key.txt dev-secrets.age\n```\n\n### For Production Environments\n\nIf you were using **Vault** or **AWS KMS** for production:\n\n#### Step 1: Set Up Cosmian KMS\n\nChoose one of these options:\n\n**Option A: Cosmian Cloud (Managed)**\n\n```\n# Sign up at https://cosmian.com\n# Get API credentials\nexport COSMIAN_KMS_URL=https://kms.cosmian.cloud\nexport COSMIAN_API_KEY=your-api-key\n```\n\n**Option B: Self-Hosted Cosmian KMS**\n\n```\n# Deploy Cosmian KMS server\n# See: https://docs.cosmian.com/kms/deployment/\n\n# Configure endpoint\nexport COSMIAN_KMS_URL=https://kms.example.com\nexport COSMIAN_API_KEY=your-api-key\n```\n\n#### Step 2: Create Master Key in Cosmian\n\n```\n# Using Cosmian CLI\ncosmian-kms create-key \\n  --algorithm AES \\n  --key-length 256 \\n  --key-id provisioning-master-key\n\n# Or via API\ncurl -X POST $COSMIAN_KMS_URL/api/v1/keys \\n  -H "X-API-Key: $COSMIAN_API_KEY" \\n  -H "Content-Type: application/json" \\n  -d '{\n    "algorithm": "AES",\n    "keyLength": 256,\n    "keyId": "provisioning-master-key"\n  }'\n```\n\n#### Step 3: Migrate Production Secrets\n\n**From Vault to Cosmian**:\n\n```\n# Export secrets from Vault\nvault kv get -format=json secret/prod > prod-secrets.json\n\n# Import to Cosmian\n# (Use temporary Age encryption for transfer)\ncat prod-secrets.json | \\n  age -r $(cat ~/.config/provisioning/age/public_key.txt) | \\n  base64 > prod-secrets.enc\n\n# On production server with Cosmian\ncat prod-secrets.enc | \\n  base64 -d | \\n  age -d -i ~/.config/provisioning/age/private_key.txt | \\n  # Re-encrypt with Cosmian\n  curl -X POST $COSMIAN_KMS_URL/api/v1/encrypt \\n    -H "X-API-Key: $COSMIAN_API_KEY" \\n    -d @-\n```\n\n**From AWS KMS to Cosmian**:\n\n```\n# Decrypt with AWS KMS\naws kms decrypt \\n  --ciphertext-blob fileb://encrypted-data \\n  --output text \\n  --query Plaintext | \\n  base64 -d > plaintext-data\n\n# Encrypt with Cosmian\ncurl -X POST $COSMIAN_KMS_URL/api/v1/encrypt \\n  -H "X-API-Key: $COSMIAN_API_KEY" \\n  -H "Content-Type: application/json" \\n  -d "{\"keyId\":\"provisioning-master-key\",\"data\":\"$(base64 plaintext-data)\"}"\n```\n\n#### Step 4: Update Production Configuration\n\n**Old (AWS KMS)**:\n\n```\n[kms]\ntype = "aws-kms"\nregion = "us-east-1"\nkey_id = "arn:aws:kms:us-east-1:123456789012:key/..."\n```\n\n**New (Cosmian)**:\n\n```\n[kms]\nenvironment = "prod"\n\n[kms.cosmian]\nserver_url = "${COSMIAN_KMS_URL}"\napi_key = "${COSMIAN_API_KEY}"\ndefault_key_id = "provisioning-master-key"\ntls_verify = true\nuse_confidential_computing = false  # Enable if using SGX/SEV\n```\n\n#### Step 5: Test Production Setup\n\n```\n# Set environment\nexport PROVISIONING_ENV=prod\nexport COSMIAN_KMS_URL=https://kms.example.com\nexport COSMIAN_API_KEY=your-api-key\n\n# Start KMS service\ncargo run --bin kms-service\n\n# Test encryption\ncurl -X POST http://localhost:8082/api/v1/kms/encrypt \\n  -H "Content-Type: application/json" \\n  -d '{"plaintext":"SGVsbG8=","context":"env=prod"}'\n\n# Test decryption\ncurl -X POST http://localhost:8082/api/v1/kms/decrypt \\n  -H "Content-Type: application/json" \\n  -d '{"ciphertext":"...","context":"env=prod"}'\n```\n\n## Configuration Comparison\n\n### Before (4 Backends)\n\n```\n# Development could use any backend\n[kms]\ntype = "vault"  # or "aws-kms"\naddress = "http://localhost:8200"\ntoken = "${VAULT_TOKEN}"\n\n# Production used Vault or AWS\n[kms]\ntype = "aws-kms"\nregion = "us-east-1"\nkey_id = "arn:aws:kms:..."\n```\n\n### After (2 Backends)\n\n```\n# Clear environment-based selection\n[kms]\ndev_backend = "age"\nprod_backend = "cosmian"\nenvironment = "${PROVISIONING_ENV:-dev}"\n\n# Age for development\n[kms.age]\npublic_key_path = "~/.config/provisioning/age/public_key.txt"\nprivate_key_path = "~/.config/provisioning/age/private_key.txt"\n\n# Cosmian for production\n[kms.cosmian]\nserver_url = "${COSMIAN_KMS_URL}"\napi_key = "${COSMIAN_API_KEY}"\ndefault_key_id = "provisioning-master-key"\ntls_verify = true\n```\n\n## Breaking Changes\n\n### API Changes\n\n#### Removed Functions\n\n- `generate_data_key()` - Now only available with Cosmian backend\n- `envelope_encrypt()` - AWS-specific, removed\n- `envelope_decrypt()` - AWS-specific, removed\n- `rotate_key()` - Now handled server-side by Cosmian\n\n#### Changed Error Types\n\n**Before**:\n\n```\nKmsError::VaultError(String)\nKmsError::AwsKmsError(String)\n```\n\n**After**:\n\n```\nKmsError::AgeError(String)\nKmsError::CosmianError(String)\n```\n\n#### Updated Configuration Enum\n\n**Before**:\n\n```\nenum KmsBackendConfig {\n    Vault { address, token, mount_point, ... },\n    AwsKms { region, key_id, assume_role },\n}\n```\n\n**After**:\n\n```\nenum KmsBackendConfig {\n    Age { public_key_path, private_key_path },\n    Cosmian { server_url, api_key, default_key_id, tls_verify },\n}\n```\n\n## Code Migration\n\n### Rust Code\n\n**Before (AWS KMS)**:\n\n```\nuse kms_service::{KmsService, KmsBackendConfig};\n\nlet config = KmsBackendConfig::AwsKms {\n    region: "us-east-1".to_string(),\n    key_id: "arn:aws:kms:...".to_string(),\n    assume_role: None,\n};\n\nlet kms = KmsService::new(config).await?;\n```\n\n**After (Cosmian)**:\n\n```\nuse kms_service::{KmsService, KmsBackendConfig};\n\nlet config = KmsBackendConfig::Cosmian {\n    server_url: env::var("COSMIAN_KMS_URL")?,\n    api_key: env::var("COSMIAN_API_KEY")?,\n    default_key_id: "provisioning-master-key".to_string(),\n    tls_verify: true,\n};\n\nlet kms = KmsService::new(config).await?;\n```\n\n### Nushell Code\n\n**Before (Vault)**:\n\n```\n# Set Vault environment\n$env.VAULT_ADDR = "http://localhost:8200"\n$env.VAULT_TOKEN = "root"\n\n# Use KMS\nkms encrypt "secret-data"\n```\n\n**After (Age for dev)**:\n\n```\n# Set environment\n$env.PROVISIONING_ENV = "dev"\n\n# Age keys automatically loaded from config\nkms encrypt "secret-data"\n```\n\n## Rollback Plan\n\nIf you need to rollback to Vault/AWS KMS:\n\n```\n# Checkout previous version\ngit checkout tags/v0.1.0\n\n# Rebuild with old dependencies\ncd provisioning/platform/kms-service\ncargo clean\ncargo build --release\n\n# Restore old configuration\ncp provisioning/config/kms.toml.backup provisioning/config/kms.toml\n```\n\n## Testing the Migration\n\n### Development Testing\n\n```\n# 1. Generate Age keys\nage-keygen -o /tmp/test_private.txt\nage-keygen -y /tmp/test_private.txt > /tmp/test_public.txt\n\n# 2. Test encryption\necho "test-data" | age -r $(cat /tmp/test_public.txt) > /tmp/encrypted\n\n# 3. Test decryption\nage -d -i /tmp/test_private.txt /tmp/encrypted\n\n# 4. Start KMS service with test keys\nexport PROVISIONING_ENV=dev\n# Update config to point to /tmp keys\ncargo run --bin kms-service\n```\n\n### Production Testing\n\n```\n# 1. Set up test Cosmian instance\nexport COSMIAN_KMS_URL=https://kms-staging.example.com\nexport COSMIAN_API_KEY=test-api-key\n\n# 2. Create test key\ncosmian-kms create-key --key-id test-key --algorithm AES --key-length 256\n\n# 3. Test encryption\ncurl -X POST $COSMIAN_KMS_URL/api/v1/encrypt \\n  -H "X-API-Key: $COSMIAN_API_KEY" \\n  -d '{"keyId":"test-key","data":"dGVzdA=="}'\n\n# 4. Start KMS service\nexport PROVISIONING_ENV=prod\ncargo run --bin kms-service\n```\n\n## Troubleshooting\n\n### Age Keys Not Found\n\n```\n# Check keys exist\nls -la ~/.config/provisioning/age/\n\n# Regenerate if missing\nage-keygen -o ~/.config/provisioning/age/private_key.txt\nage-keygen -y ~/.config/provisioning/age/private_key.txt > ~/.config/provisioning/age/public_key.txt\n```\n\n### Cosmian Connection Failed\n\n```\n# Check network connectivity\ncurl -v $COSMIAN_KMS_URL/api/v1/health\n\n# Verify API key\ncurl $COSMIAN_KMS_URL/api/v1/version \\n  -H "X-API-Key: $COSMIAN_API_KEY"\n\n# Check TLS certificate\nopenssl s_client -connect kms.example.com:443\n```\n\n### Compilation Errors\n\n```\n# Clean and rebuild\ncd provisioning/platform/kms-service\ncargo clean\ncargo update\ncargo build --release\n```\n\n## Support\n\n- **Documentation**: See README.md\n- **Issues**: Report on project issue tracker\n- **Cosmian Support**: <https://docs.cosmian.com/support/>\n\n## Timeline\n\n- **2025-10-08**: Migration guide published\n- **2025-10-15**: Deprecation notices for Vault/AWS\n- **2025-11-01**: Old backends removed from codebase\n- **2025-11-15**: Migration complete, old configs unsupported\n\n## FAQs\n\n**Q: Can I still use Vault if I really need to?**\nA: No, Vault support has been removed. Use Age for dev or Cosmian for prod.\n\n**Q: What about AWS KMS for existing deployments?**\nA: Migrate to Cosmian KMS. The API is similar, and migration tools are provided.\n\n**Q: Is Age secure enough for production?**\nA: No. Age is designed for development only. Use Cosmian KMS for production.\n\n**Q: Does Cosmian support confidential computing?**\nA: Yes, Cosmian KMS supports SGX and SEV for confidential computing workloads.\n\n**Q: How much does Cosmian cost?**\nA: Cosmian offers both cloud and self-hosted options. Contact Cosmian for pricing.\n\n**Q: Can I use my own KMS backend?**\nA: Not currently supported. Only Age and Cosmian are available.\n\n## Checklist\n\nUse this checklist to track your migration:\n\n### Development Migration\n\n- [ ] Install Age (`brew install age` or equivalent)\n- [ ] Generate Age keys (`age-keygen`)\n- [ ] Update `provisioning/config/kms.toml` to use Age backend\n- [ ] Export secrets from Vault/AWS (if applicable)\n- [ ] Re-encrypt secrets with Age\n- [ ] Test KMS service startup\n- [ ] Test encrypt/decrypt operations\n- [ ] Update CI/CD pipelines (if applicable)\n- [ ] Update documentation\n\n### Production Migration\n\n- [ ] Set up Cosmian KMS server (cloud or self-hosted)\n- [ ] Create master key in Cosmian\n- [ ] Export production secrets from Vault/AWS\n- [ ] Re-encrypt secrets with Cosmian\n- [ ] Update `provisioning/config/kms.toml` to use Cosmian backend\n- [ ] Set environment variables (`COSMIAN_KMS_URL`, `COSMIAN_API_KEY`)\n- [ ] Test KMS service startup in staging\n- [ ] Test encrypt/decrypt operations in staging\n- [ ] Load test Cosmian integration\n- [ ] Update production deployment configs\n- [ ] Deploy to production\n- [ ] Verify all secrets accessible\n- [ ] Decommission old KMS infrastructure\n\n## Conclusion\n\nThe KMS simplification reduces complexity while providing better separation between development and production use cases. Age offers a fast, offline\nsolution for development, while Cosmian KMS provides enterprise-grade security for production deployments.\n\nFor questions or issues, please refer to the documentation or open an issue.
