mirror of
				https://github.com/nitnelave/lldap.git
				synced 2023-04-12 14:25:13 +00:00 
			
		
		
		
	healthcheck: check that the server's certificate is the one in the config
This commit is contained in:
		
							parent
							
								
									558bb37354
								
							
						
					
					
						commit
						fcfe87d18a
					
				@ -31,7 +31,6 @@ lber = "0.4.1"
 | 
				
			|||||||
ldap3_proto = ">=0.3.1"
 | 
					ldap3_proto = ">=0.3.1"
 | 
				
			||||||
log = "*"
 | 
					log = "*"
 | 
				
			||||||
orion = "0.17"
 | 
					orion = "0.17"
 | 
				
			||||||
rustls = "0.20"
 | 
					 | 
				
			||||||
rustls-pemfile = "1"
 | 
					rustls-pemfile = "1"
 | 
				
			||||||
serde = "*"
 | 
					serde = "*"
 | 
				
			||||||
serde_bytes = "0.11"
 | 
					serde_bytes = "0.11"
 | 
				
			||||||
@ -115,5 +114,9 @@ version = "0.11"
 | 
				
			|||||||
default-features = false
 | 
					default-features = false
 | 
				
			||||||
features = ["rustls-tls-webpki-roots"]
 | 
					features = ["rustls-tls-webpki-roots"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.rustls]
 | 
				
			||||||
 | 
					version = "0.20"
 | 
				
			||||||
 | 
					features = ["dangerous_configuration"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dev-dependencies]
 | 
					[dev-dependencies]
 | 
				
			||||||
mockall = "0.11"
 | 
					mockall = "0.11"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::infra::configuration::LdapsOptions;
 | 
					use crate::infra::{configuration::LdapsOptions, ldap_server::read_certificates};
 | 
				
			||||||
use anyhow::{anyhow, bail, ensure, Context, Result};
 | 
					use anyhow::{anyhow, bail, ensure, Context, Result};
 | 
				
			||||||
use futures_util::SinkExt;
 | 
					use futures_util::SinkExt;
 | 
				
			||||||
