freeradius 3.0.17 rlm_rest parsing json response - json

I'm trying to authenticate RADIUS Requests against a RESTful API (provided by Customer) using rlm_rest.
The problem I am facing is that
response JSON format (of REST API provided by Customer), is different from rlm_rest default format (indicated in etc/raddb/mods-enabled/rest).
My Virtual Server configuration as below:
Default
authorize {
...
...
rest
if (ok) {
update control {
Auth-Type := rest
}
}
}
mods-enabled/rest
authorize {
uri = "https://3rd-party-API/auth"
method = 'post'
body = 'json'
chunk = 0
tls = ${..tls}
data = '{
"code": 1,
"identifier": %I,
"avps": {
"User-Name": ["%{User-Name}"],
"NAS-IP-Address": ["%{NAS-IP-Address}"],
"Called-Station-Id": ["%{Called-Station-Id}"],
"Calling-Station-Id": ["%{Calling-Station-Id}"],
"NAS-Identifier": ["%{NAS-Identifier}"]
}
}'
}
Result
/sbin/radiusd -Xxx
HTTP response code
200
JSON Body
{
"code": "2",
"identifier": "91",
"avps": {
"Customer-Attributes": "Hello"
...
...
"Acct-Interim-Interval": "300"
}
}
The JSON structure is different from the example, and xlat parse
"code"
"identifier"
"avps"
And, of course, xlat finds no attributes match with the dictionary, while it cannot find "avps" and won't dig deeper.
So I was wondering is there anyway to either
Define the response JSON structure for xlat to parsing
Insert a "is_json" or "do_xlat" flag into the JSON ("avps"), and hope xlat will then dig deeper
Save the JSON and parse with exec/rlm_exec (using JQ or any other bash/JSON tools)
Please advise if there is any workaround. Thanks!

In FreeRADIUS version 4, there's a rlm_json module, which implements a custom node query language based on xpath (jpath), it is extremely limited and only supports some very basic queries (feel free to enhance it via PR :) ).
Below is an example I pulled out of my library of customer configurations. You can see here it's pulling out two keys (externalID and macAddress) from the root level of the JSON doc and assigning them to a couple of custom attributes (Subscriber-ID and Provisioned-MAC).
map json "%{rest_api:https://${modules.rest[rest_api].server}/admin/api/${modules.rest[rest_api].api_key}/external/getDeviceBySerialNumber?certificateSerialNumber=%{lpad:&TLS-Client-Cert-Serial 40 0}}" {
&Subscriber-ID := '$.externalId'
&Provisioned-MAC := '$.macAddress'
}
The xlat expansion can also be modified to send HTTP body data. Just put a space after the URL and pass your custom JSON blob.

Related

Convert the response to Flux ignoring certain fields of the response Json

