Skip to content

Commit

Permalink
improve trivy operator slack template (#597)
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvdp authored Aug 28, 2023
1 parent 4682136 commit 7e9a0fe
Showing 1 changed file with 142 additions and 18 deletions.
160 changes: 142 additions & 18 deletions rego-templates/trivy-operator-slack.rego
Original file line number Diff line number Diff line change
@@ -1,20 +1,144 @@
package postee.trivyoperator.slack

title:=sprintf("Trivy Operator %s Report for - %s", [input.kind, input.metadata.name])

result:= res {
res:= [
{ "type":"section",
"text": {"type":"mrkdwn","text": sprintf("*CRITICAL:* %d", [input.report.summary.criticalCount])}},
{ "type":"section",
"text": {"type":"mrkdwn","text": sprintf("*HIGH:* %d", [input.report.summary.highCount])}},
{ "type":"section",
"text": {"type":"mrkdwn","text": sprintf("*MEDIUM:* %d", [input.report.summary.mediumCount])}},
{ "type":"section",
"text": {"type":"mrkdwn","text": sprintf("*LOW:* %d", [input.report.summary.lowCount])}},
{ "type":"section",
"text": {"type":"mrkdwn","text": sprintf("*UNKNOWN:* %d", [input.report.summary.unknownCount])}},
{ "type":"section",
"text": {"type":"mrkdwn","text": sprintf("*NONE:* %d", [input.report.summary.noneCount])}},
]
}
import data.postee.flat_array #converts [[{...},{...}], [{...},{...}]] to [{...},{...},{...},{...}]
import data.postee.with_default

############################################# Common functions ############################################

# render_sections split collection of cells provided to chunks of 5 rows each and wraps every chunk with section element
render_sections(rows, caption, headers) = result {
count(rows) > 0 # only if some vulnerabilities are found
rows_and_header := array.concat(headers, rows)
a := flat_array([s |
# code below converts 2 dimension array like [[row1, row2, ... row5], ....]
group_size := 10 #it's 5 but every row is represented by 2 items
num_chunks := ceil(count(rows_and_header) / group_size) - 1
indices := {b | b := numbers.range(0, num_chunks)[_] * group_size}
some k
fields := [array.slice(rows_and_header, i, i + group_size) | i := indices[_]][k]
# builds markdown section based on slice

s := with_caption(fields, caption, k)
])
result := array.concat(a, [{"type": "divider"}])
}

render_sections(rows, caption, headers) = [] { #do not render section if provided collection is empty
count(rows) == 0
}

with_caption(fields, caption, position) = s {
position == 0
s := [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": caption,
},
},
{
"type": "section",
"fields": fields,
},
]
}
with_caption(fields, caption, position) = s {
position > 0
s := [
{
"type": "section",
"fields": fields,
},
]
}


###########################################################################################################

vln_list(severity) = l {
# builds list of rows for section for the given severity
some i
vlnrb := [r |
item := input.report.vulnerabilities[i]
vlnname := item.vulnerabilityID

fxvrsn := with_default(item, "fixedVersion", "none")
resource_name = with_default(item, "resource", "none")
resource_version = with_default(item, "installedVersion", "none")
url = with_default(item, "primaryLink","")
item.severity == severity # only items with severity matched

r := [
{"type": "mrkdwn", "text": sprintf("<%s|%s>",[url,vlnname])},
{"type": "mrkdwn", "text": concat(" / ", [resource_name, resource_version, fxvrsn])},
]
]

caption := sprintf("*%s severity vulnerabilities*", [severity]) #TODO make first char uppercase

headers := [
{"type": "mrkdwn", "text": "*Vulnerability ID*"},
{"type": "mrkdwn", "text": "*Resource / Version / Fixed version*"},
]

# split rows and wrap slices with markdown section
l := render_sections(flat_array(vlnrb), caption, headers)
}

image_name := sprintf("%s:%s", [
with_default(input.report.artifact,"repository","unknown"),
with_default(input.report.artifact,"tag","unknown")
])
###########################################################################################################
postee := with_default(input, "postee", {})

title = sprintf("Vulnerability scan report %s", [image_name]) # title is

result = res {

header := [
{
"type": "header",
"text": {
"type": "plain_text",
"text": sprintf("Vulnerability issue with image:%s in namespace %s",[image_name, with_default(input.metadata,"namespace","unknown")]),
},
}
]

summary := [
{
"type": "divider"
},
{
"type": "context",
"elements": [
{"type": "mrkdwn", "text": "*Summary totals:*"},
],
},
{
"type": "context",
"elements": [
{"type": "mrkdwn", "text": sprintf("Critical: *%d*", [input.report.summary.criticalCount])},
{"type": "mrkdwn", "text": sprintf("High: *%d*", [input.report.summary.highCount])},
{"type": "mrkdwn", "text": sprintf("Medium: *%d*", [input.report.summary.mediumCount])},
{"type": "mrkdwn", "text": sprintf("Low: *%d*", [input.report.summary.lowCount])},
{"type": "mrkdwn", "text": sprintf("Unknown: *%d*", [input.report.summary.unknownCount])},
],
},
{
"type": "divider"
}
]

res := flat_array([
header,
summary,
vln_list("CRITICAL"),
vln_list("HIGH"),
vln_list("MEDIUM"),
vln_list("LOW"),
vln_list("UNKNOWN")
])
}

0 comments on commit 7e9a0fe

Please sign in to comment.