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:
Pando85 2020-04-30 16:54:46 +02:00 committed by Firstyear
parent fa43ac2110
commit 4dcad60374
7 changed files with 706 additions and 79 deletions

View file

@ -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.

View file

@ -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
========================

View file

@ -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.

View 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();
}

View 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);
});
}

View file

@ -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| {

View file

@ -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"