Issue
Users need to review logs within the Red Canary's Security Data Lake (SDL) but are unfamiliar with the specific SQL syntax required to query complex data, such as nested JSON objects, arrays, or case-insensitive strings.
Environment
Red Canary Portal
Security Data Lake (Search)
Resolution
Use the library of sample query templates provided below. These examples demonstrate how to use compatible SQL operators to perform common search tasks in Security Data Lake, though the list is not exhaustive of all supported operators and use-cases.
SELECT * and instead list only the specific columns you need to review (e.g. SELECT rc_timestamp, message). To review available columns for a table, click an integration listed on the SDL Search page and review the details blade. While the templates below use SELECT * for simplicity, specifying columns will improve search speed.Partial String Match Using Wildcards
SELECT * FROM "Your Table" WHERE Column_name LIKE '%value%';
SQL uses the LIKE operator for pattern matching. The % symbol is a wildcard that represents "any number of characters" (including zero).
• %value% finds the text anywhere in the string
• value% finds text starting with that value
• %value finds text ending with that value
Wildcards are useful when searching for part of a value, such as a partial file path, a domain suffix, or IP subnet.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE company LIKE 'Red%' LIMIT 100;
Searching Case-Insensitive Values
SELECT * FROM "Your Table" WHERE LOWER(Column_name) = 'value';
By default, SQL is case-sensitive; it treats "Malware" and "malware" as different words. Since ILIKE is not supported in Security Data Lake, use the LOWER() function to "normalize" the data. This temporarily converts all text in your chosen column to lowercase during the search.
However, you must also ensure your search term (i.e. filter_value) is written in all lowercase letters.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE LOWER(company) = 'redcanary' LIMIT 100;
Combining Multiple Filters with AND / OR Operators
SELECT * FROM "Your Table" WHERE Column_name_A = 'value_1' AND Column_name_B = 'value_2';
Logical operators allow you to connect multiple conditions.
• AND narrows your search: every condition must be true for a row to show up
• OR broadens your search: only one of the conditions needs to be true
Use AND when you need to be specific, such as looking for a specific user and a specific action. Use OR when you want to look for multiple independent indicators at once, like searching for activity from three different IP addresses.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE company = 'RedCanary' AND message = 'New user added' LIMIT 100;
Excluding Specific Values Using NOT Operators
SELECT * FROM "Your Table" WHERE NOT Column_name = 'Excluded_value';
Sometimes the most efficient way to find a "needle" is to remove the "hay." You can use the "not equal to" operator (!=) or the NOT keyword to hide results that match a specific value.
This is primarily used for filtering out noise. If your search results are flooded with logs not useful for your investigation, you can exclude those specific values so you can focus on the remaining data.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE company != 'Zscaler' LIMIT 100;
Filtering by a Field Within an Object { A=RedCanary, B=Denver}
SELECT * FROM "Your Table" WHERE Column_name.Field = 'value';
In SQL, related attributes are often grouped into an Object (also called a Struct). To access a specific value inside that group, use dot notation (Column.Field).
Use this when a single column (like actor or event) contains multiple sub-fields. Instead of searching the whole blob of data, you can pinpoint exactly what you need, such as actor.displayName or event.ClientIP.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE company.A = 'RedCanary' LIMIT 100;
Filtering by a Deeply Nested Field { A=RedCanary, B={ city=Denver, state=CO } }
SELECT * FROM "Your Table" WHERE Column_name.Field.Sub_field = 'Filter_value';
Sometimes data is organized as objects within objects. You can chain dot notation together to "drill down" through multiple layers of objects to reach a specific value.
This is common in complex cloud or identity logs. For example, you might need to navigate through loginDetails to geolocation to find a specific country.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE company.B.city = 'Denver' LIMIT 100;
Filtering by a Value Within a List [ { A=RedCanary, B=Denver }, { A=Zscaler, B=SanJose } ]
SELECT * FROM "Your Table" WHERE any_match(Column_name, temp -> temp.Field = 'Filter_value');
When a column contains a List (also called an Array) of multiple items, a standard = or LIKE won't work. To workaround this, use the any_match function combined with a Lambda expression (temp -> ...) to effectively tell the database, "Go through every item in this list one by one and let me know if any of them match my filter".
This is essential for fields that can have multiple values, such as a list of detailed netconns in a single IP chain or a list of roles assigned to a user.
Example:
SELECT rc_timestamp, company, message FROM "My Data Lake Integration" WHERE any_match(company, temp -> temp.A = 'RedCanary') LIMIT 100;
Finding Unique Values in a Column
SELECT DISTINCT Column_name FROM "Your Table" ORDER BY Column_name ASC;
The DISTINCT operator acts as a de-duplicator. It scans the specified column and returns only one instance of every unique value it finds. Adding ORDER BY ... ASC simply sorts that list alphabetically.
This is a useful tool for data exploration. As examples, if you aren't sure what event types your IdP collects, or you want to see a list of every unique host that sent data in the last hour, DISTINCT will give you a high-level summary without the noise of thousands of repetitive rows.
Example:
SELECT DISTINCT company FROM "Your Table" ORDER BY company ASC LIMIT 100;
Key Concepts
- SQL queries must follow standard order of
SELECT>FROM>JOIN>WHERE>GROUP BY>ORDER BY>LIMIT - Use 'single quotes' for values and strings and "double-quotes" for table or column names containing a hyphen or space
- For faster queries, use
=when you know the exact value you're looking for andLIKEfor partial pattern matches - When testing a new query, end it with
LIMIT 100;to cap output in the event your filter is too broad - Remember to use the
LOWER()function withLIKEand=as these are case-sensitive - Instead of adding time filters to your query, modify the selected Activity at (UTC) range in the SDL query builder
- Use the Save function in the query builder for your favorite queries, though keep in mind saved queries are not shared across Red Canary user accounts
Cause
Red Canary's Security Data Lake utilizes a Trino-based SQL engine to provide high-performance searching across large datasets. Because security logs are often structured as complex JSON or Syslog formats, specific SQL operators (like dot notation or lambda functions) are required to accurately retrieve the data.
Tags
security data lake search, getting started with SQL, SQL help, SDL search syntax, query language, SQL tips, security data lake syntax, SDL reference guide, searching SDL data, getting started with SDL search, Trino search syntax, Trino help, supported operators, searching data lake, data lake tips, SDL help, example SQL queries, SDL search templates, getting started with security data lake search, SQL cheat sheet, SQL quick reference