use ldap3_proto::{
 | 
					use ldap3_proto::{
 | 
				
			||||||
@ -65,6 +65,7 @@ where
 | 
				
			|||||||
        invalid_answer
 | 
					        invalid_answer
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    info!("Success");
 | 
					    info!("Success");
 | 
				
			||||||
 | 
					    resp.close().await?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -85,15 +86,44 @@ fn get_root_certificates() -> rustls::RootCertStore {
 | 
				
			|||||||
    root_store
 | 
					    root_store
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn get_tls_connector() -> Result<RustlsTlsConnector> {
 | 
					fn get_tls_connector(ldaps_options: &LdapsOptions) -> Result<RustlsTlsConnector> {
 | 
				
			||||||
    use rustls::ClientConfig;
 | 
					    let mut client_config = rustls::ClientConfig::builder()
 | 
				
			||||||
    let client_config = std::sync::Arc::new(
 | 
					 | 
				
			||||||
        ClientConfig::builder()
 | 
					 | 
				
			||||||
        .with_safe_defaults()
 | 
					        .with_safe_defaults()
 | 
				
			||||||
        .with_root_certificates(get_root_certificates())
 | 
					        .with_root_certificates(get_root_certificates())
 | 
				
			||||||
            .with_no_client_auth(),
 | 
					        .with_no_client_auth();
 | 
				
			||||||
    );
 | 
					    let (certs, _private_key) = read_certificates(ldaps_options)?;
 | 
				
			||||||
    Ok(client_config.into())
 | 
					    // Check that the server cert is the one in the config file.
 | 
				
			||||||
 | 
					    struct CertificateVerifier {
 | 
				
			||||||
 | 
					        certificate: rustls::Certificate,
 | 
				
			||||||
 | 
					        certificate_path: String,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    impl rustls::client::ServerCertVerifier for CertificateVerifier {
 | 
				
			||||||
 | 
					        fn verify_server_cert(
 | 
				
			||||||
 | 
					            &self,
 | 
				
			||||||
 | 
					            end_entity: &rustls::Certificate,
 | 
				
			||||||
 | 
					            _intermediates: &[rustls::Certificate],
 | 
				
			||||||
 | 
					            _server_name: &rustls::ServerName,
 | 
				
			||||||
 | 
					            _scts: &mut dyn Iterator<Item = &[u8]>,
 | 
				
			||||||
 | 
					            _ocsp_response: &[u8],
 | 
				
			||||||
 | 
					            _now: std::time::SystemTime,
 | 
				
			||||||
 | 
					        ) -> std::result::Result<rustls::client::ServerCertVerified, rustls::Error> {
 | 
				
			||||||
 | 
					            if end_entity != &self.certificate {
 | 
				
			||||||
 | 
					                return Err(rustls::Error::InvalidCertificateData(format!(
 | 
				
			||||||
 | 
					                    "Server certificate doesn't match the one in the config file {}",
 | 
				
			||||||
 | 
					                    &self.certificate_path
 | 
				
			||||||
 | 
					                )));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Ok(rustls::client::ServerCertVerified::assertion())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let mut dangerous_config = rustls::client::DangerousClientConfig {
 | 
				
			||||||
 | 
					        cfg: &mut client_config,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    dangerous_config.set_certificate_verifier(std::sync::Arc::new(CertificateVerifier {
 | 
				
			||||||
 | 
					        certificate: certs.first().expect("empty certificate chain").clone(),
 | 
				
			||||||
 | 
					        certificate_path: ldaps_options.cert_file.clone(),
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					    Ok(std::sync::Arc::new(client_config).into())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[instrument(skip_all, level = "info", err)]
 | 
					#[instrument(skip_all, level = "info", err)]
 | 
				
			||||||
@ -102,15 +132,20 @@ pub async fn check_ldaps(ldaps_options: &LdapsOptions) -> Result<()> {
 | 
				
			|||||||
        info!("LDAPS not enabled");
 | 
					        info!("LDAPS not enabled");
 | 
				
			||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    let tls_connector = get_tls_connector()?;
 | 
					    let tls_connector =
 | 
				
			||||||
 | 
					        get_tls_connector(ldaps_options).context("while preparing the tls connection")?;
 | 
				
			||||||
    let url = format!("localhost:{}", ldaps_options.port);
 | 
					    let url = format!("localhost:{}", ldaps_options.port);
 | 
				
			||||||
    check_ldap_endpoint(
 | 
					    check_ldap_endpoint(
 | 
				
			||||||
        tls_connector
 | 
					        tls_connector
 | 
				
			||||||
            .connect(
 | 
					            .connect(
 | 
				
			||||||
                rustls::ServerName::try_from(url.as_str())?,
 | 
					                rustls::ServerName::try_from("localhost")
 | 
				
			||||||
                TcpStream::connect(&url).await?,
 | 
					                    .context("while parsing the server name")?,
 | 
				
			||||||
 | 
					                TcpStream::connect(&url)
 | 
				
			||||||
 | 
					                    .await
 | 
				
			||||||
 | 
					                    .context("while connecting TCP")?,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .await?,
 | 
					            .await
 | 
				
			||||||
 | 
					            .context("while connecting TLS")?,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .await
 | 
					    .await
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,8 @@ use crate::{
 | 
				
			|||||||
        opaque_handler::OpaqueHandler,
 | 
					        opaque_handler::OpaqueHandler,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    infra::{
 | 
					    infra::{
 | 
				
			||||||
        access_control::AccessControlledBackendHandler, configuration::Configuration,
 | 
					        access_control::AccessControlledBackendHandler,
 | 
				
			||||||
 | 
					        configuration::{Configuration, LdapsOptions},
 | 
				
			||||||
        ldap_handler::LdapHandler,
 | 
					        ldap_handler::LdapHandler,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -126,20 +127,22 @@ fn read_private_key(key_file: &str) -> Result<PrivateKey> {
 | 
				
			|||||||
        .map(rustls::PrivateKey)
 | 
					        .map(rustls::PrivateKey)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn get_tls_acceptor(config: &Configuration) -> Result<RustlsTlsAcceptor> {
 | 
					pub fn read_certificates(
 | 
				
			||||||
    use rustls::{Certificate, ServerConfig};
 | 
					    ldaps_options: &LdapsOptions,
 | 
				
			||||||
    use rustls_pemfile::certs;
 | 
					) -> Result<(Vec<rustls::Certificate>, rustls::PrivateKey)> {
 | 
				
			||||||
    use std::{fs::File, io::BufReader};
 | 
					    use std::{fs::File, io::BufReader};
 | 
				
			||||||
    // Load TLS key and cert files
 | 
					    let certs = rustls_pemfile::certs(&mut BufReader::new(File::open(&ldaps_options.cert_file)?))?
 | 
				
			||||||
    let certs = certs(&mut BufReader::new(File::open(
 | 
					 | 
				
			||||||
        &config.ldaps_options.cert_file,
 | 
					 | 
				
			||||||
    )?))?
 | 
					 | 
				
			||||||
        .into_iter()
 | 
					        .into_iter()
 | 
				
			||||||
    .map(Certificate)
 | 
					        .map(rustls::Certificate)
 | 
				
			||||||
        .collect::<Vec<_>>();
 | 
					        .collect::<Vec<_>>();
 | 
				
			||||||
    let private_key = read_private_key(&config.ldaps_options.key_file)?;
 | 
					    let private_key = read_private_key(&ldaps_options.key_file)?;
 | 
				
			||||||
 | 
					    Ok((certs, private_key))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn get_tls_acceptor(ldaps_options: &LdapsOptions) -> Result<RustlsTlsAcceptor> {
 | 
				
			||||||
 | 
					    let (certs, private_key) = read_certificates(ldaps_options)?;
 | 
				
			||||||
    let server_config = std::sync::Arc::new(
 | 
					    let server_config = std::sync::Arc::new(
 | 
				
			||||||
        ServerConfig::builder()
 | 
					        rustls::ServerConfig::builder()
 | 
				
			||||||
            .with_safe_defaults()
 | 
					            .with_safe_defaults()
 | 
				
			||||||
            .with_no_client_auth()
 | 
					            .with_no_client_auth()
 | 
				
			||||||
            .with_single_cert(certs, private_key)?,
 | 
					            .with_single_cert(certs, private_key)?,
 | 
				
			||||||
@ -190,7 +193,8 @@ where
 | 
				
			|||||||
    if config.ldaps_options.enabled {
 | 
					    if config.ldaps_options.enabled {
 | 
				
			||||||
        let tls_context = (
 | 
					        let tls_context = (
 | 
				
			||||||
            context_for_tls,
 | 
					            context_for_tls,
 | 
				
			||||||
            get_tls_acceptor(config).context("while setting up the SSL certificate")?,
 | 
					            get_tls_acceptor(&config.ldaps_options)
 | 
				
			||||||
 | 
					                .context("while setting up the SSL certificate")?,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        let tls_binder = move || {
 | 
					        let tls_binder = move || {
 | 
				
			||||||
            let tls_context = tls_context.clone();
 | 
					            let tls_context = tls_context.clone();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user