provisioning/docs/src/development/kms-simplification.md
2026-01-14 03:09:18 +00:00

14 KiB

KMS Simplification Migration Guide\n\nVersion: 0.2.0\nDate: 2025-10-08\nStatus: 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\nOld (Vault):\n\n\n[kms]\ntype = "vault"\naddress = "http://localhost:8200"\ntoken = "${VAULT_TOKEN}"\nmount_point = "transit"\n\n\nNew (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\nOption 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\nOption 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\nFrom 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\nFrom 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\nOld (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\nNew (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\nBefore:\n\n\nKmsError::VaultError(String)\nKmsError::AwsKmsError(String)\n\n\nAfter:\n\n\nKmsError::AgeError(String)\nKmsError::CosmianError(String)\n\n\n#### Updated Configuration Enum\n\nBefore:\n\n\nenum KmsBackendConfig {\n Vault { address, token, mount_point, ... },\n AwsKms { region, key_id, assume_role },\n}\n\n\nAfter:\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\nBefore (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\nAfter (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\nBefore (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\nAfter (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\nQ: 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\nQ: What about AWS KMS for existing deployments?\nA: Migrate to Cosmian KMS. The API is similar, and migration tools are provided.\n\nQ: Is Age secure enough for production?\nA: No. Age is designed for development only. Use Cosmian KMS for production.\n\nQ: Does Cosmian support confidential computing?\nA: Yes, Cosmian KMS supports SGX and SEV for confidential computing workloads.\n\nQ: How much does Cosmian cost?\nA: Cosmian offers both cloud and self-hosted options. Contact Cosmian for pricing.\n\nQ: 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.