SSSD / sssd

A daemon to manage identity, authentication and authorization for centrally-managed systems.
https://sssd.io
GNU General Public License v3.0
604 stars 247 forks source link

sssd-ldap vs AD forest #7046

Open NdK73 opened 12 months ago

NdK73 commented 12 months ago

Hello all.

I have to interface with AD via ldap backend (can not join: it makes large redeploys quite problematic, having to give my own pass on every machine). Out of the many domains in the AD forest, I'm only interested in PERSONALE and STUDENTI. I can only manage OUs, groups and machine accounts in PERSONALE. My users come from both domains, but I'm only interested in memberships of groups in PERSONALE (those are 'universal' groups that contain users from both domains).

I currently use this sssd.conf file:

[sssd]
config_file_version = 2
services = nss,pam
# Order is important: if I first lookup in PERSONALE, students are also assigned to PERSONALE!
domains = studenti.domain.it,personale.domain.it
debug_level = 3
override_space = ^

[nss]
fallback_homedir = */home/*%d/%u
default_shell = /bin/bash
debug_level = 3

[pam]
debug_level = 3

[domain/personale.domain.it]
override_homedir = /home/PERSONALE/%u
id_provider = ldap
auth_provider = ldap
access_provider = ldap
ldap_group_nesting_level = 5
ldap_uri = ldaps://personale.dir.unibo.it:3269
ldap_user_search_base = DC=personale,DC=domain,DC=it???DC=studenti,DC=domain,DC=it??
ldap_group_search_base = OU=REDACTED,DC=personale,DC=domain,DC=it??
ldap_default_bind_dn = CN=REDACTED,DC=personale,DC=domain,DC=it
ldap_default_authtok_type = password
ldap_default_authtok = REDACTED
ldap_user_object_class = person
ldap_group_object_class = group
ldap_user_fullname = displayName
ldap_schema = ad
ldap_referrals = False
#ldap_referrals = true
ldap_id_mapping = True
enumerate = false

# Caching settings
cache_credentials = true
entry_cache_user_timeout = 28800
entry_cache_group_timeout = 86400

ldap_id_use_start_tls = false
debug_level = 3
ldap_access_filter =(memberOf:1.2.840.113556.1.4.1941:=CN=REDACTED,DC=personale,DC=domain,DC=it)

case_sensitive = Preserving

[domain/studenti.domain.it]
override_homedir = /home/STUDENTI/%u
id_provider = ldap
auth_provider = ldap
access_provider = ldap
ldap_group_nesting_level = 5
# **MUST** use GlobalCatalog port or can't access a group in PERSONALE for ldap_access_filter
ldap_uri = ldaps://studenti.domain.it:3269
ldap_user_search_base = DC=studenti,DC=domain,DC=it
# *NOPE*: see notes
#ldap_group_search_base = OU=REDACED,DC=personale,DC=domain,DC=it??

ldap_default_bind_dn = CN=REDACTED,DC=personale,DC=domain,DC=it
ldap_default_authtok_type = password
ldap_default_authtok = REDACTED
ldap_user_object_class = person
ldap_group_object_class = group
ldap_user_fullname = displayName
ldap_schema = ad
ldap_referrals = true
ldap_id_mapping = True
enumerate = false
cache_credentials = true
ldap_id_use_start_tls = false
debug_level = 3

ldap_access_filter =(memberOf:1.2.840.113556.1.4.1941:=CN=REDACTED,DC=domain,DC=it)

case_sensitive = Preserving

Problems:

But while 'getent group grpname' returns all users (from both domains), id username only returns groups from username's domain.

Is there a way to make sssd only consider groups in PERSONALE also for users in STUDENTI and return consistent results for both id and getent?

Tks.

sumit-bose commented 11 months ago

Hi,

SSSD does not support to mix users and groups from different configured domains in sssd.conf.

What might work in your case is to have a single domain which looks like your [domain/personale.domain.it]. But with this you cannot split the home directories into two different directories.

bye, Sumit

albertl6 commented 10 months ago

@NdK73, from your description, there are global catalog server in your environment, so you may just add the global catalog server as single domain in sssd.conf. GC (Global Catalog) is designed especially for this kind of query/authentication purpose, as AD domain services in every DC are responsible to replicate data automatically to maintain consistency globally.

NdK73 commented 10 months ago

Thanks @albertl6 but that would mean (as Sumit pointed out) that I can't have per-domain home directories (students in /home/STUDENTI/ and staff in /home/PERSONALE/ )... I'm already using GC to be able to enumerate members from both domains (else I couldn't use a group in PERSONALE as access filter for members of STUDENTI). What really puzzles me is that adding a ldap_group_search_base in STUDENTI affects members of PERSONALE... Naively I thought that it just passed a different search base for users already identified in STUDENTI.

NdK73 commented 6 months ago

I created this patch to be able to differentiate users from different domains. It adds the override_homedir macro %R (for 'Realm' but it's not the real realm) that simply extracts the part after '@' in the UPN.

--- sss_nss.c.ori       2024-04-30 14:34:21.461449851 +0200
+++ sss_nss.c   2024-04-30 14:53:07.817140238 +0200
@@ -202,6 +202,29 @@
                                                 homedir_ctx->upn);
                 break;

+            case 'R':
+                if (homedir_ctx->upn == NULL) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "Cannot expand user principal name template "
+                          "string is empty.\n");
+                    goto done;
+                }
+                const char* realm=strchr(homedir_ctx->upn, '@');
+                if(realm == NULL) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "User principal name is malformed: "
+                          "no '@' char found.\n");
+                    goto done;
+                } else if(realm+1 == '\0') {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "User principal name is malformed: "
+                          "missing or empty realm.\n");
+                    goto done;
+                }
+                result = talloc_asprintf_append(result, "%s%s", p,
+                                                realm+1);
+                break;
+
             case '%':
                 result = talloc_asprintf_append(result, "%s%%", p);
                 break;