11use std:: str:: FromStr ;
22
3+ #[ cfg( feature = "external_key_manager" ) ]
4+ use crate :: config:: ExternalKeyManagerConfig ;
35use crate :: {
46 config:: GlobalConfig ,
57 error:: { self , ResultContainerExt } ,
68} ;
79use masking:: Maskable ;
8- #[ cfg( feature = "external_key_manager_mtls " ) ]
10+ #[ cfg( feature = "external_key_manager " ) ]
911use masking:: PeekInterface ;
1012use reqwest:: StatusCode ;
1113use reqwest:: {
@@ -51,10 +53,29 @@ pub struct ApiClientConfig {
5153 pub client_idle_timeout : u64 ,
5254 pub pool_max_idle_per_host : usize ,
5355 // KMS encrypted
54- #[ cfg( feature = "external_key_manager_mtls " ) ]
56+ #[ cfg( feature = "external_key_manager " ) ]
5557 pub identity : masking:: Secret < String > ,
5658}
5759
60+ impl ApiClientConfig {
61+ #[ cfg( feature = "external_key_manager" ) ]
62+ pub fn validate_for_mtls (
63+ & self ,
64+ external_key_manager_config : & ExternalKeyManagerConfig ,
65+ ) -> Result < ( ) , crate :: error:: ConfigurationError > {
66+ // Only validate if external key manager is enabled with mTLS
67+ if external_key_manager_config. is_mtls_enabled ( ) && self . identity . peek ( ) . is_empty ( ) {
68+ return Err (
69+ crate :: error:: ConfigurationError :: InvalidConfigurationValueError (
70+ "api_client.identity is required when mTLS is enabled" . into ( ) ,
71+ ) ,
72+ ) ;
73+ }
74+
75+ Ok ( ( ) )
76+ }
77+ }
78+
5879#[ derive( Clone ) ]
5980pub struct ApiClient {
6081 pub inner : reqwest:: Client ,
@@ -80,24 +101,36 @@ impl ApiClient {
80101 ) )
81102 . pool_max_idle_per_host ( global_config. api_client . pool_max_idle_per_host ) ;
82103
83- #[ cfg( feature = "external_key_manager_mtls " ) ]
104+ #[ cfg( feature = "external_key_manager " ) ]
84105 {
85- let client_identity =
86- reqwest:: Identity :: from_pem ( global_config. api_client . identity . peek ( ) . as_ref ( ) )
87- . change_error ( error:: ApiClientError :: IdentityParseFailed ) ?;
88-
89- let external_key_manager_cert = reqwest:: Certificate :: from_pem (
90- global_config. external_key_manager . cert . peek ( ) . as_ref ( ) ,
91- )
92- . change_error ( error:: ApiClientError :: CertificateParseFailed {
93- service : "external_key_manager" ,
94- } ) ?;
95-
96- client = client
97- . use_rustls_tls ( )
98- . identity ( client_identity)
99- . add_root_certificate ( external_key_manager_cert)
100- . https_only ( true ) ;
106+ // mTLS-specific configuration
107+ if global_config. external_key_manager . is_mtls_enabled ( ) {
108+ let client_identity =
109+ reqwest:: Identity :: from_pem ( global_config. api_client . identity . peek ( ) . as_ref ( ) )
110+ . change_error ( error:: ApiClientError :: IdentityParseFailed ) ?;
111+
112+ let ca_cert = global_config
113+ . external_key_manager
114+ . get_ca_cert ( )
115+ . ok_or_else ( || {
116+ error:: ApiClientError :: MissingConfigurationError (
117+ "CA certificate not configured for mTLS" ,
118+ )
119+ } ) ?;
120+
121+ let key_manager_ca_cert = reqwest:: Certificate :: from_pem ( ca_cert. peek ( ) . as_ref ( ) )
122+ . change_error (
123+ error:: ApiClientError :: CertificateParseFailed {
124+ service : "external_key_manager" ,
125+ } ,
126+ ) ?;
127+
128+ client = client
129+ . use_rustls_tls ( )
130+ . identity ( client_identity)
131+ . add_root_certificate ( key_manager_ca_cert)
132+ . https_only ( true ) ;
133+ }
101134 }
102135
103136 let client = client
0 commit comments