From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id BEFD195175 for ; Tue, 17 Jan 2023 15:21:30 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id A01DACB31 for ; Tue, 17 Jan 2023 15:21:00 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Tue, 17 Jan 2023 15:20:58 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 7B710448D9 for ; Tue, 17 Jan 2023 15:20:58 +0100 (CET) From: Lukas Wagner To: pbs-devel@lists.proxmox.com Date: Tue, 17 Jan 2023 15:20:36 +0100 Message-Id: <20230117142037.847150-6-l.wagner@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230117142037.847150-1-l.wagner@proxmox.com> References: <20230117142037.847150-1-l.wagner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.024 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LOTSOFHASH 0.25 Emails with lots of hash-like gibberish SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [glauth.rs, invalid.host, lib.rs] Subject: [pbs-devel] [PATCH proxmox-ldap 5/6] tests: add LDAP integration tests X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Jan 2023 14:21:30 -0000 This commit adds integration tests to ensure that the crate works as intended. The tests are executed against a real LDAP server, namely `glauth`. `glauth` was chosen because it ships as a single, statically compiled binary and can be configured with a single configuration file. The tests are written as off-the-shelf unit tests. However, they are #[ignored] by default, as they have some special requirements: * They required the GLAUTH_BIN environment variable to be set, pointing to the location of the `glauth` binary. `glauth` will be started and stopped automatically by the test suite. * Tests have to be executed sequentially (`--test-threads 1`), otherwise multiple instances of the glauth server might bind to the same port. The `run_integration_tests.sh` checks whether GLAUTH_BIN is set, or if not, attempts to find `glauth` on PATH. The script also ensures that the tests are run sequentially. Signed-off-by: Lukas Wagner --- Cargo.toml | 2 + run_integration_tests.sh | 31 +++++ src/lib.rs | 2 +- tests/assets/generate_certificate.sh | 4 + tests/assets/glauth.cfg | 67 +++++++++++ tests/assets/glauth.crt | 29 +++++ tests/assets/glauth.key | 52 +++++++++ tests/assets/glauth_v6.cfg | 67 +++++++++++ tests/glauth.rs | 166 +++++++++++++++++++++++++++ 9 files changed, 419 insertions(+), 1 deletion(-) create mode 100755 run_integration_tests.sh create mode 100755 tests/assets/generate_certificate.sh create mode 100644 tests/assets/glauth.cfg create mode 100644 tests/assets/glauth.crt create mode 100644 tests/assets/glauth.key create mode 100644 tests/assets/glauth_v6.cfg create mode 100644 tests/glauth.rs diff --git a/Cargo.toml b/Cargo.toml index 021b14c..88965f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,5 @@ ldap3 = { version = "0.11", default_features = false, features = ["tls"] } serde = { version = "1.0", features = ["derive"] } native-tls = "0.2" +[dev_dependencies] +proxmox-async = "0.4" diff --git a/run_integration_tests.sh b/run_integration_tests.sh new file mode 100755 index 0000000..a7d7ed3 --- /dev/null +++ b/run_integration_tests.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Run integration tests for the proxmox_ldap crate. +# At this time, the tests require `glauth` to be available, +# either explicitly passed via $GLAUTH_PATH, or somewhere +# on $PATH. +# +# Tested with glauth v2.1.0 + +function run_tests { + # All tests that need glauth running are ignored, so + # that we can run `cargo test` without caring about them + # Also, only run on 1 thread, because otherwise + # glauth would need a separate port for each rurnning test + exec cargo test -- --ignored --test-threads 1 +} + + +if [ -z ${GLAUTH_BIN+x} ]; +then + GLAUTH_BIN=$(command -v glauth) + if [ $? -eq 0 ] ; + then + export GLAUTH_BIN + else + echo "glauth not found in PATH" + exit 1 + fi +fi + +run_tests diff --git a/src/lib.rs b/src/lib.rs index c80513e..7c808a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,7 @@ pub struct SearchParameters { pub user_filter: Option, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] /// Single LDAP user search result pub struct SearchResult { /// The full user's domain diff --git a/tests/assets/generate_certificate.sh b/tests/assets/generate_certificate.sh new file mode 100755 index 0000000..0c15216 --- /dev/null +++ b/tests/assets/generate_certificate.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +openssl req -x509 -newkey rsa:4096 -keyout glauth.key -out glauth.crt -days 36500 -nodes -subj '/CN=localhost' + diff --git a/tests/assets/glauth.cfg b/tests/assets/glauth.cfg new file mode 100644 index 0000000..8f57583 --- /dev/null +++ b/tests/assets/glauth.cfg @@ -0,0 +1,67 @@ +debug = true +[ldap] + enabled = true + listen = "0.0.0.0:3893" + +[ldaps] + enabled = true + listen = "0.0.0.0:3894" + cert = "tests/assets/glauth.crt" + key = "tests/assets/glauth.key" + + + +[backend] + datastore = "config" + baseDN = "dc=example,dc=com" + nameformat = "cn" + groupformat = "ou" + +# to create a passSHA256: echo -n "mysecret" | openssl dgst -sha256 + +[[users]] + name = "test1" + givenname="Test 1" + sn="User" + mail = "test1@example.com" + uidnumber = 1001 + primarygroup = 1000 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + +[[users]] + name = "test2" + givenname="Test 2" + sn="User" + mail = "test2@example.com" + uidnumber = 1002 + primarygroup = 1000 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + +[[users]] + name = "test3" + givenname="Test 3" + sn="User" + mail = "test3@example.com" + uidnumber = 1003 + primarygroup = 1000 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + + +[[users]] + name = "serviceuser" + mail = "serviceuser@example.com" + uidnumber = 1111 + primarygroup = 1001 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + [[users.capabilities]] + action = "search" + object = "*" + +[[groups]] + name = "testgroup" + gidnumber = 1000 + +[[groups]] + name = "svcaccts" + gidnumber = 1001 + diff --git a/tests/assets/glauth.crt b/tests/assets/glauth.crt new file mode 100644 index 0000000..6c0fdb7 --- /dev/null +++ b/tests/assets/glauth.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFCzCCAvOgAwIBAgIUREnN1wK1O6wTcVxSk6d5o0yHwjswDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIzMDExNzEwMjEwNFoYDzIxMjIx +MjI0MTAyMTA0WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC/6A+m00AXHsvecYiuzBLgL6laTCqjIXyoHKdI5znI +YOCXokCFDQI/wct1tA3GlIGuezECAHr76uF5G6T6DbSnbzE6Jd7ElKbQhnypwJc1 +4JsB7SYZVAz+Pj7CkjqmIEjwWWIFqotIvT/GfasHva/fGKKHhGFiU9N1gPthmrDr +vwr5q2b+2FxyzkBlHD0pdOIO/aXOjISkS0MqOHRmUuoADXPjonWe0ujF/oI33ZOm +8Xw+bdTuHEpgaioDP5LaSGdK+Y/1lOFqt8/9W8sCmo/Q8cLH1wZlkycl4d4jeMtK +BB/iPot8n+9uMtZCjHS8zmedZKoIFGlnfHYmP8ckY7pHXfNoun/sHB9kXHlx0Rv2 +NCnd/117oGv6FFEio6lf+11Cm6qNYOxzsoZY6VpozMrI9CDFrMGwzvUuirzMmJql +0TgrWJQE43bo5Rxkdd30TuqghXV9ENwG1sXacun2GGxuc5F6QG6l6k5H0dOh3gGG +v7NAPKuIRi7oDJ3+B8wS4PTnroqRGVoKX7luQj2JrAB7mt42fE1iL9eEIjsde678 +oomnoOVcgWOpJCzJ5J10cNddhBO1JGMN/iHULeHLKzxWBptZTYWIwKp5hgZCK1s+ +fiuvh8CRxiI5IwyDLlQbI4kf6iLxipFqIHNsddYRnzZIW/iogRfdd0iPvqorXucV +tQIDAQABo1MwUTAdBgNVHQ4EFgQULLKz9hnIn5jU7ELlth4DXPhGrywwHwYDVR0j +BBgwFoAULLKz9hnIn5jU7ELlth4DXPhGrywwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAOr9nQEvwNF2qcIteYV3WgRt//oSf/L+qYANVD86ZUK2c +07zWL9mKxXwXCz1ncfjLMMb/ZO3gnrI2yW5MJdyHup+28ESqMmvNX1Sz9hkjqaP0 +irM3sD56FhjUYa8H8g3k1kKl7N4ogt0JZpwJt+JFoRHu1vaWKahOmn8owP789CPQ +391zyhqZHOowmHSd0lu8AWSdIuzU5Q5Vk38+GW4gHAxsSG0hWempg3U7g9DOAXbe +kFHSa8H4bpXMdwndZJPv+NhA8LYG5UC2aD86dUWXrfEMuXLqvxMpYIZ76A3UZUWl ++zmEKHmjCumz5WdjnPGIC/NJiREM6kUd/UqWv4XuPkgQjmnlsB4POKaV658uYFvF +HnLPEkwT6jnJqyMH0YGhbwZdbS/UpARvoZ4ZkpKFVLB3SlG/8cn+YtXLMBwefAUr +cAwzLCcu28LX/bq+65HldFxjYr2XddcbJErLvyfl5w/+UaqrCnSXiSL5yqxpcie6 +w3r+U5Ei51iJEJTJIabcQiH0+dkLNVRvaCywcChgUjHqNdTtZvGuvGiwvfJ3ItSI +HkvcWug5pO+kyNmaDPLPYtL4mm9tIMgdIIwXZSHcOC459aVvh+5Mmqwat4Ijfa7+ +TBkr87t671pL1XH5eeeUKYbFpKq/ZxA+O8LT9IXeLyediLvcf7V5BqwuuPHkzHw= +-----END CERTIFICATE----- diff --git a/tests/assets/glauth.key b/tests/assets/glauth.key new file mode 100644 index 0000000..d29e06a --- /dev/null +++ b/tests/assets/glauth.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +yWQL2XczMt+NRQn+v23VKpQVK/R9PMEV +-----END PRIVATE KEY----- diff --git a/tests/assets/glauth_v6.cfg b/tests/assets/glauth_v6.cfg new file mode 100644 index 0000000..74e838d --- /dev/null +++ b/tests/assets/glauth_v6.cfg @@ -0,0 +1,67 @@ +debug = true +[ldap] + enabled = true + listen = "[::]:3893" + +[ldaps] + enabled = true + listen = "[::]:3894" + cert = "tests/assets/glauth.crt" + key = "tests/assets/glauth.key" + + + +[backend] + datastore = "config" + baseDN = "dc=example,dc=com" + nameformat = "cn" + groupformat = "ou" + +# to create a passSHA256: echo -n "mysecret" | openssl dgst -sha256 + +[[users]] + name = "test1" + givenname="Test 1" + sn="User" + mail = "test1@example.com" + uidnumber = 1001 + primarygroup = 1000 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + +[[users]] + name = "test2" + givenname="Test 2" + sn="User" + mail = "test2@example.com" + uidnumber = 1002 + primarygroup = 1000 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + +[[users]] + name = "test3" + givenname="Test 3" + sn="User" + mail = "test3@example.com" + uidnumber = 1003 + primarygroup = 1000 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + + +[[users]] + name = "serviceuser" + mail = "serviceuser@example.com" + uidnumber = 1111 + primarygroup = 1001 + passsha256 = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8" # password + [[users.capabilities]] + action = "search" + object = "*" + +[[groups]] + name = "testgroup" + gidnumber = 1000 + +[[groups]] + name = "svcaccts" + gidnumber = 1001 + diff --git a/tests/glauth.rs b/tests/glauth.rs new file mode 100644 index 0000000..856ddcf --- /dev/null +++ b/tests/glauth.rs @@ -0,0 +1,166 @@ +use std::{ + process::{Child, Command, Stdio}, + thread::sleep, + time::Duration, +}; + +use anyhow::{Context, Error}; +use proxmox_ldap::*; + +struct GlauthServer { + handle: Child, +} + +impl GlauthServer { + fn new(path: &str) -> Result { + let glauth_bin = std::env::var("GLAUTH_BIN").context("GLAUTH_BIN is not set")?; + let handle = Command::new(&glauth_bin) + .arg("-c") + .arg(path) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .context("Could not start glauth process")?; + + // Make 'sure' that glauth is up + sleep(Duration::from_secs(1)); + + Ok(Self { handle }) + } +} + +impl Drop for GlauthServer { + fn drop(&mut self) { + self.handle.kill().ok(); + } +} + +fn authenticate(con: &LdapConnection, user: &str, pass: &str) -> Result<(), Error> { + proxmox_async::runtime::block_on(con.authenticate_user(user, pass)) +} + +fn default_config() -> LdapConfig { + LdapConfig { + servers: vec!["localhost".into()], + port: Some(3893), + user_attr: "cn".into(), + base_dn: "dc=example,dc=com".into(), + bind_dn: Some("cn=serviceuser,ou=svcaccts,dc=example,dc=com".into()), + bind_password: Some("password".into()), + tls_mode: LdapConnectionMode::Ldap, + verify_certificate: false, + additional_trusted_certificates: None, + certificate_store_path: Some("/etc/ssl/certs".into()) + } +} + +#[test] +#[ignore] +fn test_authentication() -> Result<(), Error> { + let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?; + + let connection = LdapConnection::new(default_config()); + + assert!(authenticate(&connection, "test1", "password").is_ok()); + assert!(authenticate(&connection, "test2", "password").is_ok()); + assert!(authenticate(&connection, "test3", "password").is_ok()); + assert!(authenticate(&connection, "test1", "invalid").is_err()); + assert!(authenticate(&connection, "invalid", "password").is_err()); + + Ok(()) +} + +#[test] +#[ignore] +fn test_authentication_via_ipv6() -> Result<(), Error> { + let _glauth = GlauthServer::new("tests/assets/glauth_v6.cfg")?; + + let settings = LdapConfig { + servers: vec!["[::1]".into()], + ..default_config() + }; + + let connection = LdapConnection::new(settings); + + assert!(authenticate(&connection, "test1", "password").is_ok()); + + Ok(()) +} + +#[test] +#[ignore] +fn test_authentication_via_ldaps() -> Result<(), Error> { + let settings = LdapConfig { + port: Some(3894), + tls_mode: LdapConnectionMode::Ldaps, + verify_certificate: true, + additional_trusted_certificates: Some(vec!["tests/assets/glauth.crt".into()]), + ..default_config() + }; + + let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?; + + let connection = LdapConnection::new(settings); + + assert!(authenticate(&connection, "test1", "password").is_ok()); + assert!(authenticate(&connection, "test1", "invalid").is_err()); + + Ok(()) +} + +#[test] +#[ignore] +fn test_fallback() -> Result<(), Error> { + let settings = LdapConfig { + servers: vec!["invalid.host".into(), "localhost".into()], + ..default_config() + }; + + let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?; + + let connection = LdapConnection::new(settings); + assert!(authenticate(&connection, "test1", "password").is_ok()); + + Ok(()) +} + +#[test] +#[ignore] +fn test_search() -> Result<(), Error> { + let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?; + + let connection = LdapConnection::new(default_config()); + + let params = SearchParameters { + attributes: vec!["cn".into(), "mail".into(), "sn".into()], + user_classes: vec!["posixAccount".into()], + user_filter: Some("(cn=test*)".into()), + }; + + let search_results = proxmox_async::runtime::block_on(connection.search_entities(¶ms))?; + + assert_eq!(search_results.len(), 3); + + for a in search_results { + assert!(a.dn.starts_with("cn=test")); + assert!(a.dn.ends_with("ou=testgroup,ou=users,dc=example,dc=com")); + + assert!(a + .attributes + .get("mail") + .unwrap() + .get(0) + .unwrap() + .ends_with("@example.com")); + assert!(a + .attributes + .get("sn") + .unwrap() + .get(0) + .unwrap() + .eq("User".into())); + } + + Ok(()) +} -- 2.30.2