Advanced concepts
Passing @tables as method parameters
As your instructions become complex, you may wish to pass parameters to methods using @tables, rather than fixing the values. A common scenario of this is FOREACH – described later.
Consider the following example:
Example - passing @tables as parameters
/* Get all the files in the C:\BigFiles folder */ @files = FileSystem.GetFilesInFolder(Folder: "C:\\BigFiles"); /* Bail out if there are no files */ EVALUATE; /* Pick the biggest one */ @biggest = SELECT FileName FROM @files ORDER BY FileSize DESC LIMIT 1; /* And then delete it */ FileSystem.DeleteFileByName(FileName: @biggest.FileName);
This example deletes the biggest file in a specific folder. We use LIMIT 1 to get the biggest file ordered by FileSize, and then pass that value to the DeleteFileByName method.
However, this syntax has a specific constraint. In our example, the use of LIMIT 1 guarantees that our "biggest" @table contains exactly one row. This is important, because parameters to methods (such as "DeleteFileByName" in this case) cannot take a set of values – they take only one.
If we had removed the LIMIT 1 clause from our query (and we had more than one file in our C:\BigFiles folder), this instruction would fail. This is because we are attempting to pass multiple "rows" of values for a single parameter.
To summarize – a field (column) from a @table can be passed as a value for parameter if:
The @table contains exactly one row, and
The field from the @table is of the correct datatype for the parameter
Additionally, you can omit the field name from the @table if that @table contains exactly one field:
Example - passing non-qualified @tables as parameters
@files = FileSystem.GetFilesInFolder(Folder: "C:\\BigFiles"); EVALUATE; @biggest = SELECT FileName FROM @files ORDER BY FileSize DESC LIMIT 1; /* Valid - @biggest contains only one field (FileName) so no need to specify it */ FileSystem.DeleteFileByName(FileName: @biggest); /* ... however... */ @smallest = SELECT FileName, FileSize FROM @files ORDER BY FileSize ASC LIMIT 1; /* NOT valid - @smallest contains two fields (FileName + FileSize) */ // FileSystem.DeleteFileByName(FileName: @smallest); /* But this is fine */ FileSystem.DeleteFileByName(FileName: @smallest.FileName);
If you cannot guarantee that your @table contains exactly one row, you will need to use the FOREACH construct to iterate over the @table.
Agent SQL functions
SQLite includes a number of built-in functions which you can use in SELECT statements:
Core functions, such as IFNULL, INSTR, SUBSTR, REPLACE, TRIM, UPPER, LOWER, RANDOM, PRINTF etc. are documented online at: https://sqlite.org/lang_corefunc.html.
Aggregate functions, such as COUNT, MIN, MAX, GROUP_CONCAT etc. documented online at: https://sqlite.org/lang_aggfunc.html.
Date and time functions, documented online at: https://sqlite.org/lang_datefunc.html. See datetime handling.
The Tachyon Agent takes advantage of SQLite extensibility by providing a further "application defined functions" that are built-in to the Agent and can also be used in SELECT statements.
|
Agent built-in functions
The functions described above are SQL-based functions, so can be used in SELECT statements. The Agent language itself also offers some built-in functions used outside of SELECT statements – think of them like methods available in a "global" module.
|
Global Settings variables
Tachyon provides an ability to store variables centrally, in the master database, and use those variables in instructions, in the Readable Payload or within the instruction (Payload).
They are similar to instruction parameters but do not prompt for a value in Tachyon Explorer. They conform to following pattern: %global:variable% where variable would be the name of the variable you want to use. All variables are case-insensitive.
So if in your Global Setting table you have an entry with the name 'ExecutionPolicy' you can use this in the payload and/or readable payload: %global:ExecutionPolicy% and the Value present for that entry will be inserted into the payload(s) replacing the %global:ExecutionPolicy%.
Please note the setting you request must exist in the database in order for the instruction to be issued, as an error will be returned if you attempt to issue an instruction based on a definition that uses a Global Setting that cannot be found.
The Tachyon Settings application does not (yet) provide a means of managing Global Settings, therefore you must edit the database directly.
In TIMS, when you are testing an instruction that uses Global Settings variables, TIMS will prompt you to enter a value. This is because TIMS does not have access to a Tachyon System.
Warning
Do not use Global settings variables in Guaranteed State fragments. They are not supported. Even if they could be used, the Value would be inserted into the policy payload at the point it is deployed, and any later changes to the Value would not be used.
Instead, Guaranteed State fragments should use a normal parameter, and the value for the parameter specified when configuring rules in Guaranteed State administration UI.
Environment variables
They are similar to instruction parameters but conform to following pattern: %environment:variable% where variable would be the name of the variable you want to use. All variables are case-insensitive.
If you use one of the patterns below in the Readable Payload or within the instruction (Payload), it will be replaced with another value. The 'other' value depends on which pattern you specified.
These following variables are available and hard coded in the system. They are not extensible in any way and each has a fixed behaviour.
Variable pattern | Replaced with | Introduced |
---|---|---|
%environment:now% | UTC ISO-8601 compatible date time stamp of when the instruction was issued. NoteThis is the timestamp of when the instruction was originally run and sent by the Tachyon Server. It remains the same if the same instruction is re-run. | Tipv3.1 |
Querying historic data
The Tachyon Agent has the ability to capture security-related events from the underlying operating system and store/summarize the data in a local database.
The feature is described here: Tachyon Activity Record.
The tables used to store this data are available to be queried from within the Agent Language using a slightly modified syntax. The related tables are available using the dollar ($) prefix.
For example:
Example - querying historic captured data
/* Sum the number of connections made per process today */ SELECT SUM(ConnectionCount) AS Connections , ProcessName FROM $TCP_Daily WHERE TS = DATETRUNC(STRFTIME("%s", "now"), "day") GROUP BY ProcessName;