mirror of
https://github.com/kanidm/kanidm.git
synced 2025-06-12 11:07:46 +02:00
Add a new ACP and group allowing self-service mail updates (#672)
* Add a new ACP and group allowing self-service mail updates This adds a new "idm_people_self_write_mail_priv" group which follows the existing canned group+acp format closely. This also adds a test for the functionality See the discussion in #648 for a bit more background * Limit the self-write ACP to targets with the "account" class Per feedback on #672, it's better to limit these APIs specifically to accounts. * Fix up Co-authored-by: Firstyear <william.brown@suse.com>
This commit is contained in:
parent
d9016011f4
commit
9427d27141
kanidm_book/src
kanidm_client/tests
kanidmd/src/lib
|
@ -141,6 +141,16 @@ Whether an account is currently a "person" or not can be identified from the "ac
|
|||
The presence of a "class: person" stanza indicates that this account may have
|
||||
"people" attributes.
|
||||
|
||||
### Allowing people accounts to change their mail attribute
|
||||
|
||||
By default, Kanidm allows an account to change some attributes, but not their
|
||||
mail address.
|
||||
|
||||
Adding the user to the `idm_people_self_write_mail` group, as shown
|
||||
below, allows the user to edit their own mail.
|
||||
|
||||
kanidm group add_members idm_people_self_write_mail_priv demo_user --name idm_admin
|
||||
|
||||
## Why Can't I Change admin With idm_admin?
|
||||
|
||||
As a security mechanism there is a distinction between "accounts" and "high permission
|
||||
|
|
|
@ -185,6 +185,17 @@ fn login_account(rsclient: &KanidmClient, id: &str) -> () {
|
|||
assert!(res.is_ok());
|
||||
}
|
||||
|
||||
// Login to the given account, but first login with default admin credentials.
|
||||
// This is necessary when switching between unprivileged accounts, but adds extra calls which
|
||||
// create extra debugging noise, so should be avoided when unnecessary.
|
||||
fn login_account_via_admin(rsclient: &KanidmClient, id: &str) -> () {
|
||||
let _ = rsclient.logout();
|
||||
rsclient
|
||||
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
login_account(rsclient, id)
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -630,3 +641,33 @@ fn test_default_entries_rbac_radius_servers() {
|
|||
test_write_attrs(&rsclient, "test", &RADIUS_NECESSARY_ATTRS, false);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_self_write_mail_priv_people() {
|
||||
run_test(|rsclient: KanidmClient| {
|
||||
rsclient
|
||||
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
|
||||
.unwrap();
|
||||
|
||||
// test and other, each can write to themselves, but not each other
|
||||
create_user_with_all_attrs(&rsclient, "test", None);
|
||||
create_user_with_all_attrs(&rsclient, "other", None);
|
||||
rsclient
|
||||
.idm_group_add_members("idm_people_self_write_mail_priv", &["other", "test"])
|
||||
.unwrap();
|
||||
// a non-person, they can't write to themselves even with the priv
|
||||
create_user(&rsclient, "nonperson", "idm_people_self_write_mail_priv");
|
||||
|
||||
login_account(&rsclient, "test");
|
||||
// can write to own mail
|
||||
test_write_attrs(&rsclient, "test", &["mail"], true);
|
||||
// not someone elses
|
||||
test_write_attrs(&rsclient, "other", &["mail"], false);
|
||||
|
||||
// but they can write to theirs
|
||||
login_account_via_admin(&rsclient, "other");
|
||||
test_write_attrs(&rsclient, "other", &["mail"], true);
|
||||
login_account_via_admin(&rsclient, "nonperson");
|
||||
test_write_attrs(&rsclient, "nonperson", &["mail"], false);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ pub const JSON_IDM_SELF_ACP_WRITE_V1: &str = r#"{
|
|||
"{\"and\": [\"self\", {\"andnot\": {\"or\": [{\"eq\": [\"class\", \"tombstone\"]}, {\"eq\": [\"class\", \"recycled\"]}, {\"eq\": [\"uuid\", \"00000000-0000-0000-0000-ffffffffffff\"]}]}}]}"
|
||||
],
|
||||
"acp_targetscope": [
|
||||
"\"self\""
|
||||
"{\"and\": [{\"eq\": [\"class\",\"person\"]}, {\"eq\": [\"class\",\"account\"]}, \"self\"]}"
|
||||
],
|
||||
"acp_modify_removedattr": [
|
||||
"name", "displayname", "legalname", "radius_secret", "primary_credential", "ssh_publickey", "unix_password"
|
||||
|
@ -126,6 +126,27 @@ pub const JSON_IDM_SELF_ACP_WRITE_V1: &str = r#"{
|
|||
}
|
||||
}"#;
|
||||
|
||||
pub const JSON_IDM_PEOPLE_SELF_ACP_WRITE_MAIL_PRIV_V1: &str = r#"{
|
||||
"attrs": {
|
||||
"class": ["object", "access_control_profile", "access_control_modify"],
|
||||
"name": ["idm_people_self_acp_write_mail"],
|
||||
"uuid": ["00000000-0000-0000-0000-ffffff000041"],
|
||||
"description": ["Builtin IDM Control for self write of mail for people accounts."],
|
||||
"acp_receiver": [
|
||||
"{\"eq\":[\"memberof\",\"00000000-0000-0000-0000-000000000033\"]}"
|
||||
],
|
||||
"acp_targetscope": [
|
||||
"{\"and\": [{\"eq\": [\"class\",\"person\"]}, {\"eq\": [\"class\",\"account\"]}, \"self\"]}"
|
||||
],
|
||||
"acp_modify_removedattr": [
|
||||
"mail"
|
||||
],
|
||||
"acp_modify_presentattr": [
|
||||
"mail"
|
||||
]
|
||||
}
|
||||
}"#;
|
||||
|
||||
pub const JSON_IDM_ALL_ACP_READ_V1: &str = r#"{
|
||||
"attrs": {
|
||||
"class": ["object", "access_control_profile", "access_control_search"],
|
||||
|
|
|
@ -95,6 +95,16 @@ pub const JSON_IDM_PEOPLE_EXTEND_PRIV_V1: &str = r#"{
|
|||
}
|
||||
}"#;
|
||||
|
||||
// Self-write of mail
|
||||
pub const JSON_IDM_PEOPLE_SELF_WRITE_MAIL_PRIV_V1: &str = r#"{
|
||||
"attrs": {
|
||||
"class": ["group", "object"],
|
||||
"name": ["idm_people_self_write_mail_priv"],
|
||||
"uuid": ["00000000-0000-0000-0000-000000000033"],
|
||||
"description": ["Builtin IDM Group for people accounts to update their own mail."]
|
||||
}
|
||||
}"#;
|
||||
|
||||
pub const JSON_IDM_HP_PEOPLE_READ_PRIV_V1: &str = r#"{
|
||||
"attrs": {
|
||||
"class": ["group", "object"],
|
||||
|
|
|
@ -43,6 +43,9 @@ pub const _UUID_IDM_RADIUS_SECRET_READ_PRIV_V1: Uuid =
|
|||
pub const _UUID_IDM_RADIUS_SECRET_WRITE_PRIV_V1: Uuid =
|
||||
uuid!("00000000-0000-0000-0000-000000000031");
|
||||
|
||||
pub const _UUID_IDM_PEOPLE_SELF_WRITE_MAIL_PRIV: Uuid =
|
||||
uuid!("00000000-0000-0000-0000-000000000033");
|
||||
|
||||
//
|
||||
pub const _UUID_IDM_HIGH_PRIVILEGE: Uuid = uuid!("00000000-0000-0000-0000-000000001000");
|
||||
|
||||
|
@ -230,6 +233,8 @@ pub const _UUID_IDM_ACP_RADIUS_SECRET_READ_PRIV_V1: Uuid =
|
|||
uuid!("00000000-0000-0000-0000-ffffff000039");
|
||||
pub const _UUID_IDM_ACP_RADIUS_SECRET_WRITE_PRIV_V1: Uuid =
|
||||
uuid!("00000000-0000-0000-0000-ffffff000040");
|
||||
pub const _UUID_IDM_PEOPLE_SELF_ACP_WRITE_MAIL_V1: Uuid =
|
||||
uuid!("00000000-0000-0000-0000-ffffff000041");
|
||||
|
||||
// End of system ranges
|
||||
pub const UUID_DOES_NOT_EXIST: Uuid = uuid!("00000000-0000-0000-0000-fffffffffffe");
|
||||
|
|
|
@ -2368,6 +2368,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
JSON_IDM_PEOPLE_MANAGE_PRIV_V1,
|
||||
JSON_IDM_PEOPLE_ACCOUNT_PASSWORD_IMPORT_PRIV_V1,
|
||||
JSON_IDM_PEOPLE_EXTEND_PRIV_V1,
|
||||
JSON_IDM_PEOPLE_SELF_WRITE_MAIL_PRIV_V1,
|
||||
JSON_IDM_PEOPLE_WRITE_PRIV_V1,
|
||||
JSON_IDM_PEOPLE_READ_PRIV_V1,
|
||||
JSON_IDM_HP_PEOPLE_EXTEND_PRIV_V1,
|
||||
|
@ -2404,6 +2405,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
JSON_IDM_ALL_ACP_READ_V1,
|
||||
JSON_IDM_SELF_ACP_READ_V1,
|
||||
JSON_IDM_SELF_ACP_WRITE_V1,
|
||||
JSON_IDM_PEOPLE_SELF_ACP_WRITE_MAIL_PRIV_V1,
|
||||
JSON_IDM_ACP_PEOPLE_READ_PRIV_V1,
|
||||
JSON_IDM_ACP_PEOPLE_WRITE_PRIV_V1,
|
||||
JSON_IDM_ACP_PEOPLE_MANAGE_PRIV_V1,
|
||||
|
|
Loading…
Reference in a new issue