openzeppelin_relayer/config/config_file/signer/
aws_kms.rs

1//! Configuration for Amazon AWS KMS signer
2//!
3//! This module provides configuration for using Amazon AWS KMS as a signing service.
4//! AWS KMS allows you to manage cryptographic keys and perform signing operations
5//! without exposing private keys directly to your application.
6//!
7//! The configuration supports:
8//! - AWS Region (aws_region) - important for region-specific key
9//! - KMS Key identification (key_id)
10//!
11//! The AWS authentication is carried out
12//! through recommended credential providers as outlined in
13//! https://docs.aws.amazon.com/sdk-for-rust/latest/dg/credproviders.html
14//!
15//! Currently only EVM signing is supported since, as of June 2025,
16//! AWS does not support ed25519 scheme
17
18use serde::{Deserialize, Serialize};
19use validator::Validate;
20
21use crate::config::{validate_with_validator, ConfigFileError, SignerConfigValidate};
22
23#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Validate)]
24#[serde(deny_unknown_fields)]
25pub struct AwsKmsSignerFileConfig {
26    pub region: Option<String>,
27    #[validate(length(min = 1, message = "key_id cannot be empty"))]
28    pub key_id: String,
29}
30
31impl SignerConfigValidate for AwsKmsSignerFileConfig {
32    fn validate(&self) -> Result<(), ConfigFileError> {
33        validate_with_validator(self)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn test_aws_kms_signer_file_config_valid() {
43        let config = AwsKmsSignerFileConfig {
44            region: Some("us-east-1".to_string()),
45            key_id: "test-key-id".to_string(),
46        };
47
48        assert!(
49            Validate::validate(&config).is_ok(),
50            "Config should pass basic validation"
51        );
52        assert!(
53            SignerConfigValidate::validate(&config).is_ok(),
54            "Config should pass signer config validation"
55        );
56    }
57
58    #[test]
59    fn test_aws_signer_file_config_empty_key_id() {
60        let config = AwsKmsSignerFileConfig {
61            region: Some("us-east-1".to_string()),
62            key_id: "".to_string(),
63        };
64
65        let result = SignerConfigValidate::validate(&config);
66        assert!(
67            result.is_err(),
68            "Config should not pass the signer config validation"
69        );
70        if let Err(e) = result {
71            let error_message = format!("{:?}", e);
72            assert!(error_message.contains("key_id"));
73            assert!(error_message.contains("cannot be empty"), "{:?}", e);
74        }
75    }
76
77    #[test]
78    fn test_serde_deserialize() {
79        let json = r#"
80        {
81            "region": "us-east-1",
82            "key_id": "test-key-id"
83        }
84        "#;
85        let config: AwsKmsSignerFileConfig = serde_json::from_str(json).unwrap();
86        assert_eq!(config.region.unwrap().as_str(), "us-east-1");
87        assert_eq!(config.key_id.as_str(), "test-key-id");
88    }
89
90    #[test]
91    fn test_serde_unknown_field() {
92        let json = r#"
93        {
94            "region": "us-east-1",
95            "key_id": "test-key-id",
96            "unknown_field": "should cause error"
97        }
98        "#;
99        let result: Result<AwsKmsSignerFileConfig, _> = serde_json::from_str(json);
100        assert!(result.is_err());
101    }
102
103    #[test]
104    fn test_serde_serialize_deserialize() {
105        let config = AwsKmsSignerFileConfig {
106            region: Some("us-east-1".to_string()),
107            key_id: "test-key-id".to_string(),
108        };
109        let serialized = serde_json::to_string(&config).unwrap();
110        let deserialized: AwsKmsSignerFileConfig = serde_json::from_str(&serialized).unwrap();
111        assert_eq!(config.region, deserialized.region);
112        assert_eq!(config.key_id, deserialized.key_id);
113    }
114}