Handling Axonius Query Language on the Command Line
While working with the Axonius API client, you may come across times when you want to use Axonius Query Language (AQL) from the Axonius GUI directly on the command line. We have multiple ways that this can be accomplished and in this article we will talk about each one.
AQL Directly Into the "--query" Parameter
The simplest way to use AQL from the command line is to use the --query parameter of the client.
-q, --query QUERY Query built from the Query wizard in the GUI
[env var: AX_QUERY]
An example of an AQL statement from the GUI may like something like this:
This is looking for all devices where the "last_seen" date has been within the last 30 days. Your first instinct may be to copy this directly onto the command line and try to use it in a command... but look what happens:
❯ axonshell devices get --query=("specific_data.data.last_seen" >= date("NOW - 30d"))
zsh: parse error near `)'
When you run this command on the command line, the shell (eg. bash, zsh, command prompt, etc) has to interpret the command and all of its arguments and pass the arguments into the command. As you can see above, the shell was not able to parse the command correctly. The reason is because the shell has it's own built-in commands, functions and symbols that are supposed to be used in a certain way and in this case specifically the shell is isn't seeing what it needs to in regards to the closing parenthesis.
So how do we fix this?
There are two things we need to do. We need to tell the shell that the full AQL statement is one value that is supposed to be passed to the --query argument. The easiest way to do this is to surround the whole statement in double quotes. However that creates another problem since our statement already contains quotes. The statement is going to be passed in broken. So any quote that is inside the outmost pair of quotes needs to be escaped using whatever your shell escape character is. Most of the time it is "\".
So our command above fully fixed is going to look like this:
❯ axonshell devices get -q "(\"specific_data.data.last_seen\" >= date(\"NOW - 30d\"))"
AQL Loaded From a File
The next method is actually much simpler, however, it requires writing a file to disk. Lets take a look at the --query-file parameter:
-qf, --query-file QUERY_FILE Path to a file to override --query [env
The --query-file parameter points to a file on disk containing an AQL query. When ran, the Axonius api client will then load the query from the file bypassing the shell completely. Using this method you do not have to worry about any sort of escaping or shell specific issues. If your query on the command line isn't working trying to use the above method. Putting it in a file and running it using the --query-file parameter is a good way to test if your shell is causing problems.
AQL From Wizard-Like Syntax
The last method isn't actually using AQL directly. Just like the Axonius UI has a query builder wizard built into it, the Axonius API client does as well. This lets you write AQL using clearer and more human-readable statements. These statements are then used to programmatically generate the AQL that gets sent to the server. Lets take a look at the wizard parameter:
-wz, --wiz TYPE "EXPRESSION" Build a query using an expression
(multiples, will override --query) [env
There is also more detailed help available for this command from the client that shows quite a few examples as well as the flag operators:
So all we need to do to run the same query as above but using the wizard instead of AQL directly is to give the client the --wiz parameter, tell it if it is a simple or complex query and then show it what to look for. In our case it would look like the following:
❯ axonshell devices get --wiz simple "last_seen last_days 30"
At the beginning of the command output, you will see information about what the client is going to send to the server. Under the "Get Arguments" section. you will see a query line that shows what was generated from the provided wizard statements:
** Get Arguments:
- query: '(specific_data.data.last_seen >= date("NOW - 30d"))'
You'll notice the generated AQL is exactly the same as what we were trying to run before; only generated in a much more user friendly way.
If you would like to see an example of how wizard statements can be used with the python library that comes with our client, please see the following code example: