Investigating cloud metadata with JPQL (JSON Path Query Language)

All example queries below use GetCredentialReportStream (IAM) and EC2 streams and have been validated against the live catalog.

Query Template | Stream Filter Function (FILTER) | Boolean Logic | Comparison Operators | Membership Operators | Text / Pattern Operators | Null and Presence Operators | IP and Network Operators | Special Operators | Array Modifiers | Namespace Functions | Join Queries | Literal Values & AWS-Specific Strings

Query Template

Use this base pattern for all TotalCloud queries:

Basic structure:

SELECT <alias> 
FROM cloud.resource 
WHERE (<filters>) AS <alias>

Each query must include FROM cloud.resource, a $.streamName filter in the WHERE clause, and an alias defined with AS.

SELECT must contain exactly one alias.

Example:

SELECT r 
FROM cloud.resource 
WHERE ($.streamName = "GetCredentialReportStream" AND $.data.user = "admin") 
AS r

Stream Filter Function (FILTER)

The FILTER function defines the specific subset of data that a control should evaluate before applying its compliance checks. It narrows the scope by selecting only the relevant records from all collected data and then running the actual compliance evaluation on them. Any data that does not match the filter criteria is excluded and is therefore not considered compliant or non-compliant (No pass or fail result for that resource would be returned). This ensures that the control evaluates only the intended resources and produces accurate, relevant results.

For example, if you want to check 'Ensure no root user account access key exists', which is applicable to only root user accounts, you can first use FILTER to restrict the evaluation to root user accounts and then apply the compliance condition:

SELECT r FROM cloud.resource
    WHERE (FILTER("GetCredentialReportStream", ($.data.user = "<root_account>"))
      AND ($.data.access_key_1_active = "true"
      OR $.data.access_key_2_active = "true"))
    AS r

In this case, only user accounts with value as "<root_account>" are considered in scope, and among those, the control checks whether the access key exists.

Boolean Logic

Use AND, OR, and NOT to combine predicates. The query engine processes them as follows:

AND - Both sides are classified independently. Predicates that can be pushed to Elasticsearch are evaluated there; any remaining predicates are evaluated in DuckDB.

OR - If any branch of an OR expression is residual (cannot be pushed to Elasticsearch), the entire OR expression is evaluated in DuckDB.

NOT - Can be pushed to Elasticsearch only when the inner expression is fully pushable.

Examples:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.access_key_1_active = true
      AND NOT $.data.user = "<root_account>") AS r

<root_account> is a literal string value used by AWS in the IAM Credential Report. The user column contains the exact text <root_account> for the root user — it is not a placeholder or macro that gets substituted at runtime. See Literal Values & AWS-Specific Strings section for details.

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND ($.data.access_key_1_last_used_region = "us-east-1"
      OR $.data.access_key_1_last_used_region = "eu-west-1")) AS r

Comparison Operators

Use comparison operators to match field values exactly or by range. Numeric and date fields support range operators (>, >=, <, <=, BETWEEN). The = and != operators are supported on text, numeric, boolean, and date fields.

Operator Description Syntax

EQ or =

Exact equality. Case-sensitive for text; numeric equality for numbers and dates.

$.path = "value" or $.path EQ "value"

NEQ or !=

Not equal. Inverse of EQ.

$.path != "value" or $.path NEQ "value"

>

Greater than. Numeric and date fields only.

$.path > value

>=

Greater than or equal. Numeric and date fields only.

$.path >= value

<

Less than. Numeric and date fields only.

$.path < value

<=

Less than or equal. Numeric and date fields only.

$.path <= value

BETWEEN

Inclusive range check. Numeric and date fields only.

$.path BETWEEN lo AND hi

Find an IAM user by exact name:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream" AND $.data.user = "admin") AS r

Find IAM users that are not the root account:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream" AND $.data.user != "<root_account>") AS r

Find security groups with ports in a specific range using > and <=:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2SecurityGroupsStream"
      AND $.data.IpPermissions[*].FromPort > 1023
      AND $.data.IpPermissions[*].ToPort <= 65535) AS r

Find security groups with ports in a well-known range using BETWEEN:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2SecurityGroupsStream"
      AND $.data.IpPermissions[*].FromPort BETWEEN 8000 AND 9000) AS r

Membership Operators

Use membership operators to test whether a field value belongs to a set of values. Array-aware operators such as ANYOF, NONEOF, SUBSETOF, and INTERSECTS are designed for array-typed fields.

