1+ use std:: { io, path:: Path , sync:: Arc } ;
2+
3+ use axum_server:: tls_rustls:: RustlsConfig ;
14use rcgen:: {
25 date_time_ymd, BasicConstraints , CertificateParams , DistinguishedName , DnType , IsCa , KeyPair ,
36 KeyUsagePurpose , SanType ,
47} ;
8+ use rustls_pemfile:: Item ;
9+ use tokio_rustls:: rustls:: {
10+ pki_types:: { CertificateDer , PrivateKeyDer } ,
11+ ServerConfig ,
12+ } ;
13+
14+ // Load TLS configuration from self-signed PEM files
15+ pub async fn config_self_signed ( ) -> crate :: Result < RustlsConfig > {
16+ let ( cert, key) = get_self_signed_cert ( ) ?;
17+ let cert = rustls_pemfile:: certs ( & mut cert. as_ref ( ) )
18+ . map ( |it| it. map ( |it| it. to_vec ( ) ) )
19+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
20+
21+ // Check the entire PEM file for the key in case it is not first section
22+ let mut key_vec: Vec < Vec < u8 > > = rustls_pemfile:: read_all ( & mut key. as_ref ( ) )
23+ . filter_map ( |i| match i. ok ( ) ? {
24+ Item :: Sec1Key ( key) => Some ( key. secret_sec1_der ( ) . to_vec ( ) ) ,
25+ Item :: Pkcs1Key ( key) => Some ( key. secret_pkcs1_der ( ) . to_vec ( ) ) ,
26+ Item :: Pkcs8Key ( key) => Some ( key. secret_pkcs8_der ( ) . to_vec ( ) ) ,
27+ _ => None ,
28+ } )
29+ . collect ( ) ;
30+
31+ // Make sure file contains only one key
32+ if key_vec. len ( ) != 1 {
33+ return Err ( io:: Error :: other ( "private key format not supported" ) . into ( ) ) ;
34+ }
35+
36+ let cert = cert. into_iter ( ) . map ( CertificateDer :: from) . collect ( ) ;
37+ let key = PrivateKeyDer :: try_from (
38+ key_vec
39+ . pop ( )
40+ . expect ( "private key should be present in the file" ) ,
41+ )
42+ . map_err ( io:: Error :: other) ?;
43+
44+ Ok ( config_from_der ( cert, key) ?)
45+ }
46+
47+ /// Load TLS configuration from PEM files
48+ pub async fn config_from_pem_chain_file (
49+ cert : impl AsRef < Path > ,
50+ chain : impl AsRef < Path > ,
51+ ) -> crate :: Result < RustlsConfig > {
52+ let cert = tokio:: fs:: read ( cert. as_ref ( ) ) . await ?;
53+ let cert = rustls_pemfile:: certs ( & mut cert. as_ref ( ) )
54+ . map ( |it| it. map ( |it| CertificateDer :: from ( it. to_vec ( ) ) ) )
55+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
56+
57+ let key = tokio:: fs:: read ( chain. as_ref ( ) ) . await ?;
58+ let key_cert: PrivateKeyDer = match rustls_pemfile:: read_one ( & mut key. as_ref ( ) ) ?
59+ . ok_or_else ( || io:: Error :: other ( "could not parse pem file" ) ) ?
60+ {
61+ Item :: Pkcs8Key ( key) => Ok ( key. into ( ) ) ,
62+ Item :: Sec1Key ( key) => Ok ( key. into ( ) ) ,
63+ Item :: Pkcs1Key ( key) => Ok ( key. into ( ) ) ,
64+ x => Err ( io:: Error :: other ( format ! (
65+ "invalid certificate format, received: {x:?}"
66+ ) ) ) ,
67+ } ?;
68+
69+ Ok ( config_from_der ( cert, key_cert) ?)
70+ }
71+
72+ fn config_from_der (
73+ cert_chain : Vec < CertificateDer < ' static > > ,
74+ key_der : PrivateKeyDer < ' static > ,
75+ ) -> io:: Result < RustlsConfig > {
76+ let mut config = ServerConfig :: builder ( )
77+ . with_no_client_auth ( )
78+ . with_single_cert ( cert_chain, key_der)
79+ . map_err ( io:: Error :: other) ?;
80+
81+ config. alpn_protocols = vec ! [
82+ b"h2" . to_vec( ) ,
83+ b"http/1.1" . to_vec( ) ,
84+ b"http/1.0" . to_vec( ) ,
85+ b"http/0.9" . to_vec( ) ,
86+ ] ;
87+
88+ Ok ( RustlsConfig :: from_config ( Arc :: new ( config) ) )
89+ }
590
6- /// Get self-signed certificate and key.
7- pub fn get_self_signed_cert ( ) -> crate :: Result < ( Vec < u8 > , Vec < u8 > ) > {
91+ fn get_self_signed_cert ( ) -> crate :: Result < ( Vec < u8 > , Vec < u8 > ) > {
892 let temp_dir = std:: env:: temp_dir ( ) . join ( env ! ( "CARGO_PKG_NAME" ) ) ;
993 if !temp_dir. exists ( ) {
1094 tracing:: info!( "Creating temp cert directory: {}" , temp_dir. display( ) ) ;
@@ -25,7 +109,6 @@ pub fn get_self_signed_cert() -> crate::Result<(Vec<u8>, Vec<u8>)> {
25109 Ok ( ( cert, key) )
26110}
27111
28- /// Generate self-signed certificate and key.
29112fn generate_self_signed ( ) -> crate :: Result < ( Vec < u8 > , Vec < u8 > ) > {
30113 let mut params = CertificateParams :: default ( ) ;
31114 params. not_before = date_time_ymd ( 1975 , 1 , 1 ) ;
0 commit comments