feat: As a developer I want to create a finding that is related to my pentest

This commit is contained in:
Marcel Haag 2022-11-14 12:12:52 +01:00 committed by Cel
parent 84b7c1a07d
commit b2f430f9fd
22 changed files with 1982 additions and 39 deletions

View File

@ -49,6 +49,7 @@
size="small" size="small"
shape="round" shape="round"
class="add-finding-button" class="add-finding-button"
[disabled]="pentestInfo$.getValue().status === notStartedStatus"
(click)="onClickAddFinding()"> (click)="onClickAddFinding()">
<fa-icon [icon]="fa.faPlus" class="new-finding-icon"></fa-icon> <fa-icon [icon]="fa.faPlus" class="new-finding-icon"></fa-icon>
{{'finding.add' | translate}} {{'finding.add' | translate}}

View File

@ -1,16 +1,23 @@
import {Component, Input, OnInit} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {PentestService} from '@shared/services/pentest.service'; import {PentestService} from '@shared/services/pentest.service';
import {BehaviorSubject, Observable} from 'rxjs'; import {BehaviorSubject, Observable} from 'rxjs';
import {Pentest} from '@shared/models/pentest.model'; import {Pentest, transformPentestToRequestBody} from '@shared/models/pentest.model';
import {UntilDestroy, untilDestroyed} from '@ngneat/until-destroy'; import {UntilDestroy, untilDestroyed} from '@ngneat/until-destroy';
import {filter, mergeMap, tap} from 'rxjs/operators'; import {filter, mergeMap, tap} from 'rxjs/operators';
import {NotificationService, PopupType} from '@shared/services/notification.service'; import {NotificationService, PopupType} from '@shared/services/notification.service';
import {Finding, FindingDialogBody, FindingEntry, transformFindingsToObjectiveEntries} from '@shared/models/finding.model'; import {
Finding,
FindingDialogBody,
FindingEntry,
transformFindingsToObjectiveEntries,
transformFindingToRequestBody
} from '@shared/models/finding.model';
import {NbGetters, NbTreeGridDataSource, NbTreeGridDataSourceBuilder} from '@nebular/theme'; import {NbGetters, NbTreeGridDataSource, NbTreeGridDataSourceBuilder} from '@nebular/theme';
import * as FA from '@fortawesome/free-solid-svg-icons'; import * as FA from '@fortawesome/free-solid-svg-icons';
import {isNotNullOrUndefined} from 'codelyzer/util/isNotNullOrUndefined'; import {isNotNullOrUndefined} from 'codelyzer/util/isNotNullOrUndefined';
import {FindingDialogService} from '@shared/modules/finding-dialog/service/finding-dialog.service'; import {FindingDialogService} from '@shared/modules/finding-dialog/service/finding-dialog.service';
import {FindingDialogComponent} from '@shared/modules/finding-dialog/finding-dialog.component'; import {FindingDialogComponent} from '@shared/modules/finding-dialog/finding-dialog.component';
import {PentestStatus} from '@shared/models/pentest-status.model';
@UntilDestroy() @UntilDestroy()
@Component({ @Component({
@ -20,6 +27,13 @@ import {FindingDialogComponent} from '@shared/modules/finding-dialog/finding-dia
}) })
export class PentestFindingsComponent implements OnInit { export class PentestFindingsComponent implements OnInit {
constructor(private readonly pentestService: PentestService,
private dataSourceBuilder: NbTreeGridDataSourceBuilder<FindingEntry>,
private notificationService: NotificationService,
private findingDialogService: FindingDialogService) {
this.dataSource = dataSourceBuilder.create(this.data, this.getters);
}
@Input() @Input()
pentestInfo$: BehaviorSubject<Pentest> = new BehaviorSubject<Pentest>(null); pentestInfo$: BehaviorSubject<Pentest> = new BehaviorSubject<Pentest>(null);
@ -40,12 +54,8 @@ export class PentestFindingsComponent implements OnInit {
expandedGetter: (node: FindingEntry) => !!node.expanded, expandedGetter: (node: FindingEntry) => !!node.expanded,
}; };
constructor(private readonly pentestService: PentestService, // HTML only
private dataSourceBuilder: NbTreeGridDataSourceBuilder<FindingEntry>, notStartedStatus: PentestStatus = PentestStatus.NOT_STARTED;
private notificationService: NotificationService,
private findingDialogService: FindingDialogService) {
this.dataSource = dataSourceBuilder.create(this.data, this.getters);
}
ngOnInit(): void { ngOnInit(): void {
this.loadFindingsData(); this.loadFindingsData();
@ -87,7 +97,10 @@ export class PentestFindingsComponent implements OnInit {
filter(value => !!value), filter(value => !!value),
tap((value) => console.warn('FindingDialogBody: ', value)), tap((value) => console.warn('FindingDialogBody: ', value)),
mergeMap((value: FindingDialogBody) => mergeMap((value: FindingDialogBody) =>
this.pentestService.saveFinding(this.pentestInfo$.getValue() ? this.pentestInfo$.getValue().id : '', value) this.pentestService.saveFinding(
this.pentestInfo$.getValue() ? this.pentestInfo$.getValue().id : '',
transformFindingToRequestBody(value)
)
), ),
untilDestroyed(this) untilDestroyed(this)
).subscribe({ ).subscribe({
@ -110,7 +123,6 @@ export class PentestFindingsComponent implements OnInit {
console.info('Coming soon..'); console.info('Coming soon..');
} }
// HTML only
isLoading(): Observable<boolean> { isLoading(): Observable<boolean> {
return this.loading$.asObservable(); return this.loading$.asObservable();
} }

View File

@ -1,5 +1,7 @@
import {v4 as UUID} from 'uuid'; import {v4 as UUID} from 'uuid';
import {Severity} from '@shared/models/severity.enum'; import {Severity} from '@shared/models/severity.enum';
import {Category} from '@shared/models/category.model';
import {Pentest} from '@shared/models/pentest.model';
export class Finding { export class Finding {
id?: string; id?: string;
@ -56,6 +58,25 @@ export function transformFindingsToObjectiveEntries(findings: Finding[]): Findin
return findingEntries; return findingEntries;
} }
export function transformFindingToRequestBody(finding: FindingDialogBody | Finding): Finding {
const transformedFinding = {
...finding,
severity: typeof finding.severity === 'number' ? Severity[finding.severity] : finding.severity,
title: finding.title,
description: finding.description,
impact: finding.impact,
affectedUrls: finding.affectedUrls ? finding.affectedUrls : [],
reproduction: finding.reproduction,
mitigation: finding.mitigation,
/* Remove Table Entry Object Properties */
childEntries: undefined,
kind: undefined,
findings: undefined,
expanded: undefined,
} as unknown as Finding;
return transformedFinding;
}
export interface FindingDialogBody { export interface FindingDialogBody {
title: string; title: string;
severity: Severity; severity: Severity;

View File

@ -133,7 +133,8 @@ export class PentestService {
* @param pentestId the id of the pentest * @param pentestId the id of the pentest
* @param finding the information of the finding * @param finding the information of the finding
*/ */
public saveFinding(pentestId: string, finding: FindingDialogBody): Observable<Finding> { public saveFinding(pentestId: string, finding: Finding): Observable<Finding> {
console.warn('Finding: ', finding);
return this.http.post<Finding>(`${this.apiBaseURL}/${pentestId}/finding`, finding); return this.http.post<Finding>(`${this.apiBaseURL}/${pentestId}/finding`, finding);
} }

View File

@ -258,6 +258,55 @@
{ {
"name": "pentests", "name": "pentests",
"item": [ "item": [
{
"name": "Finding",
"item": [
{
"name": "saveFinding",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICItdG1lbEV0ZHhGTnRSMW9aNXlRdE5jaFFpX0RVN2VNeV9YcU44aXY0S3hzIn0.eyJleHAiOjE2Njg0MjU2MjgsImlhdCI6MTY2ODQyNTMyOCwianRpIjoiODQyMjE5ODgtMDhkNC00YTg1LWEwNTYtZjI0N2QxZThkNDg2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4ODg4L2F1dGgvcmVhbG1zL2M0cG9fcmVhbG1fbG9jYWwiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMTBlMDZkN2EtOGRkMC00ZWNkLTg5NjMtMDU2YjQ1MDc5YzRmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYzRwb19sb2NhbCIsInNlc3Npb25fc3RhdGUiOiJjYmMxMTJiNy03MGRlLTRhNjctYWRmYS1lNTA0NGE1ZDNjZDQiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImM0cG9fdXNlciIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJjNHBvX2xvY2FsIjp7InJvbGVzIjpbInVzZXIiXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6InRlc3QgdXNlciIsInByZWZlcnJlZF91c2VybmFtZSI6InR0dCIsImdpdmVuX25hbWUiOiJ0ZXN0IiwiZmFtaWx5X25hbWUiOiJ1c2VyIn0.glSjoxDFWzA4ApXGLMMaurfzfm0z9QU2mo1ZmPsH24pNjdp4A5CgxOIGkU6SKeHaPfeHvdaxevAWrkFdNGTJn_XLmAcqitNIEsrbIv76LKkNN2KNSltm1cfPM1fJPOXy91egX0SB3WoHzylw7zZZTsDncAcJEa1OCf6UUpKmKxmaqQLLTS4CMN82PNxeZFNgripoH5WqlutPdYCBK8WCgNoDh1njCIwevY12yi0gzAFtAH0I5Eqa5QwWpMWzB_Zs4WlqzSiuJVI7aqTRfrmZHe_qjR9riLMvgVoobLB0stbRH5VnHom-MNuUIw6SKVA0I9DPQb4jpF7Q4vqz8UBOMQ",
"type": "string"
},
{
"key": "undefined",
"type": "any"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"title\": \"Test Title\",\n \"severity\": \"LOW\",\n \"description\": \"Test Description\",\n \"impact\": \"Test Impact\",\n \"affectedUrls\": [\n \"https://akveo.github.io/nebular/docs/components/progress-bar/examples#nbprogressbarcomponent\"\n ],\n \"reproduction\": \"Step 1: Test\",\n \"mitigation\": \"Test Mitigatin\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8443/pentests/11601f51-bc17-47fd-847d-0c53df5405b5/finding",
"protocol": "http",
"host": [
"localhost"
],
"port": "8443",
"path": [
"pentests",
"11601f51-bc17-47fd-847d-0c53df5405b5",
"finding"
]
}
},
"response": []
}
]
},
{ {
"name": "getPentestsByProjectIdAndCategory", "name": "getPentestsByProjectIdAndCategory",
"request": { "request": {

View File

@ -1,4 +1,4 @@
package comment package com.securityc4po.api.comment
import org.springframework.data.mongodb.core.index.Indexed import org.springframework.data.mongodb.core.index.Indexed
import java.util.* import java.util.*

View File

@ -1,4 +1,4 @@
package comment package com.securityc4po.api.comment
import com.securityc4po.api.BaseEntity import com.securityc4po.api.BaseEntity
import org.springframework.data.mongodb.core.mapping.Document import org.springframework.data.mongodb.core.mapping.Document

View File

@ -17,6 +17,7 @@ enum class Errorcode(val code: Int) {
InvalidToken(3003), InvalidToken(3003),
TokenWithoutField(3004), TokenWithoutField(3004),
UserIdIsEmpty(3005), UserIdIsEmpty(3005),
FindingInvalid(3006),
// 4XXX Unauthorized // 4XXX Unauthorized
ProjectAdjustmentNotAuthorized(4000), ProjectAdjustmentNotAuthorized(4000),
@ -35,4 +36,5 @@ enum class Errorcode(val code: Int) {
ProjectInsertionFailed(6006), ProjectInsertionFailed(6006),
PentestInsertionFailed(6007), PentestInsertionFailed(6007),
ProjectPentestInsertionFailed(6008), ProjectPentestInsertionFailed(6008),
FindingInsertionFailed(6009),
} }

View File

@ -0,0 +1,66 @@
package com.securityc4po.api.finding
import com.securityc4po.api.ResponseBody
import org.springframework.data.mongodb.core.index.Indexed
import java.util.*
data class Finding (
@Indexed(background = true, unique = true)
val id: String = UUID.randomUUID().toString(),
val severity: Severity,
val title: String,
val description: String,
val impact: String,
val affectedUrls: List<String>? = emptyList(),
val reproduction: String?,
val mitigation: String?
)
data class FindingRequestBody(
val severity: String,
val title: String,
val description: String,
val impact: String,
val affectedUrls: List<String>? = emptyList(),
val reproduction: String?,
val mitigation: String?
)
fun Finding.toFindingResponseBody(): ResponseBody {
return mapOf(
"id" to id,
"title" to title,
"description" to description,
"impact" to impact,
"affectedUrls" to affectedUrls,
"reproduction" to reproduction,
"mitigation" to mitigation
)
}
/**
* Validates if a [FindingRequestBody] is valid
*
* @return Boolean describing if the body is valid
*/
fun FindingRequestBody.isValid(): Boolean {
return when {
this.title.isBlank() -> false
this.description.isBlank() -> false
this.impact.isBlank() -> false
else -> true
}
}
fun FindingRequestBody.toFinding(): Finding {
return Finding(
id = UUID.randomUUID().toString(),
severity = Severity.valueOf(this.severity),
title = this.title,
description = this.description,
impact = this.impact,
affectedUrls = this.affectedUrls,
reproduction = this.reproduction,
mitigation = this.mitigation
)
}

View File

@ -1,4 +1,4 @@
package finding package com.securityc4po.api.finding
import com.securityc4po.api.BaseEntity import com.securityc4po.api.BaseEntity
import org.springframework.data.mongodb.core.mapping.Document import org.springframework.data.mongodb.core.mapping.Document
@ -9,7 +9,7 @@ open class FindingEntity(
) : BaseEntity<Finding>(data) ) : BaseEntity<Finding>(data)
fun FindingEntity.toFinding(): Finding { fun FindingEntity.toFinding(): Finding {
return finding.Finding( return Finding(
this.data.id, this.data.id,
this.data.severity, this.data.severity,
this.data.title, this.data.title,

View File

@ -0,0 +1,13 @@
package com.securityc4po.api.finding
import org.springframework.data.mongodb.repository.Query
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
import org.springframework.stereotype.Repository
import reactor.core.publisher.Mono
@Repository
interface FindingRepository : ReactiveMongoRepository<FindingEntity, String> {
@Query("{'data._id' : ?0}")
fun findFindingById(id: String): Mono<FindingEntity>
}

View File

@ -0,0 +1,58 @@
package com.securityc4po.api.finding
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.configuration.error.handler.*
import com.securityc4po.api.configuration.error.handler.InvalidModelException
import com.securityc4po.api.configuration.error.handler.TransactionInterruptedException
import com.securityc4po.api.extensions.getLoggerFor
import com.securityc4po.api.pentest.PentestService
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 FindingService(private val findingRepository: FindingRepository, private val pentestService: PentestService) {
var logger = getLoggerFor<FindingService>()
/**
* Save [Finding]
*
* @throws [InvalidModelException] if the [Finding] is invalid
* @throws [TransactionInterruptedException] if the [Finding] could not be stored
* @return saved [Finding]
*/
fun saveFinding(pentestId: String, body: FindingRequestBody): Mono<Finding> {
validate(
require = body.isValid(),
logging = { logger.warn("Finding not valid.") },
mappedException = InvalidModelException(
"Finding not valid.", Errorcode.FindingInvalid
)
)
val finding = body.toFinding()
val findingEntity = FindingEntity(finding)
return findingRepository.insert(findingEntity).flatMap { newFindingEntity: FindingEntity ->
val finding = newFindingEntity.toFinding()
// After successfully saving finding add id to pentest
pentestService.updatePentestFinding(pentestId, finding.id).onErrorMap {
TransactionInterruptedException(
"Pentest could not be updated in Database.",
Errorcode.PentestInsertionFailed
)
}.map {
finding
}
}.doOnError {
throw wrappedException(
logging = { logger.warn("Finding could not be stored in Database. Thrown exception: ", it) },
mappedException = TransactionInterruptedException(
"Finding could not be stored.",
Errorcode.FindingInsertionFailed
)
)
}
}
}

View File

@ -1,4 +1,4 @@
package finding package com.securityc4po.api.finding
enum class Severity { enum class Severity {
LOW, LOW,

View File

@ -11,7 +11,7 @@ data class Pentest(
val category: PentestCategory, val category: PentestCategory,
val refNumber: String, val refNumber: String,
val status: PentestStatus, val status: PentestStatus,
val findingIds: List<String> = emptyList(), var findingIds: List<String> = emptyList(),
val commentIds: List<String> = emptyList() val commentIds: List<String> = emptyList()
) )
@ -27,6 +27,18 @@ fun buildPentest(body: PentestRequestBody, pentestEntity: PentestEntity): Pentes
) )
} }
/*fun addFindingtoPentest(findingId: String, pentestEntity: PentestEntity): Pentest {
return Pentest(
id = pentestEntity.data.id,
projectId = pentestEntity.data.projectId,
category = pentestEntity.data.category,
refNumber = pentestEntity.data.refNumber,
status = pentestEntity.data.status,
findingIds = pentestEntity.data.findingIds,
commentIds = pentestEntity.data.commentIds
)
}*/
fun Pentest.toPentestResponseBody(): ResponseBody { fun Pentest.toPentestResponseBody(): ResponseBody {
return mapOf( return mapOf(
"id" to id, "id" to id,

View File

@ -4,6 +4,9 @@ import com.securityc4po.api.configuration.BC_BAD_CAST_TO_ABSTRACT_COLLECTION
import com.securityc4po.api.extensions.getLoggerFor import com.securityc4po.api.extensions.getLoggerFor
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import com.securityc4po.api.ResponseBody import com.securityc4po.api.ResponseBody
import com.securityc4po.api.finding.FindingRequestBody
import com.securityc4po.api.finding.FindingService
import com.securityc4po.api.finding.toFindingResponseBody
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.noContent import org.springframework.http.ResponseEntity.noContent
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
@ -17,9 +20,8 @@ import reactor.core.publisher.Mono
allowedHeaders = ["*"], allowedHeaders = ["*"],
methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH] methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH]
) )
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION) @SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
class PentestController(private val pentestService: PentestService) { class PentestController(private val pentestService: PentestService, private val findingService: FindingService) {
var logger = getLoggerFor<PentestController>() var logger = getLoggerFor<PentestController>()
@ -69,4 +71,15 @@ class PentestController(private val pentestService: PentestService) {
ResponseEntity.accepted().body(it.toPentestResponseBody()) ResponseEntity.accepted().body(it.toPentestResponseBody())
} }
} }
// 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())
}
}
} }

View File

@ -115,6 +115,37 @@ class PentestService(private val pentestRepository: PentestRepository, private v
) )
} }
} }
}
/**
* Update [Pentest] for Finding
*
* @throws [InvalidModelException] if the [Pentest] is invalid
* @throws [TransactionInterruptedException] if the [Pentest] could not be updated
* @return updated [Pentest]
*/
fun updatePentestFinding(pentestId: String, findingId: String): Mono<Pentest> {
return pentestRepository.findPentestById(pentestId).switchIfEmpty {
logger.warn("Pentest with id $pentestId not found. Updating not possible.")
val msg = "Pentest with id $pentestId not found."
val ex = EntityNotFoundException(msg, Errorcode.PentestNotFound)
throw ex
}.flatMap { currentPentestEntity: PentestEntity ->
if (currentPentestEntity.data.findingIds.find { pentestData -> pentestData == findingId } == null) {
currentPentestEntity.data.findingIds += findingId
}
currentPentestEntity.lastModified = Instant.now()
this.pentestRepository.save(currentPentestEntity).map {
it.toPentest()
}.doOnError {
throw wrappedException(
logging = { logger.warn("Pentest could not be updated in Database. Thrown exception: ", it) },
mappedException = TransactionInterruptedException(
"Pentest could not be updated.",
Errorcode.PentestInsertionFailed
)
)
}
}
} }
} }

View File

@ -17,7 +17,6 @@ import reactor.kotlin.core.publisher.switchIfEmpty
allowedHeaders = ["*"], allowedHeaders = ["*"],
methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH] methods = [RequestMethod.GET, RequestMethod.DELETE, RequestMethod.POST, RequestMethod.PATCH]
) )
@SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION) @SuppressFBWarnings(BC_BAD_CAST_TO_ABSTRACT_COLLECTION)
class ProjectController(private val projectService: ProjectService) { class ProjectController(private val projectService: ProjectService) {

View File

@ -141,7 +141,7 @@ class ProjectService(private val projectRepository: ProjectRepository) {
throw ex throw ex
}.flatMap {projectEntity: ProjectEntity -> }.flatMap {projectEntity: ProjectEntity ->
val currentProjectPentestStatus = projectEntity.data.projectPentests.find { projectPentestData -> projectPentestData.pentestId == projectPentest.pentestId } val currentProjectPentestStatus = projectEntity.data.projectPentests.find { projectPentestData -> projectPentestData.pentestId == projectPentest.pentestId }
if (currentProjectPentestStatus !== null) { if (currentProjectPentestStatus != null) {
projectEntity.data.projectPentests.find { data -> data.pentestId == projectPentest.pentestId }!!.status = projectPentest.status projectEntity.data.projectPentests.find { data -> data.pentestId == projectPentest.pentestId }!!.status = projectPentest.status
} else { } else {
projectEntity.data.projectPentests += projectPentest projectEntity.data.projectPentests += projectPentest

View File

@ -1,16 +0,0 @@
package finding
import org.springframework.data.mongodb.core.index.Indexed
import java.util.*
data class Finding (
@Indexed(background = true, unique = true)
val id: String = UUID.randomUUID().toString(),
val severity: Severity,
val title: String,
val description: String,
val impact: String,
val affectedUrls: List<String>? = emptyList(),
val reproduction: String,
val mitigation: String
)

View File

@ -0,0 +1,23 @@
[{
"_id": {
"$oid": "6372223efea5724fd22bae8a"
},
"lastModified": {
"$date": {
"$numberLong": "1668424254533"
}
},
"data": {
"_id": "ef31449d-71ec-4736-952f-8b20e53117d5",
"severity": "LOW",
"title": "Test Title",
"description": "Test Description",
"impact": "Test Impact",
"affectedUrls": [
"https://akveo.github.io/nebular/docs/components/progress-bar/examples#nbprogressbarcomponent"
],
"reproduction": "Step 1: Test",
"mitigation": "Test Mitigatin"
},
"_class": "com.securityc4po.api.finding.FindingEntity"
}]

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
}, },
"lastModified": { "lastModified": {
"$date": { "$date": {
"$numberLong": "1668176064717" "$numberLong": "1668425376081"
} }
}, },
"data": { "data": {
@ -17,6 +17,294 @@
{ {
"pentestId": "11601f51-bc17-47fd-847d-0c53df5405b5", "pentestId": "11601f51-bc17-47fd-847d-0c53df5405b5",
"status": "IN_PROGRESS" "status": "IN_PROGRESS"
},
{
"pentestId": "9a073a08-e4fc-4450-8202-c902455b66ec",
"status": "OPEN"
},
{
"pentestId": "981c5e24-7276-47f8-a821-ff5976292ad4",
"status": "OPEN"
},
{
"pentestId": "2d46a183-8f11-4fbc-bbf1-e439f7282bb9",
"status": "OPEN"
},
{
"pentestId": "eb4f80f3-caac-4fef-a5dd-53616701f171",
"status": "OPEN"
},
{
"pentestId": "0ab8de31-9d5e-4b6b-a43c-12207c160863",
"status": "IN_PROGRESS"
},
{
"pentestId": "3ed9e894-58e8-46b9-9859-cde675fec17c",
"status": "OPEN"
},
{
"pentestId": "53fdab75-ea52-4cea-85ed-df8b67f41b72",
"status": "OPEN"
},
{
"pentestId": "6270d4bc-5f39-4358-ad0a-fd5791191f28",
"status": "IN_PROGRESS"
},
{
"pentestId": "1a90f468-470a-4b1e-9783-cc761b1770ee",
"status": "OPEN"
},
{
"pentestId": "6eb37869-baef-4a5b-9ac0-bf202a49874f",
"status": "OPEN"
},
{
"pentestId": "da89c933-1413-4186-ad2c-f1967cb8dbb4",
"status": "OPEN"
},
{
"pentestId": "b3682591-f6c3-4969-bf15-69f4d495ef18",
"status": "OPEN"
},
{
"pentestId": "9e8e2736-afc9-4f63-b29f-567f9f316c83",
"status": "OPEN"
},
{
"pentestId": "3405bdd6-1ae2-4876-9c18-443a791cec9c",
"status": "OPEN"
},
{
"pentestId": "2fd387b3-b7a5-4297-9790-5d7845214c05",
"status": "OPEN"
},
{
"pentestId": "a61116c5-1859-4df3-8252-7788c31472d8",
"status": "OPEN"
},
{
"pentestId": "47d8b39d-9fa7-4772-8605-84aa0531f49e",
"status": "OPEN"
},
{
"pentestId": "bd2b8899-0cd9-41fd-a975-257aac48b81f",
"status": "OPEN"
},
{
"pentestId": "b9bde632-c275-4566-b693-c57a3dad47f3",
"status": "OPEN"
},
{
"pentestId": "32cc5c4e-7234-42b7-8031-c2e231bc0404",
"status": "OPEN"
},
{
"pentestId": "07e34e95-7dda-499a-8be8-0e8378f0e0d0",
"status": "OPEN"
},
{
"pentestId": "b70f6720-ee17-49d6-8838-bd776cd18d0a",
"status": "OPEN"
},
{
"pentestId": "9fb260ea-333f-44c6-884b-e46352564e2a",
"status": "OPEN"
},
{
"pentestId": "87f492f7-991b-4e04-9531-5dba0bc34b1b",
"status": "OPEN"
},
{
"pentestId": "6d846445-d470-447a-96b3-8f4b57df3221",
"status": "OPEN"
},
{
"pentestId": "123c43ae-6870-4883-a1c5-2f99946e2c2d",
"status": "OPEN"
},
{
"pentestId": "8be5b377-3eb0-4b54-81d2-8cfd5ea1f0f1",
"status": "OPEN"
},
{
"pentestId": "6b1d2b71-9e31-4e78-a82e-5325c699658c",
"status": "OPEN"
},
{
"pentestId": "77e765ef-40fb-4b6e-9d80-1e06cae7d4a3",
"status": "OPEN"
},
{
"pentestId": "5821cd2c-aa17-4339-b697-1b4089d3bf93",
"status": "OPEN"
},
{
"pentestId": "bb57b94f-c8bc-4dd9-b4bf-e14d0a97cc31",
"status": "OPEN"
},
{
"pentestId": "a5e3aaba-268e-4a40-92f9-05c0dae4cc0f",
"status": "OPEN"
},
{
"pentestId": "18ed1ddb-524a-4333-af90-7716bd51dc7b",
"status": "OPEN"
},
{
"pentestId": "c2d19d1e-39e5-4862-82c9-d88c5d91f630",
"status": "OPEN"
},
{
"pentestId": "728e294f-e27d-4bef-903b-d9eeb54cf086",
"status": "OPEN"
},
{
"pentestId": "91cd7aee-acda-4c95-ba35-16932448f29f",
"status": "OPEN"
},
{
"pentestId": "e496d9ba-7775-479e-8904-864c04fec3f9",
"status": "OPEN"
},
{
"pentestId": "ee87e923-63d7-40bc-b41e-049fe087e1dd",
"status": "OPEN"
},
{
"pentestId": "cbe94eaf-c734-4d6f-96ec-7d84a4a5b5cc",
"status": "IN_PROGRESS"
},
{
"pentestId": "c9ecfc9f-23f1-4744-a578-54b0c96a9e87",
"status": "IN_PROGRESS"
},
{
"pentestId": "ca0c10a1-8fcc-4b0b-98c0-2403709d7e50",
"status": "OPEN"
},
{
"pentestId": "bce6f266-2c70-4e45-a1db-d767e4bcc1f8",
"status": "OPEN"
},
{
"pentestId": "be0b07a3-64e4-4122-a362-dd657b8b6b0a",
"status": "OPEN"
},
{
"pentestId": "8f2230fb-bd5c-4047-9db6-74bc49be9cc1",
"status": "OPEN"
},
{
"pentestId": "a1b00a90-cb14-475f-ba3a-5807a21df704",
"status": "OPEN"
},
{
"pentestId": "af2e7766-ecd1-4015-b4e1-c0b978643a0f",
"status": "OPEN"
},
{
"pentestId": "27b64044-b3ff-48bf-9220-837b420f3904",
"status": "OPEN"
},
{
"pentestId": "b5eb1683-700a-4522-8b53-45809e665643",
"status": "OPEN"
},
{
"pentestId": "86b4d382-e433-4bac-ab6e-530a0dce299d",
"status": "OPEN"
},
{
"pentestId": "7a118a29-f983-4219-834c-f01554231910",
"status": "OPEN"
},
{
"pentestId": "ac9bc697-a53f-4278-98b9-05d8ba19a50d",
"status": "OPEN"
},
{
"pentestId": "13cecebb-321a-4ef8-8116-f6814652f7d7",
"status": "OPEN"
},
{
"pentestId": "048287bc-c41b-49a1-aeb5-2cc98a5bad06",
"status": "OPEN"
},
{
"pentestId": "4d1b424e-05ea-468c-9902-3626a79ccfe6",
"status": "OPEN"
},
{
"pentestId": "377d73b8-f8da-461e-909b-524a38a37ed6",
"status": "OPEN"
},
{
"pentestId": "16e10ad9-f49d-4a74-9de7-10a49e2401e2",
"status": "OPEN"
},
{
"pentestId": "4c68c22e-6073-4ec8-aebb-45ad2a3cc848",
"status": "OPEN"
},
{
"pentestId": "276e5823-b517-445c-b182-e6eda6478d44",
"status": "OPEN"
},
{
"pentestId": "84c661c0-2775-440a-97c5-ff35f345cabb",
"status": "OPEN"
},
{
"pentestId": "fb6d909c-8d16-48e3-b0e5-aba9bf3e8eae",
"status": "OPEN"
},
{
"pentestId": "0b211e22-dd63-46cc-a12f-be7ac73d7a64",
"status": "OPEN"
},
{
"pentestId": "63310549-e2a8-4dd0-a91a-9cfa06e2dc41",
"status": "OPEN"
},
{
"pentestId": "ac8d52d0-f0c8-47ec-ab13-24f40dc4f9e6",
"status": "OPEN"
},
{
"pentestId": "3ddc4950-f662-4ec1-9a04-b9c3591d8b06",
"status": "OPEN"
},
{
"pentestId": "4c11d176-2ec5-4ed9-9c8a-c1edd33b262c",
"status": "OPEN"
},
{
"pentestId": "b9a6f4ba-62e6-442b-a274-b3ffe209d248",
"status": "OPEN"
},
{
"pentestId": "705e28a2-b0a4-4b8c-9922-10c5c67faf65",
"status": "OPEN"
},
{
"pentestId": "4c59259d-4a24-43ef-8738-fe214e0b0673",
"status": "OPEN"
},
{
"pentestId": "a7ab3344-db7d-495a-8e55-dd572ea7c5e0",
"status": "OPEN"
},
{
"pentestId": "195e7f58-a7b2-4571-9c66-1e91a0dfca28",
"status": "OPEN"
},
{
"pentestId": "543a9768-4e5c-4c70-9aae-977afa542afa",
"status": "OPEN"
},
{
"pentestId": "a17516de-e92a-43b9-a415-203dce48fb0e",
"status": "OPEN"
} }
], ],
"createdBy": "3c4ae87f-0d56-4634-a824-b4883c403c8a" "createdBy": "3c4ae87f-0d56-4634-a824-b4883c403c8a"