Operator

Description

Syntax

IN

Value is one of the listed values. Works like SQL IN.

$.path IN ("v1", "v2")

ANYOF

Field value matches any of the given values. Array-aware.

$.path ANYOF ("v1", "v2")

NONEOF

Field value matches none of the given values. Inverse of ANYOF.

$.path NONEOF ("v1", "v2")

MEMBER_OF

Checks if the field value is a member of the given set.

$.path MEMBER_OF ("v1", "v2")

SUBSETOF

All elements of the array are in the given set. DuckDB.

$.path SUBSETOF ("v1", "v2")

INTERSECTS

Array has at least one element in common with set. DuckDB.

$.path INTERSECTS ("v1", "v2")

Find IAM users whose access key was last used in specific regions (IN):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.access_key_1_last_used_region IN ("us-east-1", "us-west-2")) AS r

Find EC2 instances of specific types (ANYOF):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND $.data.Instances[*].InstanceType ANYOF ("t2.micro", "t3.micro")) AS r

Find EC2 instances that are not specific types (NONEOF):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND $.data.Instances[*].InstanceType NONEOF ("t2.micro", "t3.micro")) AS r

Find IAM roles whose managed policies are fully within a safe set (SUBSETOF):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "AccountAuthDetailRoleStream"
      AND $.data.AttachedManagedPolicies[*].PolicyName SUBSETOF ("ReadOnlyAccess", "ViewOnlyAccess")) AS r

Find EC2 instances attached to specific security groups (INTERSECTS):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND $.data.Instances[*].SecurityGroups[*].GroupId INTERSECTS ("sg-00001", "sg-00002")) AS r

Text / Pattern Operators

Use text operators to search string fields by substring, prefix, suffix, wildcard, or regular expression. These operators are not valid on numeric or date fields. CONTAINS, SUFFIX, and LIKE are always evaluated in DuckDB. PREFIX and MATCHES_GLOB may be pushed to Elasticsearch for structured keyword fields.

Operator

Description

Syntax

CONTAINS

Substring match. Case-sensitive.

$.path CONTAINS "substring"

PREFIX

Value starts with the given prefix.

$.path PREFIX "prefix"

SUFFIX

Value ends with the given suffix. Always DuckDB.

$.path SUFFIX "suffix"

MATCHES

Regular expression match. Uses /regex/ literal syntax.

$.path MATCHES /regex/

LIKE

SQL-style wildcard. % = any chars, _ = single char. Always DuckDB.

$.path LIKE "pattern%"

MATCHES_GLOB

Glob-style wildcard. * = any chars, ? = single char.

$.path MATCHES_GLOB "glob*"

Find IAM users whose ARN contains a specific substring (CONTAINS):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.arn CONTAINS "admin") AS r

Find IAM users whose ARN starts with a specific prefix (PREFIX):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.arn PREFIX "arn:aws:iam") AS r

Find IAM users whose username ends with a specific suffix (SUFFIX):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.user SUFFIX "_admin") AS r

Find IAM users matching a regular expression (MATCHES):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.user MATCHES /admin[0-9]+/) AS r

MATCHES uses Lucene regex syntax (ES). Lucene does NOT support lookaheads (?=...) or (?!...). Avoid patterns ending in */ as they trigger the harmful-input filter; use .+ instead of .* when the regex ends with a wildcard.

Find IAM users using a SQL-style wildcard (LIKE):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.user LIKE "admin%") AS r

Find IAM users using a glob wildcard (MATCHES_GLOB):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.user MATCHES_GLOB "admin*") AS r

Null and Presence Operators

Use these operators to check whether a field exists, is null, or is an empty array or string. EXISTS is pushable to Elasticsearch for most field types. IS NULL and IS EMPTY are always evaluated in DuckDB.

Operator

Description

Syntax

EXISTS

Field is present and not null.

$.path EXISTS

IS NULL

Field is null or missing.

$.path IS NULL

IS EMPTY

Field is an empty array or empty string.

$.path IS EMPTY

Find IAM users whose access key 1 has been used (EXISTS):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.access_key_1_last_used_date EXISTS) AS r

Find IAM users who have never used their password (IS NULL):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND $.data.password_last_used IS NULL) AS r

Find IAM roles with no managed policies attached (IS EMPTY):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "AccountAuthDetailRoleStream"
      AND $.data.AttachedManagedPolicies IS EMPTY) AS r

IP and Network Operators

