feat: As a developer I want an additional microservice for creating pentest reports

This commit is contained in:
Marcel Haag 2023-01-10 11:58:03 +01:00
parent e27d6005db
commit c3b5d0149f
74 changed files with 4225 additions and 107 deletions

View File

@ -4,6 +4,7 @@ export class Project {
title: string;
createdAt: Date;
tester: string;
summary: string;
testingProgress: number;
createdBy: string;
@ -13,6 +14,7 @@ export class Project {
createdAt: Date,
tester: string,
testingProgress: number,
summary?: string,
createdBy?: string) {
this.id = id;
this.client = client;
@ -20,6 +22,7 @@ export class Project {
this.createdAt = createdAt;
this.tester = tester;
this.testingProgress = testingProgress;
this.summary = summary;
this.createdBy = createdBy;
}
}
@ -28,4 +31,5 @@ export interface ProjectDialogBody {
title: string;
client: string;
tester: string;
// ToDo: summary: string;
}

View File

@ -1,25 +1,25 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.3.RELEASE")
classpath("org.owasp:dependency-check-gradle:6.0.0")
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.3.RELEASE")
classpath("org.owasp:dependency-check-gradle:6.0.0")
}
}
plugins {
id("org.springframework.boot") version "2.3.4.RELEASE"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
id("com.github.spotbugs") version "4.5.0"
id("org.owasp.dependencycheck") version "6.0.0"
id("org.asciidoctor.jvm.convert") version "2.4.0"
kotlin("jvm") version "1.3.72"
kotlin("plugin.spring") version "1.3.72"
jacoco
id("org.springframework.boot") version "2.3.4.RELEASE"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
id("com.github.spotbugs") version "4.5.0"
id("org.owasp.dependencycheck") version "6.0.0"
id("org.asciidoctor.jvm.convert") version "2.4.0"
kotlin("jvm") version "1.3.72"
kotlin("plugin.spring") version "1.3.72"
jacoco
}
group = "com.security-c4po.api"
@ -27,127 +27,127 @@ version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
mavenCentral()
}
apply(plugin = "org.asciidoctor.jvm.convert")
dependencyCheck {
autoUpdate = true
cveValidForHours = 1
autoUpdate = true
cveValidForHours = 1
}
spotbugs {
showProgress.set(true)
tasks.spotbugsMain {
reports.create("html") {
isEnabled = true
}
}
tasks.spotbugsTest {
reports.create("html") {
isEnabled = true
}
}
showProgress.set(true)
tasks.spotbugsMain {
reports.create("html") {
isEnabled = true
}
}
tasks.spotbugsTest {
reports.create("html") {
isEnabled = true
}
}
}
val snippetsDir = file("build/generated-snippets")
dependencies {
implementation("org.json:json:20140107")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.11.3")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive")
implementation("org.json:json:20140107")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.11.3")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions:1.1.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("com.github.spotbugs:spotbugs-annotations:4.1.2")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions:1.1.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("com.github.spotbugs:spotbugs-annotations:4.1.2")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
implementation("org.modelmapper:modelmapper:2.3.2")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
implementation("org.modelmapper:modelmapper:2.3.2")
api("org.springframework.boot:spring-boot-starter-test")
api("org.springframework.security:spring-security-jwt:1.1.1.RELEASE")
api("net.logstash.logback:logstash-logback-encoder:6.2")
api("ch.qos.logback:logback-classic:1.2.3")
api("org.springframework.boot:spring-boot-starter-test")
api("org.springframework.security:spring-security-jwt:1.1.1.RELEASE")
api("net.logstash.logback:logstash-logback-encoder:6.2")
api("ch.qos.logback:logback-classic:1.2.3")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0")
testImplementation("io.projectreactor:reactor-test")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.3.1")
testImplementation("org.springframework.cloud:spring-cloud-contract-wiremock:2.1.0.RELEASE")
testImplementation("org.springframework.restdocs:spring-restdocs-webtestclient")
testImplementation("com.github.spotbugs:spotbugs-annotations:4.1.2")
testApi("org.testcontainers:junit-jupiter:1.15.2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0")
testImplementation("io.projectreactor:reactor-test")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.3.1")
testImplementation("org.springframework.cloud:spring-cloud-contract-wiremock:2.1.0.RELEASE")
testImplementation("org.springframework.restdocs:spring-restdocs-webtestclient")
testImplementation("com.github.spotbugs:spotbugs-annotations:4.1.2")
testApi("org.testcontainers:junit-jupiter:1.15.2")
testImplementation("com.github.dasniko:testcontainers-keycloak:2.3.0")
}
jacoco {
toolVersion = "0.8.3"
reportsDir = file("$buildDir/reports/coverage")
toolVersion = "0.8.3"
reportsDir = file("$buildDir/reports/coverage")
}
tasks.withType<Test> {
useJUnitPlatform()
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
tasks.bootJar {
dependsOn(tasks.test, tasks.asciidoctor, tasks.jacocoTestReport, tasks.dependencyCheckAnalyze)
dependsOn(tasks.test, tasks.asciidoctor, tasks.jacocoTestReport, tasks.dependencyCheckAnalyze)
}
tasks.test {
outputs.dir(snippetsDir)
outputs.dir(snippetsDir)
}
tasks.dependencyCheckAnalyze {
dependsOn(tasks.test, tasks.asciidoctor, tasks.jacocoTestReport)
dependsOn(tasks.test, tasks.asciidoctor, tasks.jacocoTestReport)
}
//Issue with Kotlin assignment of sourceDir and outputDir: https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/458
tasks.asciidoctor {
inputs.dir(snippetsDir)
setSourceDir(file("src/main/asciidoc"))
setOutputDir(file("$buildDir/asciidoc"))
sources(delegateClosureOf<PatternSet> {
include("SecurityC4PO.adoc")
})
inputs.dir(snippetsDir)
setSourceDir(file("src/main/asciidoc"))
setOutputDir(file("$buildDir/asciidoc"))
sources(delegateClosureOf<PatternSet> {
include("SecurityC4PO.adoc")
})
attributes(
mapOf(
"snippets" to snippetsDir,
"source-highlighter" to "coderay",
"toc" to "left",
"toclevels" to 3,
"sectlinks" to true
)
)
dependsOn(tasks.test)
attributes(
mapOf(
"snippets" to snippetsDir,
"source-highlighter" to "coderay",
"toc" to "left",
"toclevels" to 3,
"sectlinks" to true
)
)
dependsOn(tasks.test)
}
tasks.jacocoTestReport {
reports {
xml.isEnabled = true
csv.isEnabled = false
html.isEnabled = true
html.destination = file("$buildDir/reports/coverage")
}
reports {
xml.isEnabled = true
csv.isEnabled = false
html.isEnabled = true
html.destination = file("$buildDir/reports/coverage")
}
}

View File

@ -1,5 +1,4 @@
= SecurityC4PO REST API Documentation
Novatec Consulting GmbH;
:doctype: book
:source-highlighter: highlightjs
:icons: font

View File

@ -13,4 +13,4 @@ class ErrorCodeEncoder {
""
}
}
}
}

View File

