Since this is my first blog of 2022, I would like to wish you a prosperous New Year.
As you might recall, I published a blog on Risk Meter Reports using Python in November 2021. That blog discussed two Risk Meter or Asset Group reports, “Historical Open Vulnerability Counts by Risk Level” and “Risk Accepted Over Time.” In this blog, I will be discussing two reports, “Historical Open Vulnerability Counts by Risk Level” and “Total Vulnerabilities Past Due by Risk Level,” but this time I’ll be using PowerShell.
The report compares high-risk, past-due vulnerability counts with the total vulnerability counts in a historical fashion. This will allow you to see how you’re keeping up with your vulnerability due dates (SLA) over time as compared to the total number of vulnerabilities. The report is by month from the start date.
Note: A risk meter score is the vulnerability score of an asset group. The terms risk meter and asset group are used interchangeably.
I haven’t coded PowerShell in about five years, so I’m a little rusty. Also, I coded this on a Mac without .NET. I used
Export-CSV instead of using a COM module interface to Excel. Hopefully, next time when I have a Windows box to work on. Let’s get started. The code is in
ShowHistoricalVulnCounts, has two mandatory command line input parameters: start date and the output CSV file.
csvFileName cannot be obtained from the pipeline.
Using the API Key Token
The Kenna API key token is picked up from the environment variable
$KENNA_API_KEY. Then the API key is stored in the HTTP header.
Line 219 obtains the API key and it is stored in line 230.
How to Invoke an API in PowerShell
Some of you readers might already know how to invoke APIs in PowerShell; but for those who don’t, I used the cmdlet
Invoke-RestMethod. Now I know that our API documentation uses
Invoke-WebRequest, but I used
Invoke-RestMethod because it efficiently deals with JSON content.
Invoke-WebRequest is better for HTML content. The reference section contains discussion links. Let’s look at the code for
As you can see, this function is similar to the Python one. On line 111, the List Asset Group API URL is created. The API is invoked on line 113 in a
Try-Catch block. This
Catch block is an amalgamation of
Catch blocks from past code. The list of risk meters is returned in line 125.
All the other APIs are invoked in a similar fashion. There is a function,
Invoke-Risk-Meter-Reportthat invokes historical risk meter report APIs with the report name and start date. It is called by
Processing Each Risk Meter
After all the risk meters are obtained, each risk meter is processed by obtaining the historical vulnerability counts and the historical past-due vulnerability counts. The Risk Meter Reports require an asset group ID and the start date from the command line.
Next, we pull out the vulnerability counts in lines 261 and 261.
Here is a snippet of the response so the code is more understandable.
In lines 266-270, the code extracts the high-risk score total vulnerability counts for the first day of each month from the start date. Lines 273-278 do the same for past-due vulnerability counts. An ordered hash is used to keep the CSV columns organized for a consistent display. Hashes can be easily exported to a CSV file via
The next step for each risk meter is to build a CSV row and write it to the CSV file. This is done in lines 282-289.
A risk meter row consists of the risk meter’s name, ID, score, asset count, and last updated date. The data rows consist of the vulnerability title and the monthly data. There is one data row for past due vulnerabilities and another for total vulnerabilities.
Export-Csv to work properly, each row has to have the same columns. This is done with an ordered hash. The hash keys are the columns for the CSV. Both
New-Data-Row contain all the same hash keys and are based on
New-Blank-Row. By the time I realized a row class would be useful, it was too close to the blog deadline. If you take the time to peruse the row code, you will see that
New-Blank-Row creates the order hash and initializes the non-date keys to
New-Blank-Row, sets the non-date keys to the asset group values, and creates the date keys with
"" values. On the other hand,
New-Blank-Row, sets the “Vuln Type” column, and creates date keys with values. Depending on the “Vuln Type, past due or total vulnerability counts, the date data is set with the appropriate high-risk vulnerability counts.
Here is a snippet of the report.
It looks like the admin has not been attending to the vulnerabilities since November 2021. You can tell this because the past vulnerability count is the same as the total vulnerability count. Remember that these vulnerability counts are for the high-risk vulnerabilities, and you want the past due counts to be zero. It always looks good to your management when you meet your SLAs.
Until next time,
- StackExchange: What is the difference between Invoke-WebRequest and Invoke-RestMethod?
- TheCodeBuzz: Differences Invoke-WebRequest Vs Invoke-RestMethod
- TrueSec: Invoke-WebRequest or InvokeRestMethod
- Kenna Help: How do I automatically Set Due Date (SLA) values for my vulnerabilities?
- Kenna Help: Risk Meters for Maintenance and Administration
- Kenna API Documentation: Welcome!