From af983e07fc6a2e9c619c568cb3219d7a0ba1196a Mon Sep 17 00:00:00 2001 From: guenhter Date: Tue, 24 Sep 2024 09:26:22 +0200 Subject: [PATCH] feat: support setting openssl certs for openldap --- Cargo.toml | 4 +- src/openldap/create_certs.sh | 50 ++++++++++++ src/openldap/mod.rs | 145 ++++++++++++++++++++++++++++++++++- 3 files changed, 195 insertions(+), 4 deletions(-) create mode 100755 src/openldap/create_certs.sh diff --git a/Cargo.toml b/Cargo.toml index e3610b1..e9f0c49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,9 +110,7 @@ k8s-openapi = { version = "0.21.1", features = ["v1_29"] } clickhouse = "0.11.6" vaultrs = "0.7.2" openssl-sys = { version = "0.9.103", features = ["vendored"] } - -[patch.crates-io] -testcontainers = { git = "https://github.com/guenhter/testcontainers-rs.git", branch = "release-0.23.0" } +native-tls = { version = "0.2.12", features = ["vendored"] } [[example]] name = "postgres" diff --git a/src/openldap/create_certs.sh b/src/openldap/create_certs.sh new file mode 100755 index 0000000..7f2b4c4 --- /dev/null +++ b/src/openldap/create_certs.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Set variables +ROOT_SUBJECT="/C=AT/O=Test/OU=Testcontainer/CN=rootCA" +SERVER_SUBJECT="/C=AT/O=Test/OU=Testcontainer/CN=ldap.example.org" + +# Create directory for certificates +mkdir -p certs +rm -fr certs/* +cd certs + +# Create a config file for the server certificate +cat >server.cnf <, + key: impl Into, + ca: impl Into, + ) -> Self { + self.copy_to_sources + .push(CopyToContainer::new(cert, "/certs/cert.crt")); + self.copy_to_sources + .push(CopyToContainer::new(key, "/certs/key.key")); + self.copy_to_sources + .push(CopyToContainer::new(ca, "/certs/ca.crt")); + + self.env_vars.insert( + "LDAP_TLS_CERT_FILE".to_owned(), + "/certs/cert.crt".to_owned(), + ); + self.env_vars + .insert("LDAP_TLS_KEY_FILE".to_owned(), "/certs/key.key".to_owned()); + self.env_vars + .insert("LDAP_TLS_CA_FILE".to_owned(), "/certs/ca.crt".to_owned()); + + self.env_vars + .insert("LDAP_ENABLE_TLS".to_owned(), "yes".to_owned()); + + self + } } /// hash to be used in generation of user passwords. @@ -408,7 +439,7 @@ impl Image for OpenLDAP { } fn expose_ports(&self) -> &[ContainerPort] { - &[OPENLDAP_PORT] + &[OPENLDAP_PORT, OPENLDAPS_PORT] } fn copy_to_sources(&self) -> impl IntoIterator { @@ -600,4 +631,116 @@ userpassword: {SSHA}1vtVpqX6Y77jAVs/1uTd/rHS8YRYEh/9 ldap.unbind().await?; Ok(()) } + + #[tokio::test] + async fn ldap_secure() -> Result<(), Box> { + let root_ca = r#"-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUJOEGi61FLb02VN7OyUj8WQwldEMwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVQxDTALBgNVBAoMBFRlc3QxFjAUBgNVBAsMDVRlc3Rj +b250YWluZXIxDzANBgNVBAMMBnJvb3RDQTAeFw0yNDA5MjQwNjQzMzlaFw0yNTA5 +MjQwNjQzMzlaMEUxCzAJBgNVBAYTAkFUMQ0wCwYDVQQKDARUZXN0MRYwFAYDVQQL +DA1UZXN0Y29udGFpbmVyMQ8wDQYDVQQDDAZyb290Q0EwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCI6E4qyB4jS0MDCEoREXpy93qQCYDVgkYIolmNXgKQ +PcDr+SLPifg0yybdaERFM2RFXfnOKKOIL/SWlXFMm4hlk9s2WPNVdeGmHpIcEeUH +nkw5mVIm0Bn5PN7P5GCMYrKd3sjxSBT54sQaFzOO8xUP+pGQFmWWxu89TZtusgL7 +WaEGWZng5XyjmFUNjzS8ppG19DP6FsfwkH+X//5DFc0rnQYI+vofpxe153wNYKYU +Gw6fpOvl32xkNvm0N12RV5vI0y6tDe6Mprkl4NfOSkaUv2jbQ+AwSLwfBvkXLFnK +pBF/uxEAl5LTfhaDTtbXF9X3FrVB5+kRteqg4LcFsD13AgMBAAGjUzBRMB0GA1Ud +DgQWBBTwYJpbDj3GrICSwAQj4TbBMXp46DAfBgNVHSMEGDAWgBTwYJpbDj3GrICS +wAQj4TbBMXp46DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBs +dSEzbRDQEGcD2WF+LWz0f+qYmpQZmuorhWhBMx/vsBkARVgXhO/8zYskEV3Q7JVJ +kd4b/AOrSSo8RKfn1y+ahznjlEeC0yqHl1COq+B7lc875TmOLXVNwas7QRiGU9d1 +qWmAxXV68a6KhnzWJo2YaD+QOXp3CKVgIPdYx/p5W5pESQYDEjD54SPMqj2q80iC +y5I6hJQRhE9zs3QAhA8jO8zhLo62QooWPnmToTXUXxxVhcNh5RPpUx6kY12lALim +yEd4SHpM1xUaMN6rjJLNFfU+KSQawPljBrdpiIKR/JejJTmGQ//FhMZRbF2WiBVc +vJf0O9rm9ygB3kD1Gvjc +-----END CERTIFICATE----- +"#; + let key = r#"-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCq5DVU3Q1UlJVu +swYq87ObR2vl+4NcVcZzHL1BtfGK+mAK11R3rzP4O2FmvuZQ52ad48r6z35OqcYI +BlrBHQuKcafzqSFJEIw6a1rORI51k21J4ooKdXwBoiQjYrjbGw2cV63T898Cs6+g +SVXm74dEqudA49V5VsrmgY/FP7HHHB/1Bghl9laHvP7zFyJvJ0Koxg/Hgnp4D8rE +f0nz2ZSmZsyQZI+p2hfP6te/osn11846NajnVyXqTj8azalMTn56/THidt+/0yVP +MGxeTsy12pasp2D7+tnVfQAzc0uc1QUZo67xrWWx+W62iVvUZ0l5ps/CWEbGf/vj +rUqnqxdtAgMBAAECggEATa4vufRDr3tdE/Vn69Vcgsyr9N5n/2x0KXZaZ0jL09dt +GfB40nC/SGrBo0FKk2Mkh8f4yBrSuPI+dP5ieZ741IVGiaGLYlmVzKZpIBMUyMhr +qObDxe5SoLFyCO3CxsJc5QEMIKkd6e4A+vTrCe8+x02CkkIekyoLUE17q3eBGdbm +IaSTqToNS+JpwhSwWkHK0NMzk+cTu97rxcfCPY7zjB3E4URCm345D8RHYuF+fKfH +21iXkk/JJ06OrGC6WxHhtVe5ipLKUkGUPpAi83a3GHR8RX7Xo/BVzXVqyWQfs/3l +W3/jPrFz2rQAo24NQOvW3QRHoCGaCk0v7/ix6zSI5wKBgQDb28lpgDONys9uX4AK +NOvkyT7mGry+0Laopu8oVx4thi60ixOdDnj5UUMPdmw7oabmzoXzQX+xEFb21/L1 +USfu2cPIZJoWZQwzQ1reJdoNlFYWTKCDsZ1ewUtiiY9YerFe7dplu8mx9OJz6UgI +Iem0maAiIXjVuRFI2WrOLH2ONwKBgQDG+8KFAegTIqrFklygSDQUM4/oSG9oTHjk +nZCcwr44dYkQjG2ab+PRsRu48gwsu6TcyiLg1aFkSFzhrKOjoksdYAOmGRKT1bkT +abeuQFj8PJplNjKe3JpDgwUwwwfxMLVa1qDgwxOO2ss8KumTDmH24ifwA0PAD30S +8L/NzhzVewKBgQDDE8MkrzIPL9LZ1jbf15EvUTlUJokurjZEcspletc2AYdTfsuK +YZsJbQcZozPpvUdAKCNGcemBDER9haL39GiAUAydtFXcZRBsM+lejytpPSMdaiRK +dcByoQPojLH6CfNzjYxpFDSkh+qeenEFdkHNkzo4zoZO7ITfpLpV8bf+BQKBgQDF +oqc4voUIBIXDiLTRSgXYDsKfftqQqGvm/gz1doPCxhLmSeRO4VVRH+0eC+NFxvZf +ibGMyQLs/OasC3HZBEhBG+1j20FVbpDNlFIpE6aOmY7seiFbIldiOM89+Gh6CdwH +JmhR9dAGMpBr6V9nfYCV21i5jjSLnZan6lFHk7GV4wKBgQDBVpXL+02lg7iILL6I +reAM91IO/qRD8J2Jz6YkOt3xXLWzI6lnklWTS0nNqqNu14dZ/W8X+N1yrb9rX/YD +8qOiAVLmgff95WzXgWPLLDffiIs/7rsVTdYJCEhyYeA4JJATg9y2pEgjDvUKTBI5 +erLQmtnKSEkes6jFEhOqRYgcQg== +-----END PRIVATE KEY----- +"#; + let cert = r#"-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIUTd/Zr8U53zdbEz9RMV2OD3FdxVowDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVQxDTALBgNVBAoMBFRlc3QxFjAUBgNVBAsMDVRlc3Rj +b250YWluZXIxDzANBgNVBAMMBnJvb3RDQTAeFw0yNDA5MjQwNjQzMzlaFw0yNTA5 +MjQwNjQzMzlaME8xCzAJBgNVBAYTAkFUMQ0wCwYDVQQKDARUZXN0MRYwFAYDVQQL +DA1UZXN0Y29udGFpbmVyMRkwFwYDVQQDDBBsZGFwLmV4YW1wbGUub3JnMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAquQ1VN0NVJSVbrMGKvOzm0dr5fuD +XFXGcxy9QbXxivpgCtdUd68z+DthZr7mUOdmnePK+s9+TqnGCAZawR0LinGn86kh +SRCMOmtazkSOdZNtSeKKCnV8AaIkI2K42xsNnFet0/PfArOvoElV5u+HRKrnQOPV +eVbK5oGPxT+xxxwf9QYIZfZWh7z+8xcibydCqMYPx4J6eA/KxH9J89mUpmbMkGSP +qdoXz+rXv6LJ9dfOOjWo51cl6k4/Gs2pTE5+ev0x4nbfv9MlTzBsXk7MtdqWrKdg ++/rZ1X0AM3NLnNUFGaOu8a1lsflutolb1GdJeabPwlhGxn/7461Kp6sXbQIDAQAB +o4GIMIGFMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAeBgNV +HREEFzAVgglsb2NhbGhvc3SCCG9wZW5sZGFwMB0GA1UdDgQWBBSmpP49h2VxAv31 +Cfa2awq0I8tKbTAfBgNVHSMEGDAWgBTwYJpbDj3GrICSwAQj4TbBMXp46DANBgkq +hkiG9w0BAQsFAAOCAQEAU0h83lpOFCbBfRQa7w7hZ+FJSXUZ4VX0tWFqmNx/IpxF +7Cxi/LUKg5Gpy9T45rBFJetDqWlPjR+WDMEPO1g7yb5//xawenM9SueuV0B86qyo +CmJtfAaBeEVQRZn503GJZMJzfVTRYuGQPmSF41M5O81t0Mu6Bw3qCNQgIJ5WANkm +3XIT0B77G/Y+NvTlXZEKdQ6xqbepvpUubayLR8eix7aIwT4C++dpfheQGcPVJu0j +RAK7To6s2WXfbrWo547RYux1fQrlIwF0aGbkFaHb6d2X0ifOeYAZvks7QIXyc2c0 +f8GCAzsWx/hkplHugMaa+28Tz3jVj4BXzqWas4/gcA== +-----END CERTIFICATE----- +"#; + + let _ = pretty_env_logger::try_init(); + let openldap_image = OpenLDAP::default() + .with_allow_anon_binding(false) + .with_user("maximiliane", "pwd1") + .with_certs( + cert.to_string().into_bytes(), + key.to_string().into_bytes(), + root_ca.to_string().into_bytes(), + ); + let node = openldap_image.start().await?; + + let connection_string = format!( + "ldaps://{}:{}", + node.get_host().await?, + node.get_host_port_ipv4(OPENLDAPS_PORT).await?, + ); + + let mut builder = native_tls::TlsConnector::builder(); + let root_ca = native_tls::Certificate::from_pem(root_ca.as_bytes())?; + let connector = builder.add_root_certificate(root_ca).build()?; + + let settings = ldap3::LdapConnSettings::new().set_connector(connector); + let (conn, mut ldap) = + ldap3::LdapConnAsync::with_settings(settings, &connection_string).await?; + + ldap3::drive!(conn); + ldap.simple_bind("cn=maximiliane,ou=users,dc=example,dc=org", "pwd1") + .await? + .success()?; + let users = read_users(&mut ldap, "(cn=*)", &["cn"]).await?; + assert_eq!(users.len(), 2); // cn=maximiliane and cn=readers + ldap.unbind().await?; + Ok(()) + } }