CYBER-0 ansible-testing update
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
module github.com/example/ansible-testing
|
||||
|
||||
go 1.21
|
||||
|
||||
require golang.org/x/text v0.14.0
|
||||
@@ -1,101 +0,0 @@
|
||||
// render.go — Go-based IEC 62443-3-3 SL2 compliance report renderer.
|
||||
//
|
||||
// Loads a JSON report produced by ansible-test and renders it through
|
||||
// an external Go template file (report.gohtml by default).
|
||||
//
|
||||
// Usage:
|
||||
// go run render.go <report.json> [template.gohtml]
|
||||
//
|
||||
// The template receives the full JSON document as an untyped map.
|
||||
// Registered template functions:
|
||||
// passIcon — maps passed value to ✅/❌/🔍/❓
|
||||
// severityIcon — maps severity string to 🔴/🟠/🟡/🟢/⚪
|
||||
// title — capitalizes first letter of each word
|
||||
// divf — float64 division (a/b*100) for percentages
|
||||
// add, sub — integer arithmetic
|
||||
//
|
||||
// Dependencies:
|
||||
// golang.org/x/text v0.14.0 (for cases.Title)
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: gomplate-report <report.json> [template.gohtml]\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
jsonPath := os.Args[1]
|
||||
tmplPath := "reports/report.gohtml"
|
||||
if len(os.Args) >= 3 {
|
||||
tmplPath = os.Args[2]
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(jsonPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error reading JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var report map[string]any
|
||||
if err := json.Unmarshal(data, &report); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing JSON: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
funcMap := template.FuncMap{
|
||||
"passIcon": func(v any) string {
|
||||
b, ok := v.(bool)
|
||||
if !ok {
|
||||
return "❓ MANUAL"
|
||||
}
|
||||
if b {
|
||||
return "✅ PASS"
|
||||
}
|
||||
return "❌ FAIL"
|
||||
},
|
||||
"severityIcon": func(s string) string {
|
||||
switch s {
|
||||
case "critical":
|
||||
return "🔴"
|
||||
case "high":
|
||||
return "🟠"
|
||||
case "medium":
|
||||
return "🟡"
|
||||
case "low":
|
||||
return "🟢"
|
||||
}
|
||||
return "⚪"
|
||||
},
|
||||
"title": cases.Title(language.English).String,
|
||||
"divf": func(a, b int) float64 {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(a) / float64(b) * 100.0
|
||||
},
|
||||
"add": func(a, b int) int { return a + b },
|
||||
"sub": func(a, b int) int { return a - b },
|
||||
}
|
||||
|
||||
tmpl, err := template.New("report.gohtml").Funcs(funcMap).ParseFiles(tmplPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error parsing template: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := tmpl.ExecuteTemplate(os.Stdout, "report.gohtml", report); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error rendering: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
+32
-28
@@ -1,59 +1,63 @@
|
||||
{{- /*
|
||||
report.gohtml — IEC 62443-3-3 SL2 Compliance Report Template
|
||||
|
||||
An external Go template rendered by reports/render.go. Receives the full
|
||||
JSON document as an untyped map[string]any. Access fields via (index . "key").
|
||||
Rendered directly by gomplate (https://gomplate.ca) — no custom Go binary
|
||||
required. The JSON report is loaded as the root context, so fields are
|
||||
accessed with plain dot notation (e.g. .meta.target).
|
||||
|
||||
Template functions (registered by render.go):
|
||||
passIcon v → "✅ PASS" / "❌ FAIL" / "❓ MANUAL"
|
||||
severityIcon s → 🔴/🟠/🟡/🟢/⚪
|
||||
title s → "Hello World" (capitalizes words)
|
||||
divf a b → a / b * 100.0 (percentage)
|
||||
add a b / sub a b → integer arithmetic
|
||||
Only gomplate's built-in functions (math.*, strings.*) are used, plus two
|
||||
in-line sub-templates (passIcon/severityIcon) defined below.
|
||||
|
||||
To customize: copy this file, modify, run:
|
||||
go run reports/render.go reports/*.json my-custom.gohtml
|
||||
Usage:
|
||||
gomplate --context .=reports/<hostname>-<date>.json --file reports/report.gohtml
|
||||
|
||||
To customize: copy this file, modify, and point --file at the copy.
|
||||
*/ -}}
|
||||
{{- define "passIcon" -}}
|
||||
{{- if eq . true }}✅ PASS{{ else if eq . false }}❌ FAIL{{ else }}❓ MANUAL{{ end -}}
|
||||
{{- end -}}
|
||||
{{- define "severityIcon" -}}
|
||||
{{- if eq . "critical" }}🔴{{ else if eq . "high" }}🟠{{ else if eq . "medium" }}🟡{{ else if eq . "low" }}🟢{{ else }}⚪{{ end -}}
|
||||
{{- end -}}
|
||||
╔══════════════════════════════════════════════════════════════════════════╗
|
||||
║ IEC 62443-3-3 SECURITY LEVEL 2 — COMPLIANCE REPORT ║
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
║ Target: {{ printf "%-56s" (index .meta "target") }}║
|
||||
║ Standard: {{ printf "%-56s" (index .meta "standard") }}║
|
||||
║ Level: {{ printf "%-56s" (index .meta "security_level") }}║
|
||||
║ Timestamp: {{ printf "%-56s" (index .meta "timestamp") }}║
|
||||
║ Executed by: {{ printf "%-55s" (index .meta "executed_by") }}║
|
||||
║ Target: {{ printf "%-56s" .meta.target }}║
|
||||
║ Standard: {{ printf "%-56s" .meta.standard }}║
|
||||
║ Level: {{ printf "%-56s" .meta.security_level }}║
|
||||
║ Timestamp: {{ printf "%-56s" .meta.timestamp }}║
|
||||
║ Executed by: {{ printf "%-55s" .meta.executed_by }}║
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
║ EXECUTIVE SUMMARY ║
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
║ TOTAL PASSED FAILED REVIEW COMPLIANCE ║
|
||||
║ ───── ────── ────── ────── ────────── ║
|
||||
║ {{ printf "%-8d" (index .summary "total") }} {{ printf "%-9d" (index .summary "passed") }} {{ printf "%-9d" (index .summary "failed") }} {{ printf "%-9d" (index .summary "skipped") }} {{ if gt (index .summary "total") 0 }}{{ printf "%.1f%%" (divf (index .summary "passed") (index .summary "total")) }}{{ else }}N/A{{ end }}
|
||||
║ {{ printf "%-8d" .summary.total }} {{ printf "%-9d" .summary.passed }} {{ printf "%-9d" .summary.failed }} {{ printf "%-9d" .summary.skipped }} {{ if gt .summary.total 0 }}{{ printf "%.1f%%" (mul (div .summary.passed .summary.total) 100) }}{{ else }}N/A{{ end }}
|
||||
║ ║
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
║ RESULTS BY REQUIREMENT ║
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
║ ║
|
||||
{{- $results := index . "results" }}
|
||||
{{- range $i, $r := $results }}
|
||||
║ {{ severityIcon (index $r "severity") }} [{{ index $r "test_id" }}] {{ passIcon (index $r "passed") }} {{ index $r "description" }}
|
||||
║ Requirement: {{ index $r "requirement" }}
|
||||
║ Expected: {{ index $r "expected" }}
|
||||
║ Actual: {{ index $r "actual" }}
|
||||
{{- if not (index $r "passed") }}
|
||||
║ Fix: {{ index $r "remediation" }}
|
||||
{{- range $i, $r := .results }}
|
||||
║ {{ template "severityIcon" $r.severity }} [{{ $r.test_id }}] {{ template "passIcon" $r.passed }} {{ $r.description }}
|
||||
║ Requirement: {{ $r.requirement }}
|
||||
║ Expected: {{ $r.expected }}
|
||||
║ Actual: {{ $r.actual }}
|
||||
{{- if not $r.passed }}
|
||||
║ Fix: {{ $r.remediation }}
|
||||
{{- end }}
|
||||
║ ║
|
||||
{{- end }}
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
║ FAILURE DETAIL ║
|
||||
╠══════════════════════════════════════════════════════════════════════════╣
|
||||
{{- $failures := index . "failures" }}
|
||||
{{- $failures := .failures }}
|
||||
{{- if $failures }}
|
||||
{{- range $i, $f := $failures }}
|
||||
║ ❌ {{ index $f "test_id" }} — {{ index $f "description" }}
|
||||
║ Severity: {{ index $f "severity" | title }}
|
||||
║ Remediation: {{ index $f "remediation" }}
|
||||
║ ❌ {{ $f.test_id }} — {{ $f.description }}
|
||||
║ Severity: {{ $f.severity | strings.Title }}
|
||||
║ Remediation: {{ $f.remediation }}
|
||||
║ ║
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
|
||||
Reference in New Issue
Block a user