Latest Dynatrace
Dynatrace allows you to accomplish various analysis and reporting tasks on top of the security data on Grail, helping you to maintain consistent and efficient communication within DevSecOps teams and their stakeholders. Leveraging native apps, such as Dashboards and Notebooks, you can visualize data and find answers to security-related questions.
To explore security data, you have the following options:
Built-in security query snippets
A snippet is an individual query based on a simple use case (for example, Chart open vulnerabilities by risk level over time
).
A template is a set of multiple queries based on a broad use-case scenario (for example, Threat exposure
), and is integrated into Dynatrace Application Security apps such as Third-Party Vulnerabilities, so you can remain in the context of the analysis flow.
For details on each of these options, see below.
To run security data analysis and reporting, you need to assign the following policies to the Security admin group:
Storage Security Events Read (allows querying of security data on Grail)
Alternatively, you can assign the Storage All Grail Data Read policy (includes access to the security data).
Storage All System Data Read (allows you to fully benefit from the out-of-the-box security templates, by enriching data with additional information for the Dynatrace-monitored entities, such as dt.entity.process_group
)
The built-in security snippet queries on Dashboards and Notebooks help you to
To use the snippets
Some examples of tasks that you can accomplish are listed below.
Using Open with… with snippets doesn't include the aggregation to return the same amount of data as on the source Third-party vulnerabilities list page. To aggregate data, manually run the summarize
DQL command.
Shows number of vulnerabilities by status (OPEN
, RESOLVED
, MUTED
).
Query:
fetch events| filter event.provider == "Dynatrace" // events generated by Dynatrace| filter event.type == "VULNERABILITY_STATE_REPORT_EVENT" // historical vulnerability data| filter event.level == "VULNERABILITY" // aggregation on the vulnerability level// filter only the latest snapshot data| sort timestamp, direction:"descending"| summarize event.status = takeFirst(event.status), by:{vulnerability.display_id}//end of filtering for the latest snapshot| summarize count(), by:{event.status} // event.status represents the combined status of vulnerability resolution and muting
Query result:
Shows an over-time chart with the number of open vulnerabilities split by severity. Muted vulnerabilities are counted separately.
Query:
fetch events| filter event.provider == "Dynatrace" // events generated by Dynatrace| filter event.type == "VULNERABILITY_STATE_REPORT_EVENT" // historical vulnerability data| filter event.level == "VULNERABILITY" // aggregation on the vulnerability level// first get the snapshots of each hour per vulnerability| sort timestamp, direction:"descending"| summarize {vulnerability.davis_assessment.level = takeFirst(vulnerability.davis_assessment.level),vulnerability.mute.status = takeFirst(vulnerability.mute.status),vulnerability.resolution.status=takeFirst(vulnerability.resolution.status)}, by:{vulnerability.display_id, timestamp = bin(timestamp,1h)}| filter vulnerability.resolution.status == "OPEN" // filter for open vulnerabilities only// aggregate per each timestamp| summarize {Critical = countIf((vulnerability.davis_assessment.level) == "CRITICAL" AND (vulnerability.mute.status) == "NOT_MUTED"),High = countIf((vulnerability.davis_assessment.level) == "HIGH" AND (vulnerability.mute.status) == "NOT_MUTED"),Medium = countIf((vulnerability.davis_assessment.level) == "MEDIUM" AND (vulnerability.mute.status) == "NOT_MUTED"),Low = countIf((vulnerability.davis_assessment.level) == "LOW" AND (vulnerability.mute.status) == "NOT_MUTED"),Muted = countIf((vulnerability.mute.status) == "MUTED") }, by:{timestamp}| sort timestamp, direction:"descending"
Query result:
Lists currently open non-muted vulnerabilities with basic information such as risk assessment.
Query:
fetch events| filter event.provider=="Dynatrace"| filter event.type=="VULNERABILITY_STATE_REPORT_EVENT"| filter event.level=="VULNERABILITY"// filter only the latest snapshot data| sort timestamp, direction:"descending"| summarize{vulnerability.resolution.status=takeFirst(vulnerability.resolution.status),vulnerability.resolution.change_date=takeFirst(vulnerability.resolution.change_date),vulnerability.mute.status=takeFirst(vulnerability.mute.status),vulnerability.davis_assessment.score=takeFirst(vulnerability.davis_assessment.score),vulnerability.davis_assessment.level=takeFirst(vulnerability.davis_assessment.level),vulnerability.title=takeFirst(vulnerability.title),vulnerability.external_id=takeFirst(vulnerability.external_id),vulnerability.references.cve=takeFirst(vulnerability.references.cve),timestamp=takeFirst(timestamp)},by: {vulnerability.display_id}//end of filtering for the latest snapshot| filter vulnerability.resolution.status=="OPEN" AND vulnerability.mute.status!="MUTED" // filter for open non-muted vulnerabilities| sort vulnerability.davis_assessment.score, direction:"descending"| fieldsvulnerability.display_id,Title=vulnerability.title,`Davis Security Score`=concat(vulnerability.davis_assessment.level," (",round(vulnerability.davis_assessment.score,decimals:1),")"),Status=vulnerability.resolution.status,`Status date`=formatTimestamp(toTimestamp(vulnerability.resolution.change_date), format:"MMM dd, HH:mm:ss"),`CVE list`=substring(toString(vulnerability.references.cve), from:1, to:-1),`External id`=vulnerability.external_id
Query result:
Lists top five affected entities sorted by the count of open vulnerabilities, with essential information such as internet exposure.
Query:
fetch events| filter event.provider=="Dynatrace"| filter event.type=="VULNERABILITY_STATE_REPORT_EVENT"| filter event.level=="ENTITY"// fetch the latest snapshot| sort timestamp, direction:"descending"| summarize{affected_entity.type=takeFirst(affected_entity.type),affected_entity.name=takeFirst(affected_entity.name),vulnerability.davis_assessment.exposure_status=takeFirst(vulnerability.davis_assessment.exposure_status),dt.entity.process_group=takeFirst(dt.entity.process_group),dt.entity.host=takeFirst(dt.entity.host),dt.entity.kubernetes_node=takeFirst(dt.entity.kubernetes_node)}, by: {affected_entity.id, vulnerability.display_id}// end of latest snapshot fetch// summarize per affected entity| summarize {`Affected entity name`=takeFirst(affected_entity.name),Type=takeFirst(affected_entity.type),`Vulnerabilities`=countDistinct(vulnerability.display_id),`Exposure status`=takeFirst(vulnerability.davis_assessment.exposure_status),dt.entity.process_group=takeFirst(dt.entity.process_group),dt.entity.host=takeFirst(dt.entity.host),dt.entity.kubernetes_node=takeFirst(dt.entity.kubernetes_node)},by: {affected_entity.id}| fieldsRemove affected_entity.id| sort {`Vulnerabilities`,direction:"descending"}, `Exposure status`| fieldsdt.source_entity=if(isNotNull(dt.entity.process_group),dt.entity.process_group, else:if(isNotNull(dt.entity.host),dt.entity.host,else:dt.entity.kubernetes_node)),`Affected entity name`,Type,`Vulnerabilities`,`Exposure status`| limit 5 // limit to the top 5 affected entities
Query result:
Shows the count of status change events of vulnerabilities over time, grouped in one-hour buckets.
Query:
fetch events| filter event.provider == "Dynatrace" // events generated by Dynatrace| filter event.type == "VULNERABILITY_STATUS_CHANGE_EVENT" // vulnerability status change events| filter event.level == "VULNERABILITY" // vulnerability level aggregation| summarize {Open = countIf(event.status == "OPEN"),Resolved = countIf(event.status == "RESOLVED"),Muted = countIf(event.status == "MUTED")}, by:{timestamp = bin(timestamp, 1h)}| sort timestamp, direction:"descending"
Query result:
With integrated reporting, Dynatrace helps you to quickly start from fully customizable templates that already include the most interesting insights and allows you to fine-tune them for the specific needs of your organization and share the results with shareholders.
Our out-of-the-box dashboard and notebook templates make it easy to complete various security reporting use cases, some of which are listed below.
With Threat exposure template for Dashboards, you're provided with immediate answers to the vulnerability exposure risk question and an overview of the exploitation risk and potential impact on your environment.
When generating the reports from templates, the filters and the context of the environment persist automatically in the generated dashboards.
Sample template:
For details about the mechanism used to calculate the exploitation risk, see FAQ: What is Exploitation Risk Score?.
To start generating Dashboard reports
When generating the reports from templates, the filters and the context of the environment persist automatically in the generated dashboards.
With Threat exposure template for Notebooks, you're provided with an additional level of detail, including the exact areas at risk due to the vulnerability threat, as well as the responsible teams, which allows you to prepare an efficient remediation plan.
When generating the reports from templates, the filters and the context of the environment persist automatically in the generated notebooks.
Sample template:
To start generating Notebook reports
When you run DQL queries for a specific entity, the vulnerable functions in use by all entities are reported, instead of those in use only by the specific entity.
For Entity change events, filtering by closed events (event.status_transition == "CLOSE"
) doesn't return information about the vulnerable component of an affected entity if the resolved entity is the last affected entity of a vulnerability.