Conditional shell:priv-lvl as login reply on CISCO using client's source net and user's ldap attribute.
Hi all, I need to enable some users to login on different groups of CISCO devices getting different shell:priv-lvl. I'm trying to group the devices by their ip using a dynamic-clients template. I'd like to send them to a different virtual server based on source network of the auth request. Then I'd like to be able to choose which shell:priv-lvl give them using LDAP attributes like "o=groupA-shellPriv15" or "o=groupA-shellPriv7". I'm trying to achieve the first result using a configuration like this one: client my-dynclient { ipaddr = 10.200.20.0/24 dynamic_clients = my-dynclients lifetime = 3600 } server my-dynclients { authorize { if ("%{ldap:ldap:///BASEDN?objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}") { update control { &FreeRADIUS-Client-IP-Address = "%{Packet-Src-IP-Address}" &FreeRADIUS-Client-Shortname = "%{ldap:ldap:///BASEDN?radiusClientShortname,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" &FreeRADIUS-Client-Secret = "%{ldap:ldap:///BASEDN?radiusClientSecret,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" &FreeRADIUS-Client-Virtual-Server = "%{ldap:ldap:///BASEDN?radiusClientVirtualServer,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" } } ok } } when trying the login, the if condition succeeds: Fri Jan 12 16:12:57 2018 : Debug: rlm_ldap (ldap): Bind successful Fri Jan 12 16:12:57 2018 : Debug: (0) EXPAND %{ldap:ldap:///BASEDN?objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})} Fri Jan 12 16:12:57 2018 : Debug: (0) --> radiusClient Fri Jan 12 16:12:57 2018 : Debug: (0) if ("%{ldap:ldap:///BASEDN?objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}") -> TRUE Fri Jan 12 16:12:57 2018 : Debug: (0) if ("%{ldap:ldap:///BASEDN?objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}") { Fri Jan 12 16:12:57 2018 : Debug: (0) update control { Fri Jan 12 16:12:57 2018 : Debug: (0) EXPAND %{Packet-Src-IP-Address} Fri Jan 12 16:12:57 2018 : Debug: (0) --> 10.200.20.79 Fri Jan 12 16:12:57 2018 : Debug: (0) &FreeRADIUS-Client-IP-Address = 10.200.20.79 Fri Jan 12 16:12:57 2018 : ERROR: (0) Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve even if I get for the first time: "Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve". While retrieving FreeRADIUS-Client-Shortname, FreeRADIUS-Client-Secret and FreeRADIUS-Client-Virtual-Server I got empty values and the same error about LDAP URL. I'm not sure about the debug message, I read that it is not possible to get just the value you need using an LDAP uri and no further filtering: am I wrong? Previously I did try to decide which privilege level send as a radiusReply by scanning the LDAP in a similar way: post-auth { ... if ("%{ldap:ldap://BASEDN?objectClass?one?(&(o=groupA-shellPriv15)(cn=%{User-Name})}") { update reply { #reply:ReplyAttribute += 'cisco-avpair = "shell:priv-lvl=15"' Reply-Message += "Bingo!!!" } } This worked in a setup without dynclients using the Reply-Message and raised an error while experimenting with the ReplyAttribute. Do someone have suggestions to realize such a setup? How much of this is possible to move to LDAP (and then eventually delegate to a web GUI)? Best regards, Giuseppe
On Jan 12, 2018, at 10:33 AM, Giuseppe Civitella <gcivitella@enter.eu> wrote:
I need to enable some users to login on different groups of CISCO devices getting different shell:priv-lvl.
I'm trying to group the devices by their ip using a dynamic-clients template. I'd like to send them to a different virtual server based on source network of the auth request.
That should be possible. But why use dynamic clients? Why not just use networks for a static client definition?
Then I'd like to be able to choose which shell:priv-lvl give them using LDAP attributes like "o=groupA-shellPriv15" or "o=groupA-shellPriv7".
That's a separate step. I'd test that first, and then the dynamic clients later.
I'm trying to achieve the first result using a configuration like this one:
client my-dynclient { ipaddr = 10.200.20.0/24 dynamic_clients = my-dynclients lifetime = 3600 }
Sure... but you should really have that defined to be the entire range of networks needed for dynamic clients. Not just that one network. i.e. if you're manually defining one client for each network, you might as well just use static clients.
server my-dynclients {
authorize {
if ("%{ldap:ldap:///BASEDN?objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}") { update control { &FreeRADIUS-Client-IP-Address = "%{Packet-Src-IP-Address}" &FreeRADIUS-Client-Shortname = "%{ldap:ldap:///BASEDN?radiusClientShortname,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" &FreeRADIUS-Client-Secret = "%{ldap:ldap:///BASEDN?radiusClientSecret,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" &FreeRADIUS-Client-Virtual-Server = "%{ldap:ldap:///BASEDN?radiusClientVirtualServer,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}"
What do those LDAP queries return when you run them manually? One object, or multiple objects?
... Fri Jan 12 16:12:57 2018 : ERROR: (0) Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve
even if I get for the first time: "Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve".
While retrieving FreeRADIUS-Client-Shortname, FreeRADIUS-Client-Secret and FreeRADIUS-Client-Virtual-Server I got empty values and the same error about LDAP URL.
Then your LDAP queries are wrong. Fix them so that they return the correct data.
I'm not sure about the debug message, I read that it is not possible to get just the value you need using an LDAP uri and no further filtering: am I wrong?
You can do it. But you need to have the query return one object... as the error message tells you.
Previously I did try to decide which privilege level send as a radiusReply by scanning the LDAP in a similar way:
post-auth {
...
if ("%{ldap:ldap://BASEDN?objectClass?one?(&(o=groupA-shellPriv15)(cn=%{User-Name})}") { update reply { #reply:ReplyAttribute += 'cisco-avpair = "shell:priv-lvl=15"' Reply-Message += "Bingo!!!" } }
This worked in a setup without dynclients using the Reply-Message and raised an error while experimenting with the ReplyAttribute.
Again, this is an LDAP query issue. Use the correct queries, and it will work. Alan DeKok.
Il 12/01/2018 17:12, Alan DeKok ha scritto:
You can do it. But you need to have the query return one object... as the error message tells you.
so I fixed my queries. I used something like &FreeRADIUS-Client-Secret = "%{ldap:ldap:///BASEDN?radiusClientSecret?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" instead of &FreeRADIUS-Client-Secret = "%{ldap:ldap:///BASEDN?radiusClientSecret,objectClass?one?(radiusClientIdentifier=%{Packet-Src-IP-Address})}" And I've been able to send the auth request to a virtual server where I reply a CISCO auth level looking for user's LDAP attributes. Something like: if ("%{ldap:ldap://127.0.0.1/BASEDN?objectClass?one?(&(o=ciscoAdminGroup1)(cn=%{User-Name}))}") { update reply { Reply-Message += "Hello ciscoAdminGroup1 member!" Cisco-AVPair += "shell:priv-lvl=15" } I'm not done yet. But wanted to share the result. Regards, Giuseppe
participants (2)
-
Alan DeKok -
Giuseppe Civitella