Using the Spring WebClient I am calling a Rest API that gives me a response as a JSON, following is a structure of the response -
{
"vehicles":[
{ "name":"veh1", "type":"car", "age": 5 },
{ "name":"veh2", "type":"speedboat", "age":12},
.....
]
"metadata": {
"token":"abcd",
"days":120
}
}
I am a newbie to reactive programming, I have written the following code, which works fine ..
Mono<VehicleResponse> = webclient.get()
.uri("/legacy/vehicles")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse -> Mono.empty())
.onStatus(HttpStatus::is5xxServerError, clientResponse -> Mono.empty())
.bodyToMono(VehicleResponse.class);
But, actually what I am interested in is, only the vehicles array (don't want the metadata information.) Is it possible to obtain / read only the vehicles (array) as a Flux of Vehicle ?

How to load a json file with unit ML test examples into jmeter http request payload

I have an endpoint that serves a ML model and I want to perform load testing on it. I'm using Jmeter 4.0 and its UI to construct a simple plan test. With 1 thread group that loops for a given duration and continuosly performs https requests.
How do I parse multiple test examples into the payload of a http request, one by one and in json format. These examples are contained in a json file called samples.json. The nested structure is the following:
{ "dataset": [
{"id": 1,
"in":[
{
"Feature1": 8.9
"Feature2":7.1
}],
"out": "Class1",
},
{"id": 2,
"in":[
{
"Feature1": 3.2
"Feature2":5.1
}],
"out": "Class1",
}]
}
IMPORTANT: I do not know the number of attributes a priori, so I need to retrieve them from the in key as that may change for other types of models, therefore I can't make use of harcoded jmeter variables, similar to what it's used in the CSV Config Set add-on, where they need to specify the variables names for each column of the csv file
I have no idea how you're gonna use the values from JSON in the HTTP Request sampler, however this is how you can parse your samples.json file and get in values from it in the JSR223 Sampler
new groovy.json.JsonSlurper().parse(new File('samples.json')).dataset.each { entry ->
entry.get('in').each { feature ->
feature.each { value ->
log.info(value.key + '=' + value.value)
}
}
}
The above code basically prints the keys and respective values into jmeter.log file
But you can easily amend it to store the values into JMeter Variables, write them into a CSV file, set HTTP Request sampler to use them on the fly, etc.
More information:
Groovy: Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
Apache JMeter API

How to escape \r\n in the body of a POST in JMeter

I have a JSON response as follows,
{
"name":"John Smith",
"address": "#123\r\nRenault Road\r\n123456\r\n"
}
and I need to extract the address and put it into my next POST request. I use the JSON Extractor as a post processing element and with $..address I set the extracted address to the variable address.
In my next request, I use the following as the POST data,
{
"id": "123456",
"address": "${address}"
}
So when I make the request I see the POST data as,
{
"id": "123456",
"address": "#123
Renault Road
123456
"
}
This breaks at my backend and nevertheless this payload is not identified as a valid JSON as well.
I want to make the request so that the POST data is as follow,
{
"id": "123456",
"address": "#123\r\nRenault Road\r\n123456\r\n"
}
Any help to get this done is highly appreciated.
If you really need to send these line breaks as \r\n you can use some scripting to convert them back.
Add Beanshell PreProcessor as a child of the "next request" HTTP Request Sampler
Put the following code into the PreProcessor's "Script" area:
address = vars.get("address");
address = address.replaceAll("\\r\\n","\\\\r\\\\n");
vars.put("address", address);
The above script will convert line breaks to the textual representation.
References:
vars is a shorthand for JMeterVariables class instance, it provides read/write access to all JMeter Variables
String.replaceAll() - is the method of String class which comes out of box with Java SDK
How to Use BeanShell: JMeter's Favorite Built-in Component - guide demonstrating how to use Java and JMeter APIs using Beanshell test elements to enhance your JMeter tests with scripting if required

Should I put JWT on JSON as base64 string?

I design REST API for my site. I read some info about proper JSON-API. And now draft version is look like:
{
"data":
{
//data that I will send
},
"errors":"",
"meta":
{
"token": // auth info for ever request
{
// JWT token here
}
}
}
But I can't understand should I put JWT token as base64 string like:
"token" : "base64encodedstring"
or should I put JWT as nested object in "token"?
Also I have got question. Am I right understand that it's good practice to use once designed JSON-API everywhere? I mean that same JSON (with different data section will be used for auth, for data exchange and so on)
If the JWT is in compact serialization format (3 or 5 parts separated by dots), then it is not necessary to encoded it.
Otherwise, if it is in flattened or general serialization format (a JSON object), then you will have to encode it.

How to parse a JSON response to build additional Paw request?

https://paw.cloud/
I have the following JSON coming back from a different API end point:
[
{
"id": 1,
"name": "BigCartel",
"slug": "bigcartel",
"logo_cdn_url": "http://placehold.it/200x200",
"active": true,
"authentication_type": {
"description": "Oauth Authentication Token",
"slug": "oauthauthenticationtoken"
}
},
{
"id": 2,
"name": "Lightspeed Retail",
"slug": "lightspeed_retail",
"logo_cdn_url": "http://placehold.it/200x200",
"active": true,
"authentication_type": {
"description": "Oauth Authentication Token",
"slug": "oauthauthenticationtoken"
}
}
]
I would like to parse this JSON and use it in another section of the paws application. Has anyone found any examples like this? I was trying the custom JS text but that appears to be a dead end.
Solution 1: jq
According to their website, "jq is a lightweight and flexible command-line JSON processor". And you can do jq queries in Paw. We will use it to automatically extract the ID of the field from your latest response.
On the URL field (where you want to have this "smart ID"), right-click and pick "jq JSON processor".
In the "JQ args" field, enter the query (see jq tutorial for details on how this works):
.[] | select(.slug == "bigcartel") | .id
In the JSON input field, right-click and pick Response > Response Raw Body. A popover will open, point the "Request" field to the request from which you want to extract the response body from (your "list" request). This will automatically fetch the body of the latest response of this request.
All done! You should now have this setup:
Solution 2: JavaScript Snippet
Paw exposes JavaScript bindings to write extensions (e.g. jq dynamic value used above is written as an extension). It can also be used to embed little code snippets inline a request. It's helpful to achieve more advanced setups.
Right-click on the URL field where you need to insert your ID. Pick Extensions > JS Script. In the popover, paste this code:
function evaluate(context){
var request = context.getRequestByName("List");
var httpExchange = request.getLastExchange();
var body = JSON.parse(httpExchange.responseBody);
for (var i = 0; i < body.length; i++) {
var member = body[i];
if (member.slug == "bigcartel") {
return member.id;
}
}
return null;
};
You can find the docs of this JavaScript API that Paw exposes in the Paw documentation under the "API Reference" section at the bottom.