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