diff --git a/README.md b/README.md index 89ffd2c..e7d1fff 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Penetration Test report template written in [typst](https://typst.app). - Provides a *Management Summary*, *Test Scope*, *Findings*, and *Appendix* section - Easy to use, handles the formatting and typesetting hassle for you - as well as all those text you copy-paste anyway - Supports [CVSS V3.1](https://www.first.org/cvss/v3-1/) +- Supports [TLP V2.0](https://www.first.org/tlp/) ## Usage diff --git a/helper.typ b/helper.typ index a6c61c5..fb317e1 100644 --- a/helper.typ +++ b/helper.typ @@ -133,3 +133,78 @@ } ) } + +// confidentialMark draws a "CONFIDENTIAL" stamp, used on the cover page +#let confidentialMark() = { + rect( + height: 100%, + width: 100%, + stroke: (paint: red, thickness: 2pt, dash: "solid"), + align(center + horizon, + text( + size: 18pt, + weight: "semibold", + fill: red, + "CONFIDENTIAL" + ) + ) + ) +} + +#let draftMark() = { + rect( + height: 100%, + width: 100%, + stroke: (paint: blue, thickness: 2pt, dash: "solid"), + align(center + horizon, + text( + size: 18pt, + weight: "semibold", + fill: blue, + "DRAFT" + ) + ) + ) +} + +// tlpMark draws a Traffic Light Protocol mark, used on the cover page +// light may be one of "RED", "AMBER", "AMBER+STRICT", "GREEN", or "CLEAR" +#let tlpMark(light) = { + light = upper(light) + let lightMap = ( + "RED": (color: rgb("#FF2B2B"), title: "TLP:RED", content: "recipient only"), + "AMBER": (color: rgb("#FFC000"), title: "TLP:AMBER", content: "organisation only"), + "AMBER+STRICT": (color: rgb("#FFC000"), title: "TLP:AMBER+STRICT", content: "organisation\nand its clients"), + "GREEN": (color: rgb("#33FF00"), title: "TLP:GREEN", content: "within community"), + "CLEAR": (color: rgb("#FFFFFF"), title: "TLP:CLEAR", content: "public") + ) + // check argument + panicOnInvalid(light, lightMap.keys()) + + rect( + height: 100%, + width: 100%, + stroke: (paint: lightMap.at(light).color.darken(10%), thickness: 2pt, dash: "solid"), + align(center + horizon, + grid( + columns: (80%), + rows: (18pt, auto), + gutter: 8pt, + highlight( + fill: black, + text( + size: if light == "AMBER+STRICT" { 13pt } else { 18pt }, + weight: "semibold", + fill: lightMap.at(light).color, + lightMap.at(light).title + ) + ), + text( + size: 12pt, + fill: if light == "CLEAR" { black } else { lightMap.at(light).color.darken(10%) }, + lightMap.at(light).content + ) + ) + ) + ) +} \ No newline at end of file diff --git a/main.typ b/main.typ index a15f6e0..0f62525 100644 --- a/main.typ +++ b/main.typ @@ -18,7 +18,11 @@ #set par(justify: true) // ----- Cover & Legal disclaimer(s) ----- -#pages.cover(targetFull, place, author) +#pages.cover(targetFull, place, author, + confidential: false, // set to true for a "CONFIDENTIAL" mark on the cover + tlp: "red", // set to one of "RED", "AMBER+STRICT", "AMBER", "GREEN", "CLEAR", or none. See https://www.first.org/tlp/ + draft: true // set to true for a "DRAFT" mark on the cover +) #pages.legal(author) #set page( diff --git a/pages.typ b/pages.typ index c82577e..7ca42f6 100644 --- a/pages.typ +++ b/pages.typ @@ -2,7 +2,7 @@ #import "helper.typ" -#let cover(title, place, author) = { +#let cover(title, place, author, confidential: false, tlp: none, draft: false) = { // Define page set page( paper: "a4", @@ -21,11 +21,31 @@ #text(title, weight: "black") ]) - v(0pt) + v(0.25pt) text(size: 16pt, [ #place, #datetime.today().display("[day].[month].[year]") • #author ]) + + v(1fr) + + grid( + columns: (1fr, 1fr, 1fr), + gutter: 5pt, + rows: (75pt), + // "Confidential" marking + if confidential { + helper.confidentialMark() + }, + // "Draft" marking + if draft { + helper.draftMark() + }, + // TLP marking, see https://www.first.org/tlp/ + if tlp != none { + helper.tlpMark(tlp) + } + ) } #let legal(author) = {