Skip to content
Snippets Groups Projects
Verified Commit 8b199754 authored by Jan-Niclas Strüwer's avatar Jan-Niclas Strüwer
Browse files

first technical punch through of reworked kpi calculation logic

parent 2f2ca89c
No related branches found
No related tags found
No related merge requests found
Showing with 164 additions and 278 deletions
package de.fraunhofer.iem.dataprovider.kpi.metrics
import de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.service.RepositoryDetailsService
import de.fraunhofer.iem.dataprovider.kpi.service.KPIService
import de.fraunhofer.iem.dataprovider.repository.service.RepositoryService
import de.fraunhofer.iem.dataprovider.toolRun.service.ToolRunService
import kotlinx.coroutines.CoroutineScope
......@@ -13,7 +14,8 @@ import org.springframework.stereotype.Service
class MetricsService(
private val repositoryService: RepositoryService,
private val toolRunService: ToolRunService,
private val repositoryDetailsService: RepositoryDetailsService
private val repositoryDetailsService: RepositoryDetailsService,
private val kpiService: KPIService
) {
private val defaultScope = CoroutineScope(Dispatchers.Default)
......@@ -21,6 +23,10 @@ class MetricsService(
suspend fun handleRepositoryChange(repoId: Long) = defaultScope.launch {
// TODO: we need to create the tools in the db and link them to the tool run.
// This should probably be done on the initial server startup, based on some
// config properties, as the tools don't change dynamically.
/**
* Create initial db models.
* If this fails we want the whole method to fail as we can't continue
......@@ -57,9 +63,7 @@ class MetricsService(
val repositoryDetailsKpi = async {
val repoDetailsDto = repositoryDetailsService.getRepositoryDetails(repoId)
val repositoryDetailsKpiDto = repositoryDetailsService.calculateRepositoryDetailsKpis(repoDetailsDto)
repositoryDetailsService.saveRepositoryDetailsKpi(toolRun.repository!!, repositoryDetailsKpiDto)
repositoryDetailsService.calculateRepositoryDetailsKpis(repoDetailsDto)
}
/**
......@@ -67,6 +71,7 @@ class MetricsService(
* joinAll(toolKpi)
* calculateKpiTree(toolKpi, ...)
*/
kpiService.calculateAndSaveKpiTree(toolRun.repository!!, repositoryDetailsKpi.await())
}
}
\ No newline at end of file
......@@ -6,7 +6,4 @@ data class RepositoryDetailsKpisDto(
val numberOfCommitsKpi: KPICreateDto,
val numberOfSignedCommitsKPI: KPICreateDto,
val isDefaultBranchProtectedKPI: KPICreateDto,
val signedCommitsRatioKPI: KPICreateDto,
val processComplianceKPI: KPICreateDto,
val processTransparencyKPI: KPICreateDto
)
......@@ -3,23 +3,24 @@ package de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.service
import de.fraunhofer.iem.dataprovider.gitlab.service.OpenCodeGitlabApi
import de.fraunhofer.iem.dataprovider.kpi.dto.KPICreateDto
import de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.dto.RepositoryDetailsKpisDto
import de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.dto.RepositoryDetailsKpisEntity
import de.fraunhofer.iem.dataprovider.kpi.service.KPIService
import de.fraunhofer.iem.dataprovider.kpi.strategy.AggregationKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.kpi.strategy.RatioKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.kpi.strategy.RawValueKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.repository.dto.RepositoryDetailsDto
import de.fraunhofer.iem.dataprovider.repository.entity.RepositoryEntity
import org.springframework.stereotype.Service
@Service
class RepositoryDetailsService(private val kpiService: KPIService, private val openCodeGitlabApi: OpenCodeGitlabApi) {
class RepositoryDetailsService(private val openCodeGitlabApi: OpenCodeGitlabApi) {
fun getRepositoryDetails(repoId: Long): RepositoryDetailsDto {
suspend fun getRepositoryDetails(repoId: Long): RepositoryDetailsDto {
return openCodeGitlabApi.getRepositoryDetails(repoId)
}
/**
* Creates a named map of RepositoryCreateDtos, based upon the provided repository details.
* This method only returns raw KPIs.
*/
fun calculateRepositoryDetailsKpis(repoDetailsDto: RepositoryDetailsDto): RepositoryDetailsKpisDto {
val numberOfCommitsKPI = KPICreateDto(
"Number of Commits",
"Total number of commits on the default branch of the repository.",
......@@ -39,68 +40,11 @@ class RepositoryDetailsService(private val kpiService: KPIService, private val o
RawValueKPICalculationStrategy(if (repoDetailsDto.isDefaultBranchProtected) 100 else 0)
)
val signedCommitsRatioKPI =
KPICreateDto(
"Commit Signature Ratio",
"Used to assess compliance with a common and transparent development process. It is desirable that all commits are signed by their authors. Therefore, the ratio of signed commits to all commits is determined to calculate this metric.",
false,
RatioKPICalculationStrategy()
)
signedCommitsRatioKPI.addChildKPI(numberOfCommitsKPI, 1.0)
signedCommitsRatioKPI.addChildKPI(numberOfSignedCommitsKPI, 1.0)
val processComplianceKPI = KPICreateDto(
"Process Compliance Score",
"Assesses the development process of the software provided. For this purpose, the development process traceable in the repository is compared with common development standards to enable an assessment.",
false,
AggregationKPICalculationStrategy()
)
val processTransparencyKPI = KPICreateDto(
"Process Transparency Score",
"Assesses the transparency resp. traceability of the development process of the provided software for external parties. For this purpose, various analyzes are performed that assess the availability of information about the software development process within the repository.",
false,
AggregationKPICalculationStrategy()
)
processComplianceKPI.addChildKPI(isDefaultBranchProtectedKPI, 0.5)
processComplianceKPI.addChildKPI(signedCommitsRatioKPI, 0.5)
processTransparencyKPI.addChildKPI(signedCommitsRatioKPI, 1.0)
return RepositoryDetailsKpisDto(
processComplianceKPI = processComplianceKPI,
processTransparencyKPI = processTransparencyKPI,
signedCommitsRatioKPI = signedCommitsRatioKPI,
isDefaultBranchProtectedKPI = isDefaultBranchProtectedKPI,
numberOfSignedCommitsKPI = numberOfSignedCommitsKPI,
numberOfCommitsKpi = numberOfCommitsKPI
)
}
fun saveRepositoryDetailsKpi(
repositoryEntity: RepositoryEntity,
repositoryDetailsKpisDto: RepositoryDetailsKpisDto
): RepositoryDetailsKpisEntity {
return RepositoryDetailsKpisEntity(
numberOfCommitsKpi = kpiService.saveKpi(repositoryEntity, repositoryDetailsKpisDto.numberOfCommitsKpi),
numberOfSignedCommitsKPI = kpiService.saveKpi(
repositoryEntity,
repositoryDetailsKpisDto.numberOfSignedCommitsKPI
),
isDefaultBranchProtectedKPI = kpiService.saveKpi(
repositoryEntity,
repositoryDetailsKpisDto.isDefaultBranchProtectedKPI
),
signedCommitsRatioKPI = kpiService.saveKpi(
repositoryEntity,
repositoryDetailsKpisDto.signedCommitsRatioKPI
),
processComplianceKPI = kpiService.saveKpi(repositoryEntity, repositoryDetailsKpisDto.processComplianceKPI),
processTransparencyKPI = kpiService.saveKpi(
repositoryEntity,
repositoryDetailsKpisDto.processTransparencyKPI
),
)
}
}
......@@ -3,8 +3,11 @@ package de.fraunhofer.iem.dataprovider.kpi.service
import de.fraunhofer.iem.dataprovider.kpi.dto.KPICreateDto
import de.fraunhofer.iem.dataprovider.kpi.entity.KPIEntity
import de.fraunhofer.iem.dataprovider.kpi.entity.KPIHierarchyEdgeEntity
import de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.dto.RepositoryDetailsKpisDto
import de.fraunhofer.iem.dataprovider.kpi.repository.KPIHierarchyEdgeRepository
import de.fraunhofer.iem.dataprovider.kpi.repository.KPIRepository
import de.fraunhofer.iem.dataprovider.kpi.strategy.AggregationKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.kpi.strategy.RatioKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.logger.getLogger
import de.fraunhofer.iem.dataprovider.repository.entity.RepositoryEntity
import org.springframework.data.repository.findByIdOrNull
......@@ -19,24 +22,129 @@ class KPIService(
private val logger = getLogger(javaClass)
/**
* Stores the given KPIs and links them to the given repository
*/
fun saveKpis(repositoryEntity: RepositoryEntity, createKpis: Array<KPICreateDto>): Array<KPIEntity> {
return createKpis.map { saveKpi(repositoryEntity, it) }.toTypedArray()
fun calculateAndSaveKpiTree(repository: RepositoryEntity, repoDetailsEntity: RepositoryDetailsKpisDto) {
val rootKPI = generateKPITree(repoDetailsEntity)
calculateKPIs(rootKPI)
storeAndPurgeOld(repository, rootKPI)
}
/**
* Stores the given KPI and links it to the given repository
*/
fun saveKpi(repositoryEntity: RepositoryEntity, createKpi: KPICreateDto): KPIEntity {
val kpiEntity = createKpi.toDbObject()
kpiEntity.repository = repositoryEntity
return kpiRepository.save(kpiEntity)
private fun generateKPITree(repoDetailsEntity: RepositoryDetailsKpisDto): KPICreateDto {
val signedCommitsRatioKPI =
KPICreateDto(
"Commit Signature Ratio",
"Used to assess compliance with a common and transparent development process. It is desirable that all commits are signed by their authors. Therefore, the ratio of signed commits to all commits is determined to calculate this metric.",
false,
RatioKPICalculationStrategy()
)
signedCommitsRatioKPI.addChildKPI(repoDetailsEntity.numberOfCommitsKpi, 1.0)
signedCommitsRatioKPI.addChildKPI(repoDetailsEntity.numberOfSignedCommitsKPI, 1.0)
val processComplianceKPI = KPICreateDto(
"Process Compliance Score",
"Assesses the development process of the software provided. For this purpose, the development process traceable in the repository is compared with common development standards to enable an assessment.",
false,
AggregationKPICalculationStrategy()
)
val processTransparencyKPI = KPICreateDto(
"Process Transparency Score",
"Assesses the transparency resp. traceability of the development process of the provided software for external parties. For this purpose, various analyzes are performed that assess the availability of information about the software development process within the repository.",
false,
AggregationKPICalculationStrategy()
)
processComplianceKPI.addChildKPI(repoDetailsEntity.isDefaultBranchProtectedKPI, 0.5)
processComplianceKPI.addChildKPI(signedCommitsRatioKPI, 0.5)
processTransparencyKPI.addChildKPI(signedCommitsRatioKPI, 1.0)
// val securityKPI = KPICreateDto(
// "Security Score",
// "Assesses the security of the software provided. For this purpose, various security-relevant analyzes are carried out, which, among other things, check the external dependencies or the code for vulnerabilities.",
// false,
// AggregationKPICalculationStrategy()
// )
// val maximalDependencyVulnerabilityKPI = KPICreateDto(
// "Maximal Dependency Vulnerability Score",
// "This score is calculated by the following formula: 100 - (max(CVSS score) * 10). Thus, a lower value indicates a more critical vulnerability.",
// false,
// // This strategy is tied to this specific KPI. It calculates 100 - max(children). Children are already multiplied by 10
// MaximumKPICalculationStrategy()
//
//TODO: this code will be called from the dependency api request task !
// val dependencyDtos = dependencyService.getDependenciesForRepository(repoId)
// // We change the structure to associate vulnerabilities with dependencies instead of dependencies with vulnerabilities
// val vulnerabilitiesWithDependencies = restructureDependenciesAndVulnerabilities(dependencyDtos)
// // For each vulnerability, we create a sub raw data kpi
// addMaximalDependencyVulnerabilitySubKPIs(vulnerabilitiesWithDependencies, maximalDependencyVulnerabilityKPI)
// securityKPI.addChildKPI(maximalDependencyVulnerabilityKPI, 0.5)
//
// // TODO: There might be the case that there are no latest tool runs for this repository (would end up in an exception)
// val latestToolRunOCCMD = toolRunService.getLatestToolRunsForRepo(repoId).filter { it.tool?.name == "OCCMD" }[0]
// val secretKpi = KPICreateDto(
// "Public Secrets",
// "Score to indicate whether the repository contains secrets like passwords or api keys.",
// false,
// RawValueKPICalculationStrategy(if (latestToolRunOCCMD.findings.isEmpty()) 100 else 0)
// )
// securityKPI.addChildKPI(secretKpi, 0.5)
val rootKPI = KPICreateDto(
"Project Score",
"Assesses the project resp. the provided software in the aspects of maturity (based on quality, security and usability aspects) as well as development process.",
true,
AggregationKPICalculationStrategy()
)
rootKPI.addChildKPI(processTransparencyKPI, 0.25)
rootKPI.addChildKPI(processComplianceKPI, 0.25)
// rootKPI.addChildKPI(securityKPI, 0.5)
return rootKPI
}
// private fun addMaximalDependencyVulnerabilitySubKPIs(
// vulnerabilitiesWithDependencies: HashMap<VulnerabilityDto, MutableSet<String>>,
// maximalDependencyVulnerabilityKPI: KPICreateDto
// ) {
// // We iterate through the vulnerabilities and create a sub (raw data) kpi for each of them. Dependencies are displayed in the description
// for ((vulnerability, dependencies) in vulnerabilitiesWithDependencies) {
// maximalDependencyVulnerabilityKPI.addChildKPI(
// KPICreateDto(
// "Vulnerability " + vulnerability.cveIdentifier,
// "Affected packages: " + dependencies.joinToString(", "),
// false,
// // TODO: We multiply the CVSS score by 10 as the data structure can only hold integer values. This might be changed in the future.
// RawValueKPICalculationStrategy((vulnerability.vulnerabilityScores.first().severity.toDouble() * 10).toInt()),
// // TODO: Displayscore shows the real CVSS value, might not be needed if above TODO is resolved
// displayScore = vulnerability.vulnerabilityScores.first().severity
// ), 0.0
// )
// }
// }
//
// private fun restructureDependenciesAndVulnerabilities(dependencyDtos: List<DependencyDto>): HashMap<VulnerabilityDto, MutableSet<String>> {
// val vulnerabilitiesWithDependencies = HashMap<VulnerabilityDto, MutableSet<String>>()
// // Switch structure around, so we can see which vulnerabilities are there and which dependencies are associated to them
// for (dependencyDto in dependencyDtos) {
// // Iterate through the list of vulnerabilities associated with each dependency
// for (vulnerability in dependencyDto.vulnerabilities) {
// // Check if the vulnerability is already present in the result map
// // If not, add it with an empty list of dependencies
// vulnerabilitiesWithDependencies.computeIfAbsent(vulnerability) { mutableSetOf() }
// // Add the current dependency to the list of dependencies for the vulnerability
// vulnerabilitiesWithDependencies[vulnerability]?.add(dependencyDto.name)
// }
// }
// return vulnerabilitiesWithDependencies
// }
private fun calculateKPIsRecursively(kpi: KPICreateDto, visited: MutableSet<KPICreateDto>) {
// Check if the KPI has already been visited
if (visited.contains(kpi)) {
......@@ -66,12 +174,30 @@ class KPIService(
calculateKPIsRecursively(rootKPI, visited)
}
fun findKPIById(id: UUID): KPIEntity? {
return kpiRepository.findByIdOrNull(id)
}
fun findRootKPIByRepository(repositoryEntity: RepositoryEntity): KPIEntity? {
val kpi = kpiRepository.findFirstByRepository_IdAndIsRootTrue(repositoryEntity.id!!)
if (kpi.isEmpty) {
return null
}
return kpi.get()
}
fun storeAndPurgeOld(repositoryEntity: RepositoryEntity, rootKPI: KPICreateDto) {
purgeAllKPIs(repositoryEntity)
val kpiEntityDtoToEntityMapping: MutableMap<KPICreateDto, KPIEntity> = mutableMapOf()
storeKPI(repositoryEntity, rootKPI, kpiEntityDtoToEntityMapping)
}
private fun purgeAllKPIs(repositoryEntity: RepositoryEntity) {
val kpiEntities: List<KPIEntity> = kpiRepository.findByRepository_Id(repositoryEntity.id!!)
kpiRepository.deleteAll(kpiEntities)
}
private fun storeKPI(
repositoryEntity: RepositoryEntity,
kpi: KPICreateDto,
......@@ -112,20 +238,5 @@ class KPIService(
}
}
private fun purgeAllKPIs(repositoryEntity: RepositoryEntity) {
val kpiEntities: List<KPIEntity> = kpiRepository.findByRepository_Id(repositoryEntity.id!!)
kpiRepository.deleteAll(kpiEntities)
}
fun findKPIById(id: UUID): KPIEntity? {
return kpiRepository.findByIdOrNull(id)
}
fun findRootKPIByRepository(repositoryEntity: RepositoryEntity): KPIEntity? {
val kpi = kpiRepository.findFirstByRepository_IdAndIsRootTrue(repositoryEntity.id!!)
if (kpi.isEmpty) {
return null
}
return kpi.get()
}
}
......@@ -15,6 +15,10 @@ class RepositoryService(
) {
private val logger = getLogger(javaClass)
/**
* Either creates or returns a repository entity based upon its
* opencode repository id.
*/
fun getOrCreate(gitRepository: RepositoryCreateDto): RepositoryEntity {
var repo = repositoryRepository.findByRepoId(gitRepository.id)
if (repo == null) {
......@@ -23,6 +27,9 @@ class RepositoryService(
return repo
}
/**
* Queries the gitlab api to get the repo name, url, and id.
*/
fun getRepositoryInfo(repoId: Long): RepositoryCreateDto {
return openCodeGitlabApi.getRepositoryInfo(repoId)
}
......
package de.fraunhofer.iem.dataprovider.taskManager
import de.fraunhofer.iem.dataprovider.taskManager.events.Event
import de.fraunhofer.iem.dataprovider.taskManager.events.GroupTasksDoneEvent
import de.fraunhofer.iem.dataprovider.taskManager.model.GroupTasks
import java.util.*
class GroupTaskManager(val responseChannel: suspend (event: Event) -> Unit) {
private val dependentEvents: MutableMap<UUID, GroupTasks> = mutableMapOf()
/**
* Adds new group of tasks
*/
fun createTaskGroup(repositoryId: UUID): UUID {
val groupId = UUID.randomUUID()
dependentEvents[groupId] = GroupTasks(repositoryId)
return groupId
}
fun addTaskToGroup(groupId: UUID, taskId: UUID) {
dependentEvents[groupId]?.taskIds?.add(taskId)
}
/**
* Removes the finished task with the given ID from the internal task list for the
* group. If the whole task group is finished a group finished event is sent.
*/
suspend fun taskInGroupFinished(groupId: UUID, taskId: UUID) {
val groupTasks = dependentEvents[groupId]
if (groupTasks != null) {
val taskGroupEmpty = removeTaskFromGroup(groupTasks, taskId)
if (taskGroupEmpty) {
removeGroup(groupId)
responseChannel(GroupTasksDoneEvent(groupTasks.repositoryId))
}
}
}
private fun removeTaskFromGroup(groupTasks: GroupTasks, taskId: UUID): Boolean {
groupTasks.taskIds.remove(taskId)
return groupTasks.taskIds.isEmpty()
}
private fun removeGroup(groupId: UUID) {
dependentEvents.remove(groupId)
}
}
package de.fraunhofer.iem.dataprovider.taskManager.tasks.kpiCalculation
import de.fraunhofer.iem.dataprovider.kpi.dto.KPICreateDto
import de.fraunhofer.iem.dataprovider.kpi.service.KPIService
import de.fraunhofer.iem.dataprovider.kpi.strategy.AggregationKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.kpi.strategy.MaximumKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.kpi.strategy.RawValueKPICalculationStrategy
import de.fraunhofer.iem.dataprovider.repository.dto.RepositoryDetailsDto
import de.fraunhofer.iem.dataprovider.repository.service.RepositoryService
import de.fraunhofer.iem.dataprovider.taskManager.events.Event
import de.fraunhofer.iem.dataprovider.taskManager.tasks.Task
import de.fraunhofer.iem.dataprovider.taskManager.tasks.dependency.dto.DependencyDto
import de.fraunhofer.iem.dataprovider.taskManager.tasks.dependency.dto.VulnerabilityDto
import de.fraunhofer.iem.dataprovider.toolRun.service.ToolRunService
import java.util.*
class MetricsTask(
val repoId: UUID,
private val repositoryService: RepositoryService,
private val kpiService: KPIService,
override val responseChannel: suspend (task: Event) -> Unit,
private val toolRunService: ToolRunService,
) : Task() {
override suspend fun execute() {
logger.info("Starting metrics task for repoId $repoId")
val repository = repositoryService.findRepoByID(repoId)
//TODO: this needs to be made available differently now, as we don't store it in our db!
// val repositoryDetails = repositoryService.getLatestRepositoryDetailsByRepositoryId(repoId)
// if (repositoryDetails != null && repository != null) {
// val rootKPI = generateKPITree(repositoryDetails)
// kpiService.calculateKPIs(rootKPI)
// kpiService.storeAndPurgeOld(repository, rootKPI)
// }
}
private fun generateKPITree(repositoryDetailsEntity: RepositoryDetailsDto): KPICreateDto {
val rootKPI = KPITreeFactory(repositoryDetailsEntity)
return rootKPI
}
private fun KPITreeFactory(repositoryDetailsEntity: RepositoryDetailsDto): KPICreateDto {
// second level
// TODO: @Jan-Niclas Please add the dependency kpis to the security KPI
val securityKPI = KPICreateDto(
"Security Score",
"Assesses the security of the software provided. For this purpose, various security-relevant analyzes are carried out, which, among other things, check the external dependencies or the code for vulnerabilities.",
false,
AggregationKPICalculationStrategy()
)
val maximalDependencyVulnerabilityKPI = KPICreateDto(
"Maximal Dependency Vulnerability Score",
"This score is calculated by the following formula: 100 - (max(CVSS score) * 10). Thus, a lower value indicates a more critical vulnerability.",
false,
// This strategy is tied to this specific KPI. It calculates 100 - max(children). Children are already multiplied by 10
MaximumKPICalculationStrategy()
)
//TODO: this code will be called from the dependency api request task !
// val dependencyDtos = dependencyService.getDependenciesForRepository(repoId)
// // We change the structure to associate vulnerabilities with dependencies instead of dependencies with vulnerabilities
// val vulnerabilitiesWithDependencies = restructureDependenciesAndVulnerabilities(dependencyDtos)
// // For each vulnerability, we create a sub raw data kpi
// addMaximalDependencyVulnerabilitySubKPIs(vulnerabilitiesWithDependencies, maximalDependencyVulnerabilityKPI)
// securityKPI.addChildKPI(maximalDependencyVulnerabilityKPI, 0.5)
//
// // TODO: There might be the case that there are no latest tool runs for this repository (would end up in an exception)
// val latestToolRunOCCMD = toolRunService.getLatestToolRunsForRepo(repoId).filter { it.tool?.name == "OCCMD" }[0]
// val secretKpi = KPICreateDto(
// "Public Secrets",
// "Score to indicate whether the repository contains secrets like passwords or api keys.",
// false,
// RawValueKPICalculationStrategy(if (latestToolRunOCCMD.findings.isEmpty()) 100 else 0)
// )
// securityKPI.addChildKPI(secretKpi, 0.5)
val rootKPI = KPICreateDto(
"Project Score",
"Assesses the project resp. the provided software in the aspects of maturity (based on quality, security and usability aspects) as well as development process.",
true,
AggregationKPICalculationStrategy()
)
// rootKPI.addChildKPI(processTransparencyKPI, 0.25)
// rootKPI.addChildKPI(processComplianceKPI, 0.25)
rootKPI.addChildKPI(securityKPI, 0.5)
return rootKPI
}
private fun addMaximalDependencyVulnerabilitySubKPIs(
vulnerabilitiesWithDependencies: HashMap<VulnerabilityDto, MutableSet<String>>,
maximalDependencyVulnerabilityKPI: KPICreateDto
) {
// We iterate through the vulnerabilities and create a sub (raw data) kpi for each of them. Dependencies are displayed in the description
for ((vulnerability, dependencies) in vulnerabilitiesWithDependencies) {
maximalDependencyVulnerabilityKPI.addChildKPI(
KPICreateDto(
"Vulnerability " + vulnerability.cveIdentifier,
"Affected packages: " + dependencies.joinToString(", "),
false,
// TODO: We multiply the CVSS score by 10 as the data structure can only hold integer values. This might be changed in the future.
RawValueKPICalculationStrategy((vulnerability.vulnerabilityScores.first().severity.toDouble() * 10).toInt()),
// TODO: Displayscore shows the real CVSS value, might not be needed if above TODO is resolved
displayScore = vulnerability.vulnerabilityScores.first().severity
), 0.0
)
}
}
private fun restructureDependenciesAndVulnerabilities(dependencyDtos: List<DependencyDto>): HashMap<VulnerabilityDto, MutableSet<String>> {
val vulnerabilitiesWithDependencies = HashMap<VulnerabilityDto, MutableSet<String>>()
// Switch structure around, so we can see which vulnerabilities are there and which dependencies are associated to them
for (dependencyDto in dependencyDtos) {
// Iterate through the list of vulnerabilities associated with each dependency
for (vulnerability in dependencyDto.vulnerabilities) {
// Check if the vulnerability is already present in the result map
// If not, add it with an empty list of dependencies
vulnerabilitiesWithDependencies.computeIfAbsent(vulnerability) { mutableSetOf() }
// Add the current dependency to the list of dependencies for the vulnerability
vulnerabilitiesWithDependencies[vulnerability]?.add(dependencyDto.name)
}
}
return vulnerabilitiesWithDependencies
}
}
package de.fraunhofer.iem.dataprovider.occmd.entity
package de.fraunhofer.iem.dataprovider.tools.occmd.entity
import jakarta.persistence.*
import org.hibernate.Hibernate
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.