I have Freeradius 3.0.20 from Ubuntu 20.04 working with bind as user to my Active Directory servers. https://freeradius.org/documentation/freeradius-server/3.2.4/concepts/module... I’m hoping to use this for network equipment to have a centralized login system. I’m having trouble figuring out how, with only the username like user@example.com used for the authentication, how do I look up their group membership for authorization. In the below configuration files I have sanitized my company name. Here is my file /etc/freeradius/3.0/sites-enabled/netauth: # THIS FILE IS MANAGED BY ANSIBLE server netauth { listen { ipaddr = * port = 1814 type = auth } authorize { auth_log update control { LDAP-UserDN := "%{User-Name}@example.com" Auth-Type := LDAP } if (LDAP-Group == "techops") { update reply { Juniper-Local-User-Name := "techops" } } elsif (LDAP-Group == "obsmonitor") { update reply { Juniper-Local-User-Name := "monitor" } } else { reject } } authenticate { Auth-Type LDAP { ldap } } client 10-0-0-0-8 { ipaddr = 10.0.0.0/8 secret = xxxxxx } client 172-16-0-0-12 { ipaddr = 172.16.0.0/12 secret = xxxxxx } } Here is my file /etc/freeradius/3.0/mods-enabled/ldap # THIS FILE IS MANAGED BY ANSIBLE ldap { # use the HAProxy on this same host server = 'ldap://localhost' identity = 'CN=Ldap Readonly,OU=svc_accounts,OU=Service,OU=Example Users,DC=ad,DC=example,DC=com' password = 'yyyyyyyy' group { base_dn = 'OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC=ad,DC=example,DC=com' filter = '(objectClass=group)' membership_filter = '' } } Here is the debug output during a successful login. The testobs user is in the "obsmonitor" group and NOT the "techops" group, but they are matching "techops" anyway I think because of membership_filter = "" ? I think membership_filter = "" allows any user to match the group, is that right? Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Received Access-Request Id 248 from 172.30.255.19:57489 to 10.30.0.229:1814 length 86 Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) User-Name = "testobs" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) User-Password = "Example123!" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) NAS-Identifier = "sw102-2.sql1.corp" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Calling-Station-Id = "172.16.240.5" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) NAS-IP-Address = 172.30.255.19 Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/netauth Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) authorize { Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) auth_log: EXPAND /var/log/freeradius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/auth-detail-%Y%m%d Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) auth_log: --> /var/log/freeradius/radacct/172.30.255.19/auth-detail-20240123 Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) auth_log: /var/log/freeradius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/auth-detail-%Y%m%d expands to /var/log/freeradius/radacct/172.30.255.19/auth-detail-20240123 Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) auth_log: EXPAND %t Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) auth_log: --> Tue Jan 23 04:49:52 2024 Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) [auth_log] = ok Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) update control { Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) EXPAND %{User-Name}@example.com Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) --> testobs@example.com Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) LDAP-UserDN := testobs@example.com Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Auth-Type := LDAP Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) } # update control = noop Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) if (LDAP-Group == "techops") { Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Searching for user in group "techops" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Closing connection (0): Hit idle_timeout, was idle for 154 seconds Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): You probably need to lower "min" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Closing connection (1): Hit idle_timeout, was idle for 154 seconds Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): You probably need to lower "min" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Closing connection (2): Hit idle_timeout, was idle for 154 seconds Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): You probably need to lower "min" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Closing connection (3): Hit idle_timeout, was idle for 154 seconds Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): You probably need to lower "min" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Closing connection (4): Hit idle_timeout, was idle for 154 seconds Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): You probably need to lower "min" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): 0 of 0 connections in use. You may need to increase "spare" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Opening additional connection (5), 1 of 10 pending slots used Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Connecting to ldap://localhost:389 Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Waiting for bind result... Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Bind successful Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Reserved connection (5) Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Using user DN from request "testobs@example.com" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Checking for user in group objects Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) EXPAND (&(cn=techops)(objectClass=group)) Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) --> (&(cn=techops)(objectClass=group)) Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Performing search in "OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC=ad,DC=example,DC=com" with filter "(&(cn=techops)(objectClass=group))", scope "sub" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Waiting for search result... Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) User found in group object "OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC=ad,DC=example,DC=com" Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Released connection (5) Jan 23 04:49:52 ldaps3 freeradius[2798965]: Need 4 more connections to reach min connections (5) Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Opening additional connection (6), 1 of 9 pending slots used Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Connecting to ldap://localhost:389 Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Waiting for bind result... Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Bind successful Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) if (LDAP-Group == "techops") -> TRUE Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) if (LDAP-Group == "techops") { Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) update reply { Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Juniper-Local-User-Name := "techops" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) } # update reply = noop Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) } # if (LDAP-Group == "techops") = noop Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ... skipping elsif: Preceding "if" was taken Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ... skipping else: Preceding "if" was taken Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) } # authorize = ok Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Found Auth-Type = LDAP Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/netauth Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Auth-Type LDAP { Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Reserved connection (5) Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ldap: Login attempt by "testobs" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ldap: Using user DN from request "testobs@example.com" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ldap: Waiting for bind result... Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ldap: Bind successful Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) ldap: Bind as user "testobs@example.com" was successful Jan 23 04:49:52 ldaps3 freeradius[2798965]: rlm_ldap (ldap): Released connection (5) Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) [ldap] = ok Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) } # Auth-Type LDAP = ok Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Sent Access-Accept Id 248 from 10.30.0.229:1814 to 172.30.255.19:57489 length 0 Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Juniper-Local-User-Name := "techops" Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0) Finished request Jan 23 04:49:52 ldaps3 freeradius[2798965]: Waking up in 4.9 seconds. Jan 23 04:49:57 ldaps3 freeradius[2798965]: (0) Cleaning up request packet ID 248 with timestamp +154 Jan 23 04:49:57 ldaps3 freeradius[2798965]: Ready to process requests I read https://freeradius.org/documentation/freeradius-server/4.0.0/howto/modules/l... explaining the different ways looking up groups with some different LDAP schemas. In my user definitions I have memberOf attributes like with the testobs user: memberOf: CN=obsmonitor,OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC=ad,DC=example,DC=com I have member attributes in n the group definitions like with the obsmonitor group for the testobs user: member: CN=Observium Test,OU=OKTA Test Accounts,OU=Service,OU=Example Users,DC=ad,DC=example,DC=com I can use ldapsearch and binding as our read only LDAP user to query the group with a membership filter: nicks@eel:~$ ldapsearch -x -H ldaps://sjc-1.ldap.example.com -D "CN=Ldap Readonly,OU=svc_accounts,OU=Service,OU=Example Users,DC=ad,DC=example,DC=com" -W -b 'OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC=ad,DC=example,DC=com' '(&(cn=obsmonitor)(objectClass=group)(member=CN=Observium Test,OU=OKTA Test Accounts,OU=Service,OU=Example Users,DC=ad,DC=example,DC=com))' Enter LDAP Password: # extended LDIF # # LDAPv3 # base <OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC=ad,DC=example,DC=com> with scope subtree # filter: (&(cn=obsmonitor)(objectClass=group)(member=CN=Observium Test,OU=OKTA Test Accounts,OU=Service,OU=Example Users,DC=ad,DC=example,DC=com)) # requesting: ALL # # obsmonitor, LDAP PROXY, Global Groups, Users, Example Users, ad.example.com dn: CN=obsmonitor,OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Example Users,DC= ad,DC=example,DC=com objectClass: top objectClass: group cn: obsmonitor member: CN=Observium Test,OU=OKTA Test Accounts,OU=Service,OU=Example Users,DC =ad,DC=example,DC=com distinguishedName: CN=obsmonitor,OU=LDAP PROXY,OU=Global Groups,OU=Users,OU=Co nviva Users,DC=ad,DC=example,DC=com instanceType: 4 whenCreated: 20231125033343.0Z whenChanged: 20231125041833.0Z uSNCreated: 14442815 uSNChanged: 14442906 name: obsmonitor objectGUID:: /joNsBrPiUqDzN52+a7D0Q== objectSid:: AQUAAAAAAAUVAAAAaaNyTpKL8mVbop3/gVgAAA== sAMAccountName: obsmonitor sAMAccountType: 268435456 groupType: -2147483646 objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=ad,DC=example,DC=com dSCorePropagationData: 16010101000000.0Z # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 nicks@eel:~$ With binding as the original user though, it only seems to bind and doesn't seem to query the user object, so how can I get the user's DN to check group membership in this way and with my MSAD LDAP schema? Thank you! -Nick Schmalenberger