From 3c3f0055374ef0a2c9688812bda40be5983be70c Mon Sep 17 00:00:00 2001 From: Marcel Haag Date: Tue, 10 Jan 2023 11:58:03 +0100 Subject: [PATCH] feat: As a developer I want an additional microservice for creating pentest reports --- .../src/shared/models/project.model.ts | 4 + security-c4po-api/build.gradle.kts | 184 +++--- .../src/main/asciidoc/SecurityC4PO.adoc | 1 - .../error/handler/ErrorCodeEncoder.kt | 2 +- .../com/securityc4po/api/pentest/Pentest.kt | 2 +- .../api/pentest/finding/FindingController.kt | 7 - .../com/securityc4po/api/project/Project.kt | 9 +- .../api/project/ProjectController.kt | 2 + .../securityc4po/api/project/ProjectEntity.kt | 1 + .../ProjectControllerDocumentationTest.kt | 15 +- .../api/project/ProjectControllerIntTest.kt | 5 + .../test/resources/collections/findings.json | 336 ++++++++++- security-c4po-reporting/.gitignore | 38 ++ security-c4po-reporting/Dockerfile | 20 + security-c4po-reporting/build.gradle.kts | 153 +++++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 60756 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + security-c4po-reporting/gradlew | 240 ++++++++ security-c4po-reporting/gradlew.bat | 91 +++ ...ity-c4po-reporting.postman_collection.json | 185 ++++++ security-c4po-reporting/settings.gradle.kts | 7 + security-c4po-reporting/src/gradle.properties | 4 + .../src/main/asciidoc/ReportingC4PO.adoc | 30 + .../reporting/ReportingApplication.kt | 11 + .../error/handler/ErrorCodeEncoder.kt | 16 + .../configuration/error/handler/Errorcode.kt | 8 + .../error/handler/GlobalErrorAttributes.kt | 61 ++ .../handler/GlobalErrorWebExceptionHandler.kt | 69 +++ .../configuration/security/Appuser.kt | 48 ++ .../reporting/extensions/InlineFunctions.kt | 5 + .../reporting/http/ApplicationHeaders.kt | 9 + .../reporting/http/RequestLogInterceptor.kt | 26 + .../reporting/remote/APIClient.kt | 44 ++ .../reporting/remote/APIClientCfg.kt | 22 + .../reporting/remote/APIService.kt | 20 + .../reporting/remote/model/CategoryPieData.kt | 6 + .../reporting/remote/model/Comment.kt | 8 + .../reporting/remote/model/Finding.kt | 19 + .../reporting/remote/model/PentestReport.kt | 32 + .../reporting/remote/model/ProjectReport.kt | 16 + .../reporting/remote/model/SeverityPieData.kt | 6 + .../reporting/report/ReportController.kt | 68 +++ .../reporting/report/ReportService.kt | 367 ++++++++++++ .../reporting/report/jasper/JRDbDataSource.kt | 15 + .../report/jasper/JasperReportContext.kt | 32 + .../report/jasper/ReactiveFileUtil.kt | 29 + .../reporting/report/jasper/ReportExporter.kt | 9 + .../reporting/report/jasper/ReportUtil.kt | 11 + .../jasper/export/JasperOutputFormat.kt | 26 + .../report/jasper/export/ReportExporterPDF.kt | 35 ++ .../src/main/resources/application.properties | 30 + .../jasper/C4POCoverBackground#1.jpeg | Bin 0 -> 530556 bytes .../src/main/resources/jasper/DEFAULT.pdf | 0 .../src/main/resources/jasper/Watermark.png | Bin 0 -> 9388 bytes .../jasper/reports/c4po_appendencies.jrxml | 553 ++++++++++++++++++ .../jasper/reports/c4po_content.jrxml | 229 ++++++++ .../resources/jasper/reports/c4po_cover.jrxml | 185 ++++++ .../reports/c4po_executive_summary.jrxml | 270 +++++++++ .../jasper/reports/c4po_pentests.jrxml | 314 ++++++++++ .../c4po_state_of_confidentiality.jrxml | 87 +++ .../subReports/CommentsSubreport.jasper | Bin 0 -> 19871 bytes .../subReports/FindingsSubreport.jasper | Bin 0 -> 30725 bytes .../SeverityRatingTableSubreport.jasper | Bin 0 -> 28392 bytes .../reporting/BaseDocumentationIntTest.kt | 31 + .../com/securityc4po/reporting/BaseIntTest.kt | 11 + .../src/test/resources/CategoryPieData.json | 12 + .../resources/ProjectPentestReportList.json | 59 ++ .../src/test/resources/ProjectReportData.json | 99 ++++ .../resources/ProjectReportJasperData.json | 72 +++ .../src/test/resources/SeverityPieData.json | 20 + wiki/C4PO-Architecture.png | Bin 84100 -> 103615 bytes wiki/C4PO-Datastructure.png | Bin 114607 -> 236444 bytes wiki/C4PO-RiskMatrix.png | Bin 0 -> 228191 bytes wiki/C4PO.drawio | 1 + 74 files changed, 4225 insertions(+), 107 deletions(-) create mode 100644 security-c4po-reporting/.gitignore create mode 100644 security-c4po-reporting/Dockerfile create mode 100644 security-c4po-reporting/build.gradle.kts create mode 100644 security-c4po-reporting/gradle/wrapper/gradle-wrapper.jar create mode 100644 security-c4po-reporting/gradle/wrapper/gradle-wrapper.properties create mode 100755 security-c4po-reporting/gradlew create mode 100644 security-c4po-reporting/gradlew.bat create mode 100644 security-c4po-reporting/security-c4po-reporting.postman_collection.json create mode 100644 security-c4po-reporting/settings.gradle.kts create mode 100644 security-c4po-reporting/src/gradle.properties create mode 100644 security-c4po-reporting/src/main/asciidoc/ReportingC4PO.adoc create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/ReportingApplication.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/configuration/error/handler/ErrorCodeEncoder.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/configuration/error/handler/Errorcode.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/configuration/error/handler/GlobalErrorAttributes.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/configuration/error/handler/GlobalErrorWebExceptionHandler.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/configuration/security/Appuser.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/extensions/InlineFunctions.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/http/ApplicationHeaders.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/http/RequestLogInterceptor.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/APIClient.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/APIClientCfg.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/APIService.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/model/CategoryPieData.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/model/Comment.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/model/Finding.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/model/PentestReport.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/model/ProjectReport.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/remote/model/SeverityPieData.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/ReportController.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/ReportService.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/JRDbDataSource.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/JasperReportContext.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/ReactiveFileUtil.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/ReportExporter.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/ReportUtil.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/export/JasperOutputFormat.kt create mode 100644 security-c4po-reporting/src/main/kotlin/com/securityc4po/reporting/report/jasper/export/ReportExporterPDF.kt create mode 100644 security-c4po-reporting/src/main/resources/application.properties create mode 100644 security-c4po-reporting/src/main/resources/jasper/C4POCoverBackground#1.jpeg create mode 100644 security-c4po-reporting/src/main/resources/jasper/DEFAULT.pdf create mode 100644 security-c4po-reporting/src/main/resources/jasper/Watermark.png create mode 100644 security-c4po-reporting/src/main/resources/jasper/reports/c4po_appendencies.jrxml create mode 100644 security-c4po-reporting/src/main/resources/jasper/reports/c4po_content.jrxml create mode 100644 security-c4po-reporting/src/main/resources/jasper/reports/c4po_cover.jrxml create mode 100644 security-c4po-reporting/src/main/resources/jasper/reports/c4po_executive_summary.jrxml create mode 100644 security-c4po-reporting/src/main/resources/jasper/reports/c4po_pentests.jrxml create mode 100644 security-c4po-reporting/src/main/resources/jasper/reports/c4po_state_of_confidentiality.jrxml create mode 100644 security-c4po-reporting/src/main/resources/jasper/subReports/CommentsSubreport.jasper create mode 100644 security-c4po-reporting/src/main/resources/jasper/subReports/FindingsSubreport.jasper create mode 100644 security-c4po-reporting/src/main/resources/jasper/subReports/SeverityRatingTableSubreport.jasper create mode 100644 security-c4po-reporting/src/test/kotlin/com/securityc4po/reporting/BaseDocumentationIntTest.kt create mode 100644 security-c4po-reporting/src/test/kotlin/com/securityc4po/reporting/BaseIntTest.kt create mode 100644 security-c4po-reporting/src/test/resources/CategoryPieData.json create mode 100644 security-c4po-reporting/src/test/resources/ProjectPentestReportList.json create mode 100644 security-c4po-reporting/src/test/resources/ProjectReportData.json create mode 100644 security-c4po-reporting/src/test/resources/ProjectReportJasperData.json create mode 100644 security-c4po-reporting/src/test/resources/SeverityPieData.json create mode 100644 wiki/C4PO-RiskMatrix.png create mode 100644 wiki/C4PO.drawio diff --git a/security-c4po-angular/src/shared/models/project.model.ts b/security-c4po-angular/src/shared/models/project.model.ts index 108f048..3e1f36c 100644 --- a/security-c4po-angular/src/shared/models/project.model.ts +++ b/security-c4po-angular/src/shared/models/project.model.ts @@ -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; } diff --git a/security-c4po-api/build.gradle.kts b/security-c4po-api/build.gradle.kts index 1f463d1..b601610 100644 --- a/security-c4po-api/build.gradle.kts +++ b/security-c4po-api/build.gradle.kts @@ -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 { - useJUnitPlatform() + useJUnitPlatform() } tasks.withType { - 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 { - include("SecurityC4PO.adoc") - }) + inputs.dir(snippetsDir) + setSourceDir(file("src/main/asciidoc")) + setOutputDir(file("$buildDir/asciidoc")) + sources(delegateClosureOf { + 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") + } } diff --git a/security-c4po-api/src/main/asciidoc/SecurityC4PO.adoc b/security-c4po-api/src/main/asciidoc/SecurityC4PO.adoc index 8d0a385..2d6a756 100644 --- a/security-c4po-api/src/main/asciidoc/SecurityC4PO.adoc +++ b/security-c4po-api/src/main/asciidoc/SecurityC4PO.adoc @@ -1,5 +1,4 @@ = SecurityC4PO REST API Documentation -Novatec Consulting GmbH; :doctype: book :source-highlighter: highlightjs :icons: font diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/error/handler/ErrorCodeEncoder.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/error/handler/ErrorCodeEncoder.kt index 88b30ee..2732acc 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/error/handler/ErrorCodeEncoder.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/configuration/error/handler/ErrorCodeEncoder.kt @@ -13,4 +13,4 @@ class ErrorCodeEncoder { "" } } -} \ No newline at end of file +} diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/Pentest.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/Pentest.kt index b59eb6e..4a68cf3 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/Pentest.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/Pentest.kt @@ -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, diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/finding/FindingController.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/finding/FindingController.kt index f081ace..1167c66 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/finding/FindingController.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/pentest/finding/FindingController.kt @@ -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.* diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/Project.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/Project.kt index 20b94d9..cca0f92 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/Project.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/Project.kt @@ -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 = 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() ) diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectController.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectController.kt index 63015af..26c6076 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectController.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectController.kt @@ -34,6 +34,8 @@ class ProjectController(private val projectService: ProjectService) { } } + // ToDo: Add getProjectReportDataById Endpoint with return type ProjectReport + @PostMapping fun saveProject( @RequestBody body: ProjectRequestBody diff --git a/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectEntity.kt b/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectEntity.kt index 252a58e..d8f3737 100644 --- a/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectEntity.kt +++ b/security-c4po-api/src/main/kotlin/com/securityc4po/api/project/ProjectEntity.kt @@ -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 ) diff --git a/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerDocumentationTest.kt b/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerDocumentationTest.kt index a6641e8..d7d0991 100644 --- a/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerDocumentationTest.kt +++ b/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerDocumentationTest.kt @@ -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(), 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(), 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(), 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(), 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(), createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032" ) diff --git a/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerIntTest.kt b/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerIntTest.kt index 57b0427..fad7aac 100644 --- a/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerIntTest.kt +++ b/security-c4po-api/src/test/kotlin/com/securityc4po/api/project/ProjectControllerIntTest.kt @@ -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 diff --git a/security-c4po-api/src/test/resources/collections/findings.json b/security-c4po-api/src/test/resources/collections/findings.json index 3ea22c1..0141b80 100644 --- a/security-c4po-api/src/test/resources/collections/findings.json +++ b/security-c4po-api/src/test/resources/collections/findings.json @@ -20,4 +20,338 @@ "mitigation": "Test Mitigatin" }, "_class": "com.securityc4po.api.finding.FindingEntity" -}] \ No newline at end of file +},{ + "_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