forked from proxmox-mirrors/proxmox
204 lines
5.4 KiB
Rust
204 lines
5.4 KiB
Rust
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<Self, Error> {
|
|
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: &Connection, user: &str, pass: &str) -> Result<(), Error> {
|
|
proxmox_async::runtime::block_on(con.authenticate_user(user, pass))
|
|
}
|
|
|
|
fn check_connection(config: &Config) -> Result<(), Error> {
|
|
let connection = Connection::new(config.clone());
|
|
proxmox_async::runtime::block_on(connection.check_connection())
|
|
}
|
|
|
|
fn default_config() -> Config {
|
|
Config {
|
|
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: ConnectionMode::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 = Connection::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 = Config {
|
|
servers: vec!["[::1]".into()],
|
|
..default_config()
|
|
};
|
|
|
|
let connection = Connection::new(settings);
|
|
|
|
assert!(authenticate(&connection, "test1", "password").is_ok());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn test_authentication_via_ldaps() -> Result<(), Error> {
|
|
let settings = Config {
|
|
port: Some(3894),
|
|
tls_mode: ConnectionMode::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 = Connection::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 = Config {
|
|
servers: vec!["invalid.host".into(), "localhost".into()],
|
|
..default_config()
|
|
};
|
|
|
|
let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?;
|
|
|
|
let connection = Connection::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 = Connection::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()
|
|
.first()
|
|
.unwrap()
|
|
.ends_with("@example.com"));
|
|
assert!(a.attributes.get("sn").unwrap().first().unwrap().eq("User"));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn test_check_connection() -> Result<(), Error> {
|
|
let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?;
|
|
|
|
let mut config = default_config();
|
|
assert!(check_connection(&config).is_ok());
|
|
|
|
config.base_dn = "dc=invalid,dc=com".into();
|
|
assert!(check_connection(&config).is_err());
|
|
config.base_dn = "dc=example,dc=com".into();
|
|
|
|
config.bind_password = Some("invalid".into());
|
|
assert!(check_connection(&config).is_err());
|
|
config.bind_password = Some("password".into());
|
|
|
|
config.bind_password = None;
|
|
assert!(check_connection(&config).is_err());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn test_retrieve_root_dse_attr() -> Result<(), Error> {
|
|
let _glauth = GlauthServer::new("tests/assets/glauth.cfg")?;
|
|
|
|
let connection = Connection::new(default_config());
|
|
|
|
let values = proxmox_async::runtime::block_on(
|
|
connection.retrieve_root_dse_attr("defaultNamingContext"),
|
|
)?;
|
|
|
|
assert_eq!(values, vec!["dc=example,dc=com"]);
|
|
|
|
Ok(())
|
|
}
|