@ -27,7 +27,7 @@ fun buildPentest(body: PentestRequestBody, pentestEntity: PentestEntity): Pentes
)
}
/*fun addFindingtoPentest(findingId: String, pentestEntity: PentestEntity): Pentest {
/*fun addFindingToPentest(findingId: String, pentestEntity: PentestEntity): Pentest {
return Pentest(
id = pentestEntity.data.id,
projectId = pentestEntity.data.projectId,

View File

@ -1,17 +1,10 @@
package com.securityc4po.api.pentest.finding
import com.securityc4po.api.pentest.PentestCategory
import com.securityc4po.api.pentest.PentestRequestBody
import com.securityc4po.api.pentest.PentestService
import com.securityc4po.api.pentest.toPentestResponseBody
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
import com.securityc4po.api.extensions.getLoggerFor
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import com.securityc4po.api.ResponseBody
import com.securityc4po.api.pentest.finding.FindingRequestBody
import com.securityc4po.api.pentest.finding.FindingService
import com.securityc4po.api.pentest.finding.toFindingDeleteResponseBody
import com.securityc4po.api.pentest.finding.toFindingResponseBody
import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.noContent
import org.springframework.web.bind.annotation.*

View File

@ -16,7 +16,8 @@ data class Project(
val title: String,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
val createdAt: String = Instant.now().toString(),
val tester: String? = null,
val tester: String,
val summary: String? = null,
var projectPentests: List<ProjectPentest> = emptyList(),
val createdBy: String
)
@ -28,6 +29,7 @@ fun buildProject(body: ProjectRequestBody, projectEntity: ProjectEntity): Projec
title = body.title,
createdAt = projectEntity.data.createdAt,
tester = body.tester,
summary = body.summary,
projectPentests = projectEntity.data.projectPentests,
createdBy = projectEntity.data.createdBy
)
@ -40,6 +42,7 @@ fun Project.toProjectResponseBody(): ResponseBody {
"title" to title,
"createdAt" to createdAt,
"tester" to tester,
"summary" to summary,
/* ToDo: Calculate percentage in BE type: float */
"testingProgress" to calculateProgress(),
"createdBy" to createdBy
@ -84,7 +87,8 @@ data class ProjectOverview(
data class ProjectRequestBody(
val client: String,
val title: String,
val tester: String
val tester: String,
val summary: String?
)
/**
@ -108,6 +112,7 @@ fun ProjectRequestBody.toProject(): Project {
title = this.title,
createdAt = Instant.now().toString(),
tester = this.tester,
summary = this.summary,
// ToDo: Should be changed to SUB from Token after adding AUTH Header
createdBy = UUID.randomUUID().toString()
)

View File

@ -34,6 +34,8 @@ class ProjectController(private val projectService: ProjectService) {
}
}
// ToDo: Add getProjectReportDataById Endpoint with return type ProjectReport
@PostMapping
fun saveProject(
@RequestBody body: ProjectRequestBody

View File

@ -18,6 +18,7 @@ fun ProjectEntity.toProject() : Project {
this.data.title,
this.data.createdAt,
this.data.tester,
this.data.summary,
this.data.projectPentests,
this.data.createdBy
)

View File

@ -73,6 +73,8 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
.description("The date where the project was created at"),
PayloadDocumentation.fieldWithPath("[].tester").type(JsonFieldType.STRING)
.description("The user that is assigned as a tester in the project"),
PayloadDocumentation.fieldWithPath("[].summary").type(JsonFieldType.STRING)
.description("The summary of the requested project"),
PayloadDocumentation.fieldWithPath("[].createdBy").type(JsonFieldType.STRING)
.description("The id of the user that created the project"),
PayloadDocumentation.fieldWithPath("[].testingProgress").type(JsonFieldType.NUMBER)
@ -88,6 +90,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
title = "Some Mock API (v1.0) Scanning",
createdAt = "2021-01-10T18:05:00Z",
tester = "Novatester",
summary = "Lorem Ipsum",
projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
@ -97,6 +100,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
title = "CashMyData (iOS)",
createdAt = "2021-01-10T18:05:00Z",
tester = "Elliot",
summary = "Lorem Ipsum",
projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
@ -152,7 +156,8 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
val project = ProjectRequestBody(
client = "Novatec",
title = "log4j Pentest",
tester = "Stipe"
tester = "Stipe",
summary = ""
)
}
@ -262,6 +267,8 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
.description("The date where the project was created at"),
PayloadDocumentation.fieldWithPath("tester").type(JsonFieldType.STRING)
.description("The updated user that is assigned as a tester in the project"),
PayloadDocumentation.fieldWithPath("summary").type(JsonFieldType.STRING)
.description("The summary of the requested project"),
PayloadDocumentation.fieldWithPath("createdBy").type(JsonFieldType.STRING)
.description("The id of the user that created the project"),
PayloadDocumentation.fieldWithPath("testingProgress").type(JsonFieldType.NUMBER)
@ -274,7 +281,8 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
val projectUpdateRequest = ProjectRequestBody(
client = "Novatec_updated",
title = "log4j Pentest_updated",
tester = "Stipe_updated"
tester = "Stipe_updated",
summary = ""
)
val projectUpdate = Project(
@ -283,6 +291,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
title = "log4j Pentest_updated",
createdAt = "2021-01-10T18:05:00Z",
tester = "Stipe_updated",
summary = "",
projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
@ -296,6 +305,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
title = "Some Mock API (v1.0) Scanning",
createdAt = "2021-01-10T18:05:00Z",
tester = "Novatester",
summary = "Lorem Ipsum",
projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
@ -305,6 +315,7 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
title = "CashMyData (iOS)",
createdAt = "2021-01-10T18:05:00Z",
tester = "Elliot",
summary = "Lorem Ipsum",
projectPentests = emptyList<ProjectPentest>(),
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)

View File

@ -71,6 +71,7 @@ class ProjectControllerIntTest : BaseIntTest() {
title = "Some Mock API (v1.0) Scanning",
createdAt = "2021-01-10T18:05:00Z",
tester = "Novatester",
summary = "Lorem Ipsum",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
val projectTwo = Project(
@ -79,6 +80,7 @@ class ProjectControllerIntTest : BaseIntTest() {
title = "CashMyData (iOS)",
createdAt = "2021-01-10T18:05:00Z",
tester = "Elliot",
summary = "Lorem Ipsum",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
@ -113,6 +115,7 @@ class ProjectControllerIntTest : BaseIntTest() {
title = "log4j Pentest",
createdAt = "2021-04-10T18:05:00Z",
tester = "Stipe",
summary = "",
createdBy = "a8891ad2-5cf5-4519-a89e-9ef8eec9e10c"
)
}
@ -184,6 +187,7 @@ class ProjectControllerIntTest : BaseIntTest() {
title = "Some Mock API (v1.0) Scanning",
createdAt = "2021-01-10T18:05:00Z",
tester = "Novatester",
summary = "Lorem Ipsum",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
val projectTwo = Project(
@ -192,6 +196,7 @@ class ProjectControllerIntTest : BaseIntTest() {
title = "CashMyData (iOS)",
createdAt = "2021-01-10T18:05:00Z",
tester = "Elliot",
summary = "Lorem Ipsum",
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
)
// persist test data in database

View File

@ -20,4 +20,338 @@
"mitigation": "Test Mitigatin"
},
"_class": "com.securityc4po.api.finding.FindingEntity"
}]
},{
"_id": {
"$oid": "63725fa6e612626e2c6956ee"
},
"lastModified": {
"$date": {
"$numberLong": "1668439974730"
}
},
"data": {
"_id": "0bda8950-94fa-4ec6-8fa7-e09f5a8cd3e8",
"severity": "HIGH",
"title": "High Title",
"description": "High Description",
"impact": "High Impact",
"affectedUrls": [
"https://angular.io/guide/routing-overview"
],
"reproduction": "Step 1: Not be High",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374c3c4e0136563b96187b8"
},
"lastModified": {
"$date": {
"$numberLong": "1668596676210"
}
},
"data": {
"_id": "58f63b4e-97fb-4fe8-8527-7996896089d2",
"severity": "MEDIUM",
"title": "Medium Finding",
"description": "Medium",
"impact": "Medium",
"affectedUrls": [],
"reproduction": "Medium",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374c43be0136563b96187b9"
},
"lastModified": {
"$date": {
"$numberLong": "1668596795003"
}
},
"data": {
"_id": "72886128-b2d9-4a92-bbfe-b54373441321",
"severity": "CRITICAL",
"title": "Critical Issue",
"description": "Critical",
"impact": "Critical",
"affectedUrls": [],
"reproduction": "Critical",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374c488e0136563b96187ba"
},
"lastModified": {
"$date": {
"$numberLong": "1668596872152"
}
},
"data": {
"_id": "4ddb84f6-068c-4319-a8ee-1000008bb75a",
"severity": "HIGH",
"title": "Anothe High Issues",
"description": "High",
"impact": "High",
"affectedUrls": [],
"reproduction": "High",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374c624e0136563b96187bb"
},
"lastModified": {
"$date": {
"$numberLong": "1668597284983"
}
},
"data": {
"_id": "42831151-51fd-4348-b829-6b18ddd14fe1",
"severity": "MEDIUM",
"title": "Another Medium FInding",
"description": "Medium",
"impact": "Medium",
"affectedUrls": [],
"reproduction": "Medium",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374cb33e0136563b96187bc"
},
"lastModified": {
"$date": {
"$numberLong": "1668598579443"
}
},
"data": {
"_id": "559cd0ac-9e64-41f9-892a-4c8a9dd30357",
"severity": "LOW",
"title": "Another Low One",
"description": "Low",
"impact": "Low",
"affectedUrls": [],
"reproduction": "Low",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374cb98e0136563b96187bd"
},
"lastModified": {
"$date": {
"$numberLong": "1668598680140"
}
},
"data": {
"_id": "5e22d38f-a4f6-4809-84ea-a803b5f1f9fc",
"severity": "LOW",
"title": "common",
"description": "common",
"impact": "common",
"affectedUrls": [],
"reproduction": "common",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374cc51e0136563b96187be"
},
"lastModified": {
"$date": {
"$numberLong": "1668598865728"
}
},
"data": {
"_id": "0bfa7511-fe33-4ab5-9af2-d4ed70c1b350",
"severity": "HIGH",
"title": "Highihihi",
"description": "High",
"impact": "High",
"affectedUrls": [],
"reproduction": "High",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374cd00e0136563b96187bf"
},
"lastModified": {
"$date": {
"$numberLong": "1668599040593"
}
},
"data": {
"_id": "70e413b9-d736-40d2-b7d6-236768b1230c",
"severity": "MEDIUM",
"title": "Medium Rare",
"description": "Medium",
"impact": "Medium",
"affectedUrls": [],
"reproduction": "Medium",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6374ec35e0136563b96187c8"
},
"lastModified": {
"$date": {
"$numberLong": "1668607029072"
}
},
"data": {
"_id": "672d9f87-fb3d-4fc5-8c6f-cadf97661ca5",
"severity": "HIGH",
"title": "Test",
"description": "Test",
"impact": "Test",
"affectedUrls": [],
"reproduction": "Test",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "637606830687d905ca60af1d"
},
"lastModified": {
"$date": {
"$numberLong": "1668679299814"
}
},
"data": {
"_id": "bddf810b-f20e-473e-a63d-34fcba7e48ef",
"severity": "CRITICAL",
"title": "Login SQL Injection ",
"description": "Inside Login Form using the ' or TRUE-- Syntax will enable the user to login as the Admin.",
"impact": "Active User Session with Admin priviledges can affect the whole application.",
"affectedUrls": [
"http://localhost:3000/#/login"
],
"reproduction": "Step 1:\nGo to login page.\n\nStep 2:\nEnter ' or TRUE-- in the username field and enter a random password.",
"mitigation": ""
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "637612280687d905ca60af20"
},
"lastModified": {
"$date": {
"$numberLong": "1668682280551"
}
},
"data": {
"_id": "d7c95af7-5434-4768-b62c-5b11f9396276",
"severity": "MEDIUM",
"title": "Searchbar XSS",
"description": "Adding <iframe> in the search bar of the header results in XSS Vuln.",
"impact": "This impacts the Webapplication",
"affectedUrls": [
"http://localhost:3000/#/search?q=%3Ciframe%20src%3D%22javascript:alert(%60xss%60)%22%3E"
],
"reproduction": "Step 1: \nClick on search bar of header.\n\nStep 2: \nEnter <iframe src=\"javascript:alert(`xss`)\">\n\nStep3: Press ENTER\n\nYou will now get a PopUp because the javascript code was executed inside the browser.",
"mitigation": "Sanitse Input Field."
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "63776860fcdda12bf2e51eb2"
},
"lastModified": {
"$date": {
"$numberLong": "1670489874240"
}
},
"data": {
"_id": "cb33fad4-7965-4654-a9f9-f007edaca35c",
"severity": "HIGH",
"title": "Searchbar XSS",
"description": "Adding <iframe src=\"javascript:alert('xss')\"> in the search bar of the header results in XSS Vuln.",
"impact": "This impacts the Webbapp.",
"affectedUrls": [
"http://localhost:3000/#/search?q=%3Ciframe%20src%3D%22javascript:alert('xss')%22%3E"
],
"reproduction": "Step1: \nClick on search field of the header\n\nStep 2: \nEnter <iframe src=\"javascript:alert('xss')\">\n\nStep 3: \nPress ENTER\n\nYou will now get a PopUp",
"mitigation": "Sanitise Input Fields."
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6391a364aceddd4dd1b32322"
},
"lastModified": {
"$date": {
"$numberLong": "1670488932489"
}
},
"data": {
"_id": "b6dfddde-9bc2-4658-8c18-668190053105",
"severity": "CRITICAL",
"title": "Searchbar XSS",
"description": "Adding <iframe src=\"javascript:alert('xss')\"> in the search bar of the header results in XSS Vuln.",
"impact": "This impacts the Webbapp.",
"affectedUrls": [
"http://localhost:3000/#/search?q=%3Ciframe%20src%3D%22javascript:alert('xss')%22%3E"
],
"reproduction": "Step1: \nClick on search field of the header\n\nStep 2: \nEnter <iframe src=\"javascript:alert('xss')\">\n\nStep 3: \nPress ENTER\n\nYou will now get a PopUp",
"mitigation": "Sanitise Input Fields."
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6391a39baceddd4dd1b32323"
},
"lastModified": {
"$date": {
"$numberLong": "1670488987700"
}
},
"data": {
"_id": "e9a50c5d-e9ea-4596-b1a9-8ad67eddef04",
"severity": "CRITICAL",
"title": "Searchbar XSS",
"description": "Adding <iframe src=\"javascript:alert('xss')\"> in the search bar of the header results in XSS Vuln.",
"impact": "This impacts the Webbapp.",
"affectedUrls": [
"http://localhost:3000/#/search?q=%3Ciframe%20src%3D%22javascript:alert('xss')%22%3E"
],
"reproduction": "Step1: \nClick on search field of the header\n\nStep 2: \nEnter <iframe src=\"javascript:alert('xss')\">\n\nStep 3: \nPress ENTER\n\nYou will now get a PopUp",
"mitigation": "Sanitise Input Fields."
},
"_class": "com.securityc4po.api.finding.FindingEntity"
},{
"_id": {
"$oid": "6391a3cbaceddd4dd1b32324"
},
"lastModified": {
"$date": {
"$numberLong": "1670489035954"
}
},
"data": {
"_id": "7f51e615-230f-4f90-a671-13e66e82370f",
"severity": "CRITICAL",
"title": "Searchbar XSS",
"description": "Adding <iframe src=\"javascript:alert('xss')\"> in the search bar of the header results in XSS Vuln.",
"impact": "This impacts the Webbapp.",
"affectedUrls": [
"http://localhost:3000/#/search?q=%3Ciframe%20src%3D%22javascript:alert('xss')%22%3E"
],
"reproduction": "Step1: \nClick on search field of the header\n\nStep 2: \nEnter <iframe src=\"javascript:alert('xss')\">\n\nStep 3: \nPress ENTER\n\nYou will now get a PopUp",
"mitigation": "Sanitise Input Fields."
},
"_class": "com.securityc4po.api.finding.FindingEntity"
}]

38
security-c4po-reporting/.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
HELP.md
.gradle
*.DS_Store
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

View File

@ -0,0 +1,20 @@
FROM openjdk:11-jre
ENV TZ=Europe/Berlin
RUN groupadd -g 9999 security-c4po-reporting && \
useradd -r -u 9999 -g security-c4po-reporting security-c4po-reporting
RUN mkdir /data
RUN chown security-c4po-reporting:security-c4po-reporting /data
USER security-c4po-reporting
# GET CURRENT STAGE
ARG STAGE
ENV ENV_STAGE=$STAGE
# COPY PACKAGE INTO IMAGE
COPY ./build/libs/security-c4po-reporting-0.0.1-SNAPSHOT.jar /
USER security-c4po-reporting
EXPOSE 8444
# RUN JAVA
# CMD [ "java", "-jar", "security-c4po-reporting-0.0.1-SNAPSHOT.jar" ]
ENTRYPOINT [ "java", "-jar", "-Dspring.profiles.active=${ENV_STAGE}", "security-c4po-reporting-0.0.1-SNAPSHOT.jar" ]

View File

@ -0,0 +1,153 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
repositories {
mavenCentral()
jcenter()
maven {
// jaspersoft-third-party
url = uri("https://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts/")
}
maven {
// JasperReports CE Releases
url = uri("https://jaspersoft.jfrog.io/jaspersoft/jr-ce-releases")
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.3.RELEASE")
}
}
plugins {
id("org.springframework.boot") version "2.3.4.RELEASE"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
/*id("org.springframework.boot") version "2.7.7"
id("io.spring.dependency-management") version "1.0.15.RELEASE"*/
id("org.asciidoctor.jvm.convert") version "2.4.0"
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
jacoco
}
group = "com.securityc4po.reporting"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
configurations.all {
//Little hack to retrieve the missing iText dependency from another project since it is not correctly maintained by
//Jasper-Reports. OpenPDF is using the same iText library so this is why this hack works.
resolutionStrategy.eachDependency {
if (this.requested.group == "com.lowagie" && this.requested.name == "itext") {
this.useTarget("com.github.librepdf:openpdf:1.3.30")
}
}
}
repositories {
mavenCentral()
}
apply(plugin = "org.asciidoctor.jvm.convert")
val snippetsDir = file("build/generated-snippets")
dependencies {
implementation("org.json:json:20140107")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-actuator")
/*implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
api("org.springframework.security:spring-security-jwt:1.1.1.RELEASE")*/
/* Reporting */
implementation("net.sf.jasperreports:jasperreports:6.20.0")
// https://mavenlibs.com/maven/dependency/net.sf.jasperreports/jasperreports-fonts
implementation("net.sf.jasperreports:jasperreports-fonts:6.20.0")
// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
implementation("org.apache.pdfbox:pdfbox:2.0.1")
// https://mvnrepository.com/artifact/commons-io/commons-io
implementation("commons-io:commons-io:2.6")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.11.3")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions:1.1.1")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation("org.modelmapper:modelmapper:2.3.2")
api("net.logstash.logback:logstash-logback-encoder:6.2")
api("ch.qos.logback:logback-classic:1.2.3")
api("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
testImplementation("org.springframework.restdocs:spring-restdocs-webtestclient")
testImplementation("org.springframework.security:spring-security-test")
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
tasks.bootJar {
// ToDo: Reactivate jacocoTestReport after test written
dependsOn(tasks.test, tasks.asciidoctor, /*tasks.jacocoTestReport*/)
}
jacoco {
toolVersion = "0.8.3"
reportsDir = file("$buildDir/reports/coverage")
}
//Issue with Kotlin assignment of sourceDir and outputDir: https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/458
tasks.asciidoctor {
inputs.dir(snippetsDir)
setSourceDir(file("src/main/asciidoc"))
setOutputDir(file("$buildDir/asciidoc"))
sources(delegateClosureOf<PatternSet> {
include("ReportingC4PO.adoc")
})
attributes(
mapOf(
"snippets" to snippetsDir,
"source-highlighter" to "coderay",
"toc" to "left",
"toclevels" to 3,
"sectlinks" to true
)
)
dependsOn(tasks.test)
}
tasks.test {
outputs.dir(snippetsDir)
}
// ToDo: Reactivate after test written
/*tasks.jacocoTestReport {
reports {
xml.isEnabled = true
csv.isEnabled = false
html.isEnabled = true
html.destination = file("$buildDir/reports/coverage")
}
}*/

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

240
security-c4po-reporting/gradlew vendored Executable file
View File

@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
security-c4po-reporting/gradlew.bat vendored Normal file
View File

@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,185 @@
{
"info": {
"_postman_id": "3d7cb3b3-a3f6-43b9-a537-a66088165dcd",
"name": "security-c4po-reporting",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "5225213"
},
"item": [
{
"name": "keycloak",
"item": [
{
"name": "getKeycloakConfiguration",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8888/auth/realms/c4po_realm_local/.well-known/openid-configuration",
"protocol": "http",
"host": [
"localhost"
],
"port": "8888",
"path": [
"auth",
"realms",
"c4po_realm_local",
".well-known",
"openid-configuration"
]
}
},
"response": []
},
{
"name": "postKeycloakToken",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"key": "client_id",
"value": "c4po_local",
"type": "text"
},
{
"key": "username",
"value": "ttt",
"type": "text"
},
{
"key": "password",
"value": "Test1234!",
"type": "text"
},
{
"key": "grant_type",
"value": "password",
"type": "text"
},
{
"key": "token",
"value": "",
"type": "text",
"disabled": true
},
{
"key": "client_secret",
"value": "secret",
"type": "text",
"disabled": true
}
]
},
"url": {
"raw": "http://localhost:8888/auth/realms/c4po_realm_local/protocol/openid-connect/token",
"protocol": "http",
"host": [
"localhost"
],
"port": "8888",
"path": [
"auth",
"realms",
"c4po_realm_local",
"protocol",
"openid-connect",
"token"
]
}
},
"response": []
}
]
},
{
"name": "reports",
"item": [
{
"name": "getReportPDFforProjectById",
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "application/pdf",
"type": "text"
}
],
"url": {
"raw": "http://localhost:8444/reports/195809ed-9722-4ad5-a84b-0099a9a01652/pdf",
"protocol": "http",
"host": [
"localhost"
],
"port": "8444",
"path": [
"reports",
"195809ed-9722-4ad5-a84b-0099a9a01652",
"pdf"
]
}
},
"response": []
},
{
"name": "getReportCSVforProjectById",
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "text/html",
"type": "text"
}
],
"url": {
"raw": "http://localhost:8444/reports/195809ed-9722-4ad5-a84b-0099a9a01652/csv",
"protocol": "http",
"host": [
"localhost"
],
"port": "8444",
"path": [
"reports",
"195809ed-9722-4ad5-a84b-0099a9a01652",
"csv"
]
}
},
"response": []
},
{
"name": "getReportHTMLforProjectById",
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"value": "text/csv",
"type": "text"
}
],
"url": {
"raw": "http://localhost:8444/reports/195809ed-9722-4ad5-a84b-0099a9a01652/html",
"protocol": "http",
"host": [
"localhost"
],
"port": "8444",
"path": [
"reports",
"195809ed-9722-4ad5-a84b-0099a9a01652",
"html"
]
}
},
"response": []
}
]
}
]
}

View File

@ -0,0 +1,7 @@
pluginManagement {
repositories {
gradlePluginPortal()
}
}
rootProject.name = "security-c4po-reporting"

View File

@ -0,0 +1,4 @@
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

View File

@ -0,0 +1,30 @@
= ReportingC4PO REST API Documentation
:doctype: book
:source-highlighter: highlightjs
:icons: font
:toc: left
:toclevels: 4
:sectlinks:
:data-uri:
This documentation describes the REST API for the "ReportingC4PO".
The service tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP verbs and status codes.
== Error handling
You can generally expect 4xx for client errors and 5xx for server errors.
== Request Headers
The request and response snippets shown in this documentation are generated from real interactions.
When creating requests you must not follow the examples exactly, e.g. instead of providing the Accept Header `application/json, application/javascript, text/javascript` you can also provide only one value, typically `application/json`.
== Change History
|===
|Date |Change
|2023-01-10
|Initial version
|===

View File

@ -0,0 +1,11 @@
package com.securityc4po.reporting
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class ReportingApplication
fun main(args: Array<String>) {
runApplication<ReportingApplication>(*args)
}

View File

@ -0,0 +1,16 @@
package com.securityc4po.reporting.configuration.error.handler
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.classic.spi.ThrowableProxy
class ErrorCodeEncoder {
/*override*/ fun convert(event: ILoggingEvent): String {
return if (event.throwableProxy != null) {
val throwable = event.throwableProxy as ThrowableProxy
val ex = throwable.throwable as C4POBaseException
ex.errorcode.code.toString()
} else {
""
}
}
}

View File

@ -0,0 +1,8 @@
package com.securityc4po.reporting.configuration.error.handler
enum class Errorcode(val code: Int) {
// 1XXX Information Not Found
// 4XXX Unauthorized
// 5XXX Server Errors
// 6XXX Failed transaction
}

View File

@ -0,0 +1,61 @@
package com.securityc4po.reporting.configuration.error.handler
import org.springframework.boot.web.error.ErrorAttributeOptions
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.client.WebClientResponseException
import org.springframework.web.reactive.function.server.ServerRequest
import org.json.JSONObject
@Component
class GlobalErrorAttributes: DefaultErrorAttributes() {
override fun getErrorAttributes(request: ServerRequest, options: ErrorAttributeOptions): Map<String, Any> {
val map = super.getErrorAttributes(request, options)
/////////////////////////
////// Exceptions ///////
/////////////////////////
if (getError(request) is EntityNotFoundException) {
val ex = getError(request) as EntityNotFoundException
map.put("message", ex.errormessage)
map.put("errorcode", ex.errorcode.code)
map.put("status", ex.status.value())
map.put("error", ex.status.reasonPhrase)
return map
}
if (getError(request) is UnauthorizedException) {
val ex = getError(request) as UnauthorizedException
map.put("message", ex.errormessage)
map.put("errorcode", ex.errorcode.code)
map.put("status", ex.status.value())
map.put("error", ex.status.reasonPhrase)
return map
}
if (getError(request) is TransactionInterruptedException) {
val ex = getError(request) as TransactionInterruptedException
map.put("message", ex.errormessage)
map.put("errorcode", ex.errorcode.code)
map.put("status", ex.status.value())
map.put("error", ex.status.reasonPhrase)
return map
}
if (getError(request) is WebClientResponseException) {
val ex = getError(request) as WebClientResponseException
val body = JSONObject(ex.responseBodyAsString)
map.put("message", body.get("message"))
map.put("errorcode", body.get("errorcode"))
map.put("status", ex.rawStatusCode)
map.put("error", ex.statusText)
return map
}
map.put("message", map["message"])
map.put("status", map["status"] as Int)
map.put("error", map["error"])
return map
}
}

View File

