Custom AQL functions
You can create IBM® QRadar® 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 IBM QRadar 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.
- QRadar
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 the Utils.concurrent library to ensure thread safety.
Custom AQL function management
Custom AQL functions are uploaded and updated by using the QRadar Extension Manager on the Admin tab. For more information about the QRadar Extension Manager, see the IBM QRadar Administration Guide.
The following XML file is an example of a QRadar 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 QRadar 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 QRadar
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 QRadar Extensions Management to upload
the extension to your QRadar
Console. For
more information about the QRadar 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 QRadar
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 QRadar Extension Manager to upload
the extension to your QRadar
Console. For
more information about the QRadar 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 QRadar
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 QRadar Extension Manager on the
Admin tab to upload the extension to your QRadar
Console. For more information about
the QRadar 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