Use IP operators to filter resources by IP address or port. These operators work on both scalar and array IP fields and are always evaluated in DuckDB using auto-registered macros. All arguments must be enclosed in parentheses.

Operator

Description

Syntax

IN_CIDR

IP address falls within the given CIDR block.

$.path IN_CIDR ("10.0.0.0/8")

IN_IP_RANGE

IP address falls within an inclusive range defined by a lower and upper bound.

$.path IN_IP_RANGE ("lo", "hi")

IN_PORT_RANGE

Port number falls within a numeric range.

$.path IN_PORT_RANGE (lo, hi)

Find EC2 instances with a private IP in the corporate network range (IN_CIDR):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND $.data.Instances[*].PrivateIpAddress IN_CIDR ("10.0.0.0/8")) AS r

Find EC2 instances with a private IP within a specific host range (IN_IP_RANGE):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND $.data.Instances[*].PrivateIpAddress IN_IP_RANGE ("10.0.0.1", "10.0.0.255")) AS r

Find security group rules with ports in the non-privileged range (IN_PORT_RANGE):

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2SecurityGroupsStream"
      AND $.data.IpPermissions[*].FromPort IN_PORT_RANGE (1024, 65535)) AS r

Special Operators

These operators apply computed values or namespace-qualified functions as predicates. They are always evaluated in DuckDB.

Operator

Description

Syntax

NUMBER OF WORDS

Counts whitespace-delimited words in the field value and compares to a number.

NUMBER OF WORDS($.path) > n

AGE_IN_DAYS

Computes age of a date field in days from today. Use via the _DateTime namespace.

_DateTime.ageInDays($.path) > n

Namespace function predicate

A namespace-qualified function call used as a predicate. See Namespace Functions for all available functions.

_Namespace.fn($.path) = value

Find IAM users created more than 90 days ago:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND _DateTime.ageInDays($.data.user_creation_time) > 90) AS r

Find security groups whose description has more than 3 words:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2SecurityGroupsStream"
      AND NUMBER OF WORDS($.data.Description) > 3) AS r

Find SNS topics with a safe access policy:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetTopicAttributeStream"
      AND _AWSSNS.isSnsAccessPolicySafe($.data.Policy) = true) AS r

Array Modifiers

Array modifiers prefix an operator to control how it applies across the elements of an array field. Use ANY and NONE for Elasticsearch-pushable checks; use ALL and SIZE for DuckDB-evaluated checks.

Modifier

Engine

Description

Example

ANY

ES

True if any array element satisfies the predicate.

ANY $.data.Instances[*].InstanceType EQ "t2.micro"

NONE

ES

True if no array element satisfies the predicate.

NONE $.data.Instances[*].InstanceType EQ "t2.micro"

ALL

DuckDB

True if all array elements satisfy the predicate.

ALL $.data.Instances[*].State.Name EQ "running"

SIZE

DuckDB

Applies a numeric comparison to the count of array elements.

SIZE $.data.Instances[*].SecurityGroups[*].GroupId > 2

Namespace Functions

Namespace functions are called using the syntax _Namespace.functionName(args) and are always evaluated in DuckDB. Use them as predicates in your WHERE clause.

_DateTime - Date and Time Functions

Use _DateTime functions to filter resources by the age or relative date of a date field.

Function

Description

_DateTime.ageInDays($.path)

Returns the number of days elapsed since the date field value.

_DateTime.ageInMonths($.path)

Returns the number of months elapsed since the date field value.

_DateTime.ageInYears($.path)

Returns the number of years elapsed since the date field value.

_DateTime.daysBetween($.path1, $.path2)

Returns the number of days between two date fields.

_DateTime.today()

Returns the current date as a literal value for use in comparisons.

Find IAM users created more than 90 days ago:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND _DateTime.ageInDays($.data.user_creation_time) > 90) AS r

Find IAM users created more than 6 months ago:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetCredentialReportStream"
      AND _DateTime.ageInMonths($.data.user_creation_time) > 6) AS r

Find EC2 instances launched more than 90 days ago:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND _DateTime.ageInDays($.data.Instances[*].LaunchTime) > 90) AS r

_IPAddress - IP Address Functions

Use _IPAddress functions to filter resources by whether an IP address or array of IP addresses falls within a CIDR block or a defined range.

Function

Description

_IPAddress.inCIDRRange($.path, "cidr")

True if the IP address is within the given CIDR block.

