mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Extend testing of default entries
Add default entries test to apply behaviours according to `designs/default_idm_layout.rst`. Add expected behaviours for: - Users - Account managers - Group managers - Admins - People Managers - Anonymous clients - Radius servers Also, refactor `kanidmd_client` tests to separate into different files and fix some documentation typos Resolves: #108
This commit is contained in:
parent
fa43ac2110
commit
4dcad60374
|
@ -150,7 +150,7 @@ requirements.
|
|||
An example is user Alice should only be able to create objects where the class is group, and can
|
||||
only name the group - they can not add members to the group.
|
||||
|
||||
A content requriemnt could be something such as the value an attribute can contain must conform to a
|
||||
A content requirement could be something such as the value an attribute can contain must conform to a
|
||||
regex, IE, you can create a group of any name, except where the name contains "admin" somewhere
|
||||
in it's name. Arguable, this is partially possible with filtering.
|
||||
|
||||
|
|
|
@ -65,16 +65,16 @@ account.
|
|||
As a result, this is high access. This role importantly should NOT be able to lock or alter
|
||||
credentials of high access granted accounts. That must be performed by a higher privilege.
|
||||
|
||||
* read and write to accounts, including credentials but NOT private data (see people manager)
|
||||
* read and write to accounts, including write credentials but NOT private data (see people manager)
|
||||
* ability to lock and unlock accounts, excluding high access members.
|
||||
|
||||
|
||||
Group Manager
|
||||
Group Managers
|
||||
=============
|
||||
|
||||
This is a role who is able to manage and create groups on the system. Note this does not include
|
||||
high access groups. This is intended to be for support (ie service desk) staff to help users
|
||||
be added to the necesary security groups within reason.
|
||||
be added to the necessary security groups within reason.
|
||||
|
||||
* read all groups
|
||||
* write group but not high access
|
||||
|
@ -109,7 +109,7 @@ for write.
|
|||
Due to dealing with potentially private or sensitive information, this is a "high access" account.
|
||||
|
||||
* read private or sensitive data of persons, IE legalName
|
||||
* write privare or sensitive data of persons, IE legalName
|
||||
* write private or sensitive data of persons, IE legalName
|
||||
|
||||
Remember, this role does NOT allow technical changes, IE password changes or normal technical changes.
|
||||
|
||||
|
@ -139,7 +139,7 @@ should exist by default.
|
|||
Due to the handling of credentials, this is a "high access" group.
|
||||
|
||||
* Read radius credentials
|
||||
* Read other needed attributes to fufil radius functions.
|
||||
* Read other needed attributes to fulfil radius functions.
|
||||
|
||||
External Account Systems
|
||||
========================
|
||||
|
|
|
@ -10,12 +10,12 @@ box experience possible, as well as supplying best practice examples related to
|
|||
systems.
|
||||
|
||||
The system admin account (the account you recovered in the setup) has limited privileges - only to
|
||||
manage high-privilege accounts and services. This is to help seperate system administration
|
||||
manage high-privilege accounts and services. This is to help separate system administration
|
||||
from identity administration actions. An idm_admin is also provided that is only for management
|
||||
of accounts and groups.
|
||||
|
||||
Both admin and idm_admin should *NOT* be used for daily activities - they exist for initial
|
||||
system configuration, and for disaster recovery scenarioes. You should delegate permissions
|
||||
system configuration, and for disaster recovery scenarios. You should delegate permissions
|
||||
as required to named user accounts instead.
|
||||
|
||||
The majority of the provided content is privilege groups that provide rights over Kanidm
|
||||
|
@ -42,7 +42,7 @@ We can now use the idm_admin to create initial groups and accounts.
|
|||
You can also use anonymous to view users and groups - note that you won't see as many fields due
|
||||
to the different anonymous access profile limits!
|
||||
|
||||
kanidm account get demo_user --name anonymous
|
||||
kanidm account get demo_user --name anonymous
|
||||
|
||||
## Viewing Default Groups
|
||||
|
||||
|
@ -60,8 +60,8 @@ accounts security and login aspects. This includes resetting account credentials
|
|||
We can perform a password reset on the demo_user for example as idm_admin, who is
|
||||
a default member of this group.
|
||||
|
||||
kanidm account credential set_password demo_user --name idm_admin
|
||||
kanidm self whoami --name demo_user
|
||||
kanidm account credential set_password demo_user --name idm_admin
|
||||
kanidm self whoami --name demo_user
|
||||
|
||||
## Nested Groups
|
||||
|
||||
|
@ -116,5 +116,3 @@ resources that trust Kanidm.
|
|||
|
||||
All groups that are flagged as "idm_high_privilege" should be audited and
|
||||
monitored to ensure that they are not altered.
|
||||
|
||||
|
||||
|
|
63
kanidm_client/tests/common.rs
Normal file
63
kanidm_client/tests/common.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
use kanidm::config::{Configuration, IntegrationTestConfig};
|
||||
use kanidm::core::create_server_core;
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
|
||||
use actix::prelude::*;
|
||||
|
||||
pub const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
|
||||
static PORT_ALLOC: AtomicUsize = AtomicUsize::new(8080);
|
||||
|
||||
// Test external behaviours of the service.
|
||||
|
||||
pub fn run_test(test_fn: fn(KanidmClient) -> ()) {
|
||||
// ::std::env::set_var("RUST_LOG", "actix_web=debug,kanidm=debug");
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let port = PORT_ALLOC.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
let int_config = Box::new(IntegrationTestConfig {
|
||||
admin_password: ADMIN_TEST_PASSWORD.to_string(),
|
||||
});
|
||||
|
||||
let mut config = Configuration::new();
|
||||
config.address = format!("127.0.0.1:{}", port);
|
||||
config.secure_cookies = false;
|
||||
config.integration_test_config = Some(int_config);
|
||||
// Setup the config ...
|
||||
|
||||
thread::spawn(move || {
|
||||
// Spawn a thread for the test runner, this should have a unique
|
||||
// port....
|
||||
System::run(move || {
|
||||
create_server_core(config);
|
||||
|
||||
// This appears to be bind random ...
|
||||
// let srv = srv.bind("127.0.0.1:0").unwrap();
|
||||
let _ = tx.send(System::current());
|
||||
})
|
||||
.expect("unable to start system");
|
||||
});
|
||||
let sys = rx.recv().unwrap();
|
||||
System::set_current(sys.clone());
|
||||
|
||||
// Do we need any fixtures?
|
||||
// Yes probably, but they'll need to be futures as well ...
|
||||
// later we could accept fixture as it's own future for re-use
|
||||
|
||||
// Setup the client, and the address we selected.
|
||||
let addr = format!("http://127.0.0.1:{}", port);
|
||||
let rsclient = KanidmClientBuilder::new()
|
||||
.address(addr)
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
|
||||
test_fn(rsclient);
|
||||
|
||||
// We DO NOT need teardown, as sqlite is in mem
|
||||
// let the tables hit the floor
|
||||
sys.stop();
|
||||
}
|
622
kanidm_client/tests/default_entries.rs
Normal file
622
kanidm_client/tests/default_entries.rs
Normal file
|
@ -0,0 +1,622 @@
|
|||
#![deny(warnings)]
|
||||
use std::collections::HashSet;
|
||||
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::v1::{Filter, Modify, ModifyList};
|
||||
|
||||
mod common;
|
||||
use crate::common::{run_test, ADMIN_TEST_PASSWORD};
|
||||
|
||||
static USER_READABLE_ATTRS: [&str; 9] = [
|
||||
"name",
|
||||
"spn",
|
||||
"displayname",
|
||||
"class",
|
||||
"memberof",
|
||||
"uuid",
|
||||
"gidnumber",
|
||||
"loginshell",
|
||||
"ssh_publickey",
|
||||
];
|
||||
static SELF_WRITEABLE_ATTRS: [&str; 7] = [
|
||||
"name",
|
||||
"displayname",
|
||||
"legalname",
|
||||
"radius_secret",
|
||||
"primary_credential",
|
||||
"ssh_publickey",
|
||||
"unix_password",
|
||||
];
|
||||
static DEFAULT_HP_GROUP_NAMES: [&str; 22] = [
|
||||
"idm_admins",
|
||||
"system_admins",
|
||||
"idm_people_manage_priv",
|
||||
"idm_people_account_password_import_priv",
|
||||
"idm_people_extend_priv",
|
||||
"idm_people_write_priv",
|
||||
"idm_people_read_priv",
|
||||
"idm_group_manage_priv",
|
||||
"idm_group_write_priv",
|
||||
"idm_account_manage_priv",
|
||||
"idm_account_write_priv",
|
||||
"idm_account_read_priv",
|
||||
"idm_radius_servers",
|
||||
"idm_hp_account_manage_priv",
|
||||
"idm_hp_account_write_priv",
|
||||
"idm_hp_account_read_priv",
|
||||
"idm_schema_manage_priv",
|
||||
"idm_hp_group_manage_priv",
|
||||
"idm_hp_group_write_priv",
|
||||
"idm_acp_manage_priv",
|
||||
"domain_admins",
|
||||
"idm_high_privilege",
|
||||
];
|
||||
static DEFAULT_NOT_HP_GROUP_NAMES: [&str; 2] =
|
||||
["idm_account_unix_extend_priv", "idm_group_unix_extend_priv"];
|
||||
|
||||
fn create_user(rsclient: &KanidmClient, id: &str, group_name: &str) -> () {
|
||||
rsclient.idm_account_create(id, "Deeeeemo").unwrap();
|
||||
|
||||
// Create group and add to user to test read attr: member_of
|
||||
match rsclient.idm_group_get(&group_name).unwrap() {
|
||||
Some(_) => (),
|
||||
None => rsclient.idm_group_create(&group_name).unwrap(),
|
||||
}
|
||||
|
||||
rsclient
|
||||
.idm_group_add_members(&group_name, vec![id])
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option<bool> {
|
||||
println!("writing to attribute: {}", attr);
|
||||
match attr {
|
||||
"radius_secret" => Some(
|
||||
rsclient
|
||||
.idm_account_radius_credential_regenerate(id)
|
||||
.is_ok(),
|
||||
),
|
||||
"primary_credential" => Some(
|
||||
rsclient
|
||||
.idm_account_primary_credential_set_password(id, "dsadjasiodqwjk12asdl")
|
||||
.is_ok(),
|
||||
),
|
||||
"ssh_publickey" => Some(
|
||||
rsclient
|
||||
.idm_account_post_ssh_pubkey(
|
||||
id,
|
||||
"k1",
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAeGW1P6Pc2rPq0XqbRaDKBcXZUPRklo0\
|
||||
L1EyR30CwoP william@amethyst",
|
||||
)
|
||||
.is_ok(),
|
||||
),
|
||||
"unix_password" => Some(
|
||||
rsclient
|
||||
.idm_account_unix_cred_put(id, "dsadjasiodqwjk12asdl")
|
||||
.is_ok(),
|
||||
),
|
||||
entry => {
|
||||
let new_value = match entry {
|
||||
"acp_receiver" => "{\"Eq\":[\"memberof\",\"00000000-0000-0000-0000-000000000011\"]}".to_string(),
|
||||
"acp_targetscope" => "{\"And\": [{\"Eq\": [\"class\",\"access_control_profile\"]}, {\"AndNot\": {\"Or\": [{\"Eq\": [\"class\", \"tombstone\"]}, {\"Eq\": [\"class\", \"recycled\"]}]}}]}".to_string(),
|
||||
_ => id.to_string(),
|
||||
};
|
||||
let m = ModifyList::new_list(vec![
|
||||
Modify::Purged(attr.to_string()),
|
||||
Modify::Present(attr.to_string(), new_value),
|
||||
]);
|
||||
let f = Filter::Eq("name".to_string(), id.to_string());
|
||||
Some(rsclient.modify(f.clone(), m.clone()).is_ok())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_all_attrs(mut rsclient: &mut KanidmClient, id: &str, group_name: &str) {
|
||||
// Extend with posix attrs to test read attr: gidnumber and loginshell
|
||||
rsclient
|
||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
||||
.unwrap();
|
||||
rsclient
|
||||
.idm_account_unix_extend(id, None, Some(&"/bin/bash"))
|
||||
.unwrap();
|
||||
rsclient.idm_group_unix_extend(&group_name, None).unwrap();
|
||||
|
||||
// Extend with person to allow legalname
|
||||
rsclient.idm_account_person_extend(id).unwrap();
|
||||
|
||||
["ssh_publickey", "legalname", "mail"]
|
||||
.iter()
|
||||
.for_each(|attr| {
|
||||
assert!(is_attr_writable(&rsclient, id, attr).unwrap());
|
||||
});
|
||||
|
||||
// Write radius credentials
|
||||
if id != "anonymous" {
|
||||
login_account(&mut rsclient, id);
|
||||
let _ = rsclient
|
||||
.idm_account_radius_credential_regenerate(id)
|
||||
.unwrap();
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn create_user_with_all_attrs(
|
||||
mut rsclient: &mut KanidmClient,
|
||||
id: &str,
|
||||
optional_group: Option<&str>,
|
||||
) -> () {
|
||||
let group_format = format!("{}_group", id);
|
||||
let group_name = optional_group.unwrap_or(&group_format);
|
||||
|
||||
create_user(&rsclient, id, group_name);
|
||||
add_all_attrs(&mut rsclient, id, group_name);
|
||||
}
|
||||
|
||||
fn login_account(rsclient: &mut KanidmClient, id: &str) -> () {
|
||||
rsclient
|
||||
.idm_group_add_members("idm_people_account_password_import_priv", vec!["admin"])
|
||||
.unwrap();
|
||||
rsclient
|
||||
.idm_group_add_members("idm_people_extend_priv", vec!["admin"])
|
||||
.unwrap();
|
||||
|
||||
rsclient
|
||||
.idm_account_primary_credential_set_password(id, "eicieY7ahchaoCh0eeTa")
|
||||
.unwrap();
|
||||
|
||||
let _ = rsclient.logout();
|
||||
let res = rsclient.auth_simple_password(id, "eicieY7ahchaoCh0eeTa");
|
||||
println!("{} logged in", id);
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
|
||||
fn test_read_attrs(rsclient: &KanidmClient, id: &str, attrs: &[&str], is_readable: bool) -> () {
|
||||
println!("Test read to {}, is readable: {}", id, is_readable);
|
||||
let rset = rsclient
|
||||
.search(Filter::Eq("name".to_string(), id.to_string()))
|
||||
.unwrap();
|
||||
let e = rset.first().unwrap();
|
||||
attrs
|
||||
.iter()
|
||||
.map(|attr| {
|
||||
println!("Reading {}", attr);
|
||||
match *attr {
|
||||
"radius_secret" => match rsclient.idm_account_radius_credential_get(id).unwrap() {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
},
|
||||
_ => match e.attrs.get(*attr) {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
},
|
||||
}
|
||||
})
|
||||
.for_each(|is_ok| assert!(is_ok == is_readable));
|
||||
}
|
||||
|
||||
fn test_write_attrs(rsclient: &KanidmClient, id: &str, attrs: &[&str], is_writeable: bool) -> () {
|
||||
println!("Test write to {}, is writeable: {}", id, is_writeable);
|
||||
attrs
|
||||
.iter()
|
||||
.map(|attr| {
|
||||
println!("Writing to {}", attr);
|
||||
is_attr_writable(&rsclient, id, attr).unwrap()
|
||||
})
|
||||
.for_each(|is_ok| assert!(is_ok == is_writeable));
|
||||
}
|
||||
|
||||
fn test_modify_group(rsclient: &KanidmClient, group_names: &[&str], is_modificable: bool) -> () {
|
||||
// need user test created to be added as test part
|
||||
group_names.iter().for_each(|group| {
|
||||
println!("Testing group: {}", group);
|
||||
["description", "name"].iter().for_each(|attr| {
|
||||
assert!(is_attr_writable(&rsclient, group, attr).unwrap() == is_modificable)
|
||||
});
|
||||
assert!(rsclient.idm_group_add_members(group, vec!["test"]).is_ok() == is_modificable);
|
||||
});
|
||||
}
|
||||
|
||||
// Users
|
||||
// - Read to all self attributes (within security constraints).
|
||||
// - Write to a limited set of self attributes, such as:
|
||||
// name, displayname, legalname, ssh-keys, credentials etc.
|
||||
#[test]
|
||||
fn test_default_entries_rbac_users() {
|
||||
run_test(|mut rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
|
||||
create_user_with_all_attrs(&mut rsclient, "self_account", Some("self_group"));
|
||||
create_user_with_all_attrs(&mut rsclient, "other_account", Some("other_group"));
|
||||
|
||||
login_account(&mut rsclient, "self_account");
|
||||
|
||||
test_read_attrs(&rsclient, "self_account", &USER_READABLE_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "other_account", &USER_READABLE_ATTRS, true);
|
||||
|
||||
static GROUP_READABLE_ATTRS: [&str; 5] = ["class", "name", "spn", "uuid", "member"];
|
||||
test_read_attrs(&rsclient, "self_group", &GROUP_READABLE_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "other_group", &GROUP_READABLE_ATTRS, true);
|
||||
|
||||
static USER_SENSITIVE_ATTRS: [&str; 2] = ["legalname", "mail"];
|
||||
test_read_attrs(&rsclient, "other_account", &USER_SENSITIVE_ATTRS, false);
|
||||
|
||||
static SELF_READABLE_ATTRS: [&str; 1] = ["radius_secret"];
|
||||
test_read_attrs(&rsclient, "self_account", &SELF_READABLE_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "other_account", &SELF_READABLE_ATTRS, false);
|
||||
|
||||
test_write_attrs(&rsclient, "self_account", &SELF_WRITEABLE_ATTRS, true);
|
||||
test_write_attrs(&rsclient, "other_account", &SELF_WRITEABLE_ATTRS, false);
|
||||
|
||||
static NON_SELF_WRITEABLE_ATTRS: [&str; 5] =
|
||||
["spn", "class", "memberof", "gidnumber", "uuid"];
|
||||
test_write_attrs(&rsclient, "self_account", &NON_SELF_WRITEABLE_ATTRS, false);
|
||||
});
|
||||
}
|
||||
|
||||
// Account Managers
|
||||
// read and write to accounts, including write credentials but NOT private data (see people manager)
|
||||
// ability to lock and unlock accounts, excluding high access members.
|
||||
#[test]
|
||||
fn test_default_entries_rbac_account_managers() {
|
||||
run_test(|mut rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
|
||||
create_user(&rsclient, "account_manager", "idm_account_manage_priv");
|
||||
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
|
||||
|
||||
login_account(&mut rsclient, "account_manager");
|
||||
|
||||
test_read_attrs(&rsclient, "test", &USER_READABLE_ATTRS, true);
|
||||
static ACCOUNT_MANAGER_ATTRS: [&str; 5] = [
|
||||
"name",
|
||||
"displayname",
|
||||
"primary_credential",
|
||||
"ssh_publickey",
|
||||
"mail",
|
||||
];
|
||||
test_write_attrs(&rsclient, "test", &ACCOUNT_MANAGER_ATTRS, true);
|
||||
|
||||
static PRIVATE_DATA_ATTRS: [&str; 1] = ["legalname"];
|
||||
test_read_attrs(&rsclient, "test", &PRIVATE_DATA_ATTRS, false);
|
||||
test_write_attrs(&rsclient, "test", &PRIVATE_DATA_ATTRS, false);
|
||||
// TODO: lock and _unlock, except high access members
|
||||
});
|
||||
}
|
||||
|
||||
// Group Managers
|
||||
// read all groups
|
||||
// write group but not high access
|
||||
#[test]
|
||||
fn test_default_entries_rbac_group_managers() {
|
||||
run_test(|mut rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
|
||||
create_user(&rsclient, "group_manager", "idm_group_manage_priv");
|
||||
// create test user without creating new groups
|
||||
create_user(&rsclient, "test", "idm_admins");
|
||||
|
||||
login_account(&mut rsclient, "group_manager");
|
||||
|
||||
let default_group_names: HashSet<String> =
|
||||
[&DEFAULT_HP_GROUP_NAMES[..], &DEFAULT_NOT_HP_GROUP_NAMES[..]]
|
||||
.concat()
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect();
|
||||
|
||||
let groups = rsclient.idm_group_list().unwrap();
|
||||
let group_names: HashSet<String> = groups
|
||||
.iter()
|
||||
.map(|entry| entry.attrs.get("name").unwrap().first().unwrap())
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_eq!(default_group_names, group_names);
|
||||
|
||||
test_modify_group(&rsclient, &DEFAULT_HP_GROUP_NAMES, false);
|
||||
test_modify_group(&rsclient, &DEFAULT_NOT_HP_GROUP_NAMES, true);
|
||||
|
||||
rsclient.idm_group_create("test_group").unwrap();
|
||||
rsclient
|
||||
.idm_group_add_members("test_group", vec!["test"])
|
||||
.unwrap();
|
||||
assert!(is_attr_writable(&rsclient, "test_group", "description").unwrap());
|
||||
});
|
||||
}
|
||||
|
||||
// Admins
|
||||
// read and write access control entries.
|
||||
#[test]
|
||||
fn test_default_entries_rbac_admins_access_control_entries() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
static ACP_COMMON_ATTRS: [&str; 4] =
|
||||
["name", "description", "acp_receiver", "acp_targetscope"];
|
||||
static ACP_ENTRIES: [&str; 28] = [
|
||||
"idm_admins_acp_recycle_search",
|
||||
"idm_admins_acp_revive",
|
||||
"idm_self_acp_read",
|
||||
"idm_self_acp_write",
|
||||
"idm_all_acp_read",
|
||||
"idm_acp_people_read_priv",
|
||||
"idm_acp_people_write_priv",
|
||||
"idm_acp_people_manage",
|
||||
"idm_acp_people_account_password_import_priv",
|
||||
"idm_acp_people_extend_priv",
|
||||
"idm_acp_group_write_priv",
|
||||
"idm_acp_account_read_priv",
|
||||
"idm_acp_account_write_priv",
|
||||
"idm_acp_account_manage",
|
||||
"idm_acp_radius_servers",
|
||||
"idm_acp_hp_account_read_priv",
|
||||
"idm_acp_hp_account_write_priv",
|
||||
"idm_acp_hp_group_write_priv",
|
||||
"idm_acp_schema_write_attrs_priv",
|
||||
"idm_acp_acp_manage_priv",
|
||||
"idm_acp_schema_write_classes_priv",
|
||||
"idm_acp_group_manage",
|
||||
"idm_acp_hp_account_manage",
|
||||
"idm_acp_hp_group_manage",
|
||||
"idm_acp_domain_admin_priv",
|
||||
"idm_acp_system_config_priv",
|
||||
"idm_acp_account_unix_extend_priv",
|
||||
"idm_acp_group_unix_extend_priv",
|
||||
];
|
||||
|
||||
ACP_ENTRIES.iter().for_each(|entry| {
|
||||
test_read_attrs(&rsclient, entry, &ACP_COMMON_ATTRS, true);
|
||||
test_write_attrs(&rsclient, entry, &ACP_COMMON_ATTRS, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// read schema entries.
|
||||
// TODO: write schema entries
|
||||
#[test]
|
||||
fn test_default_entries_rbac_admins_schema_entries() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
let default_classnames: HashSet<String> = [
|
||||
"access_control_create",
|
||||
"access_control_delete",
|
||||
"access_control_modify",
|
||||
"access_control_profile",
|
||||
"access_control_search",
|
||||
"attributetype",
|
||||
"classtype",
|
||||
"extensibleobject",
|
||||
"memberof",
|
||||
"object",
|
||||
"recycled",
|
||||
"system",
|
||||
"system_info",
|
||||
"tombstone",
|
||||
"person",
|
||||
"group",
|
||||
"account",
|
||||
"domain_info",
|
||||
"posixaccount",
|
||||
"posixgroup",
|
||||
"system_config",
|
||||
]
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect();
|
||||
|
||||
let classtype_entries = rsclient.idm_schema_classtype_list().unwrap();
|
||||
let classnames: HashSet<String> = classtype_entries
|
||||
.iter()
|
||||
.map(|entry| entry.attrs.get("classname").unwrap().first().unwrap())
|
||||
.cloned()
|
||||
.collect();
|
||||
println!("{:?}", classnames);
|
||||
|
||||
assert_eq!(default_classnames, classnames);
|
||||
|
||||
let default_attributenames: HashSet<String> = [
|
||||
"acp_create_attr",
|
||||
"acp_create_class",
|
||||
"acp_enable",
|
||||
"acp_modify_class",
|
||||
"acp_modify_presentattr",
|
||||
"acp_modify_removedattr",
|
||||
"acp_receiver",
|
||||
"acp_search_attr",
|
||||
"acp_targetscope",
|
||||
"attributename",
|
||||
"claim",
|
||||
"class",
|
||||
"classname",
|
||||
"description",
|
||||
"directmemberof",
|
||||
"domain",
|
||||
"index",
|
||||
"last_modified_cid",
|
||||
"may",
|
||||
"member",
|
||||
"memberof",
|
||||
"multivalue",
|
||||
"must",
|
||||
"name",
|
||||
"password_import",
|
||||
"phantom",
|
||||
"spn",
|
||||
"syntax",
|
||||
"systemmay",
|
||||
"systemmust",
|
||||
"unique",
|
||||
"uuid",
|
||||
"version",
|
||||
"displayname",
|
||||
"legalname",
|
||||
"mail",
|
||||
"ssh_publickey",
|
||||
"primary_credential",
|
||||
"radius_secret",
|
||||
"domain_name",
|
||||
"domain_uuid",
|
||||
"domain_ssid",
|
||||
"gidnumber",
|
||||
"badlist_password",
|
||||
"loginshell",
|
||||
"unix_password",
|
||||
]
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect();
|
||||
|
||||
let attributename_entries = rsclient.idm_schema_attributetype_list().unwrap();
|
||||
println!("{:?}", attributename_entries);
|
||||
let attributenames = attributename_entries
|
||||
.iter()
|
||||
.map(|entry| entry.attrs.get("attributename").unwrap().first().unwrap())
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
assert_eq!(default_attributenames, attributenames);
|
||||
});
|
||||
}
|
||||
|
||||
// modify all groups including high access groups.
|
||||
// create new accounts (to bootstrap the system).
|
||||
#[test]
|
||||
fn test_default_entries_rbac_admins_group_entries() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
create_user(&rsclient, "test", "test_group");
|
||||
|
||||
let default_group_names =
|
||||
[&DEFAULT_HP_GROUP_NAMES[..], &DEFAULT_NOT_HP_GROUP_NAMES[..]].concat();
|
||||
|
||||
test_modify_group(&rsclient, &default_group_names, true);
|
||||
});
|
||||
}
|
||||
|
||||
// modify high access accounts as an escalation for security sensitive accounts.
|
||||
#[test]
|
||||
fn test_default_entries_rbac_admins_ha_accounts() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
|
||||
static MAIN_ATTRS: [&str; 3] = ["name", "displayname", "primary_credential"];
|
||||
test_write_attrs(&rsclient, "idm_admin", &MAIN_ATTRS, true);
|
||||
});
|
||||
}
|
||||
|
||||
// recover from the recycle bin
|
||||
#[test]
|
||||
fn test_default_entries_rbac_admins_recycle_accounts() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
create_user(&rsclient, "test", "test_group");
|
||||
|
||||
rsclient.idm_account_delete("test").unwrap();
|
||||
rsclient.recycle_bin_revive("test").unwrap();
|
||||
|
||||
let acc = rsclient.idm_account_get("test").unwrap();
|
||||
assert!(acc.is_some());
|
||||
});
|
||||
}
|
||||
|
||||
// People Managers
|
||||
// read private or sensitive data of persons, IE legalName
|
||||
// write private or sensitive data of persons, IE legalName
|
||||
#[test]
|
||||
fn test_default_entries_rbac_people_managers() {
|
||||
run_test(|mut rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
|
||||
create_user(&rsclient, "read_people_manager", "idm_people_read_priv");
|
||||
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
|
||||
|
||||
static PEOPLE_MANAGER_ATTRS: [&str; 2] = ["legalname", "mail"];
|
||||
|
||||
static TECHNICAL_ATTRS: [&str; 3] =
|
||||
["primary_credential", "radius_secret", "unix_password"];
|
||||
test_read_attrs(&rsclient, "test", &PEOPLE_MANAGER_ATTRS, true);
|
||||
|
||||
login_account(&mut rsclient, "read_people_manager");
|
||||
|
||||
test_read_attrs(&rsclient, "test", &PEOPLE_MANAGER_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "test", &TECHNICAL_ATTRS, false);
|
||||
test_write_attrs(&rsclient, "test", &PEOPLE_MANAGER_ATTRS, false);
|
||||
test_write_attrs(&rsclient, "test", &TECHNICAL_ATTRS, false);
|
||||
|
||||
let _ = rsclient.logout();
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
create_user(&rsclient, "write_people_manager", "idm_people_write_priv");
|
||||
login_account(&mut rsclient, "write_people_manager");
|
||||
|
||||
test_read_attrs(&rsclient, "test", &PEOPLE_MANAGER_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "test", &TECHNICAL_ATTRS, false);
|
||||
test_write_attrs(&rsclient, "test", &PEOPLE_MANAGER_ATTRS, true);
|
||||
test_write_attrs(&rsclient, "test", &TECHNICAL_ATTRS, false);
|
||||
});
|
||||
}
|
||||
|
||||
// Anonymous Clients + Everyone Else
|
||||
// read memberof, unix attrs, name, displayname, class
|
||||
#[test]
|
||||
fn test_default_entries_rbac_anonymous_entry() {
|
||||
run_test(|mut rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
|
||||
rsclient
|
||||
.idm_group_add_members("test_group", vec!["anonymous"])
|
||||
.unwrap();
|
||||
add_all_attrs(&mut rsclient, "anonymous", "test_group");
|
||||
|
||||
let _ = rsclient.logout();
|
||||
rsclient.auth_anonymous().unwrap();
|
||||
|
||||
test_read_attrs(&rsclient, "test", &USER_READABLE_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "anonymous", &USER_READABLE_ATTRS, true);
|
||||
test_write_attrs(&rsclient, "test", &SELF_WRITEABLE_ATTRS, false);
|
||||
test_write_attrs(&rsclient, "anonymous", &SELF_WRITEABLE_ATTRS, false);
|
||||
});
|
||||
}
|
||||
|
||||
// RADIUS Servers
|
||||
// Read radius credentials
|
||||
// Read other needed attributes to fulfil radius functions.
|
||||
#[test]
|
||||
fn test_default_entries_rbac_radius_servers() {
|
||||
run_test(|mut rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password("admin", ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
create_user(&rsclient, "radius_server", "idm_radius_servers");
|
||||
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
|
||||
|
||||
login_account(&mut rsclient, "radius_server");
|
||||
static RADIUS_NECESSARY_ATTRS: [&str; 4] = ["name", "spn", "uuid", "radius_secret"];
|
||||
|
||||
test_read_attrs(&rsclient, "test", &USER_READABLE_ATTRS, true);
|
||||
test_read_attrs(&rsclient, "test", &RADIUS_NECESSARY_ATTRS, true);
|
||||
test_write_attrs(&rsclient, "test", &RADIUS_NECESSARY_ATTRS, false);
|
||||
});
|
||||
}
|
|
@ -1,75 +1,18 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use kanidm::config::{Configuration, IntegrationTestConfig};
|
||||
use kanidm::core::create_server_core;
|
||||
use kanidm::credential::totp::TOTP;
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
|
||||
|
||||
use actix::prelude::*;
|
||||
use log::debug;
|
||||
|
||||
static PORT_ALLOC: AtomicUsize = AtomicUsize::new(8080);
|
||||
const ADMIN_TEST_PASSWORD: &str = "integration test admin password";
|
||||
use kanidm::credential::totp::TOTP;
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
|
||||
|
||||
mod common;
|
||||
use crate::common::{run_test, ADMIN_TEST_PASSWORD};
|
||||
|
||||
const ADMIN_TEST_PASSWORD_CHANGE: &str = "integration test admin new🎉";
|
||||
const UNIX_TEST_PASSWORD: &str = "unix test user password";
|
||||
|
||||
// Test external behaviorus of the service.
|
||||
|
||||
fn run_test(test_fn: fn(KanidmClient) -> ()) {
|
||||
// ::std::env::set_var("RUST_LOG", "actix_web=debug,kanidm=debug");
|
||||
let _ = env_logger::builder().is_test(true).try_init();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let port = PORT_ALLOC.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
let int_config = Box::new(IntegrationTestConfig {
|
||||
admin_password: ADMIN_TEST_PASSWORD.to_string(),
|
||||
});
|
||||
|
||||
let mut config = Configuration::new();
|
||||
config.address = format!("127.0.0.1:{}", port);
|
||||
config.secure_cookies = false;
|
||||
config.integration_test_config = Some(int_config);
|
||||
// Setup the config ...
|
||||
|
||||
thread::spawn(move || {
|
||||
// Spawn a thread for the test runner, this should have a unique
|
||||
// port....
|
||||
System::run(move || {
|
||||
create_server_core(config);
|
||||
|
||||
// This appears to be bind random ...
|
||||
// let srv = srv.bind("127.0.0.1:0").unwrap();
|
||||
let _ = tx.send(System::current());
|
||||
})
|
||||
.expect("unable to start system");
|
||||
});
|
||||
let sys = rx.recv().unwrap();
|
||||
System::set_current(sys.clone());
|
||||
|
||||
// Do we need any fixtures?
|
||||
// Yes probably, but they'll need to be futures as well ...
|
||||
// later we could accept fixture as it's own future for re-use
|
||||
|
||||
// Setup the client, and the address we selected.
|
||||
let addr = format!("http://127.0.0.1:{}", port);
|
||||
let rsclient = KanidmClientBuilder::new()
|
||||
.address(addr)
|
||||
.build()
|
||||
.expect("Failed to build client");
|
||||
|
||||
test_fn(rsclient);
|
||||
|
||||
// We DO NOT need teardown, as sqlite is in mem
|
||||
// let the tables hit the floor
|
||||
sys.stop();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_server_create() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
|
@ -213,7 +156,7 @@ fn test_server_admin_change_simple_password() {
|
|||
});
|
||||
}
|
||||
|
||||
// Add a test for reseting another accounts pws via the rest api
|
||||
// Add a test for resetting another accounts pws via the rest api
|
||||
#[test]
|
||||
fn test_server_admin_reset_simple_password() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
|
|
|
@ -385,7 +385,8 @@ pub const JSON_IDM_ACP_ACCOUNT_MANAGE_PRIV_V1: &str = r#"{
|
|||
"displayname",
|
||||
"description",
|
||||
"primary_credential",
|
||||
"ssh_publickey"
|
||||
"ssh_publickey",
|
||||
"mail"
|
||||
],
|
||||
"acp_create_class": [
|
||||
"object", "account"
|
||||
|
|
Loading…
Reference in a new issue