LDAP group authorization with MSAD

Nick Schmalenberger nick at schmalenberger.us
Tue Jan 23 05:10:46 UTC 2024


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/modules/ldap/authentication.html
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 at 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 at example.com
Jan 23 04:49:52 ldaps3 freeradius[2798965]: (0)       LDAP-UserDN := testobs at 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 at 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 at 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 at 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/ldap/authorization/groups.html 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 at 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 at 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


More information about the Freeradius-Users mailing list