This document describes the implementation of AWS Key Management Service (KMS) integration for secure key management in the Axionvera network node.
The AWS KMS integration addresses the security vulnerability of storing private validator keys in plaintext on the server filesystem. The implementation provides:
- Abstract signing interface that supports multiple key management providers
- AWS KMS provider for secure key storage and signing operations
- Public key caching to reduce KMS API calls
- Payload hash forwarding to ensure private keys never leave KMS
- Comprehensive error handling for rate limits and network timeouts
- Retry logic with exponential backoff for transient failures
- Signer Trait (
src/signing.rs): Abstract interface for all signing providers - AwsKmsSigner (
src/aws_kms_signer.rs): AWS KMS implementation - SigningService (
src/signing.rs): Service managing multiple signers with caching - PublicKeyCache (
src/signing.rs): Caching layer for public keys - SignerFactory (
src/signing.rs): Factory for creating signers from configuration
- Zero-knowledge architecture: Private keys never leave AWS KMS
- Hash-based signing: Only SHA-256 hashes are sent to KMS for signing
- Cached public keys: Reduces KMS API calls while maintaining security
- Timeout protection: Prevents hanging operations
- Rate limit handling: Graceful degradation under KMS rate limits
Add the following to your configuration file:
[signing]
type = "AwsKms"
key_id = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
region = "us-east-1"
# Optional: AWS profile to use
# profile = "my-aws-profile"
# Cache configuration
cache_ttl_seconds = 3600 # Cache public keys for 1 hourThe AWS SDK will automatically use credentials from:
- AWS credentials file (
~/.aws/credentials) - Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - IAM role (when running on EC2/ECS)
- AWS profile specified in configuration
The AWS credentials need the following KMS permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"kms:GetPublicKey",
"kms:Sign"
],
"Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/KEY_ID"
}
]
}use axionvera_network::signing::{SignerConfig, SignerFactory, SigningService};
// Create AWS KMS signer
let config = SignerConfig::AwsKms {
key_id: "arn:aws:kms:us-east-1:123456789012:key/...".to_string(),
region: "us-east-1".to_string(),
profile: Some("my-profile".to_string()),
};
let signer = SignerFactory::create_signer(config).await?;
// Sign a message
let message = b"Hello, Axionvera!";
let signature = signer.sign(message).await?;
// Get public key
let public_key = signer.get_public_key().await?;use axionvera_network::signing::SigningService;
// Create signing service with 1-hour cache TTL
let mut service = SigningService::new(3600);
// Add AWS KMS signer
let signer = SignerFactory::create_signer(kms_config).await?;
let key_id = signer.get_key_id().await?;
service.add_signer(key_id.clone(), signer).await?;
service.set_default_signer(key_id).await?;
// Sign using default signer
let signature = service.sign(b"Transaction data").await?;
// Sign using specific signer
let signature = service.sign_with("key-id", b"Transaction data").await?;
// Get public key (with caching)
let public_key = service.get_public_key("key-id").await?;The integration adds the following HTTP/gRPC endpoints:
POST /api/v1/sign- Sign a message using the default signerPOST /api/v1/sign/{key_id}- Sign a message using a specific signerGET /api/v1/public-key/{key_id}- Get public key for a signerGET /api/v1/signers- List all configured signersGET /api/v1/health/signing- Health check for all signers
SigningServicewith methods for signing and key management- Integration with existing network and gateway services
The implementation includes comprehensive error handling:
NetworkError::Kms- General KMS errorsNetworkError::KmsTimeout- Operation timeoutsNetworkError::KmsRateLimit- Rate limit exceededNetworkError::Signer- Signer-specific errors
- Automatic retries for transient failures (timeouts, rate limits)
- Exponential backoff with configurable delay
- Maximum retry limit to prevent infinite loops
- Circuit breaker pattern for repeated failures
- Graceful degradation when KMS rate limits are hit
- Queue management for pending signing requests
- Backpressure to prevent overwhelming the service
Run the comprehensive test suite:
cargo test signing
cargo test aws_kms_signerFor AWS KMS integration tests (requires AWS credentials):
# Set environment variables
export TEST_KMS_KEY_ID="arn:aws:kms:..."
export TEST_AWS_REGION="us-east-1"
# Run integration tests
cargo test --ignored test_aws_kms_signer_integrationUse the local signer for development and testing:
[signing]
type = "Local"
key_path = "./test-keys/dev-key.pem"- Private keys never leave AWS KMS
- Only SHA-256 hashes are transmitted
- No key material is stored locally
- Automatic key rotation support
- TLS encryption for all AWS API calls
- VPC endpoints can be used for private connectivity
- IAM policies restrict access to specific KMS keys
- Audit logging of all signing operations
- Health monitoring for KMS connectivity
- Graceful fallback for KMS unavailability
- Public key caching reduces KMS API calls by ~90%
- Configurable TTL based on security requirements
- Cache invalidation on key rotation
- HTTP connection reuse for KMS API calls
- Configurable timeouts and retry limits
- Connection health monitoring
- Batch signature verification (existing feature)
- Future: Batch signing support for high-throughput scenarios
- Signing operation latency
- KMS API call count
- Cache hit/miss ratios
- Error rates by type
- Structured logging with tracing spans
- Correlation IDs for request tracking
- Security event logging
- KMS connectivity health
- Signer availability monitoring
- Cache performance metrics
- Create KMS key in AWS console
- Update configuration to use AWS KMS
- Deploy with both local and KMS signers
- Gradually migrate applications to use KMS
- Remove local keys after successful migration
- Create new KMS key
- Add to configuration as additional signer
- Update applications to use new key
- Decommission old key after verification
# Check IAM permissions
aws kms describe-key --key-id KEY_ID
# Verify credentials
aws sts get-caller-identity// Increase timeout in configuration
let config = AwsKmsConfig {
timeout_ms: 60000, // 60 seconds
max_retries: 5,
retry_delay_ms: 2000,
..Default::default()
};// Implement backpressure
match service.sign(message).await {
Ok(signature) => handle_signature(signature),
Err(NetworkError::KmsRateLimit(_)) => {
// Implement exponential backoff
tokio::time::sleep(Duration::from_secs(10)).await;
// Retry with backoff
}
Err(e) => handle_error(e),
}Enable debug logging for detailed troubleshooting:
RUST_LOG=debug cargo run- Multi-region KMS support for high availability
- Hardware Security Module (HSM) integration
- Batch signing for improved throughput
- Key rotation automation
- Cross-cloud KMS support (Azure Key Vault, GCP KMS)
- Asynchronous signing queues
- Smart caching strategies
- Connection pooling optimization
- Metrics-driven auto-scaling
For issues and questions:
- Check the logs for detailed error messages
- Verify AWS credentials and IAM permissions
- Test with local signer to isolate the issue
- Create an issue with detailed reproduction steps
This AWS KMS integration is part of the Axionvera network project and follows the same license terms.