2020-02-13 00:43:01 +01:00
|
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
|
|
use std::thread;
|
2020-10-22 06:40:31 +02:00
|
|
|
use std::time::Duration;
|
2020-02-13 00:43:01 +01:00
|
|
|
|
2020-06-18 02:30:42 +02:00
|
|
|
use kanidm::audit::LogLevel;
|
2020-02-13 00:43:01 +01:00
|
|
|
use kanidm::config::{Configuration, IntegrationTestConfig};
|
|
|
|
use kanidm::core::create_server_core;
|
|
|
|
|
|
|
|
use kanidm_unix_common::cache::CacheLayer;
|
2020-06-21 13:57:48 +02:00
|
|
|
use kanidm_unix_common::constants::{
|
|
|
|
DEFAULT_GID_ATTR_MAP, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL,
|
|
|
|
DEFAULT_UID_ATTR_MAP,
|
|
|
|
};
|
2020-02-13 00:43:01 +01:00
|
|
|
use tokio::runtime::Runtime;
|
|
|
|
|
2020-02-15 01:27:25 +01:00
|
|
|
use kanidm_client::asynchronous::KanidmAsyncClient;
|
2020-02-13 00:43:01 +01:00
|
|
|
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
use async_std::task;
|
2020-09-06 00:44:35 +02:00
|
|
|
use tokio::sync::mpsc;
|
2020-08-04 04:58:11 +02:00
|
|
|
|
2020-02-13 00:43:01 +01:00
|
|
|
static PORT_ALLOC: AtomicUsize = AtomicUsize::new(18080);
|
2020-05-03 08:44:01 +02:00
|
|
|
const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
|
|
|
|
const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test";
|
|
|
|
const TESTACCOUNT1_PASSWORD_B: &str = "password b for account1 test";
|
|
|
|
const TESTACCOUNT1_PASSWORD_INC: &str = "never going to work";
|
2020-10-10 02:31:51 +02:00
|
|
|
const ACCOUNT_EXPIRE: &str = "1970-01-01T00:00:00+00:00";
|
2020-02-13 00:43:01 +01:00
|
|
|
|
2020-09-18 05:19:57 +02:00
|
|
|
fn run_test(fix_fn: fn(&mut KanidmClient) -> (), test_fn: fn(CacheLayer, KanidmAsyncClient) -> ()) {
|
2020-10-10 02:31:51 +02:00
|
|
|
// ::std::env::set_var("RUST_LOG", "kanidm=debug");
|
2020-02-13 00:43:01 +01:00
|
|
|
let _ = env_logger::builder().is_test(true).try_init();
|
2020-09-06 00:44:35 +02:00
|
|
|
|
|
|
|
let (mut ready_tx, mut ready_rx) = mpsc::channel(1);
|
|
|
|
let (mut finish_tx, mut finish_rx) = mpsc::channel(1);
|
|
|
|
|
2020-02-13 00:43:01 +01:00
|
|
|
let port = PORT_ALLOC.fetch_add(1, Ordering::SeqCst);
|
|
|
|
|
|
|
|
let int_config = Box::new(IntegrationTestConfig {
|
|
|
|
admin_password: ADMIN_TEST_PASSWORD.to_string(),
|
|
|
|
});
|
|
|
|
|
2020-06-10 04:07:43 +02:00
|
|
|
// Setup the config ...
|
2020-02-13 00:43:01 +01:00
|
|
|
let mut config = Configuration::new();
|
|
|
|
config.address = format!("127.0.0.1:{}", port);
|
|
|
|
config.secure_cookies = false;
|
|
|
|
config.integration_test_config = Some(int_config);
|
2020-06-18 02:30:42 +02:00
|
|
|
config.log_level = Some(LogLevel::Quiet as u32);
|
2020-10-10 02:31:51 +02:00
|
|
|
// config.log_level = Some(LogLevel::Verbose as u32);
|
2020-09-06 00:44:35 +02:00
|
|
|
config.threads = 1;
|
|
|
|
|
|
|
|
let t_handle = thread::spawn(move || {
|
2020-02-13 00:43:01 +01:00
|
|
|
// Spawn a thread for the test runner, this should have a unique
|
|
|
|
// port....
|
2020-09-06 00:44:35 +02:00
|
|
|
let mut rt = tokio::runtime::Builder::new()
|
|
|
|
.basic_scheduler()
|
|
|
|
.enable_all()
|
|
|
|
.build()
|
|
|
|
.expect("failed to start tokio");
|
|
|
|
rt.block_on(async {
|
|
|
|
create_server_core(config)
|
|
|
|
.await
|
|
|
|
.expect("failed to start server core");
|
|
|
|
// We have to yield now to guarantee that the tide elements are setup.
|
|
|
|
task::yield_now().await;
|
|
|
|
ready_tx
|
|
|
|
.send(())
|
|
|
|
.await
|
|
|
|
.expect("failed in indicate readiness");
|
|
|
|
finish_rx.recv().await;
|
|
|
|
});
|
2020-02-13 00:43:01 +01:00
|
|
|
});
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let _ = task::block_on(ready_rx.recv()).expect("failed to start ctx");
|
2020-02-13 00:43:01 +01:00
|
|
|
// Setup the client, and the address we selected.
|
|
|
|
let addr = format!("http://127.0.0.1:{}", port);
|
|
|
|
|
|
|
|
// Run fixtures
|
2020-09-18 05:19:57 +02:00
|
|
|
let mut adminclient = KanidmClientBuilder::new()
|
2020-02-13 00:43:01 +01:00
|
|
|
.address(addr.clone())
|
|
|
|
.build()
|
|
|
|
.expect("Failed to build sync client");
|
2020-09-18 05:19:57 +02:00
|
|
|
fix_fn(&mut adminclient);
|
2020-02-15 01:27:25 +01:00
|
|
|
|
|
|
|
let client = KanidmClientBuilder::new()
|
|
|
|
.address(addr.clone())
|
|
|
|
.build_async()
|
|
|
|
.expect("Failed to build async admin client");
|
2020-02-13 00:43:01 +01:00
|
|
|
|
|
|
|
let rsclient = KanidmClientBuilder::new()
|
|
|
|
.address(addr)
|
|
|
|
.build_async()
|
|
|
|
.expect("Failed to build client");
|
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
let cachelayer = task::block_on(CacheLayer::new(
|
2020-02-13 00:43:01 +01:00
|
|
|
"", // The sqlite db path, this is in memory.
|
2020-02-29 05:02:14 +01:00
|
|
|
300,
|
|
|
|
rsclient,
|
|
|
|
vec!["allowed_group".to_string()],
|
2020-06-21 13:57:48 +02:00
|
|
|
DEFAULT_SHELL.to_string(),
|
|
|
|
DEFAULT_HOME_PREFIX.to_string(),
|
|
|
|
DEFAULT_HOME_ATTR,
|
|
|
|
DEFAULT_UID_ATTR_MAP,
|
|
|
|
DEFAULT_GID_ATTR_MAP,
|
2020-08-04 04:58:11 +02:00
|
|
|
))
|
2020-02-13 00:43:01 +01:00
|
|
|
.expect("Failed to build cache layer.");
|
|
|
|
|
2020-02-15 01:27:25 +01:00
|
|
|
test_fn(cachelayer, client);
|
2020-02-13 00:43:01 +01:00
|
|
|
|
|
|
|
// We DO NOT need teardown, as sqlite is in mem
|
|
|
|
// let the tables hit the floor
|
2020-09-06 00:44:35 +02:00
|
|
|
task::block_on(finish_tx.send(())).expect("unable to send to ctx");
|
|
|
|
t_handle.join().expect("failed to join thread");
|
2020-02-13 00:43:01 +01:00
|
|
|
}
|
|
|
|
|
2020-09-18 05:19:57 +02:00
|
|
|
fn test_fixture(rsclient: &mut KanidmClient) -> () {
|
2020-02-13 00:43:01 +01:00
|
|
|
let res = rsclient.auth_simple_password("admin", ADMIN_TEST_PASSWORD);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
// Not recommended in production!
|
|
|
|
rsclient
|
2020-08-01 12:31:05 +02:00
|
|
|
.idm_group_add_members("idm_admins", &["admin"])
|
2020-02-13 00:43:01 +01:00
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Create a new account
|
|
|
|
rsclient
|
|
|
|
.idm_account_create("testaccount1", "Posix Demo Account")
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Extend the account with posix attrs.
|
|
|
|
rsclient
|
|
|
|
.idm_account_unix_extend("testaccount1", Some(20000), None)
|
|
|
|
.unwrap();
|
|
|
|
// Assign an ssh public key.
|
|
|
|
rsclient
|
|
|
|
.idm_account_post_ssh_pubkey("testaccount1", "tk",
|
|
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAeGW1P6Pc2rPq0XqbRaDKBcXZUPRklo0L1EyR30CwoP william@amethyst")
|
|
|
|
.unwrap();
|
2020-02-29 05:02:14 +01:00
|
|
|
// Set a posix password
|
|
|
|
rsclient
|
|
|
|
.idm_account_unix_cred_put("testaccount1", TESTACCOUNT1_PASSWORD_A)
|
|
|
|
.unwrap();
|
2020-02-13 00:43:01 +01:00
|
|
|
|
|
|
|
// Setup a group
|
|
|
|
rsclient.idm_group_create("testgroup1").unwrap();
|
|
|
|
rsclient
|
2020-08-01 12:31:05 +02:00
|
|
|
.idm_group_add_members("testgroup1", &["testaccount1"])
|
2020-02-13 00:43:01 +01:00
|
|
|
.unwrap();
|
|
|
|
rsclient
|
|
|
|
.idm_group_unix_extend("testgroup1", Some(20001))
|
|
|
|
.unwrap();
|
2020-02-29 05:02:14 +01:00
|
|
|
|
|
|
|
// Setup the allowed group
|
|
|
|
rsclient.idm_group_create("allowed_group").unwrap();
|
|
|
|
rsclient
|
|
|
|
.idm_group_unix_extend("allowed_group", Some(20002))
|
|
|
|
.unwrap();
|
2020-02-13 00:43:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_sshkey() {
|
2020-02-15 01:27:25 +01:00
|
|
|
run_test(test_fixture, |cachelayer, _adminclient| {
|
2020-02-13 00:43:01 +01:00
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
// Force offline. Show we have no keys.
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
let sk = cachelayer
|
|
|
|
.get_sshkeys("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache.");
|
|
|
|
assert!(sk.len() == 0);
|
|
|
|
|
|
|
|
// Bring ourselves online.
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
|
|
|
|
let sk = cachelayer
|
|
|
|
.get_sshkeys("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache.");
|
|
|
|
assert!(sk.len() == 1);
|
|
|
|
|
|
|
|
// Go offline, and get from cache.
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
let sk = cachelayer
|
|
|
|
.get_sshkeys("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache.");
|
|
|
|
assert!(sk.len() == 1);
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
2020-02-15 01:27:25 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_account() {
|
|
|
|
run_test(test_fixture, |cachelayer, _adminclient| {
|
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
// Force offline. Show we have no account
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
let ut = cachelayer
|
|
|
|
.get_nssaccount_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(ut.is_none());
|
|
|
|
|
|
|
|
// go online
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
|
|
|
|
// get the account
|
|
|
|
let ut = cachelayer
|
|
|
|
.get_nssaccount_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(ut.is_some());
|
|
|
|
|
|
|
|
// go offline
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
// can still get account
|
|
|
|
let ut = cachelayer
|
|
|
|
.get_nssaccount_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(ut.is_some());
|
|
|
|
|
|
|
|
// Finally, check we have "all accounts" in the list.
|
|
|
|
let us = cachelayer
|
|
|
|
.get_nssaccounts()
|
2020-08-04 04:58:11 +02:00
|
|
|
.await
|
2020-02-15 01:27:25 +01:00
|
|
|
.expect("failed to list all accounts");
|
|
|
|
assert!(us.len() == 1);
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_group() {
|
|
|
|
run_test(test_fixture, |cachelayer, _adminclient| {
|
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
// Force offline. Show we have no groups.
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_none());
|
|
|
|
|
|
|
|
// go online. Get the group
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_some());
|
|
|
|
|
|
|
|
// go offline. still works
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_some());
|
|
|
|
// And check we have no members in the group. Members are an artifact of
|
|
|
|
// user lookups!
|
|
|
|
assert!(gt.unwrap().members.len() == 0);
|
|
|
|
|
|
|
|
// clear cache, go online
|
2020-08-04 04:58:11 +02:00
|
|
|
assert!(cachelayer.invalidate().await.is_ok());
|
2020-02-15 01:27:25 +01:00
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
|
|
|
|
// get an account with the group
|
|
|
|
// DO NOT get the group yet.
|
|
|
|
let ut = cachelayer
|
|
|
|
.get_nssaccount_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(ut.is_some());
|
|
|
|
|
|
|
|
// go offline.
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
// show we have the group despite no direct calls
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_some());
|
|
|
|
// And check we have members in the group, since we came from a userlook up
|
|
|
|
assert!(gt.unwrap().members.len() == 1);
|
|
|
|
|
|
|
|
// Finally, check we have "all groups" in the list.
|
|
|
|
let gs = cachelayer
|
|
|
|
.get_nssgroups()
|
2020-08-04 04:58:11 +02:00
|
|
|
.await
|
2020-02-15 01:27:25 +01:00
|
|
|
.expect("failed to list all groups");
|
|
|
|
assert!(gs.len() == 2);
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_group_delete() {
|
2020-09-18 05:19:57 +02:00
|
|
|
run_test(test_fixture, |cachelayer, mut adminclient| {
|
2020-02-15 01:27:25 +01:00
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
// get the group
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_some());
|
|
|
|
|
|
|
|
// delete it.
|
|
|
|
adminclient
|
|
|
|
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
|
|
|
.await
|
|
|
|
.expect("failed to auth as admin");
|
|
|
|
adminclient
|
|
|
|
.idm_group_delete("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("failed to delete");
|
|
|
|
|
|
|
|
// invalidate cache
|
2020-08-04 04:58:11 +02:00
|
|
|
assert!(cachelayer.invalidate().await.is_ok());
|
2020-02-15 01:27:25 +01:00
|
|
|
|
|
|
|
// "get it"
|
|
|
|
// should be empty.
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testgroup1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_none());
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_account_delete() {
|
2020-09-18 05:19:57 +02:00
|
|
|
run_test(test_fixture, |cachelayer, mut adminclient| {
|
2020-02-15 01:27:25 +01:00
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
// get the account
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
let ut = cachelayer
|
|
|
|
.get_nssaccount_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(ut.is_some());
|
|
|
|
|
|
|
|
// delete it.
|
|
|
|
adminclient
|
|
|
|
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
|
|
|
.await
|
|
|
|
.expect("failed to auth as admin");
|
|
|
|
adminclient
|
|
|
|
.idm_account_delete("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("failed to delete");
|
|
|
|
|
|
|
|
// invalidate cache
|
2020-08-04 04:58:11 +02:00
|
|
|
assert!(cachelayer.invalidate().await.is_ok());
|
2020-02-15 01:27:25 +01:00
|
|
|
|
|
|
|
// "get it"
|
|
|
|
let ut = cachelayer
|
|
|
|
.get_nssaccount_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
// should be empty.
|
|
|
|
assert!(ut.is_none());
|
|
|
|
|
|
|
|
// The group should be removed too.
|
|
|
|
let gt = cachelayer
|
|
|
|
.get_nssgroup_name("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache");
|
|
|
|
assert!(gt.is_none());
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
2020-02-29 05:02:14 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_account_password() {
|
2020-09-18 05:19:57 +02:00
|
|
|
run_test(test_fixture, |cachelayer, mut adminclient| {
|
2020-02-29 05:02:14 +01:00
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
// Test authentication failure.
|
|
|
|
let a1 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_INC)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a1 == Some(false));
|
|
|
|
|
2020-10-22 06:40:31 +02:00
|
|
|
// We have to wait due to softlocking.
|
|
|
|
task::sleep(Duration::from_secs(1)).await;
|
|
|
|
|
2020-02-29 05:02:14 +01:00
|
|
|
// Test authentication success.
|
|
|
|
let a2 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_A)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a2 == Some(true));
|
|
|
|
|
|
|
|
// change pw
|
|
|
|
adminclient
|
|
|
|
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
|
|
|
.await
|
|
|
|
.expect("failed to auth as admin");
|
|
|
|
adminclient
|
|
|
|
.idm_account_unix_cred_put("testaccount1", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("Failed to change password");
|
|
|
|
|
|
|
|
// test auth (old pw) fail
|
|
|
|
let a3 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_A)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a3 == Some(false));
|
|
|
|
|
2020-10-22 06:40:31 +02:00
|
|
|
// We have to wait due to softlocking.
|
|
|
|
task::sleep(Duration::from_secs(1)).await;
|
|
|
|
|
2020-02-29 05:02:14 +01:00
|
|
|
// test auth (new pw) success
|
|
|
|
let a4 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a4 == Some(true));
|
|
|
|
|
|
|
|
// Go offline.
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
// Test auth success
|
|
|
|
let a5 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a5 == Some(true));
|
|
|
|
|
2020-10-22 06:40:31 +02:00
|
|
|
// No softlock during offline.
|
|
|
|
|
2020-02-29 05:02:14 +01:00
|
|
|
// Test auth failure.
|
|
|
|
let a6 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_INC)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a6 == Some(false));
|
|
|
|
|
|
|
|
// clear cache
|
2020-08-04 04:58:11 +02:00
|
|
|
cachelayer
|
|
|
|
.clear_cache()
|
|
|
|
.await
|
|
|
|
.expect("failed to clear cache");
|
2020-02-29 05:02:14 +01:00
|
|
|
|
|
|
|
// test auth good (fail)
|
|
|
|
let a7 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a7 == None);
|
|
|
|
|
|
|
|
// go online
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
|
|
|
|
// test auth success
|
|
|
|
let a8 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a8 == Some(true));
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_account_pam_allowed() {
|
2020-09-18 05:19:57 +02:00
|
|
|
run_test(test_fixture, |cachelayer, mut adminclient| {
|
2020-02-29 05:02:14 +01:00
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
|
|
|
|
// Should fail
|
|
|
|
let a1 = cachelayer
|
|
|
|
.pam_account_allowed("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a1 == Some(false));
|
|
|
|
|
|
|
|
adminclient
|
|
|
|
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
|
|
|
.await
|
|
|
|
.expect("failed to auth as admin");
|
|
|
|
adminclient
|
|
|
|
.idm_group_add_members("allowed_group", vec!["testaccount1"])
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Invalidate cache to force a refresh
|
2020-08-04 04:58:11 +02:00
|
|
|
assert!(cachelayer.invalidate().await.is_ok());
|
2020-02-29 05:02:14 +01:00
|
|
|
|
|
|
|
// Should pass
|
|
|
|
let a2 = cachelayer
|
|
|
|
.pam_account_allowed("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a2 == Some(true));
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_account_pam_nonexist() {
|
|
|
|
run_test(test_fixture, |cachelayer, _adminclient| {
|
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
|
|
|
|
let a1 = cachelayer
|
|
|
|
.pam_account_allowed("NO_SUCH_ACCOUNT")
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a1 == None);
|
|
|
|
|
|
|
|
let a2 = cachelayer
|
|
|
|
.pam_account_authenticate("NO_SUCH_ACCOUNT", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a2 == None);
|
|
|
|
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
let a1 = cachelayer
|
|
|
|
.pam_account_allowed("NO_SUCH_ACCOUNT")
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a1 == None);
|
|
|
|
|
|
|
|
let a2 = cachelayer
|
|
|
|
.pam_account_authenticate("NO_SUCH_ACCOUNT", TESTACCOUNT1_PASSWORD_B)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a2 == None);
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|
2020-10-10 02:31:51 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_cache_account_expiry() {
|
|
|
|
run_test(test_fixture, |cachelayer, mut adminclient| {
|
|
|
|
let mut rt = Runtime::new().expect("Failed to start tokio");
|
|
|
|
let fut = async move {
|
|
|
|
cachelayer.attempt_online().await;
|
|
|
|
assert!(cachelayer.test_connection().await);
|
|
|
|
|
|
|
|
// We need one good auth first to prime the cache with a hash.
|
|
|
|
let a1 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_A)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a1 == Some(true));
|
|
|
|
// Invalidate to make sure we go online next checks.
|
|
|
|
assert!(cachelayer.invalidate().await.is_ok());
|
|
|
|
|
|
|
|
// expire the account
|
|
|
|
adminclient
|
|
|
|
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
|
|
|
.await
|
|
|
|
.expect("failed to auth as admin");
|
|
|
|
adminclient
|
|
|
|
.idm_account_set_attr("testaccount1", "account_expire", &[ACCOUNT_EXPIRE])
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
// auth will fail
|
|
|
|
let a2 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_A)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a2 == Some(false));
|
|
|
|
|
|
|
|
// ssh keys should be empty
|
|
|
|
let sk = cachelayer
|
|
|
|
.get_sshkeys("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache.");
|
|
|
|
assert!(sk.len() == 0);
|
|
|
|
|
|
|
|
// Pam account allowed should be denied.
|
|
|
|
let a3 = cachelayer
|
|
|
|
.pam_account_allowed("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a3 == Some(false));
|
|
|
|
|
|
|
|
// go offline
|
|
|
|
cachelayer.mark_offline().await;
|
|
|
|
|
|
|
|
// Now, check again ...
|
|
|
|
let a4 = cachelayer
|
|
|
|
.pam_account_authenticate("testaccount1", TESTACCOUNT1_PASSWORD_A)
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a4 == Some(false));
|
|
|
|
|
|
|
|
// ssh keys should be empty
|
|
|
|
let sk = cachelayer
|
|
|
|
.get_sshkeys("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("Failed to get from cache.");
|
|
|
|
assert!(sk.len() == 0);
|
|
|
|
|
|
|
|
// Pam account allowed should be denied.
|
|
|
|
let a5 = cachelayer
|
|
|
|
.pam_account_allowed("testaccount1")
|
|
|
|
.await
|
|
|
|
.expect("failed to authenticate");
|
|
|
|
assert!(a5 == Some(false));
|
|
|
|
};
|
|
|
|
rt.block_on(fut);
|
|
|
|
})
|
|
|
|
}
|