@@ -766,105 +766,123 @@ pub(crate) fn create_rustls_config(
766
766
insecure : bool ,
767
767
tls_params : Option < TlsConnParams > ,
768
768
) -> RedisResult < rustls:: ClientConfig > {
769
- // install the default (ring) crypto provider exactly once
769
+ // Install the default (aws-lc-rs) crypto provider exactly once.
770
+ // This is the recommended approach as of rustls 0.23+ for best security and performance.
770
771
CRYPTO_PROVIDER . get_or_init ( || {
771
- let _ = rustls:: crypto:: ring :: default_provider ( ) . install_default ( ) ;
772
+ let _ = rustls:: crypto:: aws_lc_rs :: default_provider ( ) . install_default ( ) ;
772
773
} ) ;
773
774
774
775
use crate :: tls:: ClientTlsParams ;
775
776
use rustls_platform_verifier:: BuilderVerifierExt ;
776
777
777
- let config = if let Some ( tls_params) = tls_params {
778
- if let Some ( root_cert_store) = tls_params. root_cert_store {
779
- // If custom root certificates are provided, use them instead of platform verifier
778
+ // Build the TLS configuration following rustls best practices:
779
+ // 1. Prefer platform verifier (recommended by rustls team for maximum compatibility)
780
+ // 2. Fall back to custom root certificates only when explicitly provided
781
+ // 3. Support client certificate authentication when needed
782
+ let config = match tls_params {
783
+ Some ( tls_params) if tls_params. root_cert_store . is_some ( ) => {
784
+ // Custom root certificates explicitly provided - use them instead of platform verifier
785
+ // This is for cases where specific certificate validation is required
786
+ let root_cert_store = tls_params. root_cert_store . unwrap ( ) ;
780
787
let config = rustls:: ClientConfig :: builder ( ) . with_root_certificates ( root_cert_store) ;
781
788
782
- if let Some ( ClientTlsParams {
783
- client_cert_chain : client_cert,
784
- client_key,
785
- } ) = tls_params. client_tls_params
786
- {
787
- config
789
+ match tls_params. client_tls_params {
790
+ Some ( ClientTlsParams {
791
+ client_cert_chain : client_cert,
792
+ client_key,
793
+ } ) => config
788
794
. with_client_auth_cert ( client_cert, client_key)
789
795
. map_err ( |err| {
790
- RedisError :: from ( (
791
- ErrorKind :: InvalidClientConfig ,
792
- "Unable to build client with TLS parameters provided." ,
793
- err. to_string ( ) ,
794
- ) )
795
- } ) ?
796
- } else {
797
- config. with_no_client_auth ( )
796
+ tls_config_error (
797
+ "Failed to configure client certificate authentication with custom root store" ,
798
+ err,
799
+ )
800
+ } ) ?,
801
+ None => config. with_no_client_auth ( ) ,
798
802
}
799
- } else {
800
- // Use platform verifier when no custom root certificates are provided
803
+ }
804
+ Some ( tls_params) => {
805
+ // TLS params provided but no custom root certificates - use platform verifier (recommended)
806
+ // Platform verifier provides live trust information and matches user expectations
801
807
let config = rustls:: ClientConfig :: builder ( )
802
808
. with_platform_verifier ( )
803
809
. map_err ( |err| {
804
- RedisError :: from ( (
805
- ErrorKind :: InvalidClientConfig ,
806
- "Unable to configure platform verifier." ,
807
- err. to_string ( ) ,
808
- ) )
810
+ tls_config_error (
811
+ "Failed to configure platform certificate verifier. This may indicate missing system certificate store or unsupported platform" ,
812
+ err,
813
+ )
809
814
} ) ?;
810
815
811
- if let Some ( ClientTlsParams {
812
- client_cert_chain : client_cert,
813
- client_key,
814
- } ) = tls_params. client_tls_params
815
- {
816
- config
816
+ match tls_params. client_tls_params {
817
+ Some ( ClientTlsParams {
818
+ client_cert_chain : client_cert,
819
+ client_key,
820
+ } ) => config
817
821
. with_client_auth_cert ( client_cert, client_key)
818
822
. map_err ( |err| {
819
- RedisError :: from ( (
820
- ErrorKind :: InvalidClientConfig ,
821
- "Unable to build client with TLS parameters provided." ,
822
- err. to_string ( ) ,
823
- ) )
824
- } ) ?
825
- } else {
826
- config. with_no_client_auth ( )
823
+ tls_config_error (
824
+ "Failed to configure client certificate authentication with platform verifier" ,
825
+ err,
826
+ )
827
+ } ) ?,
828
+ None => config. with_no_client_auth ( ) ,
827
829
}
828
830
}
829
- } else {
830
- // Default case: use platform verifier
831
- rustls:: ClientConfig :: builder ( )
832
- . with_platform_verifier ( )
833
- . map_err ( |err| {
834
- RedisError :: from ( (
835
- ErrorKind :: InvalidClientConfig ,
836
- "Unable to configure platform verifier." ,
837
- err. to_string ( ) ,
838
- ) )
839
- } ) ?
840
- . with_no_client_auth ( )
831
+ None => {
832
+ // Default case: use platform verifier with no client authentication
833
+ // This is the recommended default configuration for most applications
834
+ rustls:: ClientConfig :: builder ( )
835
+ . with_platform_verifier ( )
836
+ . map_err ( |err| {
837
+ tls_config_error (
838
+ "Failed to configure default TLS settings with platform verifier. This may indicate missing system certificate store" ,
839
+ err,
840
+ )
841
+ } ) ?
842
+ . with_no_client_auth ( )
843
+ }
841
844
} ;
842
845
846
+ // Handle insecure configurations (only when explicitly requested and feature enabled)
843
847
match ( insecure, cfg ! ( feature = "tls-rustls-insecure" ) ) {
844
848
#[ cfg( feature = "tls-rustls-insecure" ) ]
845
849
( true , true ) => {
850
+ // WARNING: This disables certificate verification - use only for testing!
851
+ // This configuration is inherently insecure and should never be used in production
846
852
let mut config = config;
847
853
config. enable_sni = false ;
848
- // nosemgrep
854
+
855
+ // Use dangerous certificate verifier that accepts any certificate
856
+ // nosemgrep - intentionally dangerous for testing purposes
849
857
config
850
858
. dangerous ( )
851
859
. set_certificate_verifier ( Arc :: new ( NoCertificateVerification {
852
- supported : rustls:: crypto:: ring :: default_provider ( )
860
+ supported : rustls:: crypto:: aws_lc_rs :: default_provider ( )
853
861
. signature_verification_algorithms ,
854
862
} ) ) ;
855
863
856
864
Ok ( config)
857
865
}
858
866
( true , false ) => {
867
+ // Insecure mode requested but feature not enabled - this is a configuration error
859
868
fail ! ( (
860
869
ErrorKind :: InvalidClientConfig ,
861
- "Cannot create insecure client without tls-rustls-insecure feature"
870
+ "Insecure TLS mode requested but 'tls-rustls-insecure' feature is not enabled. \
871
+ Enable the feature flag or use secure TLS configuration."
862
872
) ) ;
863
873
}
864
- _ => Ok ( config) ,
874
+ ( false , _) => {
875
+ // Secure mode (default) - return the properly configured client
876
+ Ok ( config)
877
+ }
865
878
}
866
879
}
867
880
881
+ /// Helper function to create consistent TLS configuration errors
882
+ fn tls_config_error ( context : & ' static str , error : impl std:: fmt:: Display ) -> RedisError {
883
+ RedisError :: from ( ( ErrorKind :: InvalidClientConfig , context, error. to_string ( ) ) )
884
+ }
885
+
868
886
fn connect_auth ( con : & mut Connection , connection_info : & RedisConnectionInfo ) -> RedisResult < ( ) > {
869
887
let mut command = cmd ( "AUTH" ) ;
870
888
if let Some ( username) = & connection_info. username {
0 commit comments