rest module to send simple API call to Infoblox for Mac Auth
Hi guys Im am trying to combine (1) Mac Auth and (2) 802.1x on FreeRADIUS 3.2. So far, with simple check on a fixed Calling-Station-Id, it works. Now I would like to implement an GET API call to our IPAM (Infoblox) in the following format: https://xyz.domain.com/wapi/v2.11.3/record:host?network=172.25.8.0/21&mac=aa... First things first, I enabled the rest module: ln -s ../mods-available/rest /etc/freeradius/mods-enabled/rest 1. With the default configuration, I get the following output: rlm_rest (rest): Opening additional connection (0), 1 of 32 pending slots used rlm_rest (rest): Connecting to http://127.0.0.1/ rlm_rest (rest): Connection failed: 7 - Couldn't connect to server rlm_rest (rest): Opening connection failed (0) rlm_rest (rest): Removing connection pool 2. When I comment the corresponding “connect_uri” like mentioned in the rest module comment, I get the next error: # rlm_rest will open a connection to the server specified in connect_uri # to populate the connection cache, ready for the first request. # The server will not start if the server specified is unreachable. # # If you wish to disable this pre-caching and reachability check, # comment out the configuration item below. # connect_uri = http://127.0.0.1/ including configuration file /etc/freeradius/sites-enabled/control-socket /etc/freeradius/mods-enabled/rest[188]: Reference "${..connect_uri}" not found Errors reading or parsing /etc/freeradius/radiusd.conf As I stated, I would like to start very simple and go step by step from there because I have absolutely no clue how to implement the requested API call so far. But if anyone has a hint to “overcome” this error and maybe has a simple example of an GET API call, I would appreciate. Thanks and best regards Dominic _________________________________ Universität Bern Abteilung Informatikdienste Dominic Stalder Network Engineer Hochschulstrasse 6 CH-3012 Bern Tel. +41 (0)31 684 38 18 dominic.stalder@unibe.ch<mailto:dominic.stalder@unibe.ch> www.id.unibe.ch _________________________________
Hi guys In the meantime I got a little clue about the rest module and got it (almost) working. One last / simple step is missing; I need to send the MAC address in the format aa:bb:cc:dd:ee:ff instead of aa-bb-cc-dd-ee-ff. We call the function rewrite_calling_station_id in /etc/freeradius/sites-available, but for the REST API call we need it with colon as delimiter? Is there an easy way to replace chars in strings in unlang / freeradius? Regards Dominic Von: "Stalder, Dominic (ID)" <dominic.stalder@unibe.ch> Datum: Montag, 23. September 2024 um 17:50 An: FreeRadius users mailing list <freeradius-users@lists.freeradius.org> Betreff: rest module to send simple API call to Infoblox for Mac Auth Hi guys Im am trying to combine (1) Mac Auth and (2) 802.1x on FreeRADIUS 3.2. So far, with simple check on a fixed Calling-Station-Id, it works. Now I would like to implement an GET API call to our IPAM (Infoblox) in the following format: https://xyz.domain.com/wapi/v2.11.3/record:host?network=172.25.8.0/21&mac=aa... First things first, I enabled the rest module: ln -s ../mods-available/rest /etc/freeradius/mods-enabled/rest 1. With the default configuration, I get the following output: rlm_rest (rest): Opening additional connection (0), 1 of 32 pending slots used rlm_rest (rest): Connecting to http://127.0.0.1/ rlm_rest (rest): Connection failed: 7 - Couldn't connect to server rlm_rest (rest): Opening connection failed (0) rlm_rest (rest): Removing connection pool 2. When I comment the corresponding “connect_uri” like mentioned in the rest module comment, I get the next error: # rlm_rest will open a connection to the server specified in connect_uri # to populate the connection cache, ready for the first request. # The server will not start if the server specified is unreachable. # # If you wish to disable this pre-caching and reachability check, # comment out the configuration item below. # connect_uri = http://127.0.0.1/ including configuration file /etc/freeradius/sites-enabled/control-socket /etc/freeradius/mods-enabled/rest[188]: Reference "${..connect_uri}" not found Errors reading or parsing /etc/freeradius/radiusd.conf As I stated, I would like to start very simple and go step by step from there because I have absolutely no clue how to implement the requested API call so far. But if anyone has a hint to “overcome” this error and maybe has a simple example of an GET API call, I would appreciate. Thanks and best regards Dominic _________________________________ Universität Bern Abteilung Informatikdienste Dominic Stalder Network Engineer Hochschulstrasse 6 CH-3012 Bern Tel. +41 (0)31 684 38 18 dominic.stalder@unibe.ch<mailto:dominic.stalder@unibe.ch> www.id.unibe.ch _________________________________
On 24/09/2024 16:22, dominic.stalder@unibe.ch wrote:
One last / simple step is missing; I need to send the MAC address in the format aa:bb:cc:dd:ee:ff instead of aa-bb-cc-dd-ee-ff. We call the function rewrite_calling_station_id in /etc/freeradius/sites-available, but for the REST API call we need it with colon as delimiter?
Is there an easy way to replace chars in strings in unlang / freeradius?
If you always want colons, edit the rewrite_calling_station_id policy to use those rather than hyphens. raddb/policy.d/canonicalization If you want both, just add another local attribute to the dictionary (raddb/dictionary) and then add that in the update section of the policy too. Then use that attribute in your rest call. -- Matthew
Thanks a lot Matthew!
If you want both, just add another local attribute to the dictionary (raddb/dictionary) and then add that in the update section of the policy too. Then use that attribute in your rest call. Exactly what I need; both variables in either way! And that's the (simple) part I was missing out: add attribute to the dictionary.
Best regards Dominic ________________________________ Von: Freeradius-Users <freeradius-users-bounces+dominic.stalder=unibe.ch@lists.freeradius.org> im Auftrag von Matthew Newton via Freeradius-Users <freeradius-users@lists.freeradius.org> Gesendet: Dienstag, September 24, 2024 5:29 PM An: freeradius-users@lists.freeradius.org <freeradius-users@lists.freeradius.org> Cc: Matthew Newton <mcn@freeradius.org> Betreff: Re: rest module to send simple API call to Infoblox for Mac Auth On 24/09/2024 16:22, dominic.stalder@unibe.ch wrote:
One last / simple step is missing; I need to send the MAC address in the format aa:bb:cc:dd:ee:ff instead of aa-bb-cc-dd-ee-ff. We call the function rewrite_calling_station_id in /etc/freeradius/sites-available, but for the REST API call we need it with colon as delimiter?
Is there an easy way to replace chars in strings in unlang / freeradius?
If you always want colons, edit the rewrite_calling_station_id policy to use those rather than hyphens. raddb/policy.d/canonicalization If you want both, just add another local attribute to the dictionary (raddb/dictionary) and then add that in the update section of the policy too. Then use that attribute in your rest call. -- Matthew - List info/subscribe/unsubscribe? See https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.freeradius.org%2Flist%2Fusers.html&data=05%7C02%7Cdominic.stalder%40unibe.ch%7Cca01f8ace7a64e80038108dcdcadb103%7Cd400387a212f43eaac7f77aa12d7977e%7C1%7C0%7C638627885786053952%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=W9dCG1hYGTlx%2Bq6qk8s021%2FpDQFzg0vS2%2FLLo8jpYEw%3D&reserved=0<http://www.freeradius.org/list/users.html>
Hi Matthew Still struggling with assigning a value to the local / custom attribute: 1. added it to /etc/freeradius/dictionary like this: --> does it need to have a naming like My-Local-xxx or are we completely free there? ATTRIBUTE My-Local-Calling-Station-Id-Colon 3000 string 2. tried to add a value to the local / custom attribute in /etc/freeradius/policy.d/canonicalization: rewrite_calling_station_id { if (&Calling-Station-Id && (&Calling-Station-Id =~ /^${policy.mac-addr-regexp}$/i)) { update request { &Calling-Station-Id := "%{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}" &My-Local-Calling-Station-Id-Colon := "Test" } updated } else { noop } } 3. Not able to get the value into /etc/freeradius/mods-available/rest --> the local / custom attribute has an empty value authorize { uri = "${..connect_uri}/wapi/v2.11.3/record:host?network=172.25.8.0/21&mac=%{request:My-Local-Calling-Station-Id-Colon}" method = 'get' auth = 'basic' require_auth = 'yes' username = "id_svcinfobloxro_test" password = "h_rB*5i.Tkc$aCb" method = 'get' tls = ${..tls} } I do not see any attribute with Name "My-Local-Calling-Station-Id-Colon" in the freeradius debug output as well. Do I miss something else? Sorry to bother you again, but still a newbie. Regards Dominic Am 24.09.24, 17:29 schrieb "Freeradius-Users im Auftrag von Matthew Newton via Freeradius-Users" <freeradius-users-bounces+dominic.stalder=unibe.ch@lists.freeradius.org <mailto:unibe.ch@lists.freeradius.org> im Auftrag von freeradius-users@lists.freeradius.org <mailto:freeradius-users@lists.freeradius.org>>: On 24/09/2024 16:22, dominic.stalder@unibe.ch <mailto:dominic.stalder@unibe.ch> wrote:
One last / simple step is missing; I need to send the MAC address in the format aa:bb:cc:dd:ee:ff instead of aa-bb-cc-dd-ee-ff. We call the function rewrite_calling_station_id in /etc/freeradius/sites-available, but for the REST API call we need it with colon as delimiter?
Is there an easy way to replace chars in strings in unlang / freeradius?
If you always want colons, edit the rewrite_calling_station_id policy to use those rather than hyphens. raddb/policy.d/canonicalization If you want both, just add another local attribute to the dictionary (raddb/dictionary) and then add that in the update section of the policy too. Then use that attribute in your rest call. -- Matthew - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html <http://www.freeradius.org/list/users.html>
On Sep 25, 2024, at 7:40 AM, <dominic.stalder@unibe.ch> <dominic.stalder@unibe.ch> wrote:
Still struggling with assigning a value to the local / custom attribute:
1. added it to /etc/freeradius/dictionary like this:
--> does it need to have a naming like My-Local-xxx or are we completely free there?
The name has to be unique.
ATTRIBUTE My-Local-Calling-Station-Id-Colon 3000 string
That's good.
2. tried to add a value to the local / custom attribute in /etc/freeradius/policy.d/canonicalization:
rewrite_calling_station_id { if (&Calling-Station-Id && (&Calling-Station-Id =~ /^${policy.mac-addr-regexp}$/i)) { update request { &Calling-Station-Id := "%{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
&My-Local-Calling-Station-Id-Colon := "Test" }
That should work.
3. Not able to get the value into /etc/freeradius/mods-available/rest --> the local / custom attribute has an empty value
No. You need to read the debug output. i.e. did it run the "rewrite_calling_station_id" policy? If so, which "if" condition did it run? Why? The point of the debug output is to read it. You can't just send the server a packet, look at the "rest" module, and then ignore the rest of it. So read it. ALL of it. Think about what it's doing.
I do not see any attribute with Name "My-Local-Calling-Station-Id-Colon" in the freeradius debug output as well.
You (a) saw it run the rewrite_calling_station_id policy, or (b) saw it NOT run the rewrite_calling_station_id policy. Which one happened? Read the debug output. Alan DeKok.
Hi Alan
The name has to be unique.
Thanks, that is good to know.
ATTRIBUTE My-Local-Calling-Station-Id-Colon 3000 string That's good. Good for the approvement.
That should work. That is what I thought too...
You need to read the debug output. i.e. did it run the "rewrite_calling_station_id" policy? If so, which "if" condition did it run? Why? Which one happened? Read the debug output. To be honest, I DID read the debug output, but maybe I am too dumb or it just does not work as I except it to work; please see below statements and debug output:
1. configuration of rewrite_calling_station_id policy: # # Add "rewrite_calling_station_id" in the "authorize" and # "preacct" sections. # # Makes Calling-Station-ID conform to what RFC3580 says should # be provided by 802.1X authenticators. # rewrite_calling_station_id { if (&Calling-Station-Id && (&Calling-Station-Id =~ /^${policy.mac-addr-regexp}$/i)) { update request { &Calling-Station-Id := "%{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}" # Format Calling-Station-Id from format xx-xx-xx-xx-xx-xx to xx:xx:xx:xx:xx:xx and assign this to local attribute locCalling-Station-Id-Colon &My-Local-Calling-Station-Id-Colon := "Test" } updated } else { noop } } 2. it does run the rewrite_calling_station_id policy: (0) # Executing section authorize from file /etc/freeradius/sites-enabled/default (0) policy rewrite_calling_station_id { 3. It does enter / hit the following if statement: (0) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) -> TRUE 4. it does update the request for variable Calling-Station-Id, BUT not for local / custom variable My-Local-Calling-Station-Id-Colon (0) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) -> TRUE (0) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (0) update request { (0) EXPAND %{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}} (0) --> AC-DF-A1-B1-F1-5A (0) &Calling-Station-Id := AC-DF-A1-B1-F1-5A (0) } # update request = noop (0) [updated] = updated *** Full debug output: (0) Received Access-Request Id 143 from 130.92.42.15:60533 to 130.92.10.33:1812 length 416 (0) User-Name = "acdfa1b1f15a" (0) User-Password = "acdfa1b1f15a" (0) Service-Type = Call-Check (0) Cisco-AVPair = "service-type=Call Check" (0) Framed-MTU = 1485 (0) Message-Authenticator = 0x7e0b273f4af8061b269ca699c0d04121 (0) Cisco-AVPair = "audit-session-id=0F2A5C820000089D2A064B45" (0) Cisco-AVPair = "method=mab" (0) Cisco-AVPair = "client-iif-id=201327528" (0) Cisco-AVPair = "vlan-id=1876" (0) NAS-IP-Address = 130.92.42.15 (0) NAS-Port-Type = Wireless-802.11 (0) NAS-Port = 4211 (0) Cisco-AVPair = "cisco-wlan-ssid=xyz-DEV" (0) Cisco-AVPair = "wlan-profile-name=xyz-DEV" (0) Called-Station-Id = "60-b9-c0-04-c4-40:xyz-DEV" (0) Calling-Station-Id = "ac-df-a1-b1-f1-5a" (0) Airespace-Wlan-Id = 97 (0) NAS-Identifier = "60-b9-c0-04-c4-40:xyz-DEV" (0) # Executing section authorize from file /etc/freeradius/sites-enabled/default (0) authorize { (0) policy rewrite_called_station_id { (0) if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) { (0) if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) -> TRUE (0) if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) { (0) update request { (0) EXPAND %{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}} (0) --> 60-B9-C0-04-C4-40 (0) &Called-Station-Id := 60-B9-C0-04-C4-40 (0) } # update request = noop (0) if ("%{8}") { (0) EXPAND %{8} (0) --> xyz-DEV (0) if ("%{8}") -> TRUE (0) if ("%{8}") { (0) update request { (0) EXPAND %{8} (0) --> xyz-DEV (0) &Called-Station-SSID := xyz-DEV (0) EXPAND %{Called-Station-Id}:%{8} (0) --> 60-B9-C0-04-C4-40:xyz-DEV (0) &Called-Station-Id := 60-B9-C0-04-C4-40:xyz-DEV (0) } # update request = noop (0) } # if ("%{8}") = noop (0) [updated] = updated (0) } # if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) = updated (0) ... skipping else: Preceding "if" was taken (0) } # policy rewrite_called_station_id = updated (0) policy rewrite_calling_station_id { (0) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (0) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) -> TRUE (0) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (0) update request { (0) EXPAND %{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}} (0) --> AC-DF-A1-B1-F1-5A (0) &Calling-Station-Id := AC-DF-A1-B1-F1-5A (0) } # update request = noop (0) [updated] = updated (0) } # if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) = updated (0) ... skipping else: Preceding "if" was taken (0) } # policy rewrite_calling_station_id = updated (0) if (NAS-Identifier == "uvisrz0215.insel.ch") { (0) if (NAS-Identifier == "uvisrz0215.insel.ch") -> FALSE (0) if (NAS-Port-Type =~ /Wireless-802\.11/i) { (0) if (NAS-Port-Type =~ /Wireless-802\.11/i) -> TRUE (0) if (NAS-Port-Type =~ /Wireless-802\.11/i) { (0) if (Service-Type == Call-Check) { (0) if (Service-Type == Call-Check) -> TRUE (0) if (Service-Type == Call-Check) { rlm_rest (rest): Reserved connection (0) (0) rest: Expanding URI components (0) rest: EXPAND https://ib-test.unibe.ch/ (0) rest: --> https://ib-test.unibe.ch/ (0) rest: EXPAND /wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=%{My-Local-Calling-Station-Id-Colon} (0) rest: --> /wapi/v2.11.3/record:host?network=0.0.0.0/0&mac= (0) rest: Sending HTTP GET to "https://ib-test.unibe.ch/wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=" (0) rest: EXPAND id_svcinfobloxro_test (0) rest: --> id_svcinfobloxro_test (0) rest: EXPAND h_rB*5i.Tkc$aCb (0) rest: --> h_rB*5i.Tkc$aCb (0) rest: Processing response header (0) rest: Status : 200 (OK) (0) rest: Type : json (application/json) (0) rest: Adding reply:REST-HTTP-Status-Code = "200" (0) rest: ERROR: Can't process VP container, expected JSON objectgot "array", skipping... (0) rest: ERROR: Server returned: (0) rest: ERROR: [] rlm_rest (rest): Released connection (0) Need more connections to reach 10 spares rlm_rest (rest): Opening additional connection (5), 1 of 27 pending slots used rlm_rest (rest): Connecting to "https://ib-test.unibe.ch/" (0) [rest] = fail (0) } # if (Service-Type == Call-Check) = fail (0) } # if (NAS-Port-Type =~ /Wireless-802\.11/i) = fail (0) } # authorize = fail (0) Invalid user (rest: Can't process VP container, expected JSON objectgot "array", skipping...): [acdfa1b1f15a] (from client cisco-wlc-9800-dev-mgmt.wifi.unibe.ch port 4211 cli AC-DF-A1-B1-F1-5A) (0) Using Post-Auth-Type Reject (0) # Executing group from file /etc/freeradius/sites-enabled/default (0) Post-Auth-Type REJECT { (0) attr_filter.access_reject: EXPAND %{User-Name} (0) attr_filter.access_reject: --> acdfa1b1f15a (0) attr_filter.access_reject: Matched entry DEFAULT at line 11 (0) [attr_filter.access_reject] = updated (0) [eap] = noop (0) policy remove_reply_message_if_eap { (0) if (&reply:EAP-Message && &reply:Reply-Message) { (0) if (&reply:EAP-Message && &reply:Reply-Message) -> FALSE (0) else { (0) [noop] = noop (0) } # else = noop (0) } # policy remove_reply_message_if_eap = noop (0) } # Post-Auth-Type REJECT = updated (0) Login incorrect (rest: Can't process VP container, expected JSON objectgot "array", skipping...): [acdfa1b1f15a] (from client cisco-wlc-9800-dev-mgmt.wifi.unibe.ch port 4211 cli AC-DF-A1-B1-F1-5A) (0) Delaying response for 1.000000 seconds Waking up in 0.9 seconds. (0) Sending delayed response (0) Sent Access-Reject Id 143 from 130.92.10.33:1812 to 130.92.42.15:60533 length 38 Waking up in 3.9 seconds. (1) Received Access-Request Id 151 from 130.92.42.15:60533 to 130.92.10.33:1812 length 417 (1) User-Name = "acdfa1b1f15a" (1) User-Password = "acdfa1b1f15a" (1) Service-Type = Call-Check (1) Cisco-AVPair = "service-type=Call Check" (1) Framed-MTU = 1485 (1) Message-Authenticator = 0x906b814968c653eba3233d254f02585a (1) Cisco-AVPair = "audit-session-id=0F2A5C820000089E2A065195" (1) Cisco-AVPair = "method=mab" (1) Cisco-AVPair = "client-iif-id=1845494859" (1) Cisco-AVPair = "vlan-id=1876" (1) NAS-IP-Address = 130.92.42.15 (1) NAS-Port-Type = Wireless-802.11 (1) NAS-Port = 4211 (1) Cisco-AVPair = "cisco-wlan-ssid=xyz-DEV" (1) Cisco-AVPair = "wlan-profile-name=xyz-DEV" (1) Called-Station-Id = "60-b9-c0-04-c4-40:xyz-DEV" (1) Calling-Station-Id = "ac-df-a1-b1-f1-5a" (1) Airespace-Wlan-Id = 97 (1) NAS-Identifier = "60-b9-c0-04-c4-40:xyz-DEV" (1) # Executing section authorize from file /etc/freeradius/sites-enabled/default (1) authorize { (1) policy rewrite_called_station_id { (1) if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) { (1) if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) -> TRUE (1) if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) { (1) update request { (1) EXPAND %{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}} (1) --> 60-B9-C0-04-C4-40 (1) &Called-Station-Id := 60-B9-C0-04-C4-40 (1) } # update request = noop (1) if ("%{8}") { (1) EXPAND %{8} (1) --> xyz-DEV (1) if ("%{8}") -> TRUE (1) if ("%{8}") { (1) update request { (1) EXPAND %{8} (1) --> xyz-DEV (1) &Called-Station-SSID := xyz-DEV (1) EXPAND %{Called-Station-Id}:%{8} (1) --> 60-B9-C0-04-C4-40:xyz-DEV (1) &Called-Station-Id := 60-B9-C0-04-C4-40:xyz-DEV (1) } # update request = noop (1) } # if ("%{8}") = noop (1) [updated] = updated (1) } # if (&Called-Station-Id && (&Called-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)) = updated (1) ... skipping else: Preceding "if" was taken (1) } # policy rewrite_called_station_id = updated (1) policy rewrite_calling_station_id { (1) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (1) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) -> TRUE (1) if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) { (1) update request { (1) EXPAND %{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}} (1) --> AC-DF-A1-B1-F1-5A (1) &Calling-Station-Id := AC-DF-A1-B1-F1-5A (1) } # update request = noop (1) [updated] = updated (1) } # if (&Calling-Station-Id && (&Calling-Station-Id =~ /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})$/i)) = updated (1) ... skipping else: Preceding "if" was taken (1) } # policy rewrite_calling_station_id = updated (1) if (NAS-Identifier == "uvisrz0215.insel.ch") { (1) if (NAS-Identifier == "uvisrz0215.insel.ch") -> FALSE (1) if (NAS-Port-Type =~ /Wireless-802\.11/i) { (1) if (NAS-Port-Type =~ /Wireless-802\.11/i) -> TRUE (1) if (NAS-Port-Type =~ /Wireless-802\.11/i) { (1) if (Service-Type == Call-Check) { (1) if (Service-Type == Call-Check) -> TRUE (1) if (Service-Type == Call-Check) { rlm_rest (rest): Reserved connection (1) (1) rest: Expanding URI components (1) rest: EXPAND https://ib-test.unibe.ch/ (1) rest: --> https://ib-test.unibe.ch/ (1) rest: EXPAND /wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=%{My-Local-Calling-Station-Id-Colon} (1) rest: --> /wapi/v2.11.3/record:host?network=0.0.0.0/0&mac= (1) rest: Sending HTTP GET to "https://ib-test.unibe.ch/wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=" (1) rest: EXPAND id_svcinfobloxro_test (1) rest: --> id_svcinfobloxro_test (1) rest: EXPAND h_rB*5i.Tkc$aCb (1) rest: --> h_rB*5i.Tkc$aCb (1) rest: Processing response header (1) rest: Status : 200 (OK) (1) rest: Type : json (application/json) (1) rest: Adding reply:REST-HTTP-Status-Code = "200" (1) rest: ERROR: Can't process VP container, expected JSON objectgot "array", skipping... (1) rest: ERROR: Server returned: (1) rest: ERROR: [] rlm_rest (rest): Released connection (1) Need more connections to reach 10 spares rlm_rest (rest): Opening additional connection (6), 1 of 26 pending slots used rlm_rest (rest): Connecting to "https://ib-test.unibe.ch/" (1) [rest] = fail (1) } # if (Service-Type == Call-Check) = fail (1) } # if (NAS-Port-Type =~ /Wireless-802\.11/i) = fail (1) } # authorize = fail (1) Invalid user (rest: Can't process VP container, expected JSON objectgot "array", skipping...): [acdfa1b1f15a] (from client cisco-wlc-9800-dev-mgmt.wifi.unibe.ch port 4211 cli AC-DF-A1-B1-F1-5A) (1) Using Post-Auth-Type Reject (1) # Executing group from file /etc/freeradius/sites-enabled/default (1) Post-Auth-Type REJECT { (1) attr_filter.access_reject: EXPAND %{User-Name} (1) attr_filter.access_reject: --> acdfa1b1f15a (1) attr_filter.access_reject: Matched entry DEFAULT at line 11 (1) [attr_filter.access_reject] = updated (1) [eap] = noop (1) policy remove_reply_message_if_eap { (1) if (&reply:EAP-Message && &reply:Reply-Message) { (1) if (&reply:EAP-Message && &reply:Reply-Message) -> FALSE (1) else { (1) [noop] = noop (1) } # else = noop (1) } # policy remove_reply_message_if_eap = noop (1) } # Post-Auth-Type REJECT = updated (1) Login incorrect (rest: Can't process VP container, expected JSON objectgot "array", skipping...): [acdfa1b1f15a] (from client cisco-wlc-9800-dev-mgmt.wifi.unibe.ch port 4211 cli AC-DF-A1-B1-F1-5A) (1) Delaying response for 1.000000 seconds Waking up in 0.9 seconds. (1) Sending delayed response (1) Sent Access-Reject Id 151 from 130.92.10.33:1812 to 130.92.42.15:60533 length 38 Waking up in 2.3 seconds. (0) Cleaning up request packet ID 143 with timestamp +8 due to cleanup_delay was reached Waking up in 1.6 seconds. (1) Cleaning up request packet ID 151 with timestamp +10 due to cleanup_delay was reached Ready to process requests I hope, you now can understand, why I am a little perplexed by the debug output; I just can't read something that is not present in the output and I don't know why, this part is not "hit"? Regards Dominic Am 25.09.24, 17:15 schrieb "Freeradius-Users im Auftrag von Alan DeKok" <freeradius-users-bounces+dominic.stalder=unibe.ch@lists.freeradius.org <mailto:unibe.ch@lists.freeradius.org> im Auftrag von aland@deployingradius.com <mailto:aland@deployingradius.com>>: On Sep 25, 2024, at 7:40 AM, <dominic.stalder@unibe.ch <mailto:dominic.stalder@unibe.ch>> <dominic.stalder@unibe.ch <mailto:dominic.stalder@unibe.ch>> wrote:
Still struggling with assigning a value to the local / custom attribute:
1. added it to /etc/freeradius/dictionary like this:
--> does it need to have a naming like My-Local-xxx or are we completely free there?
The name has to be unique.
ATTRIBUTE My-Local-Calling-Station-Id-Colon 3000 string
That's good.
2. tried to add a value to the local / custom attribute in /etc/freeradius/policy.d/canonicalization:
rewrite_calling_station_id { if (&Calling-Station-Id && (&Calling-Station-Id =~ /^${policy.mac-addr-regexp}$/i)) { update request { &Calling-Station-Id := "%{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
&My-Local-Calling-Station-Id-Colon := "Test" }
That should work.
3. Not able to get the value into /etc/freeradius/mods-available/rest --> the local / custom attribute has an empty value
No. You need to read the debug output. i.e. did it run the "rewrite_calling_station_id" policy? If so, which "if" condition did it run? Why? The point of the debug output is to read it. You can't just send the server a packet, look at the "rest" module, and then ignore the rest of it. So read it. ALL of it. Think about what it's doing.
I do not see any attribute with Name "My-Local-Calling-Station-Id-Colon" in the freeradius debug output as well.
You (a) saw it run the rewrite_calling_station_id policy, or (b) saw it NOT run the rewrite_calling_station_id policy. Which one happened? Read the debug output. Alan DeKok. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html <http://www.freeradius.org/list/users.html>
On 25/09/2024 17:47, dominic.stalder@unibe.ch wrote:
You need to read the debug output. i.e. did it run the "rewrite_calling_station_id" policy? If so, which "if" condition did it run? Why? Which one happened? Read the debug output. To be honest, I DID read the debug output, but maybe I am too dumb or it just does not work as I except it to work; please see below statements and debug output:
That debug output doesn't correspond with the updated config you pasted. I suspect FreeRADIUS isn't reading the file you edited, maybe because it's using a different config location. Look at the top of the debug output and check that the file you are editing is actually being included. If in doubt, just to prove it's reading the correct file you could e.g. add some junk to the top of the file and FreeRADIUS should fail to start. -- Matthew
Hi Matthew
I suspect FreeRADIUS isn't reading the file you edited, maybe because it's using a different config location. Look at the top of the debug output and check that the file you are editing is actually being included.
Thanks a lot, that was the hint I needed! I went to the office last night and took the debug output I sent in my last response to Alan's previous email. After your response, I restarted today and already wrote quite a long email with all the information included. And while doing that, I found the following two ADDITIONAL lines in the debug output: including configuration file /etc/freeradius/policy.d/canonicalization.20240626 including configuration file /etc/freeradius/policy.d/canonicalization.20240626 This broke my configuration: I had two copies of the file /etc/freeradius/policy.d/canonicalization as backup archives in the exact same directory (w/o the new custom attribute in there). I moved them away and now the custom attribute is loaded correctly with the dummy value in the /etc/freeradius/mods-enabled/rest: (0) rest: EXPAND /wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=%{My-Local-Calling-Station-Id-Colon} (0) rest: --> /wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=Test (0) rest: Sending HTTP GET to "https://ib-test.unibe.ch/wapi/v2.11.3/record:host?network=0.0.0.0/0&mac=Test" Thanks again a lot, I would not have found these two (additional) lines without the hint to have a look a the configurations / files loaded! I have two FOLLOW UP questions on this topic, am I allowed to post them in this thread? 1. I always did / do copies of old freeradius configuration files like this in the original directory: cp xyz xyz.{yyyymmdd}. This was never a problem, but I think it is different for special directories like /etc/freeradius/policy.d/ and others, is that correct? 2.a) I would like to add an if statement to /etc/freeradius/mods-available/rest. My goal is to change the local varialbe "network" based on the attribute Called-Station-SSID, but it seams, that the modules do not allow any if / else conditions, is that correct? 2.b) What would be an alternative to have a switch statement in the rest module? Do I have to realize this via another local / custom variable from /sites-enabled/default to /mods-enabled/rest. Something like that. --> I want to get sure, there is no "parallel" chaos, if multiple RADIUS requests arrive on the FreeRADIUS server and I set the custom variable early and it gets overwritten; hope you get my consider? # Default network network = "0.0.0.0/0" if ("%{Called-Station-SSID}" == "xyz-DEV") { network = "172.25.8.0/21" } # Create the REST API call URI: uri = "${..connect_uri}/wapi/v2.11.3/record:host?network=${network}&mac=%{My-Local-Calling-Station-Id-Colon}" Regards Dominic
On Sep 26, 2024, at 8:53 AM, <dominic.stalder@unibe.ch> <dominic.stalder@unibe.ch> wrote:
This broke my configuration: I had two copies of the file /etc/freeradius/policy.d/canonicalization as backup archives in the exact same directory (w/o the new custom attribute in there).
Use "git" for revision control.. Copying text files into multiple locations is a bad idea. You lose track of what's going on, and the server will usually load ALL files in a directory.
1. I always did / do copies of old freeradius configuration files like this in the original directory: cp xyz xyz.{yyyymmdd}. This was never a problem, but I think it is different for special directories like /etc/freeradius/policy.d/ and others, is that correct?
Use "git". Manually copying files is very much not recommended.
2.a) I would like to add an if statement to /etc/freeradius/mods-available/rest.
No. You cannot put policies into the module configurations.
My goal is to change the local varialbe "network" based on the attribute Called-Station-SSID, but it seams, that the modules do not allow any if / else conditions, is that correct?
Try it and see. You will get a message in the debug output.
2.b) What would be an alternative to have a switch statement in the rest module? Do I have to realize this via another local / custom variable from /sites-enabled/default to /mods-enabled/rest. Something like that.
You're asking if a particular solution will work. This is the wrong way to solve problems. Instead, describe what you want to do, and then ask what solution is best.
--> I want to get sure, there is no "parallel" chaos, if multiple RADIUS requests arrive on the FreeRADIUS server and I set the custom variable early and it gets overwritten; hope you get my consider?
The server tracks each request separately. If you want custom variables for a request, then you put the custom variable into the request. Not into the module configuration.
if ("%{Called-Station-SSID}" == "xyz-DEV") { network = "172.25.8.0/21" }
# Create the REST API call URI: uri = "${..connect_uri}/wapi/v2.11.3/record:host?network=${network}&mac=%{My-Local-Calling-Station-Id-Colon}"
You already know how to create custom attributes in the local dictionary, and then set them in a policy. Why not do the same thing here for "network"? Why invent another approach? Alan DeKok.
Use "git" for revision control.. Copying text files into multiple locations is a bad idea. You lose track of what's going on, and the server will usually load ALL files in a directory. Use "git". Manually copying files is very much not recommended.
I agree; git for backup and revision control is on my to do list for our quite new freeradius installation. Still takes some time to setup things up correctly.
The server tracks each request separately. If you want custom variables for a request, then you put the custom variable into the request. Not into the module configuration. You already know how to create custom attributes in the local dictionary, and then set them in a policy. Why not do the same thing here for "network"? Why invent another approach?
Good hint, did not think of this approach.
Hi guys I got my rest module finally working and in case the HTTP status code is '200 (OK)', everything is fine. Now I would like to implement a failsafe / fall back, in case the provided API / rest credentials are wrong (HTTP status code = 401 / unauthorized), something else is wrong with the API / rest call, eg. example below, or for example in case of a timeout of the HTTP service: (0) rest: Processing response header (0) rest: Status : 400 (Bad Request) (0) rest: Type : json (application/json) (0) rest: Adding reply:REST-HTTP-Status-Code = "400" (0) rest: ERROR: Server returned: (0) rest: ERROR: { "Error": "AdmConProtoError: Unknown argument/field: 'amac'", (0) rest: ERROR: "code": "Client.Ibap.Proto", (0) rest: ERROR: "text": "Unknown argument/field: 'amac'" (0) rest: ERROR: } rlm_rest (rest): Released connection (0) Need more connections to reach 10 spares rlm_rest (rest): Opening additional connection (5), 1 of 27 pending slots used rlm_rest (rest): Connecting to "https://ib-test.unibe.ch" (0) [rest] = invalid (0) } # case zmkbern-DEV = invalid (0) } # switch %{Called-Station-SSID} = invalid (0) } # if (Service-Type == Call-Check) = invalid (0) } # if (NAS-Port-Type =~ /Wireless-802\.11/i) = invalid (0) } # authorize = invalid Is there a way to still return an Access-Accept if one of the following codes is returned by the rest module? # Code Meaning Process body Module code # 404 not found no notfound # 410 gone no notfound # 403 forbidden no userlock # 401 unauthorized yes reject # 204 no content no ok # 5xx server error no fail # xxx - no invalid Thanks for a hint. Regards Dominic Am 26.09.24, 09:54 schrieb "Stalder, Dominic (ID)" <dominic.stalder@unibe.ch <mailto:dominic.stalder@unibe.ch>>:
Use "git" for revision control.. Copying text files into multiple locations is a bad idea. You lose track of what's going on, and the server will usually load ALL files in a directory. Use "git". Manually copying files is very much not recommended.
I agree; git for backup and revision control is on my to do list for our quite new freeradius installation. Still takes some time to setup things up correctly.
The server tracks each request separately. If you want custom variables for a request, then you put the custom variable into the request. Not into the module configuration. You already know how to create custom attributes in the local dictionary, and then set them in a policy. Why not do the same thing here for "network"? Why invent another approach?
Good hint, did not think of this approach.
On Sep 25, 2024, at 6:47 PM, <dominic.stalder@unibe.ch> <dominic.stalder@unibe.ch> wrote:
4. it does update the request for variable Calling-Station-Id, BUT not for local / custom variable My-Local-Calling-Station-Id-Colon
As Matthew said, you're editing the wrong file. Computers aren't magic. If you edit a file, the edits show up in the changed server output. What's likely happening is that you've installed multiple versions of FreeRADIUS. You're editing files for installed version X, and then running the binary from installed version Y. Don't install multiple versions of the server on the same system. If you do, then be aware that you have installed multiple versions, and pay attention to which files you're editing. Alan DeKok.
participants (3)
-
Alan DeKok -
dominic.stalder@unibe.ch -
Matthew Newton