@ -0,0 +1,69 @@
package com.securityc4po.reporting.configuration.error.handler
import org.springframework.boot.autoconfigure.web.ResourceProperties
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler
import org.springframework.boot.web.error.ErrorAttributeOptions
import org.springframework.boot.web.reactive.error.ErrorAttributes
import org.springframework.context.ApplicationContext
import org.springframework.core.annotation.Order
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.codec.ServerCodecConfigurer
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.server.*
import org.springframework.web.server.ResponseStatusException
import reactor.core.publisher.Mono
@Component
@Order(-2)
class GlobalErrorWebExceptionHandler(g: GlobalErrorAttributes, applicationContext: ApplicationContext,
serverCodecConfigurer: ServerCodecConfigurer
) : AbstractErrorWebExceptionHandler(g, ResourceProperties(), applicationContext) {
init {
super.setMessageWriters(serverCodecConfigurer.writers)
super.setMessageReaders(serverCodecConfigurer.readers)
}
override fun getRoutingFunction(errorAttributes: ErrorAttributes): RouterFunction<ServerResponse> {
return RouterFunctions.route(RequestPredicates.all(), HandlerFunction { this.renderErrorResponse(it) })
}
private fun renderErrorResponse(request: ServerRequest): Mono<ServerResponse> {
val errorPropertiesMap = getErrorAttributes(request, ErrorAttributeOptions.defaults())
return ServerResponse.status(HttpStatus.valueOf(errorPropertiesMap["status"] as Int))
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorPropertiesMap))
}
}
open class C4POBaseException (val errorcode: Errorcode, httpStatus: HttpStatus): ResponseStatusException(httpStatus)
internal class EntityNotFoundException(val errormessage: String, code: Errorcode): C4POBaseException(code, HttpStatus.NOT_FOUND)
internal class UnauthorizedException (val errormessage: String, code: Errorcode) : C4POBaseException(code, HttpStatus.UNAUTHORIZED)
internal class TransactionInterruptedException(val errormessage: String, code: Errorcode): C4POBaseException(code, HttpStatus.FAILED_DEPENDENCY)
/**
* This method is used to throw an exception, and log a message if needed, if a certain condition is true.
*
* @param require of type boolean. It is the condition to check on.
* @param logging lambda expression for optional logging.
* @param mappedException of type OpenSpaceBaseException.
*/
inline fun validate(require: Boolean, logging: () -> Unit, mappedException: C4POBaseException) {
if (!require) {
throw wrappedException(logging= { logging() }, mappedException = mappedException)
}
}
/**
* This method is used to reduce some lines of code when we throw an exception.
* It has an optional logging part using a lambda expression.
*
* @param logging lambda expression for optional logging.
* @param mappedException of type OpenSpaceBaseException.
*/
inline fun wrappedException(logging: () -> Unit, mappedException: C4POBaseException): C4POBaseException {
logging()
return mappedException
}

View File

@ -0,0 +1,48 @@
package com.securityc4po.reporting.configuration.security
class Appuser {}
/*import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import java.util.stream.Collectors
class Appuser internal constructor(val token: String) : UserDetails {
override fun getAuthorities(): Collection<GrantedAuthority> {
return listOf("user").stream().map {
it.toUpperCase()
}.map {
ROLE_PREFIX + it
}.map {
SimpleGrantedAuthority(it)
}.collect(Collectors.toList())
}
override fun getPassword(): String {
return "n/a"
}
d
override fun getUsername(): String {
return "n/a"
}
override fun isAccountNonExpired(): Boolean {
return true
}
override fun isAccountNonLocked(): Boolean {
return true
}
override fun isCredentialsNonExpired(): Boolean {
return true
}
override fun isEnabled(): Boolean {
return true
}
companion object {
private val ROLE_PREFIX = "ROLE_"
}
}*/

View File

@ -0,0 +1,5 @@
package com.securityc4po.reporting.extensions
import org.slf4j.LoggerFactory
inline fun <reified T> getLoggerFor() = LoggerFactory.getLogger(T::class.java)!!

View File

@ -0,0 +1,9 @@
package com.securityc4po.reporting.http
import org.springframework.http.HttpHeaders
object ApplicationHeaders {
const val AUTHORIZATION = HttpHeaders.AUTHORIZATION
const val APPLICATION_NAME = "SecurityC4PO_Reporting"
const val XVERSION = 1
}

View File

@ -0,0 +1,26 @@
package com.securityc4po.reporting.http
import com.securityc4po.reporting.extensions.getLoggerFor
import org.springframework.context.annotation.Bean
import org.springframework.stereotype.Component
import org.springframework.web.server.WebFilter
@Component
class RequestLogInterceptor {
private val logger = getLoggerFor<RequestLogInterceptor>()
@Bean
fun loggingFilter(): WebFilter =
WebFilter { exchange, chain ->
val request = exchange.request
if (request.headers.getFirst(ApplicationHeaders.AUTHORIZATION) == null) {
logger.warn("No Authorization header present for request: ${request.id}")
}
logger.info(
"Request recognized: [id: ${request.id}, method=${request.method}, " +
"path=${request.path.pathWithinApplication()}, params=[${request.queryParams}] }"
)
val result = chain.filter(exchange)
return@WebFilter result
}
}

View File

@ -0,0 +1,44 @@
package com.securityc4po.reporting.remote
import com.securityc4po.reporting.http.ApplicationHeaders
import com.securityc4po.reporting.remote.model.ProjectReport
import org.springframework.core.ParameterizedTypeReference
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.util.UriComponentsBuilder
import reactor.core.publisher.Mono
@Component
class APIClient(
private val apiClientCfg: APIClientCfg,
private val webClientBuilder: WebClient.Builder
) {
private val webClient by lazy {
webClientBuilder
.baseUrl(apiClientCfg.url.toString())
.defaultHeader("Application-Name", ApplicationHeaders.APPLICATION_NAME)
.build()
}
/**
* Retrieves the [ProjectReport] data from api service getProjectReportDataById()
*
* @param projectId String id
* @param token of String
* @return of [ProjectReport]
*/
fun retrieveProjectDataById(projectId: String, token: String): Mono<ProjectReport> {
val projectByProjectIdUriBuilder = UriComponentsBuilder
.fromPath(apiClientCfg.projectReport.path)
.queryParam("projectId", projectId)
return webClient.get()
.uri(projectByProjectIdUriBuilder.toUriString())
.headers {
it.add(ApplicationHeaders.AUTHORIZATION, "Bearer $token")
}
.retrieve()
.bodyToMono(object : ParameterizedTypeReference<ProjectReport>() {})
}
}

View File

@ -0,0 +1,22 @@
package com.securityc4po.reporting.remote
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component
import org.springframework.validation.annotation.Validated
import java.net.URL
@ConfigurationProperties("api.client")
@Validated
@Component
class APIClientCfg {
lateinit var url: URL
var projects = ApiPath()
var projectReport = ApiPath()
var pentests = ApiPath()
val findings = ApiPath()
val comments = ApiPath()
}
class ApiPath {
lateinit var path: String
}

View File

@ -0,0 +1,20 @@
package com.securityc4po.reporting.remote
import com.securityc4po.reporting.remote.model.ProjectReport
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
@Service
class APIService(private val apiClient: APIClient) {
/**
* Requests the project data by id
*
* @param id of String
* @param token of String
* @return [ProjectReport]
*/
fun requestProjectDataById(projectId: String, token: String): Mono<ProjectReport> {
return apiClient.retrieveProjectDataById(projectId, token)
}
}

View File

@ -0,0 +1,6 @@
package com.securityc4po.reporting.remote.model
data class CategoryPieData (
val category: String, // ToDo: Change to be PentestCategory enum if it can be read by Jasper
var numberOfFindings: Int
)

View File

@ -0,0 +1,8 @@
package com.securityc4po.reporting.remote.model
data class Comment (
val id: String,
val title: String,
val description: String,
val relatedFindings: List<String>? = emptyList()
)

View File

@ -0,0 +1,19 @@
package com.securityc4po.reporting.remote.model
data class Finding (
val id: String,
val severity: String, // ToDo: Change to be Severity enum if it can be read by Jasper
val title: String,
val description: String,
val impact: String,
val affectedUrls: List<String>? = emptyList(),
val reproduction: String,
val mitigation: String?
)
enum class Severity {
LOW,
MEDIUM,
HIGH,
CRITICAL
}

View File

@ -0,0 +1,32 @@
package com.securityc4po.reporting.remote.model
data class PentestReport(
val id: String,
val category: String, // ToDo: Change to be PentestCategory enum if it can be read by Jasper
val refNumber: String,
val findings: List<Finding>,
val comments: List<Comment>,
var status: PentestStatus
)
enum class PentestStatus {
NOT_STARTED,
DISABLED,
OPEN,
IN_PROGRESS,
COMPLETED
}
enum class PentestCategory {
INFORMATION_GATHERING,
CONFIGURATION_AND_DEPLOY_MANAGEMENT_TESTING,
IDENTITY_MANAGEMENT_TESTING,
AUTHENTICATION_TESTING,
AUTHORIZATION_TESTING,
SESSION_MANAGEMENT_TESTING,
INPUT_VALIDATION_TESTING,
ERROR_HANDLING,
CRYPTOGRAPHY,
BUSINESS_LOGIC_TESTING,
CLIENT_SIDE_TESTING
}

View File

@ -0,0 +1,16 @@
package com.securityc4po.reporting.remote.model
import com.fasterxml.jackson.annotation.JsonFormat
import java.time.Instant
data class ProjectReport(
val id: String,
val client: String,
val title: String,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
val createdAt: String = Instant.now().toString(),
val tester: String,
val summary: String? = null,
var projectPentestReport: List<PentestReport> = emptyList(),
val createdBy: String
)

View File

@ -0,0 +1,6 @@
package com.securityc4po.reporting.remote.model
data class SeverityPieData (
val severity: String, // ToDo: Change to be Severity enum if it can be read by Jasper
var numberOfFindings: Int
)

View File

@ -0,0 +1,68 @@
package com.securityc4po.reporting.report
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.securityc4po.reporting.extensions.getLoggerFor
import com.securityc4po.reporting.remote.APIService
import com.securityc4po.reporting.remote.model.ProjectReport
import org.apache.pdfbox.io.IOUtils
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.notFound
import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.switchIfEmpty
import java.io.File
// import com.securityc4po.reporting.configuration.security.Appuser
// import org.springframework.security.core.annotation.AuthenticationPrincipal
@RestController
@RequestMapping("/reports")
@CrossOrigin(
origins = [],
allowCredentials = "false",
allowedHeaders = ["*"],
methods = [RequestMethod.GET]
)
class ReportController(private val apiService: APIService, private val reportService: ReportService) {
var logger = getLoggerFor<ReportController>()
@GetMapping(
"/{projectId}/pdf",
produces = [MediaType.APPLICATION_PDF_VALUE]
)
fun downloadPentestReportPDF(@PathVariable(value = "projectId") projectId: String/*, @AuthenticationPrincipal user: Appuser*/): Mono<ResponseEntity<ByteArray>> {
// Todo: Create Report with Jasper
// this.apiService.requestProjectDataById(projectId, user.token)
val jsonProjectReportString: String =
File("./src/test/resources/ProjectReportData.json").readText(Charsets.UTF_8)
val jsonProjectReportCollection: ProjectReport =
jacksonObjectMapper().readValue<ProjectReport>(jsonProjectReportString)
return this.reportService.createReport(jsonProjectReportCollection, "pdf").map { reportClassLoaderFilePatch ->
val reportRessourceStream = ReportController::class.java.getResourceAsStream(reportClassLoaderFilePatch)
val response = IOUtils.toByteArray(reportRessourceStream)
this.reportService.cleanUpFiles()
ResponseEntity.ok().body(response)
}.switchIfEmpty {
Mono.just(notFound().build<ByteArray>())
}
}
// ToDo: Add download API for csv report
/*
@GetMapping(
"/{projectId}/csv",
produces = ["text/csv"]
)
fun downloadPentestReportCSV() {}
*/
// ToDo: Add download API for html report
/*
@GetMapping(
"/{projectId}/html",
produces = ["text/html"]
)
fun downloadPentestReportHTML() {}
*/
}

View File