_IPAddress.areAllInCIDRRange($.path, "cidr")

True if all IP addresses in an array field are within the CIDR block.

_IPAddress.areAnyOutsideCIDRRange($.path, "cidr")

True if any IP address in an array field falls outside the CIDR block.

_IPAddress.inRange($.path, "lo", "hi")

True if the IP address falls within the inclusive range defined by low and high bounds.

Find EC2 instances with a private IP in the corporate network:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2InstancesStream"
      AND _IPAddress.inCIDRRange($.data.Instances[*].PrivateIpAddress, "10.0.0.0/8") = true) AS r

Find security groups with any IP rule outside the allowed CIDR range:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2SecurityGroupsStream"
      AND _IPAddress.areAnyOutsideCIDRRange($.data.IpPermissions[*].IpRanges[*].CidrIp, "10.0.0.0/8") = true) AS r

_Port - Port Functions

Use _Port functions to filter resources by whether a port number falls within a defined range.

Find security group rules with high-number ports open:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeEC2SecurityGroupsStream"
      AND _Port.inRange($.data.IpPermissions[*].FromPort, 1024, 65535) = true) AS r

_AWSSNS - AWS SNS Functions

Use _AWSSNS functions to evaluate the safety of SNS topic access policies.

Find SNS topics with a safe access policy:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetTopicAttributeStream"
      AND _AWSSNS.isSnsAccessPolicySafe($.data.Policy) = true) AS r

Find SNS topics whose access policy is publicly exposed:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "GetTopicAttributeStream"
      AND _AWSSNS.isSnsAccessPolicySafe($.data.Policy) = false) AS r

_AWSVPC - AWS VPC Functions

Use _AWSVPC functions to evaluate VPC security group rules, network ACLs, and VPC endpoint policies. These functions are AWS-only — they have no Azure equivalent.

Function

Description

_AWSVPC.evaluateByIP($.ipPermissions, fromPort, toPort, "protocol", "cidr")

Checks if any inbound rule allows traffic from the specified CIDR block (e.g., "0.0.0.0/0") on the given port range and protocol.

_AWSVPC.evaluateBySG($.ipPermissions, "security-group-id", fromPort, toPort, "protocol")

Checks if any inbound rule references another security group as a traffic source. "security-group-id" is a type indicator, not a placeholder.

_AWSVPC.evaluateByPL($.ipPermissions, fromPort, toPort, "protocol", "prefix-list-id")

Checks if any inbound rule references a managed prefix list as a traffic source. "prefix-list-id" is a type indicator, not a placeholder.

_AWSVPC.isGatewayEndpointPolicySafe($.policyDocument)

Evaluates whether a VPC Gateway Endpoint's policy document is safe (not overly permissive).

Find VPC Gateway Endpoints with a safe policy:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeVpcEndpointsStream"
      AND _AWSVPC.isGatewayEndpointPolicySafe($.data.PolicyDocument) = true) AS r

Placeholders — CID 41, 42

"security-group-id" and "prefix-list-id" are actual placeholders that should be replaced with real values (e.g., "sg-0a1b2c3d4e5f67890", "pl-02dc3456") at query time. If you don't need to check by security group or prefix list, you can remove those branches and keep only the IP check.

Value

Used In

Meaning

"security-group-id"

CID 41, 42 — _AWSVPC.evaluateBySG()

Placeholder for an actual security group ID (e.g., sg-0a1b2c3d4e5f67890). Replace with a real SG ID or remove the branch.

"prefix-list-id"

CID 41, 42 — _AWSVPC.evaluateByPL()

Placeholder for an actual prefix list ID (e.g., pl-02dc3456). Replace with a real PL ID or remove the branch.

CID 41 — Unrestricted SSH (port 22) ingress via Security Groups

Stream: DescribeSecurityGroupsStream

Type indicators: "security-group-id" (in evaluateBySG), "prefix-list-id" (in evaluateByPL)

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeSecurityGroupsStream"
      AND ((_AWSVPC.evaluateByIP($.data.IpPermissions, 22, 22, "tcp", "0.0.0.0/0") = true)
      OR (_AWSVPC.evaluateBySG($.data.IpPermissions, "sg-0a1b2c3d4e5f67890", 22, 22, "tcp") = true)
      OR (_AWSVPC.evaluateByPL($.data.IpPermissions, 22, 22, "tcp", "pl-02dc3456") = true)))
    AS r

CID 42 — Unrestricted RDP (port 3389) ingress via Security Groups

