mirror of
https://github.com/kanidm/kanidm.git
synced 2025-04-22 10:15:39 +02:00
Tidy up schema
This commit is contained in:
parent
b113262357
commit
40cc9932a5
proto/src
server
lib/src
testkit/tests/testkit
|
@ -32,6 +32,7 @@ pub enum Attribute {
|
|||
AcpTargetScope,
|
||||
ApiTokenSession,
|
||||
ApplicationPassword,
|
||||
ApplicationUrl,
|
||||
AttestedPasskeys,
|
||||
#[default]
|
||||
Attr,
|
||||
|
@ -267,6 +268,7 @@ impl Attribute {
|
|||
Attribute::AcpTargetScope => ATTR_ACP_TARGET_SCOPE,
|
||||
Attribute::ApiTokenSession => ATTR_API_TOKEN_SESSION,
|
||||
Attribute::ApplicationPassword => ATTR_APPLICATION_PASSWORD,
|
||||
Attribute::ApplicationUrl => ATTR_APPLICATION_URL,
|
||||
Attribute::AttestedPasskeys => ATTR_ATTESTED_PASSKEYS,
|
||||
Attribute::Attr => ATTR_ATTR,
|
||||
Attribute::AttributeName => ATTR_ATTRIBUTENAME,
|
||||
|
@ -454,6 +456,7 @@ impl Attribute {
|
|||
ATTR_ACP_TARGET_SCOPE => Attribute::AcpTargetScope,
|
||||
ATTR_API_TOKEN_SESSION => Attribute::ApiTokenSession,
|
||||
ATTR_APPLICATION_PASSWORD => Attribute::ApplicationPassword,
|
||||
ATTR_APPLICATION_URL => Attribute::ApplicationUrl,
|
||||
ATTR_ATTESTED_PASSKEYS => Attribute::AttestedPasskeys,
|
||||
ATTR_ATTR => Attribute::Attr,
|
||||
ATTR_ATTRIBUTENAME => Attribute::AttributeName,
|
||||
|
|
|
@ -72,6 +72,7 @@ pub const ATTR_ACP_SEARCH_ATTR: &str = "acp_search_attr";
|
|||
pub const ATTR_ACP_TARGET_SCOPE: &str = "acp_targetscope";
|
||||
pub const ATTR_API_TOKEN_SESSION: &str = "api_token_session";
|
||||
pub const ATTR_APPLICATION_PASSWORD: &str = "application_password";
|
||||
pub const ATTR_APPLICATION_URL: &str = "application_url";
|
||||
pub const ATTR_ATTESTED_PASSKEYS: &str = "attested_passkeys";
|
||||
pub const ATTR_ATTR: &str = "attr";
|
||||
pub const ATTR_ATTRIBUTENAME: &str = "attributename";
|
||||
|
|
|
@ -334,6 +334,7 @@ pub const UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENT_CLASS: Uuid =
|
|||
uuid!("00000000-0000-0000-0000-ffff00000189");
|
||||
pub const UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVE_CLASS: Uuid =
|
||||
uuid!("00000000-0000-0000-0000-ffff00000190");
|
||||
pub const UUID_SCHEMA_ATTR_APPLICATION_URL: Uuid = uuid!("00000000-0000-0000-0000-ffff00000191");
|
||||
|
||||
// System and domain infos
|
||||
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
|
||||
|
|
|
@ -255,139 +255,6 @@ mod tests {
|
|||
|
||||
const TEST_CURRENT_TIME: u64 = 6000;
|
||||
|
||||
// Tests that only the correct combinations of [Account, Person, Application and
|
||||
// ServiceAccount] classes are allowed.
|
||||
#[idm_test]
|
||||
async fn test_idm_application_excludes(idms: &IdmServer, _idms_delayed: &mut IdmServerDelayed) {
|
||||
let ct = Duration::from_secs(TEST_CURRENT_TIME);
|
||||
let mut idms_prox_write = idms.proxy_write(ct).await.unwrap();
|
||||
|
||||
// ServiceAccount, Application and Person not allowed together
|
||||
let test_grp_name = "testgroup1";
|
||||
let test_grp_uuid = Uuid::new_v4();
|
||||
let e1 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Group.to_value()),
|
||||
(Attribute::Name, Value::new_iname(test_grp_name)),
|
||||
(Attribute::Uuid, Value::Uuid(test_grp_uuid))
|
||||
);
|
||||
let test_entry_uuid = Uuid::new_v4();
|
||||
let e2 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::Class, EntryClass::Person.to_value()),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
(
|
||||
Attribute::DisplayName,
|
||||
Value::new_utf8s("test_app_dispname")
|
||||
),
|
||||
(Attribute::LinkedGroup, Value::Refer(test_grp_uuid))
|
||||
);
|
||||
let ce = CreateEvent::new_internal(vec![e1, e2]);
|
||||
let cr = idms_prox_write.qs_write.create(&ce);
|
||||
assert!(cr.is_err());
|
||||
|
||||
// Application and Person not allowed together
|
||||
let test_grp_name = "testgroup1";
|
||||
let test_grp_uuid = Uuid::new_v4();
|
||||
let e1 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Group.to_value()),
|
||||
(Attribute::Name, Value::new_iname(test_grp_name)),
|
||||
(Attribute::Uuid, Value::Uuid(test_grp_uuid))
|
||||
);
|
||||
let test_entry_uuid = Uuid::new_v4();
|
||||
let e2 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::Class, EntryClass::Person.to_value()),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
(
|
||||
Attribute::DisplayName,
|
||||
Value::new_utf8s("test_app_dispname")
|
||||
),
|
||||
(Attribute::LinkedGroup, Value::Refer(test_grp_uuid))
|
||||
);
|
||||
let ce = CreateEvent::new_internal(vec![e1, e2]);
|
||||
let cr = idms_prox_write.qs_write.create(&ce);
|
||||
assert!(cr.is_err());
|
||||
|
||||
// Supplements not satisfied, Application supplements ServiceAccount
|
||||
let test_grp_name = "testgroup1";
|
||||
let test_grp_uuid = Uuid::new_v4();
|
||||
let e1 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Group.to_value()),
|
||||
(Attribute::Name, Value::new_iname(test_grp_name)),
|
||||
(Attribute::Uuid, Value::Uuid(test_grp_uuid))
|
||||
);
|
||||
let test_entry_uuid = Uuid::new_v4();
|
||||
let e2 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
(Attribute::LinkedGroup, Value::Refer(test_grp_uuid))
|
||||
);
|
||||
let ce = CreateEvent::new_internal(vec![e1, e2]);
|
||||
let cr = idms_prox_write.qs_write.create(&ce);
|
||||
assert!(cr.is_err());
|
||||
|
||||
// Supplements not satisfied, Application supplements ServiceAccount
|
||||
let test_grp_name = "testgroup1";
|
||||
let test_grp_uuid = Uuid::new_v4();
|
||||
let e1 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Group.to_value()),
|
||||
(Attribute::Name, Value::new_iname(test_grp_name)),
|
||||
(Attribute::Uuid, Value::Uuid(test_grp_uuid))
|
||||
);
|
||||
let test_entry_uuid = Uuid::new_v4();
|
||||
let e2 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
(Attribute::LinkedGroup, Value::Refer(test_grp_uuid))
|
||||
);
|
||||
let ce = CreateEvent::new_internal(vec![e1, e2]);
|
||||
let cr = idms_prox_write.qs_write.create(&ce);
|
||||
assert!(cr.is_err());
|
||||
|
||||
// Supplements satisfied, Application supplements ServiceAccount
|
||||
let test_grp_name = "testgroup1";
|
||||
let test_grp_uuid = Uuid::new_v4();
|
||||
let e1 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Group.to_value()),
|
||||
(Attribute::Name, Value::new_iname(test_grp_name)),
|
||||
(Attribute::Uuid, Value::Uuid(test_grp_uuid))
|
||||
);
|
||||
let test_entry_uuid = Uuid::new_v4();
|
||||
let e2 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
(Attribute::LinkedGroup, Value::Refer(test_grp_uuid))
|
||||
);
|
||||
let ce = CreateEvent::new_internal(vec![e1, e2]);
|
||||
let cr = idms_prox_write.qs_write.create(&ce);
|
||||
assert!(cr.is_ok());
|
||||
}
|
||||
|
||||
// Tests it is not possible to create an application without the linked group attribute
|
||||
#[idm_test]
|
||||
async fn test_idm_application_no_linked_group(
|
||||
|
@ -404,6 +271,7 @@ mod tests {
|
|||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
|
@ -547,8 +415,10 @@ mod tests {
|
|||
|
||||
let e3 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname(test_app_name)),
|
||||
(Attribute::Uuid, Value::Uuid(test_app_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(test_grp_uuid))
|
||||
|
@ -647,7 +517,9 @@ mod tests {
|
|||
let e2 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname("test_app_name")),
|
||||
(Attribute::Uuid, Value::Uuid(test_entry_uuid)),
|
||||
(Attribute::Description, Value::new_utf8s("test_app_desc")),
|
||||
|
|
|
@ -1119,8 +1119,10 @@ mod tests {
|
|||
|
||||
let e3 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname(app_name)),
|
||||
(Attribute::Uuid, Value::Uuid(app_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(grp_uuid))
|
||||
|
@ -1283,8 +1285,10 @@ mod tests {
|
|||
|
||||
let e3 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname("testapp1")),
|
||||
(Attribute::Uuid, Value::Uuid(app_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(grp_uuid))
|
||||
|
@ -1456,8 +1460,10 @@ mod tests {
|
|||
|
||||
let e4 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname(app1_name)),
|
||||
(Attribute::Uuid, Value::Uuid(app1_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(grp1_uuid))
|
||||
|
@ -1465,8 +1471,10 @@ mod tests {
|
|||
|
||||
let e5 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname(app2_name)),
|
||||
(Attribute::Uuid, Value::Uuid(app2_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(grp2_uuid))
|
||||
|
@ -1651,8 +1659,10 @@ mod tests {
|
|||
|
||||
let e3 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname(app1_name)),
|
||||
(Attribute::Uuid, Value::Uuid(app1_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(grp1_uuid))
|
||||
|
@ -2693,8 +2703,10 @@ mod tests {
|
|||
|
||||
let e3 = entry_init!(
|
||||
(Attribute::Class, EntryClass::Object.to_value()),
|
||||
(Attribute::Class, EntryClass::Account.to_value()),
|
||||
(Attribute::Class, EntryClass::ServiceAccount.to_value()),
|
||||
(Attribute::Class, EntryClass::Application.to_value()),
|
||||
(Attribute::DisplayName, Value::new_utf8s("Application")),
|
||||
(Attribute::Name, Value::new_iname(app_name)),
|
||||
(Attribute::Uuid, Value::Uuid(app_uuid)),
|
||||
(Attribute::LinkedGroup, Value::Refer(grp_uuid))
|
||||
|
|
|
@ -105,6 +105,7 @@ pub fn phase_1_schema_attrs() -> Vec<EntryInitNew> {
|
|||
// DL10
|
||||
SCHEMA_ATTR_DENIED_NAME_DL10.clone().into(),
|
||||
SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES.clone().into(),
|
||||
SCHEMA_ATTR_APPLICATION_URL.clone().into(),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -134,7 +135,7 @@ pub fn phase_2_schema_classes() -> Vec<EntryInitNew> {
|
|||
SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7.clone().into(),
|
||||
// DL8
|
||||
SCHEMA_CLASS_ACCOUNT_POLICY_DL8.clone().into(),
|
||||
SCHEMA_CLASS_APPLICATION_DL8.clone().into(),
|
||||
SCHEMA_CLASS_APPLICATION.clone().into(),
|
||||
SCHEMA_CLASS_PERSON_DL8.clone().into(),
|
||||
// DL9
|
||||
SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(),
|
||||
|
|
|
@ -729,6 +729,14 @@ pub static ref SCHEMA_ATTR_APPLICATION_PASSWORD_DL8: SchemaAttribute = SchemaAtt
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref SCHEMA_ATTR_APPLICATION_URL: SchemaAttribute = SchemaAttribute {
|
||||
uuid: UUID_SCHEMA_ATTR_APPLICATION_URL,
|
||||
name: Attribute::ApplicationUrl,
|
||||
description: "The URL of an external application".to_string(),
|
||||
syntax: SyntaxType::Url,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// === classes ===
|
||||
pub static ref SCHEMA_CLASS_PERSON_DL8: SchemaClass = SchemaClass {
|
||||
uuid: UUID_SCHEMA_CLASS_PERSON,
|
||||
|
@ -838,9 +846,9 @@ pub static ref SCHEMA_CLASS_ACCOUNT_DL5: SchemaClass = SchemaClass {
|
|||
Attribute::Spn
|
||||
],
|
||||
systemsupplements: vec![
|
||||
EntryClass::OAuth2ResourceServer.into(),
|
||||
EntryClass::Person.into(),
|
||||
EntryClass::ServiceAccount.into(),
|
||||
EntryClass::OAuth2ResourceServer.into(),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -1082,13 +1090,20 @@ pub static ref SCHEMA_CLASS_CLIENT_CERTIFICATE_DL7: SchemaClass = SchemaClass {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
pub static ref SCHEMA_CLASS_APPLICATION_DL8: SchemaClass = SchemaClass {
|
||||
pub static ref SCHEMA_CLASS_APPLICATION: SchemaClass = SchemaClass {
|
||||
uuid: UUID_SCHEMA_CLASS_APPLICATION,
|
||||
name: EntryClass::Application.into(),
|
||||
|
||||
description: "The class representing an application".to_string(),
|
||||
systemmust: vec![Attribute::Name, Attribute::LinkedGroup],
|
||||
systemmay: vec![Attribute::Description],
|
||||
systemmust: vec![Attribute::LinkedGroup],
|
||||
systemmay: vec![
|
||||
Attribute::ApplicationUrl,
|
||||
],
|
||||
// I think this could change before release - I can see a world
|
||||
// whe we may want an oauth2 application to have application passwords,
|
||||
// or for this to be it's own thing. But service accounts also don't
|
||||
// quite do enough, they have api tokens, but that's all we kind
|
||||
// of want from them?
|
||||
systemsupplements: vec![EntryClass::ServiceAccount.into()],
|
||||
..Default::default()
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use kanidmd_testkit::AsyncTestEnvironment;
|
||||
use kanidmd_testkit::{AsyncTestEnvironment, IDM_ADMIN_TEST_PASSWORD, IDM_ADMIN_TEST_USER};
|
||||
use ldap3_client::LdapClientBuilder;
|
||||
|
||||
const TEST_PERSON: &str = "user_mcuserton";
|
||||
|
||||
#[kanidmd_testkit::test(ldap = true)]
|
||||
async fn test_ldap_basic_unix_bind(test_env: &AsyncTestEnvironment) {
|
||||
let ldap_url = test_env.ldap_url.as_ref().unwrap();
|
||||
|
@ -14,3 +16,43 @@ async fn test_ldap_basic_unix_bind(test_env: &AsyncTestEnvironment) {
|
|||
|
||||
assert_eq!(whoami, Some("u: anonymous@localhost".to_string()));
|
||||
}
|
||||
|
||||
#[kanidmd_testkit::test(ldap = true)]
|
||||
async fn test_ldap_application_password_basic(test_env: &AsyncTestEnvironment) {
|
||||
// Remember, this isn't the exhaustive test for application password behaviours,
|
||||
// those are in the main server. This is just a basic smoke test that the interfaces
|
||||
// are exposed and work in a basic manner.
|
||||
|
||||
let rsclient = test_env.rsclient.new_session().unwrap();
|
||||
|
||||
// Create a person
|
||||
|
||||
rsclient
|
||||
.auth_simple_password(IDM_ADMIN_TEST_USER, IDM_ADMIN_TEST_PASSWORD)
|
||||
.await
|
||||
.expect("Failed to login as admin");
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
rsclient
|
||||
.idm_person_account_create(TEST_PERSON, TEST_PERSON)
|
||||
.await
|
||||
.expect("Failed to create the user");
|
||||
|
||||
// Create two applications
|
||||
|
||||
// List, get them.
|
||||
|
||||
// Login as the person
|
||||
|
||||
// Create application passwords
|
||||
|
||||
// Check the work.
|
||||
|
||||
// Check they can't cross talk.
|
||||
|
||||
// Done!
|
||||
|
||||
// let ldap_url = test_env.ldap_url.as_ref().unwrap();
|
||||
|
||||
// let mut ldap_client = LdapClientBuilder::new(ldap_url).build().await.unwrap();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue