Custom AQL Functions
You can create JSA apps that use custom Ariel Query Language (AQL) functions.
After you upload the app, you can use these custom functions in AQL statements in advanced searches, API calls, and application apps. For more information about AQL, see the Juniper Secure Analytics Ariel Query Language Guide.
Coding Tips
Before you implement custom AQL functions, consider these items:
Scripts are not throttled and cannot be canceled. Be careful of infinite loops and resource leaks in your code.
Deletion of custom functions is possible, but not supported.
JSA parses AQL strings much more than it needs to. Expensive
init_function_name
implementations that are combined with the use of your function in a literal context can be expensive. Use with caution.The
execute_function_name
implementation must be thread-safe. Use theUtils.concurrent
library to ensure thread safety.
Custom AQL Function Management
Custom AQL functions are uploaded and updated by using the JSA Extension Manager on the Admin tab. For more information about the JSA Extension Manager, see the JSA Administration Guide.
The following XML file is an example of a JSA extension that defines a custom AQL function.
<content> <custom_function> <namespace>application</namespace> <name>concat</name> <return_type>string</return_type> <parameter_types>string string</parameter_types> <execute_function_name>calculate</execute_function_name> <script_engine>javascript</script_engine> <varargs>false</varargs> <script> function calculate(input1, input2) { return input1 + input2; } </script> <username>user1</username> </custom_function> </content>
You can also use the Content Management Tool, which is a command-line tool, to upload extensions:
/opt/qradar/bin/contentManagement.pl -a update -f my_bundle.xml
The following code samples provide examples of how you can create JSA apps that define custom AQL functions for use in AQL statements.
Example: Custom Functions in AQL Statements
AQL statements that use custom functions use the following basic format:
SELECT <CUSTOM FUNCTION NAMESPACE>::<CUSTOM FUNCTION NAME>(<INPUTS>) FROM <TABLE>
SELECT application::concat('This is my IP: ', sourceip) FROM events LIMIT 20
Example: Simple Addition
Create the following JSA extension:
<content> <custom_function> <namespace>application</namespace> <name>add</name> <return_type>number</return_type> <parameter_types>number number</parameter_types> <execute_function_name>execute</execute_function_name> <script_engine>javascript</script_engine> <script> function execute(input1, input2) { return input1 + input2; } </script> <username>user1</username> </custom_function> </content>
Use the JSA Extensions Management to upload the extension to your JSA console. For more information about the JSA Extensions Management, see Extensions Management.
If you have multiple hosts, wait up to 60 seconds for the function to propagate across your deployment.
You can use this function in AQL statements as follows:
SELECT application::add(eventcount, 5) FROM events
Example: Variable Argument Concatenation
Create the following JSA extension:
<content> <custom_function> <namespace>application</namespace> <name>concat</name> <return_type>string</return_type> <parameter_types>string</parameter_types> <varargs>true</varargs> <execute_function_name>execute</execute_function_name> <script_engine>javascript</script_engine> <script> function execute() { var result = ""; for(var i=0; i<arguments.length; i++) result = result + arguments[i]; return result; } </script> <username>user1</username> </custom_function> </content>
Use the JSA Extension Manager to upload the extension to your JSA console. For more information about the JSA Extension Manager, see Extensions Management.
If you have multiple hosts, wait up to 60 seconds for the function to propagate across your deployment.
You can use this function in AQL statements:
SELECT application::concat(sourceip, ':', sourceport) FROM events
Example: Complex Initialization That Uses a Remote API
Create the following JSA extension:
<content> <custom_function> <namespace>application</namespace> <name>isFlaggedIP</name> <return_type>boolean</return_type> <parameter_types>host</parameter_types> <execute_function_name>isFlaggedIP</execute_function_name> <init_function_name>onInit</init_function_name> <script_engine>javascript</script_engine> <script> var flaggedIPs; function onInit() { var properties = Utils.config.readNamespacePropertiesFile('my_api.properties'); var ip = properties.get('ip'); var url = 'https://' + ip + '/my_api/flagged_ips'; var username = properties.get('username'); var token = properties.get('token'); var headers = {'SecurityToken': token}; var jsonResponse = JSON.parse(Utils.http.invokeHTTP("GET", url, 200, headers, null, null)); flaggedIPs = []; for(var i in jsonResponse) { flaggedIPs.push(jsonResponse[i]); } } function isFlaggedIP(ip) { return (flaggedIPs.indexOf(ip) >= 0); } </script> <username>user1</username> </custom_function> </content>
Use the JSA Extension Manager on the Admin tab to upload the extension to your JSA console. For more information about the JSA Extension Manager, see Extensions Management.
If you have multiple hosts, wait up to 60 seconds for the function to propagate across your deployment.
Create a properties file with the following content in the
/store/custom_functions/namespaces/application/my_api.properties
file.ip=<ip for remote API server> username=<your username for remote API server> token=<your token for remote API server>
You can use this function in AQL statements:
SELECT application::isFlaggedIP(sourceip) AS is_flagged_qradar_ip, sourceip FROM events