diff --git a/proto/src/constants.rs b/proto/src/constants.rs index de7e3c434..b86216afd 100644 --- a/proto/src/constants.rs +++ b/proto/src/constants.rs @@ -187,6 +187,7 @@ pub const OAUTH2_SCOPE_READ: &str = "read"; pub const OAUTH2_SCOPE_SUPPLEMENT: &str = "supplement"; pub const LDAP_ATTR_CN: &str = "cn"; +pub const LDAP_ATTR_DN: &str = "dn"; pub const LDAP_ATTR_DISPLAY_NAME: &str = "displayname"; pub const LDAP_ATTR_EMAIL_ALTERNATIVE: &str = "emailalternative"; pub const LDAP_ATTR_EMAIL_PRIMARY: &str = "emailprimary"; diff --git a/proto/src/scim_v1.rs b/proto/src/scim_v1.rs index a645b3c57..c10113083 100644 --- a/proto/src/scim_v1.rs +++ b/proto/src/scim_v1.rs @@ -11,7 +11,7 @@ use scim_proto::*; use crate::constants::{ ATTR_ACCOUNT_EXPIRE, ATTR_ACCOUNT_VALID_FROM, ATTR_DESCRIPTION, ATTR_DISPLAYNAME, ATTR_GIDNUMBER, ATTR_LOGINSHELL, ATTR_MAIL, ATTR_MEMBER, ATTR_NAME, ATTR_PASSWORD_IMPORT, - ATTR_SSH_PUBLICKEY, ATTR_UNIX_PASSWORD_IMPORT, ATTR_TOTP_IMPORT + ATTR_SSH_PUBLICKEY, ATTR_TOTP_IMPORT, ATTR_UNIX_PASSWORD_IMPORT, }; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)] diff --git a/server/lib/src/entry.rs b/server/lib/src/entry.rs index 0d7c15dff..b6cc7185d 100644 --- a/server/lib/src/entry.rs +++ b/server/lib/src/entry.rs @@ -2402,8 +2402,12 @@ impl Entry { .filter_map(|(ldap_a, kani_a)| { // In some special cases, we may need to transform or rewrite the values. match ldap_a { - "entrydn" => Some(LdapPartialAttribute { - atype: "entrydn".to_string(), + LDAP_ATTR_DN => Some(LdapPartialAttribute { + atype: LDAP_ATTR_DN.to_string(), + vals: vec![dn.as_bytes().to_vec()], + }), + LDAP_ATTR_ENTRYDN => Some(LdapPartialAttribute { + atype: LDAP_ATTR_ENTRYDN.to_string(), vals: vec![dn.as_bytes().to_vec()], }), LDAP_ATTR_MAIL_PRIMARY | LDAP_ATTR_EMAIL_PRIMARY => { diff --git a/server/lib/src/idm/ldap.rs b/server/lib/src/idm/ldap.rs index e16858c8e..056da2a18 100644 --- a/server/lib/src/idm/ldap.rs +++ b/server/lib/src/idm/ldap.rs @@ -268,15 +268,7 @@ impl LdapServer { // NOTE: All req_attrs are lowercase at this point. let mapped_attrs: BTreeSet<_> = req_attrs .iter() - .filter_map(|a| { - // EntryDN and DN have special handling in to_ldap in Entry. We don't - // need these here, we know they will be returned as part of the transform. - if a == "entrydn" || a == "dn" { - None - } else { - Some(AttrString::from(ldap_vattr_map(a).unwrap_or(a))) - } - }) + .map(|a| AttrString::from(ldap_vattr_map(a).unwrap_or(a))) .collect(); (Some(mapped_attrs), req_attrs) @@ -564,9 +556,10 @@ pub(crate) fn ldap_all_vattrs() -> Vec { ATTR_CN.to_string(), ATTR_EMAIL.to_string(), ATTR_LDAP_EMAIL_ADDRESS.to_string(), + LDAP_ATTR_DN.to_string(), LDAP_ATTR_EMAIL_ALTERNATIVE.to_string(), LDAP_ATTR_EMAIL_PRIMARY.to_string(), - "entrydn".to_string(), + LDAP_ATTR_ENTRYDN.to_string(), LDAP_ATTR_ENTRYUUID.to_string(), LDAP_ATTR_KEYS.to_string(), LDAP_ATTR_MAIL_ALTERNATIVE.to_string(), @@ -588,7 +581,12 @@ pub(crate) fn ldap_vattr_map(input: &str) -> Option<&str> { // // LDAP NAME KANI ATTR SOURCE NAME match input { - ATTR_CN | ATTR_UID => Some(ATTR_NAME), + // EntryDN and DN have special handling in to_ldap in Entry. However, we + // need to map them to "name" so that if the user has requested dn/entrydn + // only, then we still requested at least one attribute from the backend + // allowing the access control tests to take place. Otherwise no entries + // would be returned. + ATTR_CN | ATTR_UID | LDAP_ATTR_ENTRYDN | LDAP_ATTR_DN => Some(ATTR_NAME), ATTR_GECOS => Some(ATTR_DISPLAYNAME), ATTR_EMAIL => Some(ATTR_MAIL), ATTR_LDAP_EMAIL_ADDRESS => Some(ATTR_MAIL),