Stream: DescribeSecurityGroupsStream

Type indicators: "security-group-id" (in evaluateBySG), "prefix-list-id" (in evaluateByPL)

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeSecurityGroupsStream"
      AND (_AWSVPC.evaluateByIP($.data.item.ipPermissions, 3389, 3389, "tcp", "0.0.0.0/0") = true
      OR _AWSVPC.evaluateBySG($.data.item.ipPermissions, "sg-0a1b2c3d4e5f67890", 3389, 3389, "tcp") = true
      OR _AWSVPC.evaluateByPL($.data.item.ipPermissions, 3389, 3389, "tcp", " pl-02dc3456") = true)) AS r

If there is no need of SG or PL in the query it can also be used as below:

SELECT r FROM cloud.resource
    WHERE ($.streamName = "DescribeSecurityGroupsStream"
      AND ((_AWSVPC.evaluateByIP($.data.IpPermissions, 22, 22, "tcp", "0.0.0.0/0") = true)))
    AS r

Join Queries

Use a JOIN to correlate resources across two streams. Specify a join key in the ON clause using EQ. Use a HAVING clause to filter join results by the count of matching related records.

SELECT must contain exactly one alias

Basic join syntax:

SELECT <alias>
    FROM cloud.resource WHERE (<filters_a>) AS a
    JOIN cloud.resource WHERE (<filters_b>) AS b
    ON (a.$.path EQ b.$.path)

Find application load balancers that have at least one HTTP listener:

SELECT alb
    FROM cloud.resource WHERE ($.streamName = "GetELBV2ListStream"
      AND $.data.type = "application") AS alb
    JOIN cloud.resource WHERE ($.streamName = "GetElbV2ListenersStream"
      AND $.data.Protocol ANYOF ("HTTP")) AS lsn
    ON (alb.$.data.loadBalancerArn EQ lsn.$.data.loadBalancerArn)

Use HAVING COUNT to filter ALBs with two or more HTTP or HTTPS listeners:

SELECT alb
    FROM cloud.resource WHERE ($.streamName = "GetELBV2ListStream"
      AND $.data.type = "application") AS alb
    JOIN cloud.resource WHERE ($.streamName = "GetElbV2ListenersStream"
      AND $.data.Protocol ANYOF ("HTTP", "HTTPS")) AS lsn
    ON (alb.$.data.loadBalancerArn EQ lsn.$.data.loadBalancerArn)
    HAVING COUNT(lsn) >= 2

Find RDS SQL Server instances where rds.force_ssl is not enabled (JOIN with multiple ON conditions using CONTAINS):

SELECT x
    FROM cloud.resource
    WHERE (
      $.streamName = "DescribeDBInstancesStream"
      AND (
        $.data.Engine PREFIX "sqlserver"
        OR $.data.Engine PREFIX "SQLSERVER"
      )
    ) AS x
    JOIN cloud.resource
    WHERE (
      $.streamName = "DescribeDBParametersStream"
      AND $.data.Parameters[*].ParameterName = "rds.force_ssl"
      AND $.data.Parameters[*].ParameterValue != "1"
    ) AS y
    ON (
      x.$.data.DBParameterGroups[*].DBParameterGroupName CONTAINS y.$.cloudResourceId
      AND x.$.region CONTAINS y.$.region
    )

When a JOIN has two or more matching conditions in the ON clause, use the CONTAINS operator instead of EQ (=). This is because the left-hand side often references a nested array field ([*]), and CONTAINS correctly checks if the array-derived value set includes the scalar value from the other side of the join.

Literal Values & AWS-Specific Strings

AWS Literal Value — CID 14

<root_account> looks like a placeholder but is not. It is the actual literal value that AWS returns in the IAM Credential Report CSV under the user column for the root user. No substitution happens at runtime — this must be used exactly as shown.

Value

Used In

Meaning

<root_account>

CID 14 — GetCredentialReportStream

AWS uses the literal text <root_account> in the IAM Credential Report CSV as the user column value for the root user. It is not a placeholder.

CID 14 — Ensure no root user account access key exists

Stream: GetCredentialReportStream

Literal value: <root_account> — the exact string AWS puts in the credential report user column for the root user

SELECT r FROM cloud.resource
    WHERE (FILTER("GetCredentialReportStream", ($.data.user = "<root_account>"))
      AND ($.data.access_key_1_active = "true"
      OR $.data.access_key_2_active = "true"))
    AS r