This page has been updated to align with the new Grail security events table. For the complete list of updates and actions needed to accomplish the migration, follow the steps in the Grail security table migration guide.
The examples below illustrate how to slice and dice security data and build powerful and flexible security reports with Dynatrace Query Language (DQL).
Get the total number of open, non-muted vulnerabilities in your environment.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status=="OPEN"AND vulnerability.parent.mute.status!="MUTED"AND vulnerability.mute.status!="MUTED"// count unique vulnerabilities| summarize {`Open vulnerabilities`=countDistinctExact(vulnerability.display_id)}
Query result:
Get the total number of critical open, non-muted vulnerabilities in your environment.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for critical open non-muted vulnerabilities| filter vulnerability.resolution.status=="OPEN"AND vulnerability.parent.mute.status!="MUTED"AND vulnerability.mute.status!="MUTED"AND vulnerability.risk.level=="CRITICAL"// count unique vulnerabilities| summarize {`Critical open vulnerabilities`=countDistinctExact(vulnerability.display_id)}
Query result:
Get the total number of open, non-muted vulnerabilities in a specific management zone (in this example, AppSec: UNGUARD
).
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities in a specific management zone| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"AND in("AppSec: Unguard", affected_entity.management_zones.names)// count unique vulnerabilities| summarize {`Open vulnerabilities (unguard)`=countDistinctExact(vulnerability.display_id)}
Query result:
Get the total number of open, non-muted vulnerabilities with public internet exposure in your environment.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities with public internet exposure| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"AND vulnerability.davis_assessment.exposure_status=="PUBLIC_NETWORK"// count unique vulnerabilities| summarize {`With internet exposure`=countDistinctExact(vulnerability.display_id)}
Query result:
Get the total number of affected entities in your environment.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// count unique entities| summarize {`Affected entities`=countDistinctExact(affected_entity.id)}
Query result:
Get the total number of affected process groups in your environment.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities detected in running processes| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"AND affected_entity.type=="PROCESS_GROUP"// count unique entities| summarize {`Affected process groups`=countDistinctExact(affected_entity.id)}
Query result:
Get the total number of affected, non-muted entities over time (in three-hour buckets).
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for open non-muted vulnerabilitiesAND vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// count unique entities for each timestamp bucket of 3h| sort timestamp desc| summarize {entities=countDistinctExact(affected_entity.id)}, by: {timestamp=bin(timestamp, 3h)}
Query result:
Get the total number of hosts that are indirectly affected by open vulnerabilities in your environment.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities|filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// count hosts| summarize {`Related hosts`=arraySize(collectDistinct(related_entities.hosts.ids, expand:true))}
Query result:
Get a count of open vulnerabilities split by risk levels.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// summarize score per vulnerability| summarize {vulnerability.risk.score=takeMax(vulnerability.risk.score)}, by: {vulnerability.display_id}// map the risk level| fieldsAdd vulnerability.risk.level=if(vulnerability.risk.score>=9,"CRITICAL",else:if(vulnerability.risk.score>=7,"HIGH",else:if(vulnerability.risk.score>=4,"MEDIUM",else:if(vulnerability.risk.score>=0.1,"LOW",else:"NONE"))))// count vulnerabilities per risk level| summarize { Vulnerabilities=count(), maxScore=takeMax(vulnerability.risk.score) }, by:{vulnerability.risk.level}| sort maxScore, direction:"descending"
Query result:
Get a count of open vulnerabilities split by type.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// count vulnerabilities per type| summarize { Vulnerabilities=countDistinctExact(vulnerability.display_id) }, by:{vulnerability.type}| sort Vulnerabilities, direction:"descending"| limit 10
Query result:
Get the open vulnerability count over time, in three-hour buckets.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for open non-muted vulnerabilitiesAND vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"| sort timestamp desc| summarize {Open=countDistinctExact(vulnerability.display_id)}, by: {timestamp=bin(timestamp,3h)}
Query result:
Get the open vulnerabilities on a specific library (in this example, log4j
).
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// filter by the vulnerable library/component nameAND contains(affected_entity.vulnerable_component.name,"log4j",caseSensitive:false)// now summarize on the vulnerability level| summarize{vulnerability.risk.score=round(takeMax(vulnerability.risk.score),decimals:1),vulnerability.title=takeFirst(vulnerability.title),vulnerability.references.cve=takeFirst(vulnerability.references.cve),last_detected=coalesce(takeMax(vulnerability.resolution.change_date),takeMax(vulnerability.parent.first_seen)),affected_entities=countDistinctExact(affected_entity.id),vulnerable_function_in_use=if(in("IN_USE",collectArray(vulnerability.davis_assessment.vulnerable_function_status)),true, else:false),public_internet_exposure=if(in("PUBLIC_NETWORK",collectArray(vulnerability.davis_assessment.exposure_status)),true,else:false),public_exploit_available=if(in("AVAILABLE",collectArray(vulnerability.davis_assessment.exploit_status)),true,else:false),data_assets_within_reach=if(in("REACHABLE",collectArray(vulnerability.davis_assessment.data_assets_status)),true,else:false)}, by: {vulnerability.display_id}// map the risk level| fieldsAdd vulnerability.risk.level=if(vulnerability.risk.score>=9,"CRITICAL",else:if(vulnerability.risk.score>=7,"HIGH",else:if(vulnerability.risk.score>=4,"MEDIUM",else:if(vulnerability.risk.score>=0.1,"LOW",else:"NONE"))))| sort {vulnerability.risk.score, direction:"descending"}, {affected_entities, direction:"descending"}
Query result:
Get the open vulnerabilities directly or indirectly affecting a specific host (in this example, i-05f1305a50721e04d
).
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// filter by the host name of the related/affected hostAND in("easytravel-demo2",related_entities.hosts.names) OR affected_entity.name=="easytravel-demo2"// now summarize on the vulnerability level| summarize{vulnerability.risk.score=round(takeMax(vulnerability.risk.score),decimals:1),vulnerability.title=takeFirst(vulnerability.title),vulnerability.references.cve=takeFirst(vulnerability.references.cve),last_detected=coalesce(takeMax(vulnerability.resolution.change_date),takeMax(vulnerability.parent.first_seen)),affected_entities=countDistinctExact(affected_entity.id),vulnerable_function_in_use=if(in("IN_USE",collectArray(vulnerability.davis_assessment.vulnerable_function_status)),true, else:false),public_internet_exposure=if(in("PUBLIC_NETWORK",collectArray(vulnerability.davis_assessment.exposure_status)),true,else:false),public_exploit_available=if(in("AVAILABLE",collectArray(vulnerability.davis_assessment.exploit_status)),true,else:false),data_assets_within_reach=if(in("REACHABLE",collectArray(vulnerability.davis_assessment.data_assets_status)),true,else:false)}, by: {vulnerability.display_id}// map the risk level| fieldsAdd vulnerability.risk.level=if(vulnerability.risk.score>=9,"CRITICAL",else:if(vulnerability.risk.score>=7,"HIGH",else:if(vulnerability.risk.score>=4,"MEDIUM",else:if(vulnerability.risk.score>=0.1,"LOW",else:"NONE"))))| sort {vulnerability.risk.score, direction:"descending"}, {affected_entities, direction:"descending"}
Query result:
Get the open vulnerabilities affecting a specific application (in this example, www.easytravel.com
).
Query example:
| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// filter by name of the related applicationsAND in("www.easytravel.com",related_entities.applications.names)// now summarize on the vulnerability level| summarize{vulnerability.risk.score=round(takeMax(vulnerability.risk.score),decimals:1),vulnerability.title=takeFirst(vulnerability.title),vulnerability.references.cve=takeFirst(vulnerability.references.cve),last_detected=coalesce(takeMax(vulnerability.resolution.change_date),takeMax(vulnerability.parent.first_seen)),affected_entities=countDistinctExact(affected_entity.id),vulnerable_function_in_use=if(in("IN_USE",collectArray(vulnerability.davis_assessment.vulnerable_function_status)),true, else:false),public_internet_exposure=if(in("PUBLIC_NETWORK",collectArray(vulnerability.davis_assessment.exposure_status)),true,else:false),public_exploit_available=if(in("AVAILABLE",collectArray(vulnerability.davis_assessment.exploit_status)),true,else:false),data_assets_within_reach=if(in("REACHABLE",collectArray(vulnerability.davis_assessment.data_assets_status)),true,else:false)}, by: {vulnerability.display_id}// map the risk level| fieldsAdd vulnerability.risk.level=if(vulnerability.risk.score>=9,"CRITICAL",else:if(vulnerability.risk.score>=7,"HIGH",else:if(vulnerability.risk.score>=4,"MEDIUM",else:if(vulnerability.risk.score>=0.1,"LOW",else:"NONE"))))| sort {vulnerability.risk.score, direction:"descending"}, {affected_entities, direction:"descending"}
Query result:
Get the top 10 affected entities by the number of open vulnerabilities.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"| summarize {`Affected entity name` = takeFirst(affected_entity.name),Type = takeFirst(affected_entity.type),Vulnerabilities = countDistinctExact(vulnerability.display_id)}, by: {dt.source_entity=affected_entity.id}| sort {Vulnerabilities, direction:"descending"}| limit 10
Query result:
Get the top five process groups by the count of open vulnerabilities, with their respective owners.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"AND affected_entity.type=="PROCESS_GROUP"// summarize per process group| summarize {`Affected entity name` = takeFirst(affected_entity.name),Type = takeFirst(affected_entity.type),Vulnerabilities = countDistinctExact(vulnerability.display_id)}, by: {dt.source_entity=affected_entity.id}| sort {Vulnerabilities, direction:"descending"}| limit 10// add ownership information| lookup [fetch dt.entity.process_group| parse toString(tags), "LD ('owner:'|'owner\\\\:') (SPACE)? LD:Team ('\"')"| fields id, Team=coalesce(Team, "-")], sourceField:dt.source_entity, lookupField:id, fields:{Team}| sort Vulnerabilities, direction:"descending"
Query result:
Get the hosts that are indirectly related to open vulnerabilities on a specific library (in this example, tomcat
), with their respective owners.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"AND related_entities.hosts.count > 0// filter by the vulnerable component nameAND contains(affected_entity.vulnerable_component.name,"tomcat")| expand entity_id=related_entities.hosts.ids| summarize Vulnerabilities=countDistinctExact(vulnerability.display_id), by: {entity_id}//add ownership information| lookup [fetch dt.entity.host| parse toString(tags), "LD ('owner:'|'owner\\\\:') (SPACE)? LD:Team ('\"')"| fields id, Host=entity.name, Team=coalesce(Team, "-")], sourceField:entity_id, lookupField:id, fields: {Host,Team}| sort Vulnerabilities, direction:"descending"
Query result:
Get the vulnerable components of a specific host (in this example, HOST-4CF0F659B8823D74
) with owners.
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// filter by ID of the related or affected hostAND in("HOST-DBF63A01C27E4B50",related_entities.hosts.ids) or affected_entity.id=="HOST-DBF63A01C27E4B50"| summarize{entities=countDistinctExact(affected_entity.id),vulnerable_functions=arraySize(collectDistinct(affected_entity.vulnerable_functions, expand:true)),vulnerable_component.name=takeAny(affected_entity.vulnerable_component.name)}, by: {dt.entity.software_component=affected_entity.vulnerable_component.id}| filterOut isNull(dt.entity.software_component)// add component information| lookup [fetch dt.entity.software_component| fieldsAdd softwareComponentFileName], sourceField:dt.entity.software_component, lookupField:id, fields:{softwareComponentFileName}| fields dt.entity.software_component, vulnerable_component.name, softwareComponentFileName, entities, vulnerable_functions| sort {entities, direction:"descending"}, {vulnerable_functions, direction:"descending"}
Query result:
Get the vulnerable functions of a specific software component (in this example, SOFTWARE_COMPONENT-1D466FB7ADEBF92E
).
Query example:
fetch security.events| filter dt.system.bucket=="default_securityevents_builtin"AND event.provider=="Dynatrace"AND event.type=="VULNERABILITY_STATE_REPORT_EVENT"AND event.level=="ENTITY"// filter for the latest snapshot per entity| dedup {vulnerability.display_id, affected_entity.id}, sort:{timestamp desc}// filter for open non-muted vulnerabilities| filter vulnerability.resolution.status == "OPEN"AND vulnerability.parent.mute.status != "MUTED"AND vulnerability.mute.status != "MUTED"// filter for the software component IDAND affected_entity.vulnerable_component.id=="SOFTWARE_COMPONENT-1D466FB7ADEBF92E"| expand vulnerable_function=affected_entity.vulnerable_functions| filter isNotNull(vulnerable_function)| summarize{Usages=countIf(in(vulnerable_function,affected_entity.vulnerable_functions))}, by: {vulnerable_function}| sort {Usages, direction:"descending"}
Query result:
Get the total number of critical vulnerability findings ingested into Dynatrace.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents"AND event.type == "VULNERABILITY_FINDING"AND isNotNull(component.name)// latest findings per affected object, vulnerability and component| dedup {object.id, vulnerability.id, component.name, component.version}, sort: {timestamp desc}// aggregation and custom filtering| filter dt.security.risk.level=="CRITICAL"| summarize {Vulnerabilities=countDistinctExact(vulnerability.id)}
Query result:
Get the total number of container images containing vulnerability findings ingested into Dynatrace.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents"AND event.type == "VULNERABILITY_FINDING"AND isNotNull(component.name)// latest findings per affected object, vulnerability and component| dedup {object.id, vulnerability.id, component.name, component.version,container_image.registry, container_image.repository, container_image.tags}, sort: {timestamp desc}// aggregation and custom filtering| summarize {containerImages=countDistinctExact(container_image.digest)}
Query result:
Get the total number of vulnerable components in the container images containing vulnerability findings ingested into Dynatrace.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents"AND event.type == "VULNERABILITY_FINDING"AND isNotNull(component.name)// latest findings per affected object, vulnerability and component| dedup {object.id, vulnerability.id, component.name, component.version}, sort: {timestamp desc}// aggregation and custom filtering| summarize {components=countDistinctExact(component.name)}
Query result:
Get the most recent vulnerability findings ingested into Dynatrace.
Query example:
fetch security.events// data access| filter dt.system.bucket == "default_securityevents"AND event.type == "VULNERABILITY_FINDING"AND isNotNull(component.name)// latest findings per affected object, vulnerability and component| dedup {object.id, vulnerability.id, component.name, component.version}, sort: {timestamp desc}| sort timestamp desc
Query result:
Get the total number of ingested container images that have been scanned.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents"| filter object.type == "CONTAINER_IMAGE" // includes both SCAN_EVENTS and VULNERABILITY_FINDINGS without scan events| dedup {container_image.digest}, sort: {timestamp desc}| summarize {containerImages=count()}
Query result:
Get the total number of scan events from ingested container images.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents"| filter event.type == "VULNERABILITY_SCAN"AND object.type == "CONTAINER_IMAGE"| summarize {scanEvents=count()}
Query result:
Get the latest compliance results of supported standards for all systems covered by Security Posture Management.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents_builtin"AND event.type == "COMPLIANCE_SCAN_COMPLETED"// filter for the latest assessment| dedup {object.name}, sort:{timestamp desc}// parse the compliance percentage from json| parse `scan.result.summary_json`, """JSON{JSON_ARRAY{JSON{ STRING:standardCode, INT:compliancePercentage }}:standardResultSummaries}(flat=true)"""| expand standardResultSummaries| fieldsFlatten standardResultSummaries| fields timestamp, object.name, standard = standardResultSummaries.standardCode, compliance = standardResultSummaries.compliancePercentage
Query result:
Get the historical compliance results for a standard (in this case, DORA) for all systems covered by Security Posture Management.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents_builtin"AND event.type == "COMPLIANCE_SCAN_COMPLETED"// parse the compliance percentage from json| parse `scan.result.summary_json`, """JSON{JSON_ARRAY{JSON{ STRING:standardCode, INT:compliancePercentage }}:standardResultSummaries}(flat=true)"""| expand standardResultSummaries| fieldsFlatten standardResultSummaries// filter for the specific standard| filter standardResultSummaries.standardCode == "DORA"| fields timestamp, object.name, standardResultSummaries.compliancePercentage
Query result:
Get the latest analysis results for a given system (in this case, dt-cluster-01
) in a selected timeframe.
This results in a view similar to that displayed in the Security Posture Management app on the Assessment results page.
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents_builtin"AND event.type == "COMPLIANCE_FINDING"// filter for the latest rule assessment results in the timeframe| join [fetch security.events| filter dt.system.bucket == "default_securityevents_builtin"AND event.type == "COMPLIANCE_SCAN_COMPLETED"// filter for desired systemAND object.name == "dt-cluster-01"| sort timestamp desc| fields scan.id| limit 1], on: {scan.id}// summarize findings on rule level| summarize {compliance.rule.severity.level = takeFirst(compliance.rule.severity.level),compliance.standard.short_name = takeFirst(compliance.standard.short_name),compliance.rule.title = takeFirst(compliance.rule.title),compliance.standard.url = takeFirst(compliance.standard.url),finding.time.created = takeFirst(finding.time.created),compliance.result.count.passed = countIf(compliance.result.status.level == "PASSED"),compliance.result.count.failed = countIf(compliance.result.status.level == "FAILED"),compliance.result.count.manual = countIf(compliance.result.status.level == "MANUAL"),compliance.result.count.not_relevant = countIf(compliance.result.status.level == "NOT_RELEVANT"),compliance.rule.metadata_json = takeFirst(compliance.rule.metadata_json)},by: { compliance.rule.id }// add rule level status| fieldsAdd compliance.result.status.level =if(compliance.result.count.failed > 0, "FAILED",else: if(compliance.result.count.manual > 0, "MANUAL",else: if(compliance.result.count.passed > 0, "PASSED",else: "NOT_RELEVANT")))
Query result:
Get the counts for every assessment that happened in a selected period for a selected rule and system (in this case, dt-cluster-01
).
Query example:
fetch security.events| filter dt.system.bucket == "default_securityevents_builtin"AND event.type == "COMPLIANCE_FINDING"AND k8s.cluster.name == "dt-cluster-01"// filter for the specific ruleAND compliance.rule.id == "DORA-67950"// summarize findings on rule level| summarize {timestamp = takeFirst(timestamp),Passed=countIf(compliance.result.status.level == "PASSED"),Failed=countIf(compliance.result.status.level == "FAILED"),Manual=countIf(compliance.result.status.level == "MANUAL")}, by: {scan.id}| makeTimeseries avg(Passed), avg(Failed), avg(Manual)
Query result: