feat: added pentest endpoint to get pentests by projectId & category
This commit is contained in:
parent
ca77f6f208
commit
24dccb3e8f
|
@ -1,6 +1,6 @@
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {environment} from '../../environments/environment';
|
import {environment} from '../../environments/environment';
|
||||||
import {HttpClient} from '@angular/common/http';
|
import {HttpClient, HttpParams} from '@angular/common/http';
|
||||||
import {Observable, of} from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
import {Category} from '@shared/models/category.model';
|
import {Category} from '@shared/models/category.model';
|
||||||
import {Pentest} from '@shared/models/pentest.model';
|
import {Pentest} from '@shared/models/pentest.model';
|
||||||
|
@ -47,6 +47,7 @@ export class PentestService {
|
||||||
* @param category the categories of which the pentests should be requested
|
* @param category the categories of which the pentests should be requested
|
||||||
*/
|
*/
|
||||||
private getPentestByProjectIdAndCategory(projectId: string, category: Category): Observable<Pentest[]> {
|
private getPentestByProjectIdAndCategory(projectId: string, category: Category): Observable<Pentest[]> {
|
||||||
return this.http.get<Pentest[]>(`${this.apiBaseURL}?projectId=${projectId}?category=${category}`);
|
const queryParams = new HttpParams().append('projectId', projectId).append('category', Category[category]);
|
||||||
|
return this.http.get<Pentest[]>(`${this.apiBaseURL}`, {params: queryParams});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"info": {
|
"info": {
|
||||||
"_postman_id": "6537da59-5c7a-478d-bf24-09a39022a690",
|
"_postman_id": "58adc500-c0c6-47f3-b268-5fcc16e0944d",
|
||||||
"name": "security-c4po-api",
|
"name": "security-c4po-api",
|
||||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||||
"_exporter_id": "5225213"
|
"_exporter_id": "5225213"
|
||||||
|
@ -255,6 +255,40 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "pentests",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"name": "getPentestsByProjectIdAndCategory",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8443/pentests?projectId=8bc16303-f652-418a-b745-8a03d89356fb&category=INFORMATION_GATHERING",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8443",
|
||||||
|
"path": [
|
||||||
|
"pentests"
|
||||||
|
],
|
||||||
|
"query": [
|
||||||
|
{
|
||||||
|
"key": "projectId",
|
||||||
|
"value": "8bc16303-f652-418a-b745-8a03d89356fb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "category",
|
||||||
|
"value": "INFORMATION_GATHERING"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "getHealth",
|
"name": "getHealth",
|
||||||
"request": {
|
"request": {
|
||||||
|
|
|
@ -57,12 +57,16 @@ include::{snippets}/saveProject/response-fields.adoc[]
|
||||||
|
|
||||||
=== Delete project
|
=== Delete project
|
||||||
|
|
||||||
To delete a project, call the DELETE request /projects/{projectId}
|
To delete a project, call the DELETE request /projects/+{projectId}+
|
||||||
|
|
||||||
==== Request example
|
==== Request example
|
||||||
|
|
||||||
include::{snippets}/deleteProject/http-request.adoc[]
|
include::{snippets}/deleteProject/http-request.adoc[]
|
||||||
|
|
||||||
|
==== Request structure
|
||||||
|
|
||||||
|
include::{snippets}/deleteProject/path-parameters.adoc[]
|
||||||
|
|
||||||
==== Response example
|
==== Response example
|
||||||
|
|
||||||
include::{snippets}/deleteProject/http-response.adoc[]
|
include::{snippets}/deleteProject/http-response.adoc[]
|
||||||
|
@ -77,7 +81,7 @@ include::{snippets}/deleteProject/response-fields.adoc[]
|
||||||
|
|
||||||
=== Update project
|
=== Update project
|
||||||
|
|
||||||
To update a project, call the PATCH request /projects/{projectId}
|
To update a project, call the PATCH request /projects/+{projectId}+
|
||||||
|
|
||||||
==== Request example
|
==== Request example
|
||||||
|
|
||||||
|
@ -106,3 +110,25 @@ include::{snippets}/updateProject/response-fields.adoc[]
|
||||||
|2021-02-12
|
|2021-02-12
|
||||||
|Initial version
|
|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[]
|
|
@ -1,6 +1,5 @@
|
||||||
package com.securityc4po.api.configuration.security
|
package com.securityc4po.api.configuration.security
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.ComponentScan
|
import org.springframework.context.annotation.ComponentScan
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
|
@ -34,6 +33,7 @@ class WebSecurityConfiguration(private val userAccountDetailsService: UserAccoun
|
||||||
.disable()
|
.disable()
|
||||||
.authorizeExchange()
|
.authorizeExchange()
|
||||||
.pathMatchers(HttpMethod.GET, "/v1/projects/**").authenticated()
|
.pathMatchers(HttpMethod.GET, "/v1/projects/**").authenticated()
|
||||||
|
.pathMatchers(HttpMethod.GET, "/v1/pentests/**").authenticated()
|
||||||
.pathMatchers("/actuator/**").permitAll()
|
.pathMatchers("/actuator/**").permitAll()
|
||||||
.pathMatchers("/docs/SecurityC4PO.html").permitAll()
|
.pathMatchers("/docs/SecurityC4PO.html").permitAll()
|
||||||
.anyExchange().authenticated()
|
.anyExchange().authenticated()
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
import com.securityc4po.api.ResponseBody
|
||||||
|
import org.springframework.data.mongodb.core.index.Indexed
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
data class Pentest(
|
||||||
|
@Indexed(background = true, unique = true)
|
||||||
|
val id: String = UUID.randomUUID().toString(),
|
||||||
|
val projectId: String,
|
||||||
|
val category: PentestCategory,
|
||||||
|
val title: String,
|
||||||
|
val refNumber: String,
|
||||||
|
val status: PentestStatus,
|
||||||
|
val findingIds: String,
|
||||||
|
val commentIds: String
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Pentest.toPentestResponseBody(): ResponseBody {
|
||||||
|
return mapOf(
|
||||||
|
"id" to id,
|
||||||
|
"projectId" to projectId,
|
||||||
|
"category" to category,
|
||||||
|
"title" to title,
|
||||||
|
"refNumber" to refNumber,
|
||||||
|
"status" to status,
|
||||||
|
"findingIds" to findingIds,
|
||||||
|
"commentIds" to commentIds
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
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 org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.http.ResponseEntity.noContent
|
||||||
|
import org.springframework.web.bind.annotation.*
|
||||||
|
import reactor.core.publisher.Mono
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/pentests")
|
||||||
|
@CrossOrigin(
|
||||||
|
origins = [],
|
||||||
|
allowCredentials = "false",
|
||||||
|
allowedHeaders = ["*"],
|
||||||
|
methods = [RequestMethod.GET]
|
||||||
|
)
|
||||||
|
|
||||||
|
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||||
|
class PentestController(private val pentestService: PentestService) {
|
||||||
|
|
||||||
|
var logger = getLoggerFor<PentestController>()
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun getPentestsByProjectIdAndCategory(
|
||||||
|
@RequestParam("projectId") projectId: String,
|
||||||
|
@RequestParam("category") category: String
|
||||||
|
): Mono<ResponseEntity<List<ResponseBody>>> {
|
||||||
|
return pentestService.getPentests(projectId, PentestCategory.valueOf(category)).map { pentestList ->
|
||||||
|
pentestList.map {
|
||||||
|
it.toPentestResponseBody()
|
||||||
|
}
|
||||||
|
}.map {
|
||||||
|
if (it.isEmpty()) noContent().build()
|
||||||
|
else ResponseEntity.ok(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
import com.securityc4po.api.BaseEntity
|
||||||
|
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||||
|
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||||
|
import org.springframework.data.mongodb.core.mapping.Document
|
||||||
|
|
||||||
|
@Document(collection = "pentests")
|
||||||
|
open class PentestEntity(
|
||||||
|
data: Pentest
|
||||||
|
) : BaseEntity<Pentest>(data)
|
||||||
|
|
||||||
|
fun PentestEntity.toPentest(): Pentest {
|
||||||
|
return Pentest(
|
||||||
|
this.data.id,
|
||||||
|
this.data.projectId,
|
||||||
|
this.data.category,
|
||||||
|
this.data.title,
|
||||||
|
this.data.refNumber,
|
||||||
|
this.data.status,
|
||||||
|
this.data.findingIds,
|
||||||
|
this.data.commentIds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION, MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||||
|
fun List<PentestEntity>.toPentests(): List<Pentest> {
|
||||||
|
return this.map {
|
||||||
|
it.toPentest()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
import org.springframework.data.mongodb.repository.Query
|
||||||
|
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
import reactor.core.publisher.Flux
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
interface PentestRepository : ReactiveMongoRepository<PentestEntity, String> {
|
||||||
|
|
||||||
|
@Query("{'data.projectId': ?0, 'data.category': ?1}")
|
||||||
|
fun findPentestByProjectIdAndCategory(projectId: String, category: PentestCategory): Flux<PentestEntity>
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||||
|
import com.securityc4po.api.configuration.MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION
|
||||||
|
import com.securityc4po.api.extensions.getLoggerFor
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import reactor.core.publisher.Mono
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION, MESSAGE_BAD_CAST_TO_ABSTRACT_COLLECTION)
|
||||||
|
class PentestService(private val pentestRepository: PentestRepository) {
|
||||||
|
|
||||||
|
var logger = getLoggerFor<PentestService>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all [Pentest]s by projectId and category
|
||||||
|
*
|
||||||
|
* @return list of [Pentest]
|
||||||
|
*/
|
||||||
|
fun getPentests(projectId: String, category: PentestCategory): Mono<List<Pentest>> {
|
||||||
|
return pentestRepository.findPentestByProjectIdAndCategory(projectId, category).collectList().map {
|
||||||
|
it.map { pentestEntity -> pentestEntity.toPentest() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
enum class PentestStatus {
|
||||||
|
NOT_STARTED,
|
||||||
|
OPEN,
|
||||||
|
UNDER_REVIEW,
|
||||||
|
DISABLED,
|
||||||
|
CHECKED,
|
||||||
|
REPORTED,
|
||||||
|
TRIAGED
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||||
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Nested
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.data.mongodb.core.MongoTemplate
|
||||||
|
import org.springframework.data.mongodb.core.query.Query
|
||||||
|
import org.springframework.restdocs.operation.preprocess.Preprocessors
|
||||||
|
import org.springframework.restdocs.payload.JsonFieldType
|
||||||
|
import org.springframework.restdocs.payload.PayloadDocumentation
|
||||||
|
import org.springframework.restdocs.request.RequestDocumentation
|
||||||
|
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
|
||||||
|
|
||||||
|
@SuppressFBWarnings(
|
||||||
|
SIC_INNER_SHOULD_BE_STATIC,
|
||||||
|
NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR,
|
||||||
|
RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||||
|
)
|
||||||
|
class PentestControllerDocumentationTest : BaseDocumentationIntTest() {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
lateinit var mongoTemplate: MongoTemplate
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun init() {
|
||||||
|
configureAdminToken()
|
||||||
|
persistBasicTestScenario()
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
fun destroy() {
|
||||||
|
cleanUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class GetPentests {
|
||||||
|
@Test
|
||||||
|
fun getPentestsByProjectIdAndCategory() {
|
||||||
|
val projectId = "d2e126ba-f608-11ec-b939-0242ac120002"
|
||||||
|
val category = "INFORMATION_GATHERING"
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/pentests?projectId={projectId}&category={category}", projectId, category)
|
||||||
|
.header("Authorization", "Bearer $tokenAdmin")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk
|
||||||
|
.expectHeader().doesNotExist("")
|
||||||
|
.expectBody().json(Json.write(getProjectsResponse()))
|
||||||
|
.consumeWith(
|
||||||
|
WebTestClientRestDocumentation.document(
|
||||||
|
"{methodName}",
|
||||||
|
Preprocessors.preprocessRequest(
|
||||||
|
Preprocessors.prettyPrint(),
|
||||||
|
Preprocessors.modifyUris().removePort(),
|
||||||
|
Preprocessors.removeHeaders("Host", "Content-Length")
|
||||||
|
),
|
||||||
|
Preprocessors.preprocessResponse(
|
||||||
|
Preprocessors.prettyPrint()
|
||||||
|
),
|
||||||
|
RequestDocumentation.relaxedRequestParameters(
|
||||||
|
RequestDocumentation.parameterWithName("projectId").description("The id of the project you want to get the pentests for"),
|
||||||
|
RequestDocumentation.parameterWithName("category").description("The category you want to get the pentests for")
|
||||||
|
),
|
||||||
|
PayloadDocumentation.relaxedResponseFields(
|
||||||
|
PayloadDocumentation.fieldWithPath("[].id").type(JsonFieldType.STRING)
|
||||||
|
.description("The id of the requested pentest"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].projectId").type(JsonFieldType.STRING)
|
||||||
|
.description("The id of the project of the requested pentest"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].category").type(JsonFieldType.STRING)
|
||||||
|
.description("The category of the requested pentest"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].title").type(JsonFieldType.STRING)
|
||||||
|
.description("The title of the requested pentest"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].refNumber").type(JsonFieldType.STRING)
|
||||||
|
.description("The reference number of the requested pentest according to the current OWASP Testing Guide"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].status").type(JsonFieldType.STRING)
|
||||||
|
.description("The status of the requested pentest"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].findingIds").type(JsonFieldType.STRING)
|
||||||
|
.description("The ids of the findings in the requested pentest"),
|
||||||
|
PayloadDocumentation.fieldWithPath("[].commentIds").type(JsonFieldType.STRING)
|
||||||
|
.description("The ids of the comments of the requested pentest")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val pentestOne = Pentest(
|
||||||
|
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Search engine discovery/reconnaissance",
|
||||||
|
refNumber = "OTG-INFO-001",
|
||||||
|
status = PentestStatus.NOT_STARTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
private val pentestTwo = Pentest(
|
||||||
|
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Fingerprint Web Server",
|
||||||
|
refNumber = "OTG-INFO-002",
|
||||||
|
status = PentestStatus.REPORTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun getProjectsResponse() = listOf(
|
||||||
|
pentestOne.toPentestResponseBody(),
|
||||||
|
pentestTwo.toPentestResponseBody()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun persistBasicTestScenario() {
|
||||||
|
// setup test data
|
||||||
|
val pentestOne = Pentest(
|
||||||
|
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Search engine discovery/reconnaissance",
|
||||||
|
refNumber = "OTG-INFO-001",
|
||||||
|
status = PentestStatus.NOT_STARTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
val pentestTwo = Pentest(
|
||||||
|
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Fingerprint Web Server",
|
||||||
|
refNumber = "OTG-INFO-002",
|
||||||
|
status = PentestStatus.REPORTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
val pentestThree = Pentest(
|
||||||
|
id = "74eae112-f62c-11ec-b939-0242ac120002",
|
||||||
|
projectId = "6fad3474-fc29-49f9-bd37-e039e9e60c18",
|
||||||
|
category = PentestCategory.AUTHENTICATION_TESTING,
|
||||||
|
title = "Testing for Credentials Transported over an Encrypted Channel",
|
||||||
|
refNumber = "OTG-AUTHN-001",
|
||||||
|
status = PentestStatus.CHECKED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
// persist test data in database
|
||||||
|
mongoTemplate.save(PentestEntity(pentestOne))
|
||||||
|
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||||
|
mongoTemplate.save(PentestEntity(pentestThree))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureAdminToken() {
|
||||||
|
tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cleanUp() {
|
||||||
|
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||||
|
|
||||||
|
tokenAdmin = "n/a"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package com.securityc4po.api.pentest
|
||||||
|
|
||||||
|
import com.github.tomakehurst.wiremock.common.Json
|
||||||
|
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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||||
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Nested
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
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 java.time.Duration
|
||||||
|
|
||||||
|
@SuppressFBWarnings(
|
||||||
|
SIC_INNER_SHOULD_BE_STATIC,
|
||||||
|
NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR,
|
||||||
|
RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
|
||||||
|
)
|
||||||
|
class PentestControllerIntTest : BaseIntTest() {
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private var port = 0
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
lateinit var mongoTemplate: MongoTemplate
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private lateinit var webTestClient: WebTestClient
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setupWebClient() {
|
||||||
|
webTestClient = WebTestClient.bindToServer()
|
||||||
|
.baseUrl("http://localhost:$port")
|
||||||
|
.responseTimeout(Duration.ofMillis(10000))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun init() {
|
||||||
|
configureAdminToken()
|
||||||
|
persistBasicTestScenario()
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
fun destroy() {
|
||||||
|
cleanUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class GetPentests {
|
||||||
|
@Test
|
||||||
|
fun `requesting pentests by projectId and category successfully`() {
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/pentests?projectId=d2e126ba-f608-11ec-b939-0242ac120002&category=INFORMATION_GATHERING")
|
||||||
|
.header("Authorization", "Bearer $tokenAdmin")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk
|
||||||
|
.expectHeader().valueEquals("Application-Name", "SecurityC4PO")
|
||||||
|
.expectBody().json(Json.write(getPentests()))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val pentestOne = Pentest(
|
||||||
|
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Search engine discovery/reconnaissance",
|
||||||
|
refNumber = "OTG-INFO-001",
|
||||||
|
status = PentestStatus.NOT_STARTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
private val pentestTwo = Pentest(
|
||||||
|
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Fingerprint Web Server",
|
||||||
|
refNumber = "OTG-INFO-002",
|
||||||
|
status = PentestStatus.REPORTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun getPentests() = listOf(
|
||||||
|
pentestOne.toPentestResponseBody(),
|
||||||
|
pentestTwo.toPentestResponseBody()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun persistBasicTestScenario() {
|
||||||
|
// setup test data
|
||||||
|
val pentestOne = Pentest(
|
||||||
|
id = "9c8af320-f608-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Search engine discovery/reconnaissance",
|
||||||
|
refNumber = "OTG-INFO-001",
|
||||||
|
status = PentestStatus.NOT_STARTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
val pentestTwo = Pentest(
|
||||||
|
id = "43fbc63c-f624-11ec-b939-0242ac120002",
|
||||||
|
projectId = "d2e126ba-f608-11ec-b939-0242ac120002",
|
||||||
|
category = PentestCategory.INFORMATION_GATHERING,
|
||||||
|
title = "Fingerprint Web Server",
|
||||||
|
refNumber = "OTG-INFO-002",
|
||||||
|
status = PentestStatus.REPORTED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
val pentestThree = Pentest(
|
||||||
|
id = "74eae112-f62c-11ec-b939-0242ac120002",
|
||||||
|
projectId = "6fad3474-fc29-49f9-bd37-e039e9e60c18",
|
||||||
|
category = PentestCategory.AUTHENTICATION_TESTING,
|
||||||
|
title = "Testing for Credentials Transported over an Encrypted Channel",
|
||||||
|
refNumber = "OTG-AUTHN-001",
|
||||||
|
status = PentestStatus.CHECKED,
|
||||||
|
findingIds = "",
|
||||||
|
commentIds = ""
|
||||||
|
)
|
||||||
|
// persist test data in database
|
||||||
|
mongoTemplate.save(PentestEntity(pentestOne))
|
||||||
|
mongoTemplate.save(PentestEntity(pentestTwo))
|
||||||
|
mongoTemplate.save(PentestEntity(pentestThree))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureAdminToken() {
|
||||||
|
tokenAdmin = getAccessToken("test_admin", "test", "c4po_local", "c4po_realm_local")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cleanUp() {
|
||||||
|
mongoTemplate.findAllAndRemove(Query(), PentestEntity::class.java)
|
||||||
|
|
||||||
|
tokenAdmin = "n/a"
|
||||||
|
}
|
||||||
|
}
|
|
@ -154,7 +154,8 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
|
||||||
inner class DeleteProject {
|
inner class DeleteProject {
|
||||||
@Test
|
@Test
|
||||||
fun deleteProject() {
|
fun deleteProject() {
|
||||||
webTestClient.delete().uri("/projects/${project.id}")
|
val id = project.id
|
||||||
|
webTestClient.delete().uri("/projects/{id}", id)
|
||||||
.header("Authorization", "Bearer $tokenAdmin")
|
.header("Authorization", "Bearer $tokenAdmin")
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isOk
|
.expectStatus().isOk
|
||||||
|
@ -172,6 +173,9 @@ class ProjectControllerDocumentationTest : BaseDocumentationIntTest() {
|
||||||
Preprocessors.preprocessResponse(
|
Preprocessors.preprocessResponse(
|
||||||
Preprocessors.prettyPrint()
|
Preprocessors.prettyPrint()
|
||||||
),
|
),
|
||||||
|
RequestDocumentation.relaxedPathParameters(
|
||||||
|
RequestDocumentation.parameterWithName("id").description("The id of the project you want to delete")
|
||||||
|
),
|
||||||
PayloadDocumentation.relaxedResponseFields(
|
PayloadDocumentation.relaxedResponseFields(
|
||||||
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
PayloadDocumentation.fieldWithPath("id").type(JsonFieldType.STRING)
|
||||||
.description("The id of the deleted project")
|
.description("The id of the deleted project")
|
||||||
|
|
Loading…
Reference in New Issue