Add a new ACP and group allowing self-service mail updates ()

* 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  for a bit more background

* Limit the self-write ACP to targets with the "account" class

Per feedback on , 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:
Euan Kemp 2022-04-13 03:45:45 -07:00 committed by GitHub
parent d9016011f4
commit 9427d27141
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 1 deletions
kanidm_book/src
kanidm_client/tests
kanidmd/src/lib

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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