fix: As a developer I want tests for the new API's and document them
This commit is contained in:
parent
a4536e9735
commit
4e4a5e0604
|
@ -95,10 +95,114 @@ include::{snippets}/updateProject/http-response.adoc[]
|
|||
|
||||
include::{snippets}/updateProject/response-fields.adoc[]
|
||||
|
||||
== Pentest
|
||||
|
||||
=== Get pentests for category
|
||||
|
||||
To get pentests by projectId and category, call the GET request /pentests with the appropriate parameters.
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/http-request.adoc[]
|
||||
|
||||
==== Request structure
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/request-parameters.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/response-fields.adoc[]
|
||||
|
||||
=== Save pentest
|
||||
|
||||
To save a pentest, call the POST request /pentests/+{projectId}+
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/savePentestByProjectId/http-request.adoc[]
|
||||
|
||||
==== Request structure
|
||||
|
||||
include::{snippets}/savePentestByProjectId/path-parameters.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/savePentestByProjectId/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/savePentestByProjectId/response-fields.adoc[]
|
||||
|
||||
=== Update pentest
|
||||
|
||||
To update a pentest, call the PATCH request /pentests/+{pentestId}+
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/updatePentestByProjectId/http-request.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/updatePentestByProjectId/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/updatePentestByProjectId/response-fields.adoc[]
|
||||
|
||||
== Finding
|
||||
|
||||
=== Get findings for pentest
|
||||
|
||||
To get findings by pentestId, call the GET request /pentests/+{pentestId}+/findings.
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/getFindingsByPentestId/http-request.adoc[]
|
||||
|
||||
==== Request structure
|
||||
|
||||
include::{snippets}/getFindingsByPentestId/path-parameters.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/getFindingsByPentestId/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/getFindingsByPentestId/response-fields.adoc[]
|
||||
|
||||
=== Save finding
|
||||
|
||||
To save a finding, call the POST request /pentests/+{pentestId}+/finding
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/saveFindingByPentestId/http-request.adoc[]
|
||||
|
||||
==== Request structure
|
||||
|
||||
include::{snippets}/saveFindingByPentestId/path-parameters.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/saveFindingByPentestId/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/saveFindingByPentestId/response-fields.adoc[]
|
||||
|
||||
== Change History
|
||||
|
||||
|===
|
||||
|Date |Change
|
||||
|2022-12-02
|
||||
|Added GET and POST endpoint for Findings
|
||||
|2022-11-21
|
||||
|Added GET, POST and PATCH endpoint for Pentests
|
||||
|2022-03-07
|
||||
|Added PATCH endpoint to update Projects
|
||||
|2022-02-01
|
||||
|
@ -110,25 +214,3 @@ include::{snippets}/updateProject/response-fields.adoc[]
|
|||
|2021-02-12
|
||||
|Initial version
|
||||
|===
|
||||
|
||||
== Pentest
|
||||
|
||||
=== Get pentests by projectId and category
|
||||
|
||||
To get pentests by projectId and category, call the GET request /pentests with the appropriate parameters.
|
||||
|
||||
==== Request example
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/http-request.adoc[]
|
||||
|
||||
==== Request Structure
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/request-parameters.adoc[]
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/http-response.adoc[]
|
||||
|
||||
==== Response structure
|
||||
|
||||
include::{snippets}/getPentestsByProjectIdAndCategory/response-fields.adoc[]
|
|
@ -12,7 +12,7 @@ data class Finding (
|
|||
val description: String,
|
||||
val impact: String,
|
||||
val affectedUrls: List<String>? = emptyList(),
|
||||
val reproduction: String?,
|
||||
val reproduction: String,
|
||||
val mitigation: String?
|
||||
)
|
||||
|
||||
|
@ -22,7 +22,7 @@ data class FindingRequestBody(
|
|||
val description: String,
|
||||
val impact: String,
|
||||
val affectedUrls: List<String>? = emptyList(),
|
||||
val reproduction: String?,
|
||||
val reproduction: String,
|
||||
val mitigation: String?
|
||||
)
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ class PentestController(private val pentestService: PentestService, private val
|
|||
}
|
||||
}*/
|
||||
|
||||
// ToDo: Add Documentation & Tests
|
||||
@PostMapping("/{projectId}")
|
||||
fun savePentest(
|
||||
@PathVariable(value = "projectId") projectId: String,
|
||||
|
@ -61,7 +60,6 @@ class PentestController(private val pentestService: PentestService, private val
|
|||
}
|
||||
}
|
||||
|
||||
// ToDo: Add Documentation & Tests
|
||||
@PatchMapping("/{pentestId}")
|
||||
fun updatePentest(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
|
@ -72,18 +70,6 @@ class PentestController(private val pentestService: PentestService, private val
|
|||
}
|
||||
}
|
||||
|
||||
// ToDo: Add Documentation & Tests
|
||||
@PostMapping("/{pentestId}/finding")
|
||||
fun saveFinidng(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
@RequestBody body: FindingRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.saveFinding(pentestId, body).map {
|
||||
ResponseEntity.accepted().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
|
||||
// ToDo: Add Documentation & Tests
|
||||
@GetMapping("/{pentestId}/findings")
|
||||
fun getFindings(@PathVariable(value = "pentestId") pentestId: String): Mono<ResponseEntity<List<ResponseBody>>> {
|
||||
return this.pentestService.getFindingIdsByPentestId(pentestId).flatMap { findingIds: List<String> ->
|
||||
|
@ -95,4 +81,14 @@ class PentestController(private val pentestService: PentestService, private val
|
|||
else ResponseEntity.ok(it)
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/{pentestId}/finding")
|
||||
fun saveFinding(
|
||||
@PathVariable(value = "pentestId") pentestId: String,
|
||||
@RequestBody body: FindingRequestBody
|
||||
): Mono<ResponseEntity<ResponseBody>> {
|
||||
return this.findingService.saveFinding(pentestId, body).map {
|
||||
ResponseEntity.accepted().body(it.toFindingResponseBody())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -151,7 +151,7 @@ class ProjectService(private val projectRepository: ProjectRepository) {
|
|||
it.toProject()
|
||||
}.doOnError {
|
||||
throw wrappedException(
|
||||
logging = { logger.warn("Project Pentests could not be updated in Database. Thrown exception: ", it) },
|
||||
logging = { logger.warn("Project Pentests could not be updated or saved in Database. Thrown exception: ", it) },
|
||||
mappedException = TransactionInterruptedException(
|
||||
"Project could not be updated.",
|
||||
Errorcode.ProjectInsertionFailed
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package com.securityc4po.api.pentest
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.github.tomakehurst.wiremock.common.Json
|
||||
import com.securityc4po.api.BaseDocumentationIntTest
|
||||
import com.securityc4po.api.configuration.NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
|
||||
import com.securityc4po.api.configuration.RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
import com.securityc4po.api.configuration.SIC_INNER_SHOULD_BE_STATIC
|
||||
import com.securityc4po.api.finding.*
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
|
@ -18,6 +22,7 @@ import org.springframework.restdocs.payload.JsonFieldType
|
|||
import org.springframework.restdocs.payload.PayloadDocumentation
|
||||
import org.springframework.restdocs.request.RequestDocumentation
|
||||
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
|
||||
import reactor.core.publisher.Mono
|
||||
|
||||
@SuppressFBWarnings(
|
||||
SIC_INNER_SHOULD_BE_STATIC,
|
||||
|
@ -28,6 +33,7 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
|
||||
@Autowired
|
||||
lateinit var mongoTemplate: MongoTemplate
|
||||
var mapper = ObjectMapper()
|
||||
|
||||
@BeforeEach
|
||||
fun init() {
|
||||
|
@ -44,7 +50,7 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
inner class GetPentests {
|
||||
@Test
|
||||
fun getPentestsByProjectIdAndCategory() {
|
||||
val projectId = "d2e126ba-f608-11ec-b939-0242ac120002"
|
||||
val projectId = "d2e126ba-f608-11ec-b939-0242ac120025"
|
||||
val category = "INFORMATION_GATHERING"
|
||||
webTestClient.get()
|
||||
.uri("/pentests?projectId={projectId}&category={category}", projectId, category)
|
||||
|
@ -90,7 +96,7 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
|
||||
private val pentestOne = Pentest(
|
||||
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = PentestStatus.NOT_STARTED,
|
||||
|
@ -99,11 +105,11 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
)
|
||||
private val pentestTwo = Pentest(
|
||||
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = emptyList(),
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
|
||||
|
@ -113,11 +119,260 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SavePentest {
|
||||
@Test
|
||||
fun savePentestByProjectId() {
|
||||
val projectId = "d2e126ba-f608-11ec-b939-0242ac120025"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{projectId}", projectId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(newPentestBody), PentestRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(newPentestBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("projectId").description("The id of the project you want to save the pentest for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the created pentest"),
|
||||
PayloadDocumentation.fieldWithPath("projectId").type(JsonFieldType.STRING)
|
||||
.description("The id of the project of the created pentest"),
|
||||
PayloadDocumentation.fieldWithPath("category").type(JsonFieldType.STRING)
|
||||
.description("The category of the created pentest"),
|
||||
PayloadDocumentation.fieldWithPath("refNumber").type(JsonFieldType.STRING)
|
||||
.description("The reference number of the created pentest according to the current OWASP Testing Guide"),
|
||||
PayloadDocumentation.fieldWithPath("status").type(JsonFieldType.STRING)
|
||||
.description("The status of the created pentest"),
|
||||
PayloadDocumentation.fieldWithPath("findingIds").type(JsonFieldType.ARRAY)
|
||||
.description("List of ids of the findings in the created pentest"),
|
||||
PayloadDocumentation.fieldWithPath("commentIds").type(JsonFieldType.ARRAY)
|
||||
.description("List of ids of the comments of the created pentest")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val newPentestBody = PentestRequestBody(
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = "CLIENT_SIDE_TESTING",
|
||||
refNumber = "OTG-CLIENT-001",
|
||||
status = "IN_PROGRESS",
|
||||
findingIds = emptyList<String>(),
|
||||
commentIds = emptyList<String>()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdatePentest {
|
||||
@Test
|
||||
fun updatePentestByProjectId() {
|
||||
val pentestOneId = "9c8af320-f608-11ec-b939-0242ac120002"
|
||||
webTestClient.patch()
|
||||
.uri("/pentests/{pentestId}", pentestOneId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(pentestOneBody), PentestRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(pentestOneBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to update")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the updated pentest"),
|
||||
PayloadDocumentation.fieldWithPath("projectId").type(JsonFieldType.STRING)
|
||||
.description("The id of the project of the updated pentest"),
|
||||
PayloadDocumentation.fieldWithPath("category").type(JsonFieldType.STRING)
|
||||
.description("The category of the updated pentest"),
|
||||
PayloadDocumentation.fieldWithPath("refNumber").type(JsonFieldType.STRING)
|
||||
.description("The reference number of the updated pentest according to the current OWASP Testing Guide"),
|
||||
PayloadDocumentation.fieldWithPath("status").type(JsonFieldType.STRING)
|
||||
.description("The status of the updated pentest"),
|
||||
PayloadDocumentation.fieldWithPath("findingIds").type(JsonFieldType.ARRAY)
|
||||
.description("List of ids of the findings in the updated pentest"),
|
||||
PayloadDocumentation.fieldWithPath("commentIds").type(JsonFieldType.ARRAY)
|
||||
.description("List of ids of the comments of the updated pentest")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val pentestOneBody = PentestRequestBody(
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = "INFORMATION_GATHERING",
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = "OPEN",
|
||||
findingIds = emptyList<String>(),
|
||||
commentIds = emptyList<String>()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFindings {
|
||||
@Test
|
||||
fun getFindingsByPentestId() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{pentestId}/findings", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(getFindingsResponse()))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to get the findings for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("[].id").type(JsonFieldType.STRING)
|
||||
.description("The id of the requested pentest"),
|
||||
PayloadDocumentation.fieldWithPath("[].severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("[].mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
|
||||
private fun getFindingsResponse() = listOf(
|
||||
findingOne.toFindingResponseBody()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveFinding {
|
||||
@Test
|
||||
fun saveFindingByPentestId() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{pentestId}/finding", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().doesNotExist("")
|
||||
.expectBody().json(Json.write(findingBody))
|
||||
.consumeWith(
|
||||
WebTestClientRestDocumentation.document(
|
||||
"{methodName}",
|
||||
Preprocessors.preprocessRequest(
|
||||
Preprocessors.prettyPrint(),
|
||||
Preprocessors.modifyUris().removePort(),
|
||||
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||
),
|
||||
Preprocessors.preprocessResponse(
|
||||
Preprocessors.prettyPrint()
|
||||
),
|
||||
RequestDocumentation.relaxedPathParameters(
|
||||
RequestDocumentation.parameterWithName("pentestId").description("The id of the pentest you want to save the finding for")
|
||||
),
|
||||
PayloadDocumentation.relaxedResponseFields(
|
||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||
.description("The id of the requested pentest"),
|
||||
PayloadDocumentation.fieldWithPath("severity").type(JsonFieldType.STRING)
|
||||
.description("The severity of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("title").type(JsonFieldType.STRING)
|
||||
.description("The title of the requested finding"),
|
||||
PayloadDocumentation.fieldWithPath("description").type(JsonFieldType.STRING)
|
||||
.description("The description number of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("impact").type(JsonFieldType.STRING)
|
||||
.description("The impact of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("affectedUrls").type(JsonFieldType.ARRAY)
|
||||
.description("List of affected Urls of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("reproduction").type(JsonFieldType.STRING)
|
||||
.description("The reproduction steps of the finding"),
|
||||
PayloadDocumentation.fieldWithPath("mitigation").type(JsonFieldType.STRING)
|
||||
.description("The example mitigation for the finding")
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "MEDIUM",
|
||||
title = "Found another Bug",
|
||||
description = "Another OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack more",
|
||||
mitigation = "Another None"
|
||||
)
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
// Project
|
||||
val projectOne = Project(
|
||||
id = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
client = "E Corp",
|
||||
title = "Some Mock API (v1.0) Scanning",
|
||||
createdAt = "2021-01-10T18:05:00Z",
|
||||
tester = "Novatester",
|
||||
projectPentests = emptyList(),
|
||||
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
|
||||
)
|
||||
// Pentests
|
||||
val pentestOne = Pentest(
|
||||
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = PentestStatus.NOT_STARTED,
|
||||
|
@ -126,26 +381,39 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
)
|
||||
val pentestTwo = Pentest(
|
||||
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = emptyList(),
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestThree = Pentest(
|
||||
id = "74eae112-f62c-11ec-b939-0242ac120002",
|
||||
projectId = "6fad3474-fc29-49f9-bd37-e039e9e60c18",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.AUTHENTICATION_TESTING,
|
||||
refNumber = "OTG-AUTHN-001",
|
||||
status = PentestStatus.COMPLETED,
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
// persist test data in database
|
||||
// Findings
|
||||
val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
// persist test data in database
|
||||
mongoTemplate.save(ProjectEntity(projectOne))
|
||||
mongoTemplate.save(PentestEntity(pentestOne))
|
||||
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||
mongoTemplate.save(PentestEntity(pentestThree))
|
||||
mongoTemplate.save(FindingEntity(findingOne))
|
||||
}
|
||||
|
||||
private fun configureAdminToken() {
|
||||
|
@ -153,7 +421,9 @@ class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
|||
}
|
||||
|
||||
private fun cleanUp() {
|
||||
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), FindingEntity::class.java)
|
||||
|
||||
tokenAdmin = "n/a"
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import com.securityc4po.api.BaseIntTest
|
|||
import com.securityc4po.api.configuration.NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR
|
||||
import com.securityc4po.api.configuration.RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||
import com.securityc4po.api.configuration.SIC_INNER_SHOULD_BE_STATIC
|
||||
import com.securityc4po.api.finding.*
|
||||
import com.securityc4po.api.project.Project
|
||||
import com.securityc4po.api.project.ProjectEntity
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
|
@ -15,6 +18,7 @@ import org.springframework.boot.web.server.LocalServerPort
|
|||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.data.mongodb.core.query.Query
|
||||
import org.springframework.test.web.reactive.server.WebTestClient
|
||||
import reactor.core.publisher.Mono
|
||||
import java.time.Duration
|
||||
|
||||
@SuppressFBWarnings(
|
||||
|
@ -56,8 +60,10 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
inner class GetPentests {
|
||||
@Test
|
||||
fun `requesting pentests by projectId and category successfully`() {
|
||||
val projectId = "d2e126ba-f608-11ec-b939-0242ac120025"
|
||||
val category = "INFORMATION_GATHERING"
|
||||
webTestClient.get()
|
||||
.uri("/pentests?projectId=d2e126ba-f608-11ec-b939-0242ac120002&category=INFORMATION_GATHERING")
|
||||
.uri("/pentests?projectId={projectId}&category={category}", projectId, category)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
|
@ -67,7 +73,7 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
|
||||
private val pentestOne = Pentest(
|
||||
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = PentestStatus.NOT_STARTED,
|
||||
|
@ -76,11 +82,11 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
)
|
||||
private val pentestTwo = Pentest(
|
||||
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = emptyList(),
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
|
||||
|
@ -90,11 +96,147 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SavePentest {
|
||||
@Test
|
||||
fun `save pentest successfully`() {
|
||||
val projectId = "d2e126ba-f608-11ec-b939-0242ac120025"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{projectId}", projectId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(pentestRequestBody), PentestRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.projectId").isEqualTo("d2e126ba-f608-11ec-b939-0242ac120025")
|
||||
.jsonPath("$.category").isEqualTo("CLIENT_SIDE_TESTING")
|
||||
.jsonPath("$.refNumber").isEqualTo("OTG-CLIENT-001")
|
||||
.jsonPath("$.status").isEqualTo("IN_PROGRESS")
|
||||
.jsonPath("$.findingIds").isEmpty
|
||||
.jsonPath("$.commentIds").isEmpty
|
||||
}
|
||||
|
||||
val pentestRequestBody = PentestRequestBody(
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = "CLIENT_SIDE_TESTING",
|
||||
refNumber = "OTG-CLIENT-001",
|
||||
status = "IN_PROGRESS",
|
||||
findingIds = emptyList<String>(),
|
||||
commentIds = emptyList<String>()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class UpdatePentest {
|
||||
@Test
|
||||
fun `update pentest successfully`() {
|
||||
val pentestOneId = "9c8af320-f608-11ec-b939-0242ac120002"
|
||||
webTestClient.patch()
|
||||
.uri("/pentests/{pentestId}", pentestOneId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(pentestOneRequestBody), PentestRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.id").isEqualTo(pentestOneId)
|
||||
.jsonPath("$.projectId").isEqualTo("d2e126ba-f608-11ec-b939-0242ac120025")
|
||||
.jsonPath("$.category").isEqualTo("INFORMATION_GATHERING")
|
||||
.jsonPath("$.refNumber").isEqualTo("OTG-INFO-001")
|
||||
.jsonPath("$.status").isEqualTo("OPEN")
|
||||
.jsonPath("$.findingIds").isEmpty
|
||||
.jsonPath("$.commentIds").isEmpty
|
||||
}
|
||||
|
||||
val pentestOneRequestBody = PentestRequestBody(
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = "INFORMATION_GATHERING",
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = "OPEN",
|
||||
findingIds = emptyList<String>(),
|
||||
commentIds = emptyList<String>()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class GetFindings {
|
||||
@Test
|
||||
fun `requesting findings by pentestId successfully`() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.get()
|
||||
.uri("/pentests/{pentestId}/findings", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.exchange()
|
||||
.expectStatus().isOk
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody().json(Json.write(getFindings()))
|
||||
}
|
||||
|
||||
private val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
|
||||
private fun getFindings() = listOf(
|
||||
findingOne.toFindingResponseBody()
|
||||
)
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class SaveFindings {
|
||||
@Test
|
||||
fun `save finding successfully`() {
|
||||
val pentestTwoId = "43fbc63c-f624-11ec-b939-0242ac120002"
|
||||
webTestClient.post()
|
||||
.uri("/pentests/{pentestId}/finding", pentestTwoId)
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(findingBody), FindingRequestBody::class.java)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted
|
||||
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||
.expectBody()
|
||||
.jsonPath("$.severity").isEqualTo("MEDIUM")
|
||||
.jsonPath("$.title").isEqualTo("Found another Bug")
|
||||
.jsonPath("$.description").isEqualTo("Another OTG-INFO-002 Bug")
|
||||
.jsonPath("$.impact").isEqualTo("Service")
|
||||
.jsonPath("$.affectedUrls").isEmpty
|
||||
.jsonPath("$.reproduction").isEqualTo("Step 1: Hack more")
|
||||
.jsonPath("$.mitigation").isEqualTo("Another None")
|
||||
}
|
||||
|
||||
private val findingBody = FindingRequestBody(
|
||||
severity = "MEDIUM",
|
||||
title = "Found another Bug",
|
||||
description = "Another OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack more",
|
||||
mitigation = "Another None"
|
||||
)
|
||||
}
|
||||
|
||||
private fun persistBasicTestScenario() {
|
||||
// setup test data
|
||||
// project
|
||||
val projectOne = Project(
|
||||
id = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
client = "E Corp",
|
||||
title = "Some Mock API (v1.0) Scanning",
|
||||
createdAt = "2021-01-10T18:05:00Z",
|
||||
tester = "Novatester",
|
||||
createdBy = "f8aab31f-4925-4242-a6fa-f98135b4b032"
|
||||
)
|
||||
// pentests
|
||||
val pentestOne = Pentest(
|
||||
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-001",
|
||||
status = PentestStatus.NOT_STARTED,
|
||||
|
@ -103,26 +245,39 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
)
|
||||
val pentestTwo = Pentest(
|
||||
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.INFORMATION_GATHERING,
|
||||
refNumber = "OTG-INFO-002",
|
||||
status = PentestStatus.IN_PROGRESS,
|
||||
findingIds = emptyList(),
|
||||
findingIds = listOf("ab62d365-1b1d-4da1-89bc-5496616e220f"),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
val pentestThree = Pentest(
|
||||
id = "74eae112-f62c-11ec-b939-0242ac120002",
|
||||
projectId = "6fad3474-fc29-49f9-bd37-e039e9e60c18",
|
||||
id = "16vbc63c-f624-11ec-b939-0242ac120002",
|
||||
projectId = "d2e126ba-f608-11ec-b939-0242ac120025",
|
||||
category = PentestCategory.AUTHENTICATION_TESTING,
|
||||
refNumber = "OTG-AUTHN-001",
|
||||
status = PentestStatus.COMPLETED,
|
||||
findingIds = emptyList(),
|
||||
commentIds = emptyList()
|
||||
)
|
||||
// Finding
|
||||
val findingOne = Finding(
|
||||
id = "ab62d365-1b1d-4da1-89bc-5496616e220f",
|
||||
severity = Severity.LOW,
|
||||
title = "Found Bug",
|
||||
description = "OTG-INFO-002 Bug",
|
||||
impact = "Service",
|
||||
affectedUrls = emptyList(),
|
||||
reproduction = "Step 1: Hack",
|
||||
mitigation = "None"
|
||||
)
|
||||
// persist test data in database
|
||||
mongoTemplate.save(ProjectEntity(projectOne))
|
||||
mongoTemplate.save(PentestEntity(pentestOne))
|
||||
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||
mongoTemplate.save(PentestEntity(pentestThree))
|
||||
mongoTemplate.save(FindingEntity(findingOne))
|
||||
}
|
||||
|
||||
private fun configureAdminToken() {
|
||||
|
@ -130,7 +285,9 @@ class PentestControllerIntTest : BaseIntTest() {
|
|||
}
|
||||
|
||||
private fun cleanUp() {
|
||||
mongoTemplate.findAllAndRemove(Query(), ProjectEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||
mongoTemplate.findAllAndRemove(Query(), FindingEntity::class.java)
|
||||
|
||||
tokenAdmin = "n/a"
|
||||
}
|
||||
|
|
|
@ -92,7 +92,8 @@ class ProjectControllerIntTest : BaseIntTest() {
|
|||
inner class SaveProject {
|
||||
@Test
|
||||
fun `save project successfully`() {
|
||||
webTestClient.post().uri("/projects")
|
||||
webTestClient.post()
|
||||
.uri("/projects")
|
||||
.header("Authorization", "Bearer $tokenAdmin")
|
||||
.body(Mono.just(project), ProjectRequestBody::class.java)
|
||||
.exchange()
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 286 KiB After Width: | Height: | Size: 283 KiB |
Loading…
Reference in New Issue