update templates

This commit is contained in:
jgsqware 2016-05-18 08:41:03 +02:00
parent d78cb4356d
commit b3d7eb7060
6 changed files with 648 additions and 502 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
**/.vscode **/.vscode
/cmd/clairctl/reports

View File

@ -20,26 +20,33 @@ var Report ReportConfig
//VulnerabiliesCounts Total count of vulnerabilities //VulnerabiliesCounts Total count of vulnerabilities
type VulnerabiliesCounts struct { type VulnerabiliesCounts struct {
Total int Total int
High int Unknown, Negligible, Low, Medium, High, Critical, Defcon1 int
Medium int
Low int
Negligible int
} }
//RelativeCount get the percentage of vulnerabilities of a severity //RelativeCount get the percentage of vulnerabilities of a severity
func (vulnerabilityCount VulnerabiliesCounts) RelativeCount(severity string) float64 { func (vulnerabilityCount VulnerabiliesCounts) RelativeCount(severity string) float64 {
var count int var count int
switch severity { switch strings.TrimSpace(severity) {
case "Defcon1":
count = vulnerabilityCount.Defcon1
case "Critical":
count = vulnerabilityCount.Critical
case "High": case "High":
count = vulnerabilityCount.High count = vulnerabilityCount.High
case "Medium": case "Medium":
count = vulnerabilityCount.Medium count = vulnerabilityCount.Medium
case "Low": case "Low":
count = vulnerabilityCount.Low count = vulnerabilityCount.Low
case "Negligible":
count = vulnerabilityCount.Negligible
case "Unknown":
count = vulnerabilityCount.Unknown
} }
return math.Ceil(float64(count)/float64(vulnerabilityCount.Total)*100*100) / 100 result := float64(count) / float64(vulnerabilityCount.Total) * 100
return math.Ceil(result*100) / 100
} }
//ImageAnalysis Full image analysis //ImageAnalysis Full image analysis
@ -71,16 +78,26 @@ func (imageAnalysis ImageAnalysis) CountVulnerabilities(l v1.Layer) int {
func (imageAnalysis ImageAnalysis) CountAllVulnerabilities() VulnerabiliesCounts { func (imageAnalysis ImageAnalysis) CountAllVulnerabilities() VulnerabiliesCounts {
var result VulnerabiliesCounts var result VulnerabiliesCounts
result.Total = 0 result.Total = 0
result.Defcon1 = 0
result.Critical = 0
result.High = 0 result.High = 0
result.Medium = 0 result.Medium = 0
result.Low = 0 result.Low = 0
result.Negligible = 0 result.Negligible = 0
result.Unknown = 0
l := imageAnalysis.Layers[len(imageAnalysis.Layers)-1]
for _, l := range imageAnalysis.Layers {
for _, f := range l.Layer.Features { for _, f := range l.Layer.Features {
result.Total += len(f.Vulnerabilities) result.Total += len(f.Vulnerabilities)
for _, v := range f.Vulnerabilities { for _, v := range f.Vulnerabilities {
switch v.Severity { switch v.Severity {
case "Defcon1":
result.Defcon1++
case "Critical":
result.Critical++
case "High": case "High":
result.High++ result.High++
case "Medium": case "Medium":
@ -89,7 +106,8 @@ func (imageAnalysis ImageAnalysis) CountAllVulnerabilities() VulnerabiliesCounts
result.Low++ result.Low++
case "Negligible": case "Negligible":
result.Negligible++ result.Negligible++
} case "Unknown":
result.Unknown++
} }
} }
} }
@ -107,13 +125,19 @@ func (v Vulnerability) Weight() int {
weight := 0 weight := 0
switch v.Severity { switch v.Severity {
case "Defcon1":
weight = 7
case "Critical":
weight = 6
case "High": case "High":
weight = 4 weight = 5
case "Medium": case "Medium":
weight = 3 weight = 4
case "Low": case "Low":
weight = 2 weight = 3
case "Negligible": case "Negligible":
weight = 2
case "Unknown":
weight = 1 weight = 1
} }
@ -193,8 +217,9 @@ func (a FeatureByVulnerabilities) Less(i, j int) bool {
// SortLayers give layers ordered by vulnerability algorithm // SortLayers give layers ordered by vulnerability algorithm
func (imageAnalysis ImageAnalysis) SortLayers() []Layer { func (imageAnalysis ImageAnalysis) SortLayers() []Layer {
layers := []Layer{} layers := []Layer{}
l := imageAnalysis.Layers[len(imageAnalysis.Layers)-1]
for _, l := range imageAnalysis.Layers { // for _, l := range imageAnalysis.Layers {
features := []Feature{} features := []Feature{}
for _, f := range l.Layer.Features { for _, f := range l.Layer.Features {
@ -232,7 +257,7 @@ func (imageAnalysis ImageAnalysis) SortLayers() []Layer {
Features: features, Features: features,
} }
layers = append(layers, nl) layers = append(layers, nl)
} // }
sort.Sort(LayerByVulnerabilities(layers)) sort.Sort(LayerByVulnerabilities(layers))
@ -244,7 +269,9 @@ func (imageAnalysis ImageAnalysis) SortVulnerabilities() []Vulnerability {
vulnerabilities := []Vulnerability{} vulnerabilities := []Vulnerability{}
// there should be a better method, but I don't know how to easlily concert []v1.Vulnerability to [Vulnerability] // there should be a better method, but I don't know how to easlily concert []v1.Vulnerability to [Vulnerability]
for _, l := range imageAnalysis.Layers { l := imageAnalysis.Layers[len(imageAnalysis.Layers)-1]
// for _, l := range imageAnalysis.Layers {
for _, f := range l.Layer.Features { for _, f := range l.Layer.Features {
for _, v := range f.Vulnerabilities { for _, v := range f.Vulnerabilities {
nv := Vulnerability{ nv := Vulnerability{
@ -258,7 +285,7 @@ func (imageAnalysis ImageAnalysis) SortVulnerabilities() []Vulnerability {
vulnerabilities = append(vulnerabilities, nv) vulnerabilities = append(vulnerabilities, nv)
} }
} }
} // }
sort.Sort(VulnerabilitiesBySeverity(vulnerabilities)) sort.Sort(VulnerabilitiesBySeverity(vulnerabilities))

View File

@ -6,6 +6,7 @@ import (
"text/template" "text/template"
) )
//execute go generate ./clair
//go:generate go-bindata -pkg clair -o templates.go templates/... //go:generate go-bindata -pkg clair -o templates.go templates/...
//ReportConfig Reporting configuration //ReportConfig Reporting configuration

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<title>Clair Control report : {{.ImageName}}</title> <title>Clair Control report : {{.ImageName}}</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,600italic,400italic,300italic,300' rel='stylesheet' type='text/css'> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,600italic,400italic,300italic,300' rel='stylesheet' type='text/css'>
@ -14,22 +15,21 @@
background: ghostwhite; background: ghostwhite;
padding-bottom: 2em; padding-bottom: 2em;
} }
/* Typography */ /* Typography */
.lead { .lead {
font-size: 1.4em; font-size: 1.4em;
} }
/* global layout */ /* global layout */
.container { .container {
padding: 0 0; padding: 0 0;
} }
.clearfix:after { .clearfix:after {
content:""; content: "";
display:block; display: block;
clear:both; clear: both;
} }
.row { .row {
@ -64,10 +64,9 @@
border-bottom: solid 1px gainsboro; border-bottom: solid 1px gainsboro;
} }
.panel :last-child { .panel:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
/* Header */ /* Header */
.app-header { .app-header {
@ -101,7 +100,6 @@
.summary { .summary {
line-height: .6em; line-height: .6em;
} }
/* report */ /* report */
.report { .report {
@ -113,8 +111,8 @@
max-width: 960px; max-width: 960px;
margin-top: 30px; margin-top: 30px;
} }
/* Style of the graph */ /* Style of the graph */
.graph .node { .graph .node {
position: relative; position: relative;
display: inline-block; display: inline-block;
@ -122,21 +120,26 @@
width: 24px; width: 24px;
margin: 2px; margin: 2px;
} }
.graph .node .dot { .graph .node .dot {
position: relative; position: relative;
height: 24px; height: 24px;
width: 24px; width: 24px;
border-radius: 24px; border-radius: 24px;
float: left; float: left;
background: gray; background: gray;
/* box-shadow: 0 1px 2px rgba(0, 0, 0, .2); /* box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
border: solid 1px rgba(255, 255, 255, .2); */ border: solid 1px rgba(255, 255, 255, .2); */
} }
.graph .node.Defcon1 .dot {
background: black;
}
.graph .node.Critical .dot {
background: #e81e1e;
}
.graph .node.High .dot { .graph .node.High .dot {
background: #E91E63; background: #E91E63;
} }
@ -149,20 +152,24 @@
background: #8BC34A; background: #8BC34A;
} }
.graph .node.Negligible .dot {
background: #37474F;
}
.graph .node.Unknown .dot {
background: #37474F;
}
.graph .node .popup { .graph .node .popup {
display: none; display: none;
width: 300px; width: 300px;
position: absolute; position: absolute;
bottom: 100%; bottom: 100%;
margin-bottom: 20px; margin-bottom: 20px;
margin-left: -150px; margin-left: -150px;
left: 2px; left: 2px;
background: white; background: white;
box-shadow: 0px 1px 2px rgba(0, 0, 0, .2); box-shadow: 0px 1px 2px rgba(0, 0, 0, .2);
padding: 10px; padding: 10px;
border-radius: 4px; border-radius: 4px;
/* border: solid 1px #e2e2e2; */ /* border: solid 1px #e2e2e2; */
@ -211,8 +218,8 @@
max-height: 180px; max-height: 180px;
color: dimgray; color: dimgray;
} }
/* bars */ /* bars */
.bar-bg { .bar-bg {
display: inline-block; display: inline-block;
width: 240px; width: 240px;
@ -230,6 +237,14 @@
border-radius: 2px; border-radius: 2px;
} }
.bar-bar.Defcon1 {
background: black;
}
.bar-bar.Critical {
background: #e81e1e;
}
.bar-bar.High { .bar-bar.High {
background: #E91E63; background: #E91E63;
} }
@ -242,7 +257,15 @@
background: #8BC34A; background: #8BC34A;
} }
.bar-bar.Negligible {
background: #37474F;
}
.bar-bar.Unknown {
background: #37474F;
}
/* vulnerabilities */ /* vulnerabilities */
.report { .report {
margin: 18px auto; margin: 18px auto;
max-width: 960px; max-width: 960px;
@ -279,6 +302,14 @@
padding-right: 2.2em; padding-right: 2.2em;
} }
.vulnerabilities .Defcon1 .name {
color: black;
}
.vulnerabilities .Critical .name {
color: #e81e1e;
}
.vulnerabilities .High .name { .vulnerabilities .High .name {
color: #E91E63; color: #E91E63;
} }
@ -291,6 +322,13 @@
color: #8BC34A; color: #8BC34A;
} }
.vulnerabilities .Negligible .name {
color: #37474F;
}
.vulnerabilities .Unknown .name {
color: #37474F;
}
/* layers */ /* layers */
.layer .layer__title { .layer .layer__title {
@ -309,9 +347,104 @@
display: none; display: none;
} }
.summary-text {
display: flex;
max-width: 940px;
margin: 0 auto;
margin-bottom: 1em;
margin-top: 3em;
}
.summary-text .node {
text-align: center;
flex: 1;
}
.summary-text .node:before {
content: '';
display: inline-block;
height: 10px;
width: 10px;
border-radius: 50%;
background: #2196F3;
margin-right: 10px;
}
.summary-text .node.Defcon1:before {
background: black;
}
.summary-text .node.Critical:before {
background: #e81e1e;
}
.summary-text .node.High:before {
background: #E91E63;
}
.summary-text .node.Medium:before {
background: #FFA726;
}
.summary-text .node.Low:before {
background: #8BC34A;
}
.summary-text .node.Negligible:before {
background: #37474F;
}
.summary-text .node.Unknown:before {
background: #37474F;
}
.relative-graph {
display: flex;
max-width: 940px;
margin: 0 auto;
background: #2196F3;
flex-direction: row-reverse;
border-radius: 3px;
overflow: hidden;
}
.relative-graph .node {
text-align: center;
height: 8px;
background: #2196F3;
}
.relative-graph .node.Defcon1 {
background: black;
}
.relative-graph .node.Critical {
background: #e81e1e;
}
.relative-graph .node.High {
background: #E91E63;
}
.relative-graph .node.Medium {
background: #FFA726;
}
.relative-graph .node.Low {
background: #8BC34A;
}
.relative-graph .node.Negligible {
background: #37474F;
}
.relative-graph .node.Unknown {
background: #37474F;
}
</style> </style>
</head> </head>
<body>
<body>
<div class="container"> <div class="container">
<header class="app-header"> <header class="app-header">
<h1>Clair Control report</h1> <h1>Clair Control report</h1>
@ -323,28 +456,34 @@
<section class="summary"> <section class="summary">
<div> <div>
{{with $vulnerabilitiesCount := .CountAllVulnerabilities}} {{with $vulnerabilitiesCount := .CountAllVulnerabilities}}
<p><span class="lead"><strong>Total : {{$vulnerabilitiesCount.Total}}</strong></span></p> <p><span class="lead"><strong>Total : {{$vulnerabilitiesCount.Total}} vulnerabilities</strong></span></p>
<p>
<span style="display: inline-block; width: 120px;">Critical : <strong>{{$vulnerabilitiesCount.High}}</strong></span>
<!--<span class="bar-bg">
<span class="bar-bar High" style="width: {{$vulnerabilitiesCount.RelativeCount "High"}}%"></span>
</span>-->
</p>
<p>
<span style="display: inline-block; width: 120px;">Medium : <strong>{{$vulnerabilitiesCount.Medium}}</strong></span>
<!--<span class="bar-bg">
<span class="bar-bar Medium" style="width: {{$vulnerabilitiesCount.RelativeCount "Medium"}}%"></span>
</span>-->
</p>
<p>
<span style="display: inline-block; width: 120px;">Low : <strong>{{$vulnerabilitiesCount.Low}}</strong></span>
<!--<span class="bar-bg">
<span class="bar-bar Low" style="width: {{$vulnerabilitiesCount.RelativeCount "Low"}}%"></span>
</span>-->
</p>
<span style="display: inline-block; width: 120px;">Negligible : <strong>{{$vulnerabilitiesCount.Negligible}}</strong></span>
<p>
</p> </p>
<div class="summary-text">
{{if gt $vulnerabilitiesCount.Unknown 0}}
<div class="node Unknown">Unknown : <strong>{{$vulnerabilitiesCount.Unknown}}</strong></div>
{{end}} {{if gt $vulnerabilitiesCount.Negligible 0}}
<div class="node Negligible">Negligible : <strong>{{$vulnerabilitiesCount.Negligible}}</strong></div>
{{end}} {{if gt $vulnerabilitiesCount.Low 0}}
<div class="node Low">Low : <strong>{{$vulnerabilitiesCount.Low}}</strong></div>
{{end}} {{if gt $vulnerabilitiesCount.Medium 0}}
<div class="node Medium">Medium : <strong>{{$vulnerabilitiesCount.Medium}}</strong></div>
{{end}} {{if gt $vulnerabilitiesCount.High 0}}
<div class="node High">High : <strong>{{$vulnerabilitiesCount.High}}</strong></div>
{{end}} {{if gt $vulnerabilitiesCount.Critical 0}}
<div class="node Critical">Critical : <strong>{{$vulnerabilitiesCount.Critical}}</strong></div>
{{end}} {{if gt $vulnerabilitiesCount.Defcon1 0}}
<div class="node Defcon1">Defcon1 : <strong>{{$vulnerabilitiesCount.Defcon1}}</strong></div>
{{end}}
</div>
<div class="relative-graph">
<div class="node Defcon1" style="width: {{$vulnerabilitiesCount.RelativeCount " Defcon1 "}}%"></div>
<div class="node Critical" style="width: {{$vulnerabilitiesCount.RelativeCount " Critical "}}%"></div>
<div class="node High" style="width: {{$vulnerabilitiesCount.RelativeCount " High "}}%"></div>
<div class="node Medium" style="width: {{$vulnerabilitiesCount.RelativeCount " Medium "}}%"></div>
<div class="node Low" style="width: {{$vulnerabilitiesCount.RelativeCount " Low "}}%"></div>
<div class="node Negligible" style="width: {{$vulnerabilitiesCount.RelativeCount " Negligible "}}%"></div>
<div class="node Unknown" style="width: {{$vulnerabilitiesCount.RelativeCount " Unknown "}}%"></div>
</div>
{{end}} {{end}}
</div> </div>
</section> </section>
@ -405,16 +544,17 @@
</div> </div>
<script> <script>
(function () { (function() {
const togglers = document.querySelectorAll('[data-toggle-layer]'); const togglers = document.querySelectorAll('[data-toggle-layer]');
console.log(togglers); console.log(togglers);
for (var i = togglers.length - 1; i >= 0; i--) { for (var i = togglers.length - 1; i >= 0; i--) {
togglers[i].onclick = function (e) { togglers[i].onclick = function(e) {
e.target.parentNode.classList.toggle('closed'); e.target.parentNode.classList.toggle('closed');
}; };
} }
})(); })();
</script> </script>
</body> </body>
</html> </html>