@ -0,0 +1,367 @@
package com.securityc4po.reporting.report
import com.securityc4po.reporting.extensions.getLoggerFor
import com.securityc4po.reporting.remote.model.*
import net.sf.jasperreports.engine.*
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
import org.apache.commons.io.FileUtils
import org.apache.pdfbox.multipdf.PDFMergerUtility
import org.springframework.stereotype.Service
import org.springframework.util.ResourceUtils
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toMono
import java.io.File
@Service
/*
* This Service makes use of the created Jasper Templates
* https://community.jaspersoft.com/system/files/restricted-docs/jaspersoft-studio-user-guide.pdf
*/
class ReportService {
var logger = getLoggerFor<ReportService>()
private val reportCoverDesignTemplate = "./src/main/resources/jasper/reports/c4po_cover.jrxml"
private val reportContentDesignTemplate = "./src/main/resources/jasper/reports/c4po_content.jrxml"
private val reportStateOfConfidentialityDesignTemplate = "./src/main/resources/jasper/reports/c4po_state_of_confidentiality.jrxml"
private val reportExecutiveSummaryDesignTemplate = "./src/main/resources/jasper/reports/c4po_executive_summary.jrxml"
private val reportPentestsDesignTemplate = "./src/main/resources/jasper/reports/c4po_pentests.jrxml"
private val reportAppendenciesDesignTemplate = "./src/main/resources/jasper/reports/c4po_appendencies.jrxml"
// Path to default pdf file
private val reportDefaultPdf = "./src/main/resources/jasper/DEFAULT.pdf"
// Path where the created Reports are saved
private val reportDestination = "./src/main/resources/jasper/reportPDFs/"
// Path where the completed Report is saved
private val reportFileDestination = "./src/main/resources/jasper/finalReport/"
// Path where the completed Report can be found by class loader
private val reportFileForClassLoader = "/jasper/finalReport/"
fun createReport(projectReportCollection: ProjectReport, reportFormat: String): Mono<String> {
val C4POPentestReport: PDFMergerUtility = PDFMergerUtility()
val reportFilePathDestination: String = reportFileDestination + projectReportCollection.title.replace(" ", "_") + "_report.pdf"
val reportFilePathForClassLoader: String = reportFileForClassLoader + projectReportCollection.title.replace(" ", "_") + "_report.pdf"
// Try to create report files & merge them together
return try {
// Create report files
val coverFile: File = createCover(projectReportCollection, reportFormat)
val contentFile: File = createTableOfContent(projectReportCollection, reportFormat)
val confidentialityFile: File = createStateOfConfidentiality(projectReportCollection, reportFormat)
val summaryFile: File = createExecutiveSummary(projectReportCollection, reportFormat)
val pentestFiles: List<File> = createPentestReports(projectReportCollection, reportFormat)
val appendenciesFile: File = createAppendencies(reportFormat)
// Add files to [C4POPentestReport]
C4POPentestReport.addSource(coverFile)
C4POPentestReport.addSource(contentFile)
C4POPentestReport.addSource(confidentialityFile)
C4POPentestReport.addSource(summaryFile)
// Merge every Pentestreport file in List of File
pentestFiles.forEach { pentestFile -> C4POPentestReport.addSource(pentestFile) }
C4POPentestReport.addSource(appendenciesFile)
// Save completed report
C4POPentestReport.destinationFileName = reportFilePathDestination
C4POPentestReport.mergeDocuments()
reportFilePathForClassLoader.toMono()
} catch (e: Exception) {
logger.error("Report generation failed.")
Mono.just("")
}
}
fun cleanUpFiles() {
val cleanUpDirectoryReportsPath = "./src/main/resources/jasper/reportPDFs"
val cleanUpDirectoryCompletedReportsPath = "./src/main/resources/jasper/finalReport"
try {
FileUtils.cleanDirectory(File(cleanUpDirectoryReportsPath))
FileUtils.cleanDirectory(File(cleanUpDirectoryCompletedReportsPath))
} catch (e: Exception) {
logger.error("Report file cleanup failed with exception: ", e)
}
}
private fun createCover(projectReportCollection: ProjectReport, reportFormat: String): File {
// Load Jasper Files
val fileCover: File = ResourceUtils.getFile(reportCoverDesignTemplate)
// Compile Jasper Reports
val jasperReportCover: JasperReport = JasperCompileManager.compileReport(fileCover.absolutePath)
// Setup Main Datasource
val dataSource: JRBeanCollectionDataSource = JRBeanCollectionDataSource(mutableListOf(projectReportCollection))
// Setup Parameter & add Sub-datasets
val parameters = HashMap<String, Any>()
// Fill Reports
val jasperPrintCover: JasperPrint = JasperFillManager.fillReport(jasperReportCover, parameters, dataSource)
// Create File
var finalFile: File = File(reportDefaultPdf)
return if (reportFormat.equals("pdf")) {
JasperExportManager.exportReportToPdfFile(jasperPrintCover, reportDestination + "A_Cover.pdf")
finalFile = File(reportDestination + "A_Cover.pdf")
finalFile
} else {
// ToDo: Implement different report formats
finalFile
}
}
private fun createTableOfContent(projectReportCollection: ProjectReport, reportFormat: String): File {
// Load Jasper Files
val fileContent: File = ResourceUtils.getFile(reportContentDesignTemplate)
// Compile Jasper Reports
val jasperReportContent: JasperReport = JasperCompileManager.compileReport(fileContent.absolutePath)
// Setup Sub-dataset for Table of Content generation
val projectPentestReportDataSource: JRBeanCollectionDataSource =
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport)
// Setup Parameter & add Sub-datasets
val parameters = HashMap<String, Any>()
parameters["ProjectPentestReportDataSource"] = projectPentestReportDataSource
// Fill Reports
val jasperPrintContent: JasperPrint =
JasperFillManager.fillReport(jasperReportContent, parameters, JREmptyDataSource())
// Create File
var finalFile: File = File(reportDefaultPdf)
return if (reportFormat.equals("pdf")) {
JasperExportManager.exportReportToPdfFile(jasperPrintContent, reportDestination + "B_Content.pdf")
finalFile = File(reportDestination + "B_Content.pdf")
finalFile
} else {
// ToDo: Implement different report formats
finalFile
}
}
private fun createStateOfConfidentiality(projectReportCollection: ProjectReport, reportFormat: String): File {
// Load Jasper Files
val fileContent: File = ResourceUtils.getFile(reportStateOfConfidentialityDesignTemplate)
// Compile Jasper Reports
val jasperReportContent: JasperReport = JasperCompileManager.compileReport(fileContent.absolutePath)
// Setup Main Datasource
val dataSource: JRBeanCollectionDataSource = JRBeanCollectionDataSource(mutableListOf(projectReportCollection))
// Setup Parameter & add Sub-datasets
val parameters = HashMap<String, Any>()
// Fill Reports
val jasperPrintContent: JasperPrint = JasperFillManager.fillReport(jasperReportContent, parameters, dataSource)
// Create File
var finalFile: File = File(reportDefaultPdf)
return if (reportFormat.equals("pdf")) {
JasperExportManager.exportReportToPdfFile(
jasperPrintContent,
reportDestination + "C_StateOfConfidentiality.pdf"
)
finalFile = File(reportDestination + "C_StateOfConfidentiality.pdf")
finalFile
} else {
// ToDo: Implement different report formats
finalFile
}
}
private fun createExecutiveSummary(projectReportCollection: ProjectReport, reportFormat: String): File {
// Load Jasper Files
val fileContent: File = ResourceUtils.getFile(reportExecutiveSummaryDesignTemplate)
// Compile Jasper Reports
val jasperReportContent: JasperReport = JasperCompileManager.compileReport(fileContent.absolutePath)
// Setup Main Datasource
val dataSource: JRBeanCollectionDataSource = JRBeanCollectionDataSource(mutableListOf(projectReportCollection))
// Setup Sub-dataset for pentest evaluation pie charts
// Setup CategoryPieDataSet for each Category
val categoryFindings: MutableList<CategoryPieData> = mutableListOf<CategoryPieData>(
CategoryPieData("INFORMATION_GATHERING", 0),
CategoryPieData("CONFIGURATION_AND_DEPLOY_MANAGEMENT_TESTING", 0),
CategoryPieData("IDENTITY_MANAGEMENT_TESTING", 0),
CategoryPieData("AUTHENTICATION_TESTING", 0),
CategoryPieData("AUTHORIZATION_TESTING", 0),
CategoryPieData("SESSION_MANAGEMENT_TESTING", 0),
CategoryPieData("INPUT_VALIDATION_TESTING", 0),
CategoryPieData("ERROR_HANDLING", 0),
CategoryPieData("CRYPTOGRAPHY", 0),
CategoryPieData("BUSINESS_LOGIC_TESTING", 0),
CategoryPieData("CLIENT_SIDE_TESTING", 0)
)
// Fill data for CategoryPieDataSet
for (i in 0 until projectReportCollection.projectPentestReport.size) {
when (projectReportCollection.projectPentestReport[i].category) {
"INFORMATION_GATHERING" -> {
categoryFindings[0].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"CONFIGURATION_AND_DEPLOY_MANAGEMENT_TESTING" -> {
categoryFindings[1].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"IDENTITY_MANAGEMENT_TESTING" -> {
categoryFindings[2].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"AUTHENTICATION_TESTING" -> {
categoryFindings[3].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"AUTHORIZATION_TESTING" -> {
categoryFindings[4].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"SESSION_MANAGEMENT_TESTING" -> {
categoryFindings[5].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"INPUT_VALIDATION_TESTING" -> {
categoryFindings[6].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"ERROR_HANDLING" -> {
categoryFindings[7].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"CRYPTOGRAPHY" -> {
categoryFindings[8].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size
}
"BUSINESS_LOGIC_TESTING" -> {
categoryFindings[9].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size - 1
}
"CLIENT_SIDE_TESTING" -> {
categoryFindings[10].numberOfFindings += projectReportCollection.projectPentestReport[i].findings.size - 1
}
else -> {
categoryFindings.add(
CategoryPieData(
"UNKNOWN_CATEGORY",
projectReportCollection.projectPentestReport[i].findings.size
)
)
}
}
}
val categoryFindingsDataSource: JRBeanCollectionDataSource = JRBeanCollectionDataSource(categoryFindings)
// Setup SeverityPieData for each Severity
val severityFindings: MutableList<SeverityPieData> = mutableListOf<SeverityPieData>(
SeverityPieData("LOW", 0),
SeverityPieData("MEDIUM", 0),
SeverityPieData("HIGH", 0),
SeverityPieData("CRITICAL", 0)
)
// Fill data for SeverityPieData
for (i in 0 until projectReportCollection.projectPentestReport.size) {
for (j in 0 until projectReportCollection.projectPentestReport[i].findings.size) {
when (projectReportCollection.projectPentestReport[i].findings[j].severity) {
"LOW" -> {
severityFindings[0].numberOfFindings += 1
}
"MEDIUM" -> {
severityFindings[1].numberOfFindings += 1
}
"HIGH" -> {
severityFindings[2].numberOfFindings += 1
}
"CRITICAL" -> {
severityFindings[3].numberOfFindings += 1
}
else -> {
severityFindings.add(
SeverityPieData(
"UNKNOWN_SEVERITY",
projectReportCollection.projectPentestReport[i].findings.size
)
)
}
}
}
}
val severityFindingsDataSource: JRBeanCollectionDataSource = JRBeanCollectionDataSource(severityFindings)
// Setup Parameter & add Sub-datasets
val parameters = HashMap<String, Any>()
parameters["CategoryFindingsPieChartDataSource"] = categoryFindingsDataSource
parameters["SeverityFindingsPieChartDataSource"] = severityFindingsDataSource
// Fill Reports
val jasperPrintContent: JasperPrint = JasperFillManager.fillReport(jasperReportContent, parameters, dataSource)
// Create File
var finalFile: File = File(reportDefaultPdf)
return if (reportFormat.equals("pdf")) {
JasperExportManager.exportReportToPdfFile(jasperPrintContent,reportDestination + "D_ExecutiveSummary.pdf")
finalFile = File(reportDestination + "D_ExecutiveSummary.pdf")
finalFile
} else {
// ToDo: Implement different report formats
finalFile
}
}
private fun createPentestReports(projectReportCollection: ProjectReport, reportFormat: String): List<File> {
// Create List of Files
var finalFiles: List<File> = emptyList()
// Load Jasper Files
val filePentests: File = ResourceUtils.getFile(reportPentestsDesignTemplate)
// Compile Jasper Reports
val jasperReportPentests: JasperReport = JasperCompileManager.compileReport(filePentests.absolutePath)
// Create pentestReport content for every objective
for (i in 0 until projectReportCollection.projectPentestReport.size) {
val projectSinglePentestReportDataSource: JRBeanCollectionDataSource =
JRBeanCollectionDataSource(mutableListOf(projectReportCollection.projectPentestReport[i]))
// Setup Sub-dataset for Findings of Pentest
val pentestFindingsDataSource: JRBeanCollectionDataSource =
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport[i].findings)
// Setup Sub-dataset for Comments of Pentest
// val pentestCommentsDataSource =
// Setup Parameter & add Sub-datasets
val parameters = HashMap<String, Any>()
parameters["PentestFindingsDataSource"] = if (projectReportCollection.projectPentestReport[i].findings.isNotEmpty()) {
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport[i].findings)
} else {
JRBeanCollectionDataSource(emptyList<Finding>())
}
parameters["PentestCommentsDataSource"] = if (projectReportCollection.projectPentestReport[i].comments.isNotEmpty()) {
JRBeanCollectionDataSource(projectReportCollection.projectPentestReport[i].comments)
} else {
JRBeanCollectionDataSource(emptyList<Comment>())
}
// Fill Reports
// Print one report for each objective and merge them together afterwards
val jasperPrintPentests: JasperPrint =
JasperFillManager.fillReport(jasperReportPentests, parameters, projectSinglePentestReportDataSource)
// Create File
var finalFile: File = File(reportDefaultPdf)
if (reportFormat.equals("pdf")) {
JasperExportManager.exportReportToPdfFile(
jasperPrintPentests,
reportDestination + "E" + i.toString() + "_Pentestreport.pdf"
)
finalFile = File(reportDestination + "E" + i.toString() + "_Pentestreport.pdf")
finalFiles += (finalFile)
} else {
// ToDo: Implement different report formats
finalFiles += (finalFile)
}
}
return finalFiles
}
private fun createAppendencies(reportFormat: String): File {
// Load Jasper Files
val fileCover: File = ResourceUtils.getFile(reportAppendenciesDesignTemplate)
// Compile Jasper Reports
val jasperReportCover: JasperReport = JasperCompileManager.compileReport(fileCover.absolutePath)
// Setup Parameter & add Sub-datasets
val parameters = HashMap<String, Any>()
parameters["SeverityRatingDefinition"] = JREmptyDataSource()
// Fill Reports
val jasperPrintCover: JasperPrint =
JasperFillManager.fillReport(jasperReportCover, parameters, JREmptyDataSource())
// Create File
var finalFile: File = File(reportDefaultPdf)
return if (reportFormat.equals("pdf")) {
JasperExportManager.exportReportToPdfFile(jasperPrintCover, reportDestination + "F_Appendencies.pdf")
finalFile = File(reportDestination + "F_Appendencies.pdf")
finalFile
} else {
// ToDo: Implement different report formats
finalFile
}
}
}

View File

@ -0,0 +1,15 @@
package com.securityc4po.reporting.report.jasper
import net.sf.jasperreports.engine.JRDataSource
import net.sf.jasperreports.engine.JRField
class JRDbDataSource: JRDataSource {
override fun next(): Boolean {
TODO("Not yet implemented")
}
override fun getFieldValue(jrField: JRField?): Any {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,32 @@
package com.securityc4po.reporting.report.jasper
import com.securityc4po.reporting.report.jasper.export.JasperOutputFormat
import net.sf.jasperreports.engine.JRDataSource
import net.sf.jasperreports.engine.JREmptyDataSource
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.sql.Connection
/**
* First shot of a so called report which holds all data which is relevant for a report to be able to be generated.
* This should be extended as necessary. When extending it should be made sure that it is as abstract as possible and
* also non blocking (streams over locations).
* A special thing about this report context is that it is a composite or a recursive structure. This enables us to use
* subreports. This structure can be simplified when we get a better understanding of Jasper whether it is for example
* allowed that subreports can have their own datasources and so on.
*/
data class JasperReportContext(
val name: String,
val format: JasperOutputFormat,
val designFileHash: String,
val source: InputStream,
val target: ByteArrayOutputStream,
val subReports: List<JasperReportContext> = emptyList(),
val dataSource: JRDataSource? = JREmptyDataSource(),
val dataSourceConnection: Connection? = null,
val parameters: Map<String, Any>? = mutableMapOf()
) {
override fun equals(other: Any?): Boolean {
return super.equals(other)
}
}

View File

@ -0,0 +1,29 @@
package com.securityc4po.reporting.report.jasper
import reactor.core.publisher.Flux
import java.nio.file.Files
import java.nio.file.Path
import java.security.MessageDigest
import java.util.stream.Stream
import javax.xml.bind.DatatypeConverter
class ReactiveFileUtil {
companion object {
fun readFile(path: Path): Flux<String> {
return Flux.using(
{ Files.lines(path) },
{ s: Stream<String>? -> Flux.fromStream(s!!) }
) { obj: Stream<String> -> obj.close() }
}
fun md5(input: String) = hashString("MD5", input)
fun sha1(input: String) = hashString("SHA-1", input)
private fun hashString(type: String, input: String): String {
val bytes = MessageDigest
.getInstance(type)
.digest(input.toByteArray())
return DatatypeConverter.printHexBinary(bytes).toUpperCase()
}
}
}

View File

@ -0,0 +1,9 @@
package com.securityc4po.reporting.report.jasper
import net.sf.jasperreports.engine.JasperPrint
interface ReportExporter {
fun export(reportContext: JasperReportContext, filledReports: List<JasperPrint>)
}

View File

@ -0,0 +1,11 @@
package com.securityc4po.reporting.report.jasper
import java.io.File
class ReportUtil {
companion object {
fun extractReportName(reportFile: File): String {
return reportFile.name.replace(".${reportFile.extension}", "")
}
}
}

View File

@ -0,0 +1,26 @@
package com.securityc4po.reporting.report.jasper.export
import com.securityc4po.reporting.report.jasper.ReportExporter
enum class JasperOutputFormat {
PDF,
CSV,
HTML,
XLS;
companion object {
fun fileEnding(format: JasperOutputFormat): String {
return ".${format.name.toLowerCase()}"
}
fun createExporter(format: JasperOutputFormat): ReportExporter {
return when(format) {
PDF -> ReportExporterPDF()
/*CSV -> ReportExporterCSV()
HTML -> ReportExporterHTML()
XLS -> ReportExporterXLS()*/
else -> {ReportExporterPDF()}
}
}
}
}

View File

@ -0,0 +1,35 @@
package com.securityc4po.reporting.report.jasper.export
import com.securityc4po.reporting.report.jasper.JasperReportContext
import com.securityc4po.reporting.report.jasper.ReportExporter
import net.sf.jasperreports.engine.JasperPrint
import net.sf.jasperreports.engine.export.JRPdfExporter
import net.sf.jasperreports.export.SimpleExporterInput
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput
import net.sf.jasperreports.export.SimplePdfExporterConfiguration
import net.sf.jasperreports.export.SimplePdfReportConfiguration
class ReportExporterPDF: ReportExporter {
override fun export(reportContext: JasperReportContext, filledReports: List<JasperPrint>) {
val exporter = JRPdfExporter()
exporter.setExporterInput(SimpleExporterInput.getInstance(filledReports))
exporter.exporterOutput = SimpleOutputStreamExporterOutput(reportContext.target)
// TODO make report ReportExportConfiguration customizable? -> parameter?
val reportConfig = SimplePdfReportConfiguration()
reportConfig.isSizePageToContent = true
reportConfig.isForceLineBreakPolicy = false
// TODO make ExporterConfiguration customizable? -> parameter?
val exportConfig = SimplePdfExporterConfiguration()
exportConfig.metadataAuthor = "Author"
exportConfig.isEncrypted = true
exportConfig.setAllowedPermissionsHint("PRINTING")
exporter.setConfiguration(reportConfig)
exporter.setConfiguration(exportConfig)
exporter.exportReport()
}
}

View File

@ -0,0 +1,30 @@
## General Properties ##
# spring.main.web-application-type=reactive
spring.main.allow-bean-definition-overriding=true
spring.jackson.default-property-inclusion=non_null
## Server Config ##
server.port=8444
## Actuator Endpoints ##
management.endpoints.enabled-by-default=false
management.endpoint.health.enabled=true
management.endpoints.web.exposure.include=info, health, metrics
## C4PO_ApiService ##
api.client.url=http://localhost:8443/
api.client.projects.path=projects
api.client.projectReport.path=projects/report
api.client.pentests.path=pentests
api.client.findings.path=pentests/findings
api.client.comments.path=pentests/comments
## IdentityProvider (Keycloak) ##
# spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8888/auth/realms/c4po_realm_local
# keycloakhost=localhost
# keycloak.client.url=http://localhost:8888
# keycloak.client.realm.path=auth/realms/c4po_realm_local/
## Total number of pentests listet in the OWASP testing guide
## https://owasp.org/www-project-web-security-testing-guide/assets/archive/OWASP_Testing_Guide_v4.pdf
owasp.web.pentests=95

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,553 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_Appendencies" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="dd2c2daf-6b71-4752-8ed0-e25ae2523a51">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<queryString>
<![CDATA[]]>
</queryString>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="47" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="0" width="573" height="30" forecolor="#232B44" backcolor="#232B44" uuid="cc5cd9d2-1739-472f-8591-007eee7de961"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<ellipse>
<reportElement x="537" y="0" width="30" height="30" backcolor="#232B44" uuid="ce224d19-10b2-46f4-8dd9-a397a5c7aef2"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<image>
<reportElement x="539" y="3" width="23" height="24" uuid="74214b7e-f089-49f2-9ef9-ef134386750c"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/Watermark.png"]]></imageExpression>
</image>
<staticText>
<reportElement x="0" y="0" width="432" height="30" forecolor="#FFFFFF" uuid="cb237865-2647-4ee2-a85c-ebc5c8f84f9e"/>
<textElement verticalAlignment="Middle">
<font size="16" isBold="true"/>
</textElement>
<text><![CDATA[Appendencies]]></text>
</staticText>
</band>
</title>
<detail>
<band height="540" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="280" height="20" forecolor="#232B44" uuid="32713af0-e0bd-432b-b369-db31f8617e26"/>
<textElement>
<font size="12" isBold="true"/>
</textElement>
<text><![CDATA[Findings Severities]]></text>
</staticText>
<staticText>
<reportElement x="0" y="20" width="553" height="50" uuid="e43d5ec6-84d5-4d8e-9aca-94c3c48697e8"/>
<textElement>
<font size="12"/>
</textElement>
<text><![CDATA[Each finding has been assigned a severity rating of critical high, medium, or low. The rating is based off of an assessment of the priority with which each finding should be viewed and the potential impact each has on the confidentiality, integrity, and availability.]]></text>
</staticText>
<subreport>
<reportElement positionType="Float" x="-3" y="510" width="553" height="30" uuid="ca9b0ff4-30c6-43d0-8da2-458d1960ef0b"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.JREmptyDataSource()]]></dataSourceExpression>
<subreportExpression><![CDATA["./src/main/resources/jasper/subreports/"+"SeverityRatingTableSubreport.jasper"]]></subreportExpression>
</subreport>
<staticText>
<reportElement x="0" y="83" width="280" height="20" forecolor="#232B44" uuid="147e164e-f290-4751-82ca-e4b55508408f"/>
<textElement>
<font size="12" isBold="true"/>
</textElement>
<text><![CDATA[Risk Matrix]]></text>
</staticText>
<rectangle>
<reportElement x="0" y="162" width="70" height="27" backcolor="#232B44" uuid="71a50420-4cd9-4b6a-b84d-80d3f860562b"/>
</rectangle>
<rectangle>
<reportElement x="0" y="189" width="70" height="27" backcolor="#232B44" uuid="981168d3-aabf-4390-81f5-3da4accedacb"/>
</rectangle>
<rectangle>
<reportElement x="0" y="216" width="70" height="27" backcolor="#232B44" uuid="c5c0d73b-fa7d-4714-a56e-2b054dd07e90"/>
</rectangle>
<rectangle>
<reportElement x="0" y="243" width="70" height="27" backcolor="#232B44" uuid="cc5c4219-5c9f-451c-9ef1-f1b631625a53"/>
</rectangle>
<rectangle>
<reportElement x="70" y="162" width="120" height="27" backcolor="#232B44" uuid="2a0b9744-8651-4a13-ba0c-f2b74f81c58b"/>
</rectangle>
<textField>
<reportElement x="0" y="162" width="70" height="26" forecolor="#FFFFFF" uuid="e339fe11-71e6-4ca3-b0a6-ba6cc18bf655"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Risk score"]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="0" y="270" width="70" height="27" backcolor="#232B44" uuid="318d3354-5dd7-4585-b609-4e56c2db0cfc"/>
</rectangle>
<textField>
<reportElement x="70" y="162" width="120" height="26" forecolor="#FFFFFF" uuid="80821d8f-03fd-42bb-907b-2049ecdb8d43"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Risk level category"]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="0" y="297" width="70" height="135" backcolor="#232B44" uuid="87004217-c837-4b5a-98a5-8007ba939214"/>
</rectangle>
<rectangle>
<reportElement x="70" y="189" width="120" height="27" backcolor="#01D68F" uuid="dea95328-d4c3-4a63-bccd-022c65dd611d"/>
</rectangle>
<textField>
<reportElement x="80" y="189" width="100" height="26" forecolor="#FFFFFF" uuid="b21bdbfa-910d-45d6-8bb0-3797ee1b49e2"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="70" y="216" width="120" height="27" backcolor="#35A4FE" uuid="3254bdd7-5edb-42cf-bab6-0e1a7008ca2b"/>
</rectangle>
<rectangle>
<reportElement x="70" y="243" width="120" height="27" backcolor="#FFAB00" uuid="cb019ffa-342a-4f3f-8b04-08ab4a486ea3"/>
</rectangle>
<rectangle>
<reportElement x="70" y="270" width="120" height="27" backcolor="#FF3D70" uuid="578bc2cd-50f2-4d6a-b2f7-f77c76007e7d"/>
</rectangle>
<textField>
<reportElement x="80" y="216" width="100" height="26" forecolor="#FFFFFF" uuid="23e08f29-89d8-4ce2-b320-1fac1074d8b2"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="80" y="243" width="100" height="26" forecolor="#FFFFFF" uuid="076a9ebd-c3d6-4c0a-8b2a-df1a8e4600b8"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["High"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="80" y="270" width="100" height="26" forecolor="#FFFFFF" uuid="ee724a01-8cf0-4c92-a327-11c4002cfafe"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Critical"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="309" width="70" height="110" forecolor="#FFFFFF" uuid="44517da7-70bb-4224-957c-cb05dfb3be0c"/>
<textElement textAlignment="Center" verticalAlignment="Middle" rotation="Left">
<font size="14" isBold="true" isItalic="true"/>
</textElement>
<textFieldExpression><![CDATA["Severity"]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="190" y="162" width="345" height="81" backcolor="#232B44" uuid="fcfd3c38-9b82-4492-b52e-037be743c7b5"/>
</rectangle>
<textField>
<reportElement x="190" y="172" width="344" height="60" forecolor="#FFFFFF" uuid="6a52e378-0f70-4a8d-943f-42b24454bd89"/>
<textElement textAlignment="Center" verticalAlignment="Middle" rotation="None">
<font size="14" isBold="true" isItalic="true"/>
</textElement>
<textFieldExpression><![CDATA["Likelihood"]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="190" y="243" width="69" height="55" backcolor="#232B44" uuid="d6f79cc1-0658-442e-8e95-f0af4e56043a"/>
</rectangle>
<rectangle>
<reportElement x="259" y="243" width="69" height="55" backcolor="#232B44" uuid="d0d15a53-6521-4524-a49e-e08a20bb24f3"/>
</rectangle>
<rectangle>
<reportElement x="328" y="243" width="69" height="55" backcolor="#232B44" uuid="563c3a03-e1de-43ba-936a-d0e8de05d3d3"/>
</rectangle>
<rectangle>
<reportElement x="397" y="243" width="69" height="55" backcolor="#232B44" uuid="24250a69-7294-459a-a114-77c49a11690c"/>
</rectangle>
<rectangle>
<reportElement x="466" y="243" width="69" height="55" backcolor="#232B44" uuid="d80b908b-0ef3-48fb-8282-914b07a9a6a1"/>
</rectangle>
<rectangle>
<reportElement x="70" y="297" width="121" height="27" backcolor="#232B44" uuid="c9bfbde3-2012-42dd-9702-2171734a83c0"/>
</rectangle>
<rectangle>
<reportElement x="328" y="297" width="69" height="27" backcolor="#FFAB00" uuid="81772667-1e77-4052-b360-6de4f6a685da"/>
</rectangle>
<rectangle>
<reportElement x="70" y="324" width="121" height="27" backcolor="#232B44" uuid="0add25ed-9cf2-4c31-88d8-f4df5c62e883"/>
</rectangle>
<rectangle>
<reportElement x="70" y="351" width="121" height="27" backcolor="#232B44" uuid="d72b969e-3537-49e1-a840-4030a2646bf3"/>
</rectangle>
<rectangle>
<reportElement x="70" y="378" width="130" height="27" backcolor="#232B44" uuid="e5566809-cb09-4d6b-abb5-a8d9c683b464"/>
</rectangle>
<rectangle>
<reportElement x="70" y="405" width="130" height="27" backcolor="#232B44" uuid="c2961bbe-9fe1-45fe-8940-baa8334b5dff"/>
</rectangle>
<rectangle>
<reportElement x="190" y="297" width="69" height="27" backcolor="#35A4FE" uuid="f79cf14d-d1dc-4072-a761-26cbfb2e2499"/>
</rectangle>
<rectangle>
<reportElement x="259" y="297" width="69" height="27" backcolor="#35A4FE" uuid="5cdf6b3c-c523-4486-8304-b5845a9e9219"/>
</rectangle>
<rectangle>
<reportElement x="397" y="297" width="69" height="27" backcolor="#FF3D70" uuid="b1f96b91-e01a-4ed7-a146-24d643ed93b6"/>
</rectangle>
<rectangle>
<reportElement x="466" y="297" width="69" height="27" backcolor="#FF3D70" uuid="51fd00e0-7252-4c94-b582-fcd6275d462a"/>
</rectangle>
<rectangle>
<reportElement x="190" y="405" width="69" height="27" backcolor="#01D68F" uuid="b67969c8-2f0c-4705-81a1-a3e378d775c5"/>
</rectangle>
<rectangle>
<reportElement x="190" y="324" width="69" height="27" backcolor="#01D68F" uuid="35b8dfe6-8283-4857-bdec-07f084cb7fcd"/>
</rectangle>
<rectangle>
<reportElement x="190" y="351" width="69" height="27" backcolor="#01D68F" uuid="ec9fcbbd-58ec-4215-8b28-d7f6459f0373"/>
</rectangle>
<rectangle>
<reportElement x="190" y="378" width="69" height="27" backcolor="#01D68F" uuid="f2a5dc00-f507-4704-8572-ac6856f85436"/>
</rectangle>
<rectangle>
<reportElement x="259" y="324" width="69" height="27" backcolor="#35A4FE" uuid="cba2c5ac-3e98-4073-b98c-aaca3120ef02"/>
</rectangle>
<rectangle>
<reportElement x="328" y="324" width="69" height="27" backcolor="#FFAB00" uuid="b9ae2fc9-5d74-4c7e-9b25-1d679497a3d6"/>
</rectangle>
<rectangle>
<reportElement x="397" y="324" width="69" height="27" backcolor="#FFAB00" uuid="739c6b7a-4916-4d5c-99a0-afba58103d81"/>
</rectangle>
<rectangle>
<reportElement x="466" y="324" width="69" height="27" backcolor="#FF3D70" uuid="42df19ae-22e2-41af-b855-4e8887ce4e9e"/>
</rectangle>
<rectangle>
<reportElement x="259" y="351" width="69" height="27" backcolor="#35A4FE" uuid="809167ab-3759-4785-9c7c-43e6550518be"/>
</rectangle>
<rectangle>
<reportElement x="259" y="378" width="69" height="27" backcolor="#01D68F" uuid="6d79a3ab-c876-4bc3-8ed4-3d022830bf6c"/>
</rectangle>
<rectangle>
<reportElement x="259" y="405" width="69" height="27" backcolor="#01D68F" uuid="8f085084-70b7-4bdb-96dc-adbf9a360522"/>
</rectangle>
<rectangle>
<reportElement x="328" y="405" width="69" height="27" backcolor="#01D68F" uuid="5e0a7a42-dbdc-4c3c-8d17-31f6de288e1e"/>
</rectangle>
<rectangle>
<reportElement x="328" y="351" width="69" height="27" backcolor="#35A4FE" uuid="3717f087-0c4a-41d3-b9be-f6f82156e292"/>
</rectangle>
<rectangle>
<reportElement x="328" y="378" width="69" height="27" backcolor="#35A4FE" uuid="3263c8d0-ab9a-4bce-bff9-80db704bc4ef"/>
</rectangle>
<rectangle>
<reportElement x="397" y="351" width="69" height="27" backcolor="#FFAB00" uuid="e8c0da95-97cf-493b-a47e-5fc7ddcc9900"/>
</rectangle>
<rectangle>
<reportElement x="397" y="378" width="69" height="27" backcolor="#35A4FE" uuid="8c7bc3ab-573b-4b9d-9ec3-a26555027520"/>
</rectangle>
<rectangle>
<reportElement x="397" y="405" width="69" height="27" backcolor="#01D68F" uuid="43c782fe-c312-463d-8eae-802fbafde71e"/>
</rectangle>
<rectangle>
<reportElement x="466" y="351" width="69" height="27" backcolor="#FFAB00" uuid="33ee43a1-05d0-4adf-9ccc-eaf8f6f5f745"/>
</rectangle>
<rectangle>
<reportElement x="466" y="378" width="69" height="27" backcolor="#35A4FE" uuid="688174a5-4f75-4576-abd2-3303073d9d0c"/>
</rectangle>
<rectangle>
<reportElement x="466" y="405" width="69" height="27" backcolor="#35A4FE" uuid="06224646-ed1a-442d-be03-4071cda7c249"/>
</rectangle>
<textField>
<reportElement x="191" y="324" width="67" height="26" forecolor="#FFFFFF" uuid="48472f37-d09b-41de-a4b4-accbeeff24dc"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="191" y="352" width="67" height="26" forecolor="#FFFFFF" uuid="f5bfd9b4-9e90-4688-829f-9a23670150a1"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="191" y="379" width="67" height="26" forecolor="#FFFFFF" uuid="708605ba-7dcb-4f2f-9c79-7900c78b5da5"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="191" y="405" width="67" height="26" forecolor="#FFFFFF" uuid="4dce76da-28cb-483b-b687-35ccf1da1079"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="260" y="379" width="67" height="26" forecolor="#FFFFFF" uuid="b162ba73-8beb-4bc5-8d49-15ef4fc3fe39"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="260" y="405" width="67" height="26" forecolor="#FFFFFF" uuid="a3edcc39-6cf9-44f4-9139-e237522d4792"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="406" width="67" height="26" forecolor="#FFFFFF" uuid="96ea36ed-5562-4ca3-bd25-15959ed630c1"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="329" y="406" width="67" height="26" forecolor="#FFFFFF" uuid="68343592-bf57-4c7d-bc96-bd4128215f66"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Low"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="298" width="67" height="26" forecolor="#FFFFFF" uuid="6e361aec-8e15-42d2-a1bb-8dd6aa605b5c"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Critical"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="467" y="298" width="67" height="26" forecolor="#FFFFFF" uuid="f2ed9687-fd93-40c8-a449-9ec035bee86a"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Critical"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="467" y="325" width="67" height="26" forecolor="#FFFFFF" uuid="648382ca-71be-434f-9dd2-fc18b3a9b782"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Critical"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="467" y="352" width="67" height="26" forecolor="#FFFFFF" uuid="34d48479-1f13-4a47-90cd-34e9b00b8ad5"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["High"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="352" width="67" height="26" forecolor="#FFFFFF" uuid="eff6813a-063b-4f07-ac52-077171d5e242"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["High"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="325" width="67" height="26" forecolor="#FFFFFF" uuid="b9b39f04-d428-47ac-b610-4c628a6eeef4"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["High"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="329" y="298" width="67" height="26" forecolor="#FFFFFF" uuid="2f8cfcdc-aca9-4232-9245-53792a4ccb77"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["High"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="329" y="325" width="67" height="26" forecolor="#FFFFFF" uuid="6c6ed175-6e42-4621-96f7-8b1fd18f0e59"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["High"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="260" y="298" width="67" height="26" forecolor="#FFFFFF" uuid="0dc1b554-4bb3-4778-bf71-c3762d1896d1"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="260" y="325" width="67" height="26" forecolor="#FFFFFF" uuid="ee4a4104-166e-4f30-888f-33357fb3644b"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="329" y="379" width="67" height="26" forecolor="#FFFFFF" uuid="443a9ff7-2032-46c3-9dc2-20972aa1271f"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="329" y="352" width="67" height="26" forecolor="#FFFFFF" uuid="c0e34639-1a32-4ec1-b1f0-fee15c001e36"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="467" y="406" width="67" height="26" forecolor="#FFFFFF" uuid="07ff00a4-d3d1-44f4-9ace-8384b67a72a5"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="467" y="379" width="67" height="26" forecolor="#FFFFFF" uuid="ddfd14e3-5e0c-4e30-8487-499b137f0bf8"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="379" width="67" height="26" forecolor="#FFFFFF" uuid="c42c4212-c598-44bf-92ee-4942ed09bdb1"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="260" y="352" width="67" height="26" forecolor="#FFFFFF" uuid="269c7354-f692-4fba-99bd-5fe27ff705ea"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="191" y="298" width="67" height="26" forecolor="#FFFFFF" uuid="2b025744-ec64-4c12-9588-01790f263d49"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Medium"]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="1" y="450" width="553" height="50" uuid="a2abe321-3344-4e53-9e2b-67a415b68e38"/>
<textElement>
<font size="12"/>
</textElement>
<text><![CDATA[Example, if Likelihood = Possible (3) and Severity = Major (4), the risk level is determined by severity * likelihood, which is 3*4 = 12. The score 12 falls in 'High' risk range.]]></text>
</staticText>
<staticText>
<reportElement x="0" y="103" width="552" height="66" uuid="c91f1515-1d18-4c4f-91b8-6c4b957f46db"/>
<textElement>
<font size="12"/>
</textElement>
<text><![CDATA[The risk matrix is used to assess the potential damage of a hazard, based on the likelihood and severity factors. The likelihood and severity scores are multiplied to obtain a score value. This score is looked up in the risk ranges to determine the risk level. An example of a hazard risk matrix is given below:
]]></text>
</staticText>
<textField>
<reportElement x="191" y="243" width="67" height="53" forecolor="#FFFFFF" uuid="0fd887e8-76e4-4098-9a1b-3db131529904"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Rare (1)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="329" y="243" width="67" height="53" forecolor="#FFFFFF" uuid="2508e027-31fb-446d-b0b9-b8e580720852"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Possible (3)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="398" y="243" width="67" height="53" forecolor="#FFFFFF" uuid="ce5f3ba9-6844-4a80-9a42-bf83f214167c"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Likely (4)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="467" y="243" width="67" height="53" forecolor="#FFFFFF" uuid="a56ddfd6-2208-45ca-9520-4382473db1fe"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Almost certain (5)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="70" y="298" width="119" height="26" forecolor="#FFFFFF" uuid="697fe7ea-d9b0-4987-b6bd-81bb86ae494b"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Catastrophic (5)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="70" y="325" width="118" height="26" forecolor="#FFFFFF" uuid="d045b5f3-c8a3-4ccd-90e9-84665d513598"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Major (4)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="70" y="353" width="118" height="26" forecolor="#FFFFFF" uuid="548ef559-8535-492d-a377-bfcea621c7e8"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Moderate (3)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="70" y="380" width="118" height="26" forecolor="#FFFFFF" uuid="e63fdc52-3815-4bbe-982d-bc3407020a0d"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Minor (2)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="70" y="406" width="118" height="26" forecolor="#FFFFFF" uuid="d6b54c01-00d8-46b7-b60f-76d14573a43c"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Insignificant (1)"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="189" width="70" height="26" forecolor="#FFFFFF" uuid="bca9c1cb-f112-41e2-8744-2567e75f1207"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA[1 + " to " + 4]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="216" width="70" height="26" forecolor="#FFFFFF" uuid="d2414371-7103-4bd1-92a1-2ebc2b5810c8"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA[5 + " to " + 10]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="244" width="70" height="26" forecolor="#FFFFFF" uuid="ff567b36-de30-4526-8e54-4a3d15ccc8db"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA[11 + " to " + 18]]></textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="270" width="70" height="26" forecolor="#FFFFFF" uuid="88308555-1cca-43b2-9e43-24ea40df5b8e"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA[19 + " to " + 25]]></textFieldExpression>
</textField>
<textField>
<reportElement x="265" y="243" width="57" height="53" forecolor="#FFFFFF" uuid="8081c1bf-ddd0-4207-a9df-3337e0c84936"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Unlikely (2)"]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>

View File

@ -0,0 +1,229 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_Content" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="3c42fdce-1295-4279-a59a-999f57d99afc">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportData JSON Adapter"/>
<style name="Table_TH" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#FFFFFF"/>
<topPen lineWidth="0.5" lineColor="#FFFFFF"/>
<leftPen lineWidth="0.5" lineColor="#FFFFFF"/>
<bottomPen lineWidth="0.5" lineColor="#FFFFFF"/>
<rightPen lineWidth="0.5" lineColor="#FFFFFF"/>
</box>
</style>
<style name="Table_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#FFFFFF"/>
<topPen lineWidth="0.5" lineColor="#FFFFFF"/>
<leftPen lineWidth="0.5" lineColor="#FFFFFF"/>
<bottomPen lineWidth="0.5" lineColor="#FFFFFF"/>
<rightPen lineWidth="0.5" lineColor="#FFFFFF"/>
</box>
</style>
<style name="Table_CH" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#FFFFFF"/>
<topPen lineWidth="0.5" lineColor="#FFFFFF"/>
<leftPen lineWidth="0.5" lineColor="#FFFFFF"/>
<bottomPen lineWidth="0.5" lineColor="#FFFFFF"/>
<rightPen lineWidth="0.5" lineColor="#FFFFFF"/>
</box>
</style>
<subDataset name="TableOfContent" uuid="ebd355ab-7b52-4ad9-8dcf-238c9d5465e5">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/>
<queryString>
<![CDATA[]]>
</queryString>
<field name="id" class="java.lang.String"/>
<field name="category" class="java.lang.String"/>
<field name="refNumber" class="java.lang.String"/>
<field name="findings" class="java.lang.String"/>
<field name="comments" class="java.lang.String"/>
<field name="status" class="java.lang.String"/>
</subDataset>
<parameter name="ProjectPentestReportDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<queryString language="JSON">
<![CDATA[projectReportData]]>
</queryString>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="50" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="0" width="573" height="30" forecolor="#232B44" backcolor="#232B44" uuid="be4caa3a-e834-45a6-82d3-587930118a1c"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<staticText>
<reportElement x="0" y="0" width="432" height="30" forecolor="#FFFFFF" uuid="59ee1bdf-8502-4520-8bd1-4f6e4d88df61"/>
<textElement verticalAlignment="Middle">
<font size="16" isBold="true"/>
</textElement>
<text><![CDATA[Table of Contents]]></text>
</staticText>
<ellipse>
<reportElement x="537" y="0" width="30" height="30" backcolor="#232B44" uuid="afe21e22-58aa-4b83-ae86-c7ecd482d732"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<image>
<reportElement x="539" y="3" width="23" height="24" uuid="2ca905b3-37c8-40ae-a9ea-3beb016b504c"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/Watermark.png"]]></imageExpression>
</image>
</band>
</title>
<detail>
<band height="464" splitType="Stretch">
<componentElement>
<reportElement x="0" y="0" width="560" height="464" forecolor="#FFFFFF" uuid="925ff93f-70df-4093-a209-f9faaecb205c">
<property name="com.jaspersoft.studio.layout" value="com.jaspersoft.studio.editor.layout.VerticalRowLayout"/>
<property name="com.jaspersoft.studio.table.style.table_header" value="Table_TH"/>
<property name="com.jaspersoft.studio.table.style.column_header" value="Table_CH"/>
<property name="com.jaspersoft.studio.table.style.detail" value="Table_TD"/>
<property name="com.jaspersoft.studio.components.autoresize.proportional" value="true"/>
</reportElement>
<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
<datasetRun subDataset="TableOfContent" uuid="ca33a240-1f7b-4729-a278-6148b82621a5">
<dataSourceExpression><![CDATA[$P{ProjectPentestReportDataSource}]]></dataSourceExpression>
</datasetRun>
<jr:column width="400" uuid="e1ddda3b-a51b-4ebc-ab41-72ba37cb90fc">
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column1"/>
<jr:tableHeader style="Table_TH" height="30" rowSpan="1">
<staticText>
<reportElement x="0" y="0" width="400" height="30" uuid="dade4652-f819-4d79-8d3d-4b2b2d569f9f"/>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
</textElement>
<text><![CDATA[State of Confidentiality]]></text>
</staticText>
</jr:tableHeader>
<jr:tableFooter style="Table_TH" height="100" rowSpan="1">
<staticText>
<reportElement x="0" y="0" width="400" height="25" uuid="75eee7d9-35ab-43f9-9a65-041cbeec379e"/>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
</textElement>
<text><![CDATA[Appendencies]]></text>
</staticText>
<staticText>
<reportElement x="0" y="25" width="400" height="25" forecolor="#232B44" uuid="9c81fdd0-7620-4ac9-8554-a686bd61e868">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<text><![CDATA[Findings Severities]]></text>
</staticText>
<staticText>
<reportElement x="0" y="50" width="400" height="25" forecolor="#232B44" uuid="c2e58188-b6bf-4184-afc4-f4fc122e4ac1">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<text><![CDATA[Risk Matrix]]></text>
</staticText>
<staticText>
<reportElement x="0" y="75" width="400" height="25" forecolor="#232B44" uuid="76a14be3-8f39-4052-a22f-2f3dac68e0ae">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<text><![CDATA[Severity Rating Definitions]]></text>
</staticText>
</jr:tableFooter>
<jr:columnHeader style="Table_CH" height="170" rowSpan="1">
<staticText>
<reportElement x="0" y="0" width="400" height="34" uuid="9d638d8b-7d1c-4fe2-b494-d8ee3c337a9f"/>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
</textElement>
<text><![CDATA[Executive Summary]]></text>
</staticText>
<staticText>
<reportElement x="0" y="34" width="400" height="34" forecolor="#232B44" uuid="3089a5ee-9038-4d3d-b7c7-ff7be4a1a91e">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<text><![CDATA[Assessment Overview and Recommendations]]></text>
</staticText>
<staticText>
<reportElement x="0" y="68" width="400" height="34" forecolor="#232B44" uuid="03912891-062e-41e2-88fb-1cd2dd0eb37c">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<text><![CDATA[Number of Findings per Category]]></text>
</staticText>
<staticText>
<reportElement x="0" y="102" width="400" height="34" forecolor="#232B44" uuid="cf22afbf-5690-4d33-86be-f671daa668ac">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<text><![CDATA[Severity Overview of Findings]]></text>
</staticText>
<staticText>
<reportElement x="0" y="136" width="400" height="34" uuid="642bc39c-e2fd-47bb-ae15-8a30fb59ad72">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="0"/>
</textElement>
<text><![CDATA[Technical Findings and Comments Details]]></text>
</staticText>
</jr:columnHeader>
<jr:detailCell style="Table_TD" height="30">
<textField>
<reportElement x="0" y="0" width="400" height="30" forecolor="#232B44" uuid="1930eea5-6835-498a-bcdd-d4fe0423a18a">
<property name="com.jaspersoft.studio.unit.leftIndent" value="px"/>
</reportElement>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
<paragraph leftIndent="10"/>
</textElement>
<textFieldExpression><![CDATA[$F{category}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
<jr:column width="160" uuid="76741c88-65a6-4032-8d17-c6ba755c1a64">
<property name="com.jaspersoft.studio.components.table.model.column.name" value="Column2"/>
<jr:tableHeader style="Table_TH" height="30" rowSpan="1"/>
<jr:tableFooter style="Table_TH" height="100" rowSpan="1"/>
<jr:columnHeader style="Table_CH" height="170" rowSpan="1"/>
<jr:detailCell style="Table_TD" height="30">
<textField>
<reportElement x="0" y="0" width="160" height="30" forecolor="#232B44" uuid="4c14b6ea-020c-4527-b853-543ac119003b"/>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="12" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{refNumber}]]></textFieldExpression>
</textField>
</jr:detailCell>
</jr:column>
</jr:table>
</componentElement>
</band>
</detail>
<columnFooter>
<band height="49" splitType="Stretch"/>
</columnFooter>
<pageFooter>
<band height="54" splitType="Stretch"/>
</pageFooter>
</jasperReport>

View File

@ -0,0 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_Coverpage" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="1e81cc75-35cb-406c-934f-0bc56dfd965d">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportJasperData Template JSON Adapter"/>
<!-- Ignores Issue about not finding a specific font -->
<property name="net.sf.jasperreports.awt.ignore.missing.font" value="true"/>
<queryString language="JSON">
<![CDATA[projectReportData]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="client" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="client"/>
<fieldDescription><![CDATA[client]]></fieldDescription>
</field>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="createdAt" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdAt"/>
<fieldDescription><![CDATA[createdAt]]></fieldDescription>
</field>
<field name="tester" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="tester"/>
<fieldDescription><![CDATA[tester]]></fieldDescription>
</field>
<field name="summary" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="summary"/>
<fieldDescription><![CDATA[summary]]></fieldDescription>
</field>
<field name="projectPentestReport" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="projectPentestReport"/>
<fieldDescription><![CDATA[projectPentestReport]]></fieldDescription>
</field>
<field name="createdBy" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdBy"/>
<fieldDescription><![CDATA[createdBy]]></fieldDescription>
</field>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="390" splitType="Stretch">
<image>
<reportElement x="-20" y="-20" width="595" height="409" uuid="7b8866c7-8b72-43a8-9428-2404a75e803e"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/C4POCoverBackground#1.jpeg"]]></imageExpression>
</image>
<rectangle>
<reportElement x="-20" y="-20" width="595" height="280" forecolor="#151B2E" backcolor="rgba(35, 43, 68, 0.5882353)" uuid="7412dfc2-c785-4584-b8e9-120df2ef41f2"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<rectangle>
<reportElement x="-20" y="241" width="595" height="120" forecolor="#232B44" backcolor="#232B44" uuid="c3646ed4-24af-4969-990a-322ff29697a9"/>
</rectangle>
<textField textAdjust="StretchHeight">
<reportElement x="6" y="280" width="543" height="51" forecolor="#FFFFFF" uuid="563ae593-7ae8-47fc-8728-01da0a717aad"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="SansSerif" size="26" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{client}]]></textFieldExpression>
</textField>
<textField>
<reportElement mode="Transparent" x="5" y="0" width="544" height="219" forecolor="#FEFEFF" backcolor="#232B44" uuid="173fc927-62f1-4242-9c7e-638a21a9672f">
<property name="net.sf.jasperreports.export.accessibility.tag" value="h1"/>
<property name="net.sf.jasperreports.export.pdf.tag.table" value="full"/>
</reportElement>
<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
<font fontName="SansSerif" size="36" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{title}]]></textFieldExpression>
</textField>
<rectangle>
<reportElement x="-2" y="220" width="577" height="40" forecolor="#232B44" backcolor="#151B2E" uuid="2d5d891c-1d0f-4d81-beab-6d6937f08b5b"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<ellipse>
<reportElement x="-20" y="220" width="38" height="40" backcolor="#151B2E" uuid="fefe65c4-59db-4810-9539-1865db235814"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<image>
<reportElement x="-14" y="224" width="31" height="37" uuid="ae84d484-ee44-436a-a0cd-e94a265ed665"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/Watermark.png"]]></imageExpression>
</image>
<staticText>
<reportElement mode="Transparent" x="22" y="226" width="82" height="20" forecolor="#FEFEFF" backcolor="#151B2E" uuid="b40755db-f42b-47cf-9e73-57cd092f7bde"/>
<textElement>
<font fontName="SansSerif&#xA;&#xA;" size="12" isBold="true" isItalic="false"/>
</textElement>
<text><![CDATA[C4PO]]></text>
</staticText>
<staticText>
<reportElement mode="Transparent" x="23" y="242" width="82" height="20" forecolor="#FEFEFF" backcolor="#151B2E" uuid="1e37e3b3-b3d2-4621-9928-08497bd4f667"/>
<textElement>
<font fontName="SansSerif&#xA;&#xA;" size="10" isItalic="true"/>
</textElement>
<text><![CDATA[v.0.0.1]]></text>
</staticText>
<rectangle>
<reportElement x="-20" y="350" width="595" height="30" uuid="e6a81d95-840a-42a8-860d-cb1957d1775c"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
</band>
</title>
<columnHeader>
<band height="190" splitType="Stretch">
<textField>
<reportElement x="107" y="20" width="340" height="40" forecolor="#232B44" uuid="0c2fdc55-5038-49f5-a972-3575837bb8a6"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="26" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Penetration Test"]]></textFieldExpression>
</textField>
<textField>
<reportElement x="107" y="61" width="340" height="40" forecolor="#232B44" uuid="edce29e2-8963-43bd-8361-69e579e4a1e1"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="26" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Report of Findings"]]></textFieldExpression>
</textField>
</band>
</columnHeader>
<detail>
<band height="91" splitType="Stretch">
<textField>
<reportElement x="0" y="10" width="551" height="30" uuid="54c4a617-82ea-4ec4-aa3c-d52e8fd22406"/>
<textElement textAlignment="Right">
<font fontName="SansSerif" size="20" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{tester}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="80" y="50" width="471" height="30" uuid="f13c2ce6-8960-4ac8-ba3a-f79823f07025"/>
<textElement textAlignment="Right">
<font fontName="SansSerif" size="12" isBold="true" isItalic="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{createdAt}]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="70" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="30" width="595" height="30" forecolor="#232B44" backcolor="#232B44" uuid="1ed47e2d-9d46-44b9-bad7-8eeb1143c83c"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="35" width="551" height="20" forecolor="#FEFEFF" backcolor="#232B44" uuid="fc82cf8c-f284-413c-9c49-ad924c765c48"/>
<textElement textAlignment="Right" verticalAlignment="Middle">
<font fontName="SansSerif&#xA;&#xA;" size="12" isBold="false" isItalic="true"/>
</textElement>
<text><![CDATA[Version 1.0]]></text>
</staticText>
<rectangle>
<reportElement x="-20" y="20" width="595" height="10" forecolor="#151B2E" backcolor="#151B2E" uuid="b9a5cd43-3460-4177-97f5-a46eac874e7d"/>
</rectangle>
</band>
</columnFooter>
<pageFooter>
<band height="10" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="-10" width="595" height="20" forecolor="#151B2E" backcolor="#151B2E" uuid="724a02c5-82c8-4a72-bf81-b77baa72c723"/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="-9" width="551" height="18" forecolor="#FEFEFF" backcolor="#151B2E" uuid="3291af19-09ed-453c-a068-90a951d4f7b5"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="SansSerif&#xA;&#xA;" size="8" isBold="true" isItalic="false"/>
</textElement>
<text><![CDATA[No part of this document may be disclosed to outside sources without the explicit written authorization of the tester]]></text>
</staticText>
</band>
</pageFooter>
</jasperReport>

View File

@ -0,0 +1,270 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_ExecutiveSummary" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="a71c3e72-ee88-496d-967d-a33d331426ab">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectPentestReportJasperData Template JSON Adapter"/>
<style name="PieChart">
<conditionalStyle>
<conditionExpression><![CDATA["LOW"]]></conditionExpression>
<style forecolor="#A4A8B0" backcolor="#A4A8B0"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA["MEDIUM"]]></conditionExpression>
<style backcolor="#35A4FE"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA["HIGH"]]></conditionExpression>
<style backcolor="#FFAB00"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA["CRITICAL"]]></conditionExpression>
<style backcolor="#FF3D70"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA["PRIMARY"]]></conditionExpression>
<style backcolor="#3267FE"/>
</conditionalStyle>
<conditionalStyle>
<conditionExpression><![CDATA["SUCCESS"]]></conditionExpression>
<style backcolor="#01D68F"/>
</conditionalStyle>
</style>
<subDataset name="CategoryFindingsPieChartDataSource" uuid="0ea170d1-b9d6-4209-b81e-f19a84332933">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="CategoryPieData"/>
<queryString language="json">
<![CDATA[CategoryPieData]]>
</queryString>
<field name="category" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="category"/>
<fieldDescription><![CDATA[category]]></fieldDescription>
</field>
<field name="numberOfFindings" class="java.lang.Integer">
<property name="net.sf.jasperreports.json.field.expression" value="numberOfFindings"/>
<fieldDescription><![CDATA[numberOfFindings]]></fieldDescription>
</field>
<group name="category">
<groupExpression><![CDATA[$F{category}]]></groupExpression>
</group>
<group name="numberOfFindings">
<groupExpression><![CDATA[$F{numberOfFindings}]]></groupExpression>
</group>
</subDataset>
<subDataset name="SeverityPieData" uuid="5beef60f-b9d1-4eae-8975-e07bc624c759">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="SeverityPieData"/>
<queryString language="json">
<![CDATA[SeverityPieData]]>
</queryString>
<field name="severity" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="severity"/>
<fieldDescription><![CDATA[severity]]></fieldDescription>
</field>
<field name="numberOfFindings" class="java.lang.Integer">
<property name="net.sf.jasperreports.json.field.expression" value="numberOfFindings"/>
<fieldDescription><![CDATA[numberOfFindings]]></fieldDescription>
</field>
<group name="severity">
<groupExpression><![CDATA[$F{severity}]]></groupExpression>
</group>
<group name="numberOfFindings">
<groupExpression><![CDATA[$F{numberOfFindings}]]></groupExpression>
</group>
</subDataset>
<parameter name="CategoryFindingsPieChartDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="SeverityFindingsPieChartDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<queryString language="json">
<![CDATA[projectReportData]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="client" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="client"/>
<fieldDescription><![CDATA[client]]></fieldDescription>
</field>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="createdAt" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdAt"/>
<fieldDescription><![CDATA[createdAt]]></fieldDescription>
</field>
<field name="tester" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="tester"/>
<fieldDescription><![CDATA[tester]]></fieldDescription>
</field>
<field name="summary" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="summary"/>
<fieldDescription><![CDATA[summary]]></fieldDescription>
</field>
<field name="projectPentestReport" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="projectPentestReport"/>
<fieldDescription><![CDATA[projectPentestReport]]></fieldDescription>
</field>
<field name="createdBy" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdBy"/>
<fieldDescription><![CDATA[createdBy]]></fieldDescription>
</field>
<group name="id">
<groupExpression><![CDATA[$F{id}]]></groupExpression>
</group>
<group name="client">
<groupExpression><![CDATA[$F{client}]]></groupExpression>
</group>
<group name="title">
<groupExpression><![CDATA[$F{title}]]></groupExpression>
</group>
<group name="createdAt">
<groupExpression><![CDATA[$F{createdAt}]]></groupExpression>
</group>
<group name="tester">
<groupExpression><![CDATA[$F{tester}]]></groupExpression>
</group>
<group name="projectPentestReport">
<groupExpression><![CDATA[$F{projectPentestReport}]]></groupExpression>
</group>
<group name="createdBy">
<groupExpression><![CDATA[$F{createdBy}]]></groupExpression>
</group>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="41" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="0" width="573" height="30" forecolor="#232B44" backcolor="#232B44" uuid="d35a1b95-3ef6-4626-8827-2509ce34d362"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<staticText>
<reportElement x="0" y="0" width="432" height="30" forecolor="#FFFFFF" uuid="727c5a22-9505-4eee-8697-c33c25770203"/>
<textElement verticalAlignment="Middle">
<font size="16" isBold="true"/>
</textElement>
<text><![CDATA[Executive Summary]]></text>
</staticText>
<ellipse>
<reportElement x="537" y="0" width="30" height="30" backcolor="#232B44" uuid="94ae9350-4d6a-4660-a412-628324e3e766"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<image>
<reportElement x="539" y="3" width="23" height="24" uuid="e47a59e3-90b6-43d3-9d42-930a6d497a05"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/Watermark.png"]]></imageExpression>
</image>
</band>
</title>
<columnHeader>
<band height="148" splitType="Stretch">
<textField textAdjust="StretchHeight">
<reportElement x="0" y="30" width="545" height="118" uuid="3364c8ce-4b56-4965-b4ad-6f7062fa7789"/>
<textElement>
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA[$F{summary}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="0" y="10" width="380" height="20" forecolor="#232B44" uuid="b508eb27-8cf7-40f3-86e8-6b7c9328d919"/>
<textElement>
<font size="12" isBold="true"/>
</textElement>
<text><![CDATA[Assessment Overview and Recommendations]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="500" splitType="Stretch">
<staticText>
<reportElement x="0" y="20" width="380" height="20" forecolor="#232B44" uuid="43e826cd-e910-4ab5-a689-935baa555e58"/>
<textElement>
<font size="12" isBold="true"/>
</textElement>
<text><![CDATA[Number of Findings per Category]]></text>
</staticText>
<staticText>
<reportElement positionType="Float" x="0" y="300" width="380" height="20" forecolor="#232B44" uuid="daae5600-96f6-4f4c-b3ce-a12aadf2696a"/>
<textElement>
<font size="12" isBold="true"/>
</textElement>
<text><![CDATA[Severity Overview of Findings]]></text>
</staticText>
<pieChart>
<chart evaluationTime="Report">
<reportElement key="" positionType="Float" stretchType="ElementGroupHeight" x="0" y="40" width="553" height="239" uuid="aaf04aa7-f7c5-48b9-b422-0f210e35d7be"/>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
<chartTitle/>
<chartSubtitle/>
<chartLegend/>
</chart>
<pieDataset>
<dataset resetType="Report">
<datasetRun subDataset="CategoryFindingsPieChartDataSource" uuid="a4ca39d4-0e4d-4131-be73-97b5ae1e8945">
<dataSourceExpression><![CDATA[$P{CategoryFindingsPieChartDataSource}]]></dataSourceExpression>
</datasetRun>
</dataset>
<keyExpression><![CDATA[$F{category}]]></keyExpression>
<valueExpression><![CDATA[$F{numberOfFindings}]]></valueExpression>
<labelExpression><![CDATA[$F{numberOfFindings} + ""]]></labelExpression>
</pieDataset>
<piePlot>
<plot>
<seriesColor seriesOrder="0" color="#007AB5"/>
<seriesColor seriesOrder="1" color="#5E0779"/>
<seriesColor seriesOrder="2" color="#10C3F4"/>
<seriesColor seriesOrder="3" color="#232B44"/>
<seriesColor seriesOrder="4" color="#71BE52"/>
<seriesColor seriesOrder="5" color="#174F28"/>
<seriesColor seriesOrder="6" color="#FFE25C"/>
<seriesColor seriesOrder="7" color="#EF4523"/>
<seriesColor seriesOrder="8" color="#7C1124"/>
<seriesColor seriesOrder="9" color="#8085E9"/>
<seriesColor seriesOrder="10" color="#D021C4"/>
<seriesColor seriesOrder="11" color="#A4A8B0"/>
</plot>
<itemLabel/>
</piePlot>
</pieChart>
<pieChart>
<chart evaluationTime="Report">
<reportElement positionType="Float" stretchType="ElementGroupHeight" x="0" y="320" width="553" height="179" uuid="0082b083-fdcf-4d69-bd20-98c36c2825ff"/>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<bottomPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
<chartTitle/>
<chartSubtitle/>
<chartLegend/>
</chart>
<pieDataset>
<dataset resetType="Report">
<datasetRun subDataset="SeverityPieData" uuid="43b5d9b9-7b09-4789-8311-09b39c30e70c">
<dataSourceExpression><![CDATA[$P{SeverityFindingsPieChartDataSource}]]></dataSourceExpression>
</datasetRun>
</dataset>
<keyExpression><![CDATA[$F{severity}]]></keyExpression>
<valueExpression><![CDATA[$F{numberOfFindings}]]></valueExpression>
<labelExpression><![CDATA[$F{numberOfFindings} + " " +$F{severity}]]></labelExpression>
</pieDataset>
<piePlot>
<plot>
<seriesColor seriesOrder="0" color="#01D68F"/>
<seriesColor seriesOrder="1" color="#35A4FE"/>
<seriesColor seriesOrder="2" color="#FFAB00"/>
<seriesColor seriesOrder="3" color="#FF3D70"/>
<seriesColor seriesOrder="4" color="#647687"/>
</plot>
<itemLabel/>
</piePlot>
</pieChart>
</band>
</detail>
</jasperReport>

View File

@ -0,0 +1,314 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_Pentest" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="d4d219cb-f6cb-4f7b-9d33-c00b82eaa1b7">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectPentestReportJasperData Template JSON Adapter"/>
<style name="Table_TH" mode="Opaque" backcolor="#232B44">
<box>
<pen lineWidth="0.5" lineColor="#151B2E"/>
<topPen lineWidth="0.5" lineColor="#151B2E"/>
<leftPen lineWidth="0.5" lineColor="#151B2E"/>
<bottomPen lineWidth="0.5" lineColor="#151B2E"/>
<rightPen lineWidth="0.5" lineColor="#151B2E"/>
</box>
</style>
<style name="Table_CH" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#151B2E"/>
<topPen lineWidth="0.5" lineColor="#151B2E"/>
<leftPen lineWidth="0.5" lineColor="#151B2E"/>
<bottomPen lineWidth="0.5" lineColor="#151B2E"/>
<rightPen lineWidth="0.5" lineColor="#151B2E"/>
</box>
</style>
<style name="Table_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#151B2E"/>
<topPen lineWidth="0.5" lineColor="#151B2E"/>
<leftPen lineWidth="0.5" lineColor="#151B2E"/>
<bottomPen lineWidth="0.5" lineColor="#151B2E"/>
<rightPen lineWidth="0.5" lineColor="#151B2E"/>
</box>
</style>
<style name="Table 1_TH" mode="Opaque" backcolor="#232B44">
<box>
<pen lineWidth="0.5" lineColor="#232B44"/>
<topPen lineWidth="0.5" lineColor="#232B44"/>
<leftPen lineWidth="0.5" lineColor="#232B44"/>
<bottomPen lineWidth="0.5" lineColor="#232B44"/>
<rightPen lineWidth="0.5" lineColor="#232B44"/>
</box>
</style>
<style name="Table 1_CH" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#232B44"/>
<topPen lineWidth="0.5" lineColor="#232B44"/>
<leftPen lineWidth="0.5" lineColor="#232B44"/>
<bottomPen lineWidth="0.5" lineColor="#232B44"/>
<rightPen lineWidth="0.5" lineColor="#232B44"/>
</box>
</style>
<style name="Table 1_TD" mode="Opaque" backcolor="#FFFFFF">
<box>
<pen lineWidth="0.5" lineColor="#232B44"/>
<topPen lineWidth="0.5" lineColor="#232B44"/>
<leftPen lineWidth="0.5" lineColor="#232B44"/>
<bottomPen lineWidth="0.5" lineColor="#232B44"/>
<rightPen lineWidth="0.5" lineColor="#232B44"/>
</box>
</style>
<subDataset name="projectPentestReport Sub Datasource" uuid="f4b3a379-ea17-4640-8dfc-e04d6c738694">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportData JSON Adapter"/>
<queryString language="json">
<![CDATA[projectPentestReport]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="category" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="category"/>
<fieldDescription><![CDATA[category]]></fieldDescription>
</field>
<field name="refNumber" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="refNumber"/>
<fieldDescription><![CDATA[refNumber]]></fieldDescription>
</field>
<field name="findings" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="findings"/>
<fieldDescription><![CDATA[findings]]></fieldDescription>
</field>
<field name="comments" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="comments"/>
<fieldDescription><![CDATA[comments]]></fieldDescription>
</field>
<field name="status" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="status"/>
<fieldDescription><![CDATA[status]]></fieldDescription>
</field>
<group name="id">
<groupExpression><![CDATA[$F{id}]]></groupExpression>
</group>
<group name="category">
<groupExpression><![CDATA[$F{category}]]></groupExpression>
</group>
<group name="refNumber">
<groupExpression><![CDATA[$F{refNumber}]]></groupExpression>
</group>
<group name="findings">
<groupExpression><![CDATA[$F{findings}]]></groupExpression>
</group>
<group name="comments">
<groupExpression><![CDATA[$F{comments}]]></groupExpression>
</group>
<group name="status">
<groupExpression><![CDATA[$F{status}]]></groupExpression>
</group>
</subDataset>
<subDataset name="findings Sub Datasource" uuid="ef4e1d36-83dd-461c-b31f-0c517e3f3da7">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportData JSON Adapter"/>
<queryString language="json">
<![CDATA[projectPentestReport.findings]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="severity" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="severity"/>
<fieldDescription><![CDATA[severity]]></fieldDescription>
</field>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="description" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="description"/>
<fieldDescription><![CDATA[description]]></fieldDescription>
</field>
<field name="impact" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="impact"/>
<fieldDescription><![CDATA[impact]]></fieldDescription>
</field>
<field name="affectedUrls" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="affectedUrls"/>
<fieldDescription><![CDATA[affectedUrls]]></fieldDescription>
</field>
<field name="reproduction" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="reproduction"/>
<fieldDescription><![CDATA[reproduction]]></fieldDescription>
</field>
<field name="mitigation" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="mitigation"/>
<fieldDescription><![CDATA[mitigation]]></fieldDescription>
</field>
<group name="id">
<groupExpression><![CDATA[$F{id}]]></groupExpression>
</group>
<group name="severity">
<groupExpression><![CDATA[$F{severity}]]></groupExpression>
</group>
<group name="title">
<groupExpression><![CDATA[$F{title}]]></groupExpression>
</group>
<group name="description">
<groupExpression><![CDATA[$F{description}]]></groupExpression>
</group>
<group name="impact">
<groupExpression><![CDATA[$F{impact}]]></groupExpression>
</group>
<group name="affectedUrls">
<groupExpression><![CDATA[$F{affectedUrls}]]></groupExpression>
</group>
<group name="reproduction">
<groupExpression><![CDATA[$F{reproduction}]]></groupExpression>
</group>
<group name="mitigation">
<groupExpression><![CDATA[$F{mitigation}]]></groupExpression>
</group>
</subDataset>
<subDataset name="comments Sub Datasource" uuid="797bf326-f0eb-4f3c-b5a5-3113f7320b18">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportData JSON Adapter"/>
<queryString language="json">
<![CDATA[projectPentestReport.comments]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="description" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="description"/>
<fieldDescription><![CDATA[description]]></fieldDescription>
</field>
<field name="relatedFindings" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="relatedFindings"/>
<fieldDescription><![CDATA[relatedFindings]]></fieldDescription>
</field>
<group name="id">
<groupExpression><![CDATA[$F{id}]]></groupExpression>
</group>
<group name="title">
<groupExpression><![CDATA[$F{title}]]></groupExpression>
</group>
<group name="description">
<groupExpression><![CDATA[$F{description}]]></groupExpression>
</group>
<group name="relatedFindings">
<groupExpression><![CDATA[$F{relatedFindings}]]></groupExpression>
</group>
</subDataset>
<subDataset name="Findingstable" uuid="a71c37db-6f21-464d-af41-45f08103128e">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectPentestReportJasperData Template JSON Adapter"/>
<queryString language="JSON">
<![CDATA[comments]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="severity" class="java.lang.String"/>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="description" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="description"/>
<fieldDescription><![CDATA[description]]></fieldDescription>
</field>
<field name="impact" class="java.lang.String"/>
<field name="affectedUrls" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="relatedFindings"/>
<fieldDescription><![CDATA[affectedUrls]]></fieldDescription>
</field>
<field name="reproduction" class="java.lang.String"/>
<field name="mitigation" class="java.lang.String"/>
</subDataset>
<subDataset name="Commentstable" uuid="f301d27e-9489-4007-8675-68f5bcb787c4">
<queryString>
<![CDATA[]]>
</queryString>
<field name="id" class="java.lang.String"/>
<field name="title" class="java.lang.String"/>
<field name="description" class="java.lang.String"/>
<field name="relatedFindings" class="java.lang.String"/>
</subDataset>
<parameter name="PentestFindingsDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<parameter name="PentestCommentsDataSource" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
<queryString language="JSON">
<![CDATA[projectPentestReport]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="category" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="category"/>
<fieldDescription><![CDATA[category]]></fieldDescription>
</field>
<field name="refNumber" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="refNumber"/>
<fieldDescription><![CDATA[refNumber]]></fieldDescription>
</field>
<field name="findings" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="findings"/>
<fieldDescription><![CDATA[findings]]></fieldDescription>
</field>
<field name="comments" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="comments"/>
<fieldDescription><![CDATA[comments]]></fieldDescription>
</field>
<field name="status" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="status"/>
<fieldDescription><![CDATA[status]]></fieldDescription>
</field>
<title>
<band height="42" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="0" width="573" height="30" forecolor="#232B44" backcolor="#232B44" uuid="d90debc9-13dd-404a-a1d1-d227e0a208a5"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<ellipse>
<reportElement x="537" y="0" width="30" height="30" backcolor="#232B44" uuid="e6ecfe00-ba27-44b0-ad8c-82d2b15657e6"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<textField>
<reportElement x="0" y="5" width="553" height="20" forecolor="#FFFFFF" uuid="b91211d3-616c-40d7-9836-7884989c270f"/>
<textElement verticalAlignment="Middle">
<font fontName="SansSerif" size="16" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA[$F{category} + ": " + $F{refNumber}]]></textFieldExpression>
</textField>
<image>
<reportElement x="539" y="3" width="23" height="24" uuid="110809ac-8a68-486d-93f4-35a583bd1759"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/Watermark.png"]]></imageExpression>
</image>
</band>
</title>
<detail>
<band height="699" splitType="Stretch">
<subreport>
<reportElement positionType="Float" x="0" y="0" width="554" height="349" isRemoveLineWhenBlank="true" uuid="5b74c6df-2b20-462b-bfbb-be7d3efee10f"/>
<subreportParameter name="PentestFindingsDataSource">
<subreportParameterExpression><![CDATA[]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$P{PentestFindingsDataSource}]]></dataSourceExpression>
<subreportExpression><![CDATA["./src/main/resources/jasper/subreports/"+"FindingsSubreport.jasper"]]></subreportExpression>
</subreport>
<subreport>
<reportElement positionType="Float" x="0" y="360" width="554" height="334" isRemoveLineWhenBlank="true" uuid="48da877f-cf38-4fc2-9104-934c8a528d6e"/>
<dataSourceExpression><![CDATA[$P{PentestCommentsDataSource}]]></dataSourceExpression>
<subreportExpression><![CDATA["./src/main/resources/jasper/subreports/"+"CommentsSubreport.jasper"]]></subreportExpression>
</subreport>
</band>
</detail>
<pageFooter>
<band height="29" splitType="Stretch"/>
</pageFooter>
</jasperReport>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.20.0.final using JasperReports Library version 6.20.0-2bc7ab61c56f459e8176eb05c7705e145cd400ad -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="C4PO_StateOfConfidentiality" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="c9281989-500e-499e-a5f4-ede1c502fcbc">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="ProjectReportJasperData Template JSON Adapter"/>
<queryString language="JSON">
<![CDATA[projectReportData]]>
</queryString>
<field name="id" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="id"/>
<fieldDescription><![CDATA[id]]></fieldDescription>
</field>
<field name="client" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="client"/>
<fieldDescription><![CDATA[client]]></fieldDescription>
</field>
<field name="title" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="title"/>
<fieldDescription><![CDATA[title]]></fieldDescription>
</field>
<field name="createdAt" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdAt"/>
<fieldDescription><![CDATA[createdAt]]></fieldDescription>
</field>
<field name="tester" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="tester"/>
<fieldDescription><![CDATA[tester]]></fieldDescription>
</field>
<field name="projectPentestReport" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="projectPentestReport"/>
<fieldDescription><![CDATA[projectPentestReport]]></fieldDescription>
</field>
<field name="createdBy" class="java.lang.String">
<property name="net.sf.jasperreports.json.field.expression" value="createdBy"/>
<fieldDescription><![CDATA[createdBy]]></fieldDescription>
</field>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="49" splitType="Stretch">
<rectangle>
<reportElement x="-20" y="0" width="573" height="30" forecolor="#232B44" backcolor="#232B44" uuid="91d6614c-09e9-48a1-87ca-fc8c33a04ae4"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</rectangle>
<ellipse>
<reportElement x="537" y="0" width="30" height="30" backcolor="#232B44" uuid="3efa01f7-db61-406b-840b-8f2b5357d46c"/>
<graphicElement>
<pen lineWidth="0.0"/>
</graphicElement>
</ellipse>
<image>
<reportElement x="539" y="3" width="23" height="24" uuid="75a577b3-42df-4d40-be10-d0991b2769e2"/>
<imageExpression><![CDATA["/Users/mhg/Documents/Projects/security-c4po/security-c4po-reporting/src/main/resources/jasper/Watermark.png"]]></imageExpression>
</image>
<staticText>
<reportElement x="0" y="0" width="432" height="30" forecolor="#FFFFFF" uuid="329f5881-cba9-4418-9ef0-99a6805906ba"/>
<textElement verticalAlignment="Middle">
<font size="16" isBold="true"/>
</textElement>
<text><![CDATA[State of Confidentiality]]></text>
</staticText>
</band>
</title>
<detail>
<band height="460" splitType="Stretch">
<textField textAdjust="StretchHeight">
<reportElement x="0" y="0" width="552" height="99" uuid="155d6f81-907f-49ed-ae21-2dae085f72b2"/>
<textElement>
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA["The contents of this document have been developed by " + $F{tester} + ". " + $F{tester} + " considers the contents of this document to be proprietary and business confidential information. This information is to be used only in the performance of its intended use. This document may not be released to another vendor, business partner or contractor without prior written consent from " + $F{tester} + ". Additionally, no portion of this document may be communicated, reproduced, copied or distributed without the prior consent of " + $F{tester} + "." ]]></textFieldExpression>
</textField>
<textField textAdjust="StretchHeight">
<reportElement positionType="Float" x="0" y="100" width="551" height="100" uuid="6b5626a8-ff7b-450b-8c53-93c2115bd56c"/>
<textElement>
<font size="12"/>
</textElement>
<textFieldExpression><![CDATA["The contents of this document do not constitute legal advice. " + $F{tester}+"s offer of services that relate to compliance, litigation or other legal interests are not intended as legal counsel and should not be taken as such. The assessment detailed herein is against the company " + $F{client} + " for examination purposes, and the vulnerabilities included in this document should be mitigated in order to secure " + $F{client} + " external or internal infrastructure."]]></textFieldExpression>
</textField>
</band>
</detail>
<pageFooter>
<band height="54" splitType="Stretch"/>
</pageFooter>
</jasperReport>

View File

@ -0,0 +1,31 @@
package com.securityc4po.reporting
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.web.server.LocalServerPort
import org.springframework.restdocs.RestDocumentationContextProvider
import org.springframework.restdocs.RestDocumentationExtension
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.reactive.server.WebTestClient
import java.time.Duration
@ExtendWith(value = [RestDocumentationExtension::class, SpringExtension::class])
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
abstract class BaseDocumentationIntTest {
@LocalServerPort
private var port = 0
lateinit var webTestClient: WebTestClient
@BeforeEach
fun setupDocs(restDocumentation: RestDocumentationContextProvider) {
webTestClient = WebTestClient.bindToServer()
.baseUrl("http://localhost:$port")
.filter(documentationConfiguration(restDocumentation))
.responseTimeout(Duration.ofMillis(10000))
.build()
}
}

View File

@ -0,0 +1,11 @@
package com.securityc4po.reporting
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.annotation.DirtiesContext
import org.springframework.test.context.junit.jupiter.SpringExtension
@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext
abstract class BaseIntTest

View File

@ -0,0 +1,12 @@
{
"CategoryPieData": [
{
"category": "INFORMATION_GATHERING",
"numberOfFindings": 4
},
{
"category": "CONFIGURATION_AND_DEPLOY_MANAGEMENT_TESTING",
"numberOfFindings": 2
}
]
}

View File

@ -0,0 +1,59 @@
[
{
"id": "11601f51-bc17-47fd-847d-0c53df5405b5",
"category": "INFORMATION_GATHERING",
"refNumber": "OTG-INFO-001",
"findings": [
{
"id": "ef31449d-71ec-4736-952f-8b20e53117d5",
"severity": "LOW",
"title": "Test Title",
"description": "Test Description",
"impact": "Test Impact",
"affectedUrls": [
"https://akveo.github.io/nebular/docs/components/progress-bar/examples#nbprogressbarcomponent"
],
"reproduction": "Step 1: Test",
"mitigation": "Test Mitigation"
},
{
"id": "58f63b4e-97fb-4fe8-8527-7996896089d2",
"severity": "MEDIUM",
"title": "Medium Finding",
"description": "Medium",
"impact": "Medium",
"affectedUrls": [],
"reproduction": "Medium",
"mitigation": ""
}
],
"comments": [
{
"id": "89703b19-16c7-49e5-8e33-0c706313e5fe",
"title": "Test Comment",
"description": "No related findings",
"relatedFindings": []
}
],
"status": "COMPLETED"
},
{
"id": "9a073a08-e4fc-4450-8202-c902455b66ec",
"category": "INFORMATION_GATHERING",
"refNumber": "OTG-INFO-002",
"findings": [
{
"id": "4ddb84f6-068c-4319-a8ee-1000008bb75a",
"severity": "HIGH",
"title": "Anothe High Issues",
"description": "High",
"impact": "High",
"affectedUrls": [],
"reproduction": "High",
"mitigation": ""
}
],
"comments": [],
"status": "COMPLETED"
}
]

View File

@ -0,0 +1,99 @@
{
"id": "195809ed-9722-4ad5-a84b-0099a9a01652",
"client": "Dio Stonemask Inc.",
"title": "log4jj bizarre adventure",
"createdAt": "2022-08-10T14:47:40.140406Z",
"tester": "Jojo",
"summary": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet.",
"projectPentestReport": [
{
"id": "11601f51-bc17-47fd-847d-0c53df5405b5",
"category": "INFORMATION_GATHERING",
"refNumber": "OTG-INFO-001",
"findings": [
{
"id": "ef31449d-71ec-4736-952f-8b20e53117d5",
"severity": "LOW",
"title": "Test Title",
"description": "Test Description Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut tristique sodales leo, eget porta dolor porttitor vitae. Nunc semper a est in porttitor. Aliquam imperdiet mi eget orci egestas euismod. Fusce sit amet massa efficitur, egestas neque vitae, elementum orci. Nullam accumsan nunc id risus volutpat, quis sagittis lorem sollicitudin. Nam finibus justo non arcu vulputate dignissim. Etiam libero felis, dignissim non feugiat at, ornare non elit. Sed hendrerit risus id magna porttitor interdum. Cras vehicula odio id metus elementum porta. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur tempor eu purus ut aliquet. Nam.",
"impact": "Test Impact Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut tristique sodales leo, eget porta dolor porttitor vitae. Nunc semper a est in porttitor. Aliquam imperdiet mi eget orci egestas euismod. Fusce sit amet massa efficitur, egestas neque vitae, elementum orci. Nullam accumsan nunc id risus volutpat, quis sagittis lorem sollicitudin.",
"affectedUrls": [
"https://akveo.github.io/nebular/docs/components/progress-bar/examples#nbprogressbarcomponent",
"https://www.google.de/"
],
"reproduction": "Step 1: Test",
"mitigation": ""
},
{
"id": "58f63b4e-97fb-4fe8-8527-7996896089d2",
"severity": "MEDIUM",
"title": "Medium Finding",
"description": "Medium Description Nam finibus justo non arcu vulputate dignissim. Etiam libero felis, dignissim non feugiat at, ornare non elit. Sed hendrerit risus id magna porttitor interdum. Cras vehicula odio id metus elementum porta. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur tempor eu purus ut aliquet.",
"impact": "Medium Impact",
"affectedUrls": [],
"reproduction": "Step 1: Medium",
"mitigation": "Fusce sit amet massa efficitur, egestas neque vitae, elementum orci. Nullam accumsan nunc id risus volutpat, quis sagittis lorem sollicitudin. Nam finibus justo non arcu vulputate dignissim. Etiam libero felis, dignissim non feugiat at, ornare non elit. Sed hendrerit risus id magna porttitor interdum."
},
{
"id": "58f63b4e-97fb-4fe8-8527-7996896089d2",
"severity": "HIGH",
"title": "High Finding",
"description": "High Description Nam finibus justo non arcu vulputate dignissim. Etiam libero felis, dignissim non feugiat at, ornare non elit. Sed hendrerit risus id magna porttitor interdum. Cras vehicula odio id metus elementum porta. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur tempor eu purus ut aliquet.",
"impact": "High Impact",
"affectedUrls": [],
"reproduction": "Step 1: High",
"mitigation": ""
},
{
"id": "58f63b4e-97fb-4fe8-8527-7996896089d2",
"severity": "CRITICAL",
"title": "Critical Finding",
"description": "Critical Description Nam finibus justo non arcu vulputate dignissim. Etiam libero felis, dignissim non feugiat at, ornare non elit. Sed hendrerit risus id magna porttitor interdum. Cras vehicula odio id metus elementum porta. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur tempor eu purus ut aliquet.",
"impact": "Critical Impact",
"affectedUrls": [
"https://community.jaspersoft.com/system/files/restricted-docs/jaspersoft-studio-user-guide.pdf"
],
"reproduction": "Step 1: Critical",
"mitigation": "Fusce sit amet massa efficitur, egestas neque vitae, elementum orci. Nullam accumsan nunc id risus volutpat, quis sagittis lorem sollicitudin. Nam finibus justo non arcu vulputate dignissim. Etiam libero felis, dignissim non feugiat at, ornare non elit. Sed hendrerit risus id magna porttitor interdum."
}
],
"comments": [
{
"id": "89703b19-16c7-49e5-8e33-0c706313e5fe",
"title": "Test Comment",
"description": "Not related to findings",
"relatedFindings": [
"58f63b4e-97fb-4fe8-8527-7996896089d2"
]
},
{
"id": "89703b19-16c7-49e5-8e33-0c706313e5fe",
"title": "Test Comment",
"description": "Test Decription",
"relatedFindings": []
}
],
"status": "COMPLETED"
},
{
"id": "9a073a08-e4fc-4450-8202-c902455b66ec",
"category": "INFORMATION_GATHERING",
"refNumber": "OTG-INFO-002",
"findings": [
{
"id": "4ddb84f6-068c-4319-a8ee-1000008bb75a",
"severity": "HIGH",
"title": "Anothe High Issues",
"description": "High",
"impact": "High",
"affectedUrls": [],
"reproduction": "High",
"mitigation": ""
}
],
"comments": [],
"status": "COMPLETED"
}
],
"createdBy": "7fe49c8d-fee3-47e0-9224-94e0ac7436c6"
}

View File

@ -0,0 +1,72 @@
{
"projectReportData": [
{
"id": "195809ed-9722-4ad5-a84b-0099a9a01652",
"client": "Dio Stonemask Inc.",
"title": "log4jj bizarre adventure",
"createdAt": "2022-08-10T14:47:40.140406Z",
"tester": "Jojo",
"summary": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet.",
"projectPentestReport": [
{
"id": "11601f51-bc17-47fd-847d-0c53df5405b5",
"category": "INFORMATION_GATHERING",
"refNumber": "OTG-INFO-001",
"findings": [
{
"id": "ef31449d-71ec-4736-952f-8b20e53117d5",
"severity": "LOW",
"title": "Test Title",
"description": "Test Description",
"impact": "Test Impact",
"affectedUrls": [
"https://akveo.github.io/nebular/docs/components/progress-bar/examples#nbprogressbarcomponent"
],
"reproduction": "Step 1: Test",
"mitigation": "Test Mitigation"
},
{
"id": "58f63b4e-97fb-4fe8-8527-7996896089d2",
"severity": "MEDIUM",
"title": "Medium Finding",
"description": "Medium",
"impact": "Medium",
"affectedUrls": [],
"reproduction": "Medium",
"mitigation": ""
}
],
"comments": [
{
"id": "89703b19-16c7-49e5-8e33-0c706313e5fe",
"title": "Test Comment",
"description": "No related findings",
"relatedFindings": []
}
],
"status": "COMPLETED"
},
{
"id": "9a073a08-e4fc-4450-8202-c902455b66ec",
"category": "INFORMATION_GATHERING",
"refNumber": "OTG-INFO-002",
"findings": [
{
"id": "4ddb84f6-068c-4319-a8ee-1000008bb75a",
"severity": "HIGH",
"title": "Anothe High Issues",
"description": "High",
"impact": "High",
"affectedUrls": [],
"reproduction": "High",
"mitigation": ""
}
],
"comments": [],
"status": "COMPLETED"
}
],
"createdBy": "7fe49c8d-fee3-47e0-9224-94e0ac7436c6"
}
]
}

View File

@ -0,0 +1,20 @@
{
"SeverityPieData": [
{
"severity": "LOW",
"numberOfFindings": 4
},
{
"severity": "MEDIUM",
"numberOfFindings": 2
},
{
"severity": "HIGH",
"numberOfFindings": 1
},
{
"severity": "CRITICAL",
"numberOfFindings": 1
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 231 KiB

BIN
wiki/C4PO-RiskMatrix.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

1
wiki/C4PO.drawio Normal file

File diff suppressed because one or more lines are too long