Moved everything to the DB!

This commit is contained in:
Sebastiano Tocci 2025-02-15 23:20:32 +01:00
parent 7a829646c4
commit 31c28fe9a8
15 changed files with 147 additions and 78 deletions
libs/client/src
proto/src
server
tools/cli/src
cli/domain
opt

View file

@ -30,8 +30,8 @@ use compact_jwt::Jwk;
use kanidm_proto::constants::uri::V1_AUTH_VALID;
use kanidm_proto::constants::{
ATTR_DOMAIN_DISPLAY_NAME, ATTR_DOMAIN_LDAP_BASEDN, ATTR_DOMAIN_SSID, ATTR_ENTRY_MANAGED_BY,
ATTR_KEY_ACTION_REVOKE, ATTR_LDAP_ALLOW_UNIX_PW_BIND, ATTR_NAME, CLIENT_TOKEN_CACHE, KOPID,
KSESSIONID, KVERSION,
ATTR_KEY_ACTION_REVOKE, ATTR_LDAP_ALLOW_UNIX_PW_BIND, ATTR_LDAP_MAX_QUERYABLE_ATTRS, ATTR_NAME,
CLIENT_TOKEN_CACHE, KOPID, KSESSIONID, KVERSION,
};
use kanidm_proto::internal::*;
use kanidm_proto::v1::*;
@ -2075,6 +2075,18 @@ impl KanidmClient {
.await
}
/// Sets the maximum number of LDAP attributes that can be queryed in a single operation
pub async fn idm_domain_set_ldap_max_queryable_attrs(
&self,
max_queryable_attrs: usize,
) -> Result<(), ClientError> {
self.perform_put_request(
&format!("/v1/domain/_attr/{}", ATTR_LDAP_MAX_QUERYABLE_ATTRS),
vec![max_queryable_attrs.to_string()],
)
.await
}
pub async fn idm_set_ldap_allow_unix_password_bind(
&self,
enable: bool,

View file

@ -94,6 +94,7 @@ pub enum Attribute {
LdapEmailAddress,
/// An LDAP Compatible sshkeys virtual attribute
LdapKeys,
LdapMaxQueryableAttrs,
LegalName,
LimitSearchMaxResults,
LimitSearchMaxFilterTest,
@ -322,6 +323,7 @@ impl Attribute {
Attribute::LdapAllowUnixPwBind => ATTR_LDAP_ALLOW_UNIX_PW_BIND,
Attribute::LdapEmailAddress => ATTR_LDAP_EMAIL_ADDRESS,
Attribute::LdapKeys => ATTR_LDAP_KEYS,
Attribute::LdapMaxQueryableAttrs => ATTR_LDAP_MAX_QUERYABLE_ATTRS,
Attribute::LdapSshPublicKey => ATTR_LDAP_SSHPUBLICKEY,
Attribute::LegalName => ATTR_LEGALNAME,
Attribute::LimitSearchMaxResults => ATTR_LIMIT_SEARCH_MAX_RESULTS,
@ -505,6 +507,7 @@ impl Attribute {
ATTR_LDAP_ALLOW_UNIX_PW_BIND => Attribute::LdapAllowUnixPwBind,
ATTR_LDAP_EMAIL_ADDRESS => Attribute::LdapEmailAddress,
ATTR_LDAP_KEYS => Attribute::LdapKeys,
ATTR_LDAP_MAX_QUERYABLE_ATTRS => Attribute::LdapMaxQueryableAttrs,
ATTR_SSH_PUBLICKEY => Attribute::SshPublicKey,
ATTR_LEGALNAME => Attribute::LegalName,
ATTR_LINKEDGROUP => Attribute::LinkedGroup,

View file

@ -104,6 +104,7 @@ pub const ATTR_DYNGROUP_FILTER: &str = "dyngroup_filter";
pub const ATTR_DYNGROUP: &str = "dyngroup";
pub const ATTR_DYNMEMBER: &str = "dynmember";
pub const ATTR_LDAP_EMAIL_ADDRESS: &str = "emailaddress";
pub const ATTR_LDAP_MAX_QUERYABLE_ATTRS: &str = "ldap_max_queryable_attrs";
pub const ATTR_EMAIL_ALTERNATIVE: &str = "emailalternative";
pub const ATTR_EMAIL_PRIMARY: &str = "emailprimary";
pub const ATTR_EMAIL: &str = "email";

View file

@ -14,7 +14,6 @@ use kanidm_proto::constants::DEFAULT_SERVER_ADDRESS;
use kanidm_proto::internal::FsType;
use kanidm_proto::messages::ConsoleOutputMode;
use kanidmd_lib::prelude::DEFAULT_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES;
use serde::Deserialize;
use sketching::LogLevel;
use url::Url;
@ -117,9 +116,6 @@ pub struct ServerConfig {
///
/// If unset, the LDAP server will be disabled.
pub ldapbindaddress: Option<String>,
/// The maximum number of LDAP attributes that can be queried in one operation.
/// Defaults to [kanidm_proto::constants::DEFAULT_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES]
pub ldap_maximum_queryable_attributes: Option<usize>,
/// The role of this server, one of write_replica, write_replica_no_ui, read_only_replica, defaults to [ServerRole::WriteReplica]
#[serde(default)]
pub role: ServerRole,
@ -480,7 +476,6 @@ pub struct IntegrationReplConfig {
pub struct Configuration {
pub address: String,
pub ldapaddress: Option<String>,
pub ldap_maximum_queryable_attrs: usize,
pub adminbindpath: String,
pub threads: usize,
// db type later
@ -575,7 +570,6 @@ impl Configuration {
Configuration {
address: DEFAULT_SERVER_ADDRESS.to_string(),
ldapaddress: None,
ldap_maximum_queryable_attrs: DEFAULT_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES,
adminbindpath: env!("KANIDM_SERVER_ADMIN_BIND_PATH").to_string(),
threads: std::thread::available_parallelism()
.map(|t| t.get())
@ -653,9 +647,6 @@ impl Configuration {
self.update_ldapbind(&sconfig.ldapbindaddress);
self.update_online_backup(&sconfig.online_backup);
self.update_log_level(&sconfig.log_level);
if let Some(ldap_maximum_queryable_attrs) = sconfig.ldap_maximum_queryable_attributes {
self.update_ldap_maximum_queryable_attrs(ldap_maximum_queryable_attrs);
}
}
pub fn update_trust_x_forward_for(&mut self, t: Option<bool>) {
@ -742,9 +733,4 @@ impl Configuration {
pub fn update_threads_count(&mut self, threads: usize) {
self.threads = std::cmp::min(self.threads, threads);
}
// Updates the maximum number of LDAP attributes that can be queried in a single operation
pub fn update_ldap_maximum_queryable_attrs(&mut self, maximum_queryable_attrs: usize) {
self.ldap_maximum_queryable_attrs = maximum_queryable_attrs;
}
}

View file

@ -937,7 +937,7 @@ pub async fn create_server_core(
}
}
let ldap = match LdapServer::new(&idms, config.ldap_maximum_queryable_attrs).await {
let ldap = match LdapServer::new(&idms).await {
Ok(l) => l,
Err(e) => {
error!("Unable to start LdapServer -> {:?}", e);

View file

@ -1045,6 +1045,7 @@ lazy_static! {
Attribute::DomainDisplayName,
Attribute::DomainName,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainSsid,
Attribute::DomainUuid,
// Grants read access to the key object.
@ -1058,6 +1059,7 @@ lazy_static! {
Attribute::DomainDisplayName,
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::KeyActionRevoke,
Attribute::KeyActionRotate,
@ -1065,6 +1067,7 @@ lazy_static! {
modify_present_attrs: vec![
Attribute::DomainDisplayName,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainSsid,
Attribute::LdapAllowUnixPwBind,
Attribute::KeyActionRevoke,
@ -1100,6 +1103,7 @@ lazy_static! {
Attribute::DomainDisplayName,
Attribute::DomainName,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainSsid,
Attribute::DomainUuid,
Attribute::KeyInternalData,
@ -1111,6 +1115,7 @@ lazy_static! {
Attribute::DomainDisplayName,
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::KeyActionRevoke,
Attribute::KeyActionRotate,
@ -1119,6 +1124,7 @@ lazy_static! {
modify_present_attrs: vec![
Attribute::DomainDisplayName,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainSsid,
Attribute::LdapAllowUnixPwBind,
Attribute::KeyActionRevoke,
@ -1156,6 +1162,7 @@ lazy_static! {
Attribute::DomainDisplayName,
Attribute::DomainName,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainSsid,
Attribute::DomainUuid,
Attribute::KeyInternalData,
@ -1167,6 +1174,7 @@ lazy_static! {
Attribute::DomainDisplayName,
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainAllowEasterEggs,
Attribute::LdapAllowUnixPwBind,
Attribute::KeyActionRevoke,
@ -1176,6 +1184,7 @@ lazy_static! {
modify_present_attrs: vec![
Attribute::DomainDisplayName,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::DomainSsid,
Attribute::DomainAllowEasterEggs,
Attribute::LdapAllowUnixPwBind,

View file

@ -167,6 +167,17 @@ pub static ref SCHEMA_ATTR_DOMAIN_LDAP_BASEDN: SchemaAttribute = SchemaAttribute
..Default::default()
};
pub static ref SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES: SchemaAttribute = SchemaAttribute {
uuid: UUID_SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES,
name: Attribute::LdapMaxQueryableAttrs,
description: "The maximum number of LDAP attributes that can be queried in one operation".to_string(),
multivalue: false,
sync_allowed: true,
syntax: SyntaxType::Uint32,
..Default::default()
};
pub static ref SCHEMA_ATTR_DOMAIN_DISPLAY_NAME: SchemaAttribute = SchemaAttribute {
uuid: UUID_SCHEMA_ATTR_DOMAIN_DISPLAY_NAME,
name: Attribute::DomainDisplayName,
@ -1133,6 +1144,7 @@ pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL6: SchemaClass = SchemaClass {
systemmay: vec![
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::PrivateCookieKey,
Attribute::FernetPrivateKeyStr,
@ -1158,6 +1170,7 @@ pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL7: SchemaClass = SchemaClass {
systemmay: vec![
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::PatchLevel,
Attribute::DomainDevelopmentTaint,
@ -1180,6 +1193,7 @@ pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL8: SchemaClass = SchemaClass {
systemmay: vec![
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::Image,
Attribute::PatchLevel,
@ -1203,6 +1217,7 @@ pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL9: SchemaClass = SchemaClass {
systemmay: vec![
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::Image,
Attribute::PatchLevel,
@ -1227,6 +1242,7 @@ pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL10: SchemaClass = SchemaClass {
systemmay: vec![
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::Image,
Attribute::PatchLevel,

View file

@ -131,7 +131,8 @@ pub const UUID_SCHEMA_ATTR_PRIMARY_CREDENTIAL: Uuid = uuid!("00000000-0000-0000-
pub const UUID_SCHEMA_CLASS_PERSON: Uuid = uuid!("00000000-0000-0000-0000-ffff00000044");
pub const UUID_SCHEMA_CLASS_GROUP: Uuid = uuid!("00000000-0000-0000-0000-ffff00000045");
pub const UUID_SCHEMA_CLASS_ACCOUNT: Uuid = uuid!("00000000-0000-0000-0000-ffff00000046");
// GAP - 47
pub const UUID_SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES: Uuid =
uuid!("00000000-0000-0000-0000-ffff00000187");
pub const UUID_SCHEMA_ATTR_ATTRIBUTENAME: Uuid = uuid!("00000000-0000-0000-0000-ffff00000048");
pub const UUID_SCHEMA_ATTR_CLASSNAME: Uuid = uuid!("00000000-0000-0000-0000-ffff00000049");
pub const UUID_SCHEMA_ATTR_LEGALNAME: Uuid = uuid!("00000000-0000-0000-0000-ffff00000050");

View file

@ -60,7 +60,7 @@ pub struct LdapServer {
basedn: String,
dnre: Regex,
binddnre: Regex,
maximum_queryable_attrs: usize,
max_queryable_attrs: usize,
}
#[derive(Debug)]
@ -71,10 +71,7 @@ enum LdapBindTarget {
}
impl LdapServer {
pub async fn new(
idms: &IdmServer,
maximum_queryable_attrs: usize,
) -> Result<Self, OperationError> {
pub async fn new(idms: &IdmServer) -> Result<Self, OperationError> {
// let ct = duration_from_epoch_now();
let mut idms_prox_read = idms.proxy_read().await?;
// This is the rootdse path.
@ -83,6 +80,12 @@ impl LdapServer {
.qs_read
.internal_search_uuid(UUID_DOMAIN_INFO)?;
// Get the maximum number of queryable attributes from the domain entry
let max_queryable_attrs = domain_entry
.get_ava_single_uint32(Attribute::LdapMaxQueryableAttrs)
.map(|u| u as usize)
.unwrap_or(DEFAULT_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES);
let basedn = domain_entry
.get_ava_single_iutf8(Attribute::DomainLdapBasedn)
.map(|s| s.to_string())
@ -158,7 +161,7 @@ impl LdapServer {
basedn,
dnre,
binddnre,
maximum_queryable_attrs,
max_queryable_attrs,
})
}
@ -244,10 +247,11 @@ impl LdapServer {
let mut all_attrs = false;
let mut all_op_attrs = false;
let attrs_len = sr.attrs.len();
if sr.attrs.is_empty() {
// If [], then "all" attrs
all_attrs = true;
} else if sr.attrs.len() < self.maximum_queryable_attrs {
} else if attrs_len < self.max_queryable_attrs {
sr.attrs.iter().for_each(|a| {
if a == "*" {
all_attrs = true;
@ -272,6 +276,10 @@ impl LdapServer {
}
})
} else {
admin_error!(
"Too many LDAP attributes requested. Maximum allowed is {}, while your search query had {}",
self.max_queryable_attrs, attrs_len
);
return Err(OperationError::ResourceLimit);
// TODO: Should we return ResourceLimit or InvalidRequestState here?
}
@ -866,9 +874,7 @@ mod tests {
#[idm_test]
async fn test_ldap_simple_bind(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let mut idms_prox_write = idms.proxy_write(duration_from_epoch_now()).await.unwrap();
// make the admin a valid posix account
@ -1063,9 +1069,7 @@ mod tests {
#[idm_test]
async fn test_ldap_application_dnre(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let testdn = format!("app=app1,{0}", ldaps.basedn);
let captures = ldaps.dnre.captures(testdn.as_str()).unwrap();
@ -1088,9 +1092,7 @@ mod tests {
#[idm_test]
async fn test_ldap_application_search(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let usr_uuid = Uuid::new_v4();
let grp_uuid = Uuid::new_v4();
@ -1173,9 +1175,7 @@ mod tests {
#[idm_test]
async fn test_ldap_spn_search(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let usr_uuid = Uuid::new_v4();
let usr_name = "panko";
@ -1257,9 +1257,7 @@ mod tests {
#[idm_test]
async fn test_ldap_application_bind(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let usr_uuid = Uuid::new_v4();
let grp_uuid = Uuid::new_v4();
@ -1415,9 +1413,7 @@ mod tests {
idms: &IdmServer,
_idms_delayed: &IdmServerDelayed,
) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let usr_uuid = Uuid::new_v4();
let usr_name = "testuser1";
@ -1621,9 +1617,7 @@ mod tests {
idms: &IdmServer,
_idms_delayed: &IdmServerDelayed,
) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let usr_uuid = Uuid::new_v4();
let usr_name = "testuser1";
@ -1760,9 +1754,7 @@ mod tests {
idms: &IdmServer,
_idms_delayed: &IdmServerDelayed,
) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let ssh_ed25519 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAeGW1P6Pc2rPq0XqbRaDKBcXZUPRklo0L1EyR30CwoP william@amethyst";
@ -1925,9 +1917,7 @@ mod tests {
_idms_delayed: &IdmServerDelayed,
) {
// Setup the ldap server
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
// Prebuild the search req we'll be using this test.
let sr = SearchRequest {
@ -2167,9 +2157,7 @@ mod tests {
idms: &IdmServer,
_idms_delayed: &IdmServerDelayed,
) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let acct_uuid = uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
@ -2238,9 +2226,7 @@ mod tests {
// Test behaviour of the 1.1 attribute.
#[idm_test]
async fn test_ldap_one_dot_one_attribute(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let acct_uuid = uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
@ -2329,9 +2315,7 @@ mod tests {
#[idm_test]
async fn test_ldap_rootdse_basedn_change(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let anon_t = ldaps.do_bind(idms, "", "").await.unwrap().unwrap();
assert_eq!(
@ -2387,9 +2371,7 @@ mod tests {
assert!(idms_prox_write.commit().is_ok());
// Now re-test
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let anon_t = ldaps.do_bind(idms, "", "").await.unwrap().unwrap();
assert_eq!(
@ -2430,9 +2412,7 @@ mod tests {
#[idm_test]
async fn test_ldap_sssd_compat(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let acct_uuid = uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");
@ -2540,9 +2520,7 @@ mod tests {
#[idm_test]
async fn test_ldap_compare_request(idms: &IdmServer, _idms_delayed: &IdmServerDelayed) {
let ldaps = LdapServer::new(idms, 1000)
.await
.expect("failed to start ldap");
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
// Setup a user we want to check.
{
@ -2674,9 +2652,21 @@ mod tests {
idms: &IdmServer,
_idms_delayed: &IdmServerDelayed,
) {
let ldaps = LdapServer::new(idms, 2)
.await
.expect("failed to start ldap");
// Set the max queryable attrs to 2
let mut server_txn = idms.proxy_write(duration_from_epoch_now()).await.unwrap();
let set_ldap_maximum_queryable_attrs = ModifyEvent::new_internal_invalid(
filter!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_DOMAIN_INFO))),
ModifyList::new_purge_and_set(Attribute::LdapMaxQueryableAttrs, Value::Uint32(2)),
);
assert!(server_txn
.qs_write
.modify(&set_ldap_maximum_queryable_attrs)
.and_then(|_| server_txn.commit())
.is_ok());
let ldaps = LdapServer::new(idms).await.expect("failed to start ldap");
let usr_uuid = Uuid::new_v4();
let grp_uuid = Uuid::new_v4();
@ -2756,6 +2746,6 @@ mod tests {
.await;
assert_eq!(invalid_res, Err(OperationError::ResourceLimit));
assert_ne!(valid_res, Err(OperationError::ResourceLimit));
assert!(valid_res.is_ok());
}
}

View file

@ -25,6 +25,7 @@ lazy_static! {
// modification of some domain info types for local configuratiomn.
Attribute::DomainSsid,
Attribute::DomainLdapBasedn,
Attribute::LdapMaxQueryableAttrs,
Attribute::LdapAllowUnixPwBind,
Attribute::FernetPrivateKeyStr,
Attribute::Es256PrivateKeyDer,

View file

@ -519,6 +519,7 @@ impl QueryServerWriteTransaction<'_> {
// SCHEMA_ATTR_DISPLAYNAME.clone().into(),
SCHEMA_ATTR_DOMAIN_DISPLAY_NAME.clone().into(),
SCHEMA_ATTR_DOMAIN_LDAP_BASEDN.clone().into(),
SCHEMA_ATTR_LDAP_MAXIMUM_QUERYABLE_ATTRIBUTES.clone().into(),
SCHEMA_ATTR_DOMAIN_NAME.clone().into(),
SCHEMA_ATTR_LDAP_ALLOW_UNIX_PW_BIND.clone().into(),
SCHEMA_ATTR_DOMAIN_SSID.clone().into(),

View file

@ -26,6 +26,19 @@ async fn test_idm_domain_set_ldap_basedn(rsclient: KanidmClient) {
.expect("Failed to set idm_domain_set_ldap_basedn");
}
#[kanidmd_testkit::test]
async fn test_idm_domain_set_ldap_max_queryable_attrs(rsclient: KanidmClient) {
rsclient
.auth_simple_password(ADMIN_TEST_USER, ADMIN_TEST_PASSWORD)
.await
.expect("Failed to login as admin");
rsclient
.idm_domain_set_ldap_max_queryable_attrs(30)
.await
.expect("Failed to set idm_domain_set_ldap_max_queryable_attrs");
}
#[kanidmd_testkit::test]
async fn test_idm_domain_set_display_name(rsclient: KanidmClient) {
rsclient

View file

@ -231,6 +231,19 @@ async fn test_idm_domain_set_ldap_basedn(rsclient: KanidmClient) {
.is_err());
}
#[kanidmd_testkit::test]
async fn test_idm_domain_set_ldap_max_queryable_attrs(rsclient: KanidmClient) {
login_put_admin_idm_admins(&rsclient).await;
assert!(rsclient
.idm_domain_set_ldap_max_queryable_attrs(20)
.await
.is_ok());
assert!(rsclient
.idm_domain_set_ldap_max_queryable_attrs(10) //TODO: Help, Rust's type safety is so good I can't come up with a way to pass an invalid value
.await
.is_ok()); // Ideally this should be "is_err"
}
#[kanidmd_testkit::test]
/// Checks that a built-in group idm_all_persons has the "builtin" class as expected.
async fn test_all_persons_has_builtin_class(rsclient: KanidmClient) {

View file

@ -14,7 +14,8 @@ impl DomainOpt {
| DomainOpt::SetLdapAllowUnixPasswordBind { copt, .. }
| DomainOpt::SetAllowEasterEggs { copt, .. }
| DomainOpt::RevokeKey { copt, .. }
| DomainOpt::Show(copt) => copt.debug,
| DomainOpt::Show(copt)
| DomainOpt::SetLdapMaxQueryableAttrs { copt, .. } => copt.debug,
}
}
@ -34,6 +35,23 @@ impl DomainOpt {
Err(e) => handle_client_error(e, opt.copt.output_mode),
}
}
DomainOpt::SetLdapMaxQueryableAttrs {
copt,
new_max_queryable_attrs,
} => {
eprintln!(
"Attempting to set the maximum number of queryable LDAP attributes to: {:?}",
new_max_queryable_attrs
);
let client = copt.to_client(OpType::Write).await;
match client
.idm_domain_set_ldap_max_queryable_attrs(*new_max_queryable_attrs)
.await
{
Ok(_) => println!("Success"),
Err(e) => handle_client_error(e, copt.output_mode),
}
}
DomainOpt::SetLdapBasedn { copt, new_basedn } => {
eprintln!(
"Attempting to set the domain's ldap basedn to: {:?}",

View file

@ -198,7 +198,6 @@ pub enum GroupAccountPolicyOpt {
copt: CommonOpt,
},
/// Set the maximum time for privilege session expiry in seconds.
#[clap(name = "privilege-expiry")]
PrivilegedSessionExpiry {
@ -208,7 +207,6 @@ pub enum GroupAccountPolicyOpt {
copt: CommonOpt,
},
/// The WebAuthn attestation CA list that should be enforced
/// on members of this group. Prevents use of passkeys that are
/// not in this list. To create this list, use `fido-mds-tool`
@ -294,7 +292,6 @@ pub enum GroupAccountPolicyOpt {
#[clap(flatten)]
copt: CommonOpt,
},
}
#[derive(Debug, Subcommand)]
@ -1313,6 +1310,14 @@ pub enum DomainOpt {
#[clap[name = "set-displayname"]]
/// Set the domain display name
SetDisplayname(OptSetDomainDisplayname),
/// Sets the maximum number of LDAP attributes that can be queried in one operation.
#[clap[name = "set-ldap-queryable-attrs"]]
SetLdapMaxQueryableAttrs {
#[clap(flatten)]
copt: CommonOpt,
#[clap(name = "maximum-queryable-attrs")]
new_max_queryable_attrs: usize,
},
#[clap[name = "set-ldap-basedn"]]
/// Change the basedn of this server. Takes effect after a server restart.
/// Examples are `o=organisation` or `dc=domain,dc=name`. Must be a valid ldap