From 479293bd8a531c18f51e3c84fbe70769e943fc6c Mon Sep 17 00:00:00 2001 From: Jan-Niclas Struewer <j.n.struewer@gmail.com> Date: Mon, 25 Sep 2023 17:40:22 +0200 Subject: [PATCH] added ort api connection --- .../dataprovider/DataProviderApplication.kt | 2 + .../dataprovider/configuration/ApiPaths.kt | 4 +- .../configuration/OpenCodeApiProperties.kt | 24 +++ .../debug/controller/MetricsController.kt | 22 --- .../kpi/metrics/MetricsService.kt | 15 +- .../dataprovider/kpi/service/KPIService.kt | 52 +++--- .../dataprovider/taskManager/TaskManager.kt | 173 ------------------ .../taskManager/tasks/tools/ort/OrtApiTask.kt | 2 +- .../tools/ort/dto/VulnerabilityDto.kt | 3 + .../tasks => }/tools/ort/json/DataJson.kt | 2 +- .../tasks => }/tools/ort/json/OrtJson.kt | 2 +- .../tools/ort/json/ReferenceJson.kt | 2 +- .../tasks => }/tools/ort/json/ResultJson.kt | 4 +- .../tools/ort/service/OrtService.kt | 62 +++++++ src/main/resources/application.properties | 5 +- 15 files changed, 146 insertions(+), 228 deletions(-) create mode 100644 src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/OpenCodeApiProperties.kt delete mode 100644 src/main/kotlin/de/fraunhofer/iem/dataprovider/debug/controller/MetricsController.kt delete mode 100644 src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt create mode 100644 src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/dto/VulnerabilityDto.kt rename src/main/kotlin/de/fraunhofer/iem/dataprovider/{taskManager/tasks => }/tools/ort/json/DataJson.kt (83%) rename src/main/kotlin/de/fraunhofer/iem/dataprovider/{taskManager/tasks => }/tools/ort/json/OrtJson.kt (76%) rename src/main/kotlin/de/fraunhofer/iem/dataprovider/{taskManager/tasks => }/tools/ort/json/ReferenceJson.kt (80%) rename src/main/kotlin/de/fraunhofer/iem/dataprovider/{taskManager/tasks => }/tools/ort/json/ResultJson.kt (89%) create mode 100644 src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/service/OrtService.kt diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/DataProviderApplication.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/DataProviderApplication.kt index 27be12dc..6f72be00 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/DataProviderApplication.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/DataProviderApplication.kt @@ -1,6 +1,7 @@ package de.fraunhofer.iem.dataprovider import de.fraunhofer.iem.dataprovider.configuration.DirectoryPathsProperties +import de.fraunhofer.iem.dataprovider.configuration.OpenCodeApiProperties import de.fraunhofer.iem.dataprovider.configuration.OpenCodeGitlabApiProperties import de.fraunhofer.iem.dataprovider.configuration.security.SecurityProperties import org.springframework.boot.autoconfigure.SpringBootApplication @@ -12,6 +13,7 @@ import org.springframework.boot.runApplication @EnableConfigurationProperties( DirectoryPathsProperties::class, OpenCodeGitlabApiProperties::class, + OpenCodeApiProperties::class, SecurityProperties::class ) class DataProviderApplication diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/ApiPaths.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/ApiPaths.kt index c85024f5..4a311a71 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/ApiPaths.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/ApiPaths.kt @@ -3,13 +3,13 @@ package de.fraunhofer.iem.dataprovider.configuration object ApiPaths { private const val BASE = "/api" - const val GITLAB = "$BASE/gitlab" + private const val GITLAB = "$BASE/gitlab" const val OPENCODE_REPO_CHANGED = "$GITLAB/opencode/repoChanged" const val DEBUG = "$BASE/debug/metrics" const val DEBUG_RECALCULATE_KPIS = "$DEBUG/recalculateAllKPIs" - const val KPI = "$BASE/kpi" + private const val KPI = "$BASE/kpi" const val KPI_ID = "$KPI/{id}" const val KPI_ROOT_REPOSITORY = "$KPI/root/repository/{id}" diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/OpenCodeApiProperties.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/OpenCodeApiProperties.kt new file mode 100644 index 00000000..f3ecdde4 --- /dev/null +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/configuration/OpenCodeApiProperties.kt @@ -0,0 +1,24 @@ +package de.fraunhofer.iem.dataprovider.configuration + +import jakarta.annotation.PostConstruct +import jakarta.validation.constraints.NotBlank +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.validation.annotation.Validated +import java.net.URL + + +@ConfigurationProperties(prefix = "opencode.api") +@Validated +data class OpenCodeApiProperties( + @NotBlank + val basePath: String, + @NotBlank + val ort: String +) { + @PostConstruct + fun postConstruct() { + // There is no try catch block around the operations on purpose! + // We want to throw here if this operations fail. + URL(basePath).toURI() + } +} \ No newline at end of file diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/debug/controller/MetricsController.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/debug/controller/MetricsController.kt deleted file mode 100644 index 699bd0fe..00000000 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/debug/controller/MetricsController.kt +++ /dev/null @@ -1,22 +0,0 @@ -package de.fraunhofer.iem.dataprovider.debug.controller - -import de.fraunhofer.iem.dataprovider.configuration.ApiPaths -import de.fraunhofer.iem.dataprovider.logger.getLogger -import de.fraunhofer.iem.dataprovider.taskManager.TaskManager -import de.fraunhofer.iem.dataprovider.taskManager.events.RecalculateAllKpisEvent -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RestController - -@RestController -class MetricsController( - private val taskManager: TaskManager -) { - - private val logger = getLogger(javaClass) - - @PostMapping(ApiPaths.DEBUG_RECALCULATE_KPIS) - suspend fun recalculateAllKPIs() { - logger.info("Recalculation of all KPIs was triggered") - taskManager.addEvent(RecalculateAllKpisEvent) - } -} diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/metrics/MetricsService.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/metrics/MetricsService.kt index e6a4f8f1..718e9071 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/metrics/MetricsService.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/metrics/MetricsService.kt @@ -4,6 +4,7 @@ import de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.service.Repo 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 de.fraunhofer.iem.dataprovider.tools.ort.service.OrtService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -15,7 +16,8 @@ class MetricsService( private val repositoryService: RepositoryService, private val toolRunService: ToolRunService, private val repositoryDetailsService: RepositoryDetailsService, - private val kpiService: KPIService + private val kpiService: KPIService, + private val ortService: OrtService ) { private val defaultScope = CoroutineScope(Dispatchers.Default) @@ -60,6 +62,11 @@ class MetricsService( * } */ + val vulnerabilityKpis = async { + val vulnerabilityDtos = ortService.getOrtResults(repoId) + ortService.calculateVulnerabilityKpis(vulnerabilityDtos) + } + val repositoryDetailsKpi = async { val repoDetailsDto = repositoryDetailsService.getRepositoryDetails(repoId) @@ -71,7 +78,11 @@ class MetricsService( * joinAll(toolKpi) * calculateKpiTree(toolKpi, ...) */ - kpiService.calculateAndSaveKpiTree(toolRun.repository!!, repositoryDetailsKpi.await()) + kpiService.calculateAndSaveKpiTree( + repository = toolRun.repository!!, + repositoryDetailsKpi = repositoryDetailsKpi.await(), + vulnerabilityKpis = vulnerabilityKpis.await() + ) } } \ No newline at end of file diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/service/KPIService.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/service/KPIService.kt index d304a0ec..63a5ee35 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/service/KPIService.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/kpi/service/KPIService.kt @@ -7,6 +7,7 @@ import de.fraunhofer.iem.dataprovider.kpi.metrics.repositoryDetails.dto.Reposito 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.MaximumKPICalculationStrategy import de.fraunhofer.iem.dataprovider.kpi.strategy.RatioKPICalculationStrategy import de.fraunhofer.iem.dataprovider.logger.getLogger import de.fraunhofer.iem.dataprovider.repository.entity.RepositoryEntity @@ -22,14 +23,22 @@ class KPIService( private val logger = getLogger(javaClass) - fun calculateAndSaveKpiTree(repository: RepositoryEntity, repoDetailsEntity: RepositoryDetailsKpisDto) { - val rootKPI = generateKPITree(repoDetailsEntity) + fun calculateAndSaveKpiTree( + repository: RepositoryEntity, + repositoryDetailsKpi: RepositoryDetailsKpisDto, + vulnerabilityKpis: List<KPICreateDto> + ) { + val rootKPI = + generateKPITree(repositoryDetailsKpi = repositoryDetailsKpi, vulnerabilityKpis = vulnerabilityKpis) calculateKPIs(rootKPI) storeAndPurgeOld(repository, rootKPI) } - private fun generateKPITree(repoDetailsEntity: RepositoryDetailsKpisDto): KPICreateDto { + private fun generateKPITree( + repositoryDetailsKpi: RepositoryDetailsKpisDto, + vulnerabilityKpis: List<KPICreateDto> + ): KPICreateDto { val signedCommitsRatioKPI = @@ -39,8 +48,8 @@ class KPIService( false, RatioKPICalculationStrategy() ) - signedCommitsRatioKPI.addChildKPI(repoDetailsEntity.numberOfCommitsKpi, 1.0) - signedCommitsRatioKPI.addChildKPI(repoDetailsEntity.numberOfSignedCommitsKPI, 1.0) + signedCommitsRatioKPI.addChildKPI(repositoryDetailsKpi.numberOfCommitsKpi, 1.0) + signedCommitsRatioKPI.addChildKPI(repositoryDetailsKpi.numberOfSignedCommitsKPI, 1.0) val processComplianceKPI = KPICreateDto( "Process Compliance Score", @@ -56,26 +65,28 @@ class KPIService( AggregationKPICalculationStrategy() ) - processComplianceKPI.addChildKPI(repoDetailsEntity.isDefaultBranchProtectedKPI, 0.5) + processComplianceKPI.addChildKPI(repositoryDetailsKpi.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 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() -// + 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() + ) + vulnerabilityKpis.forEach { maximalDependencyVulnerabilityKPI.addChildKPI(it, 0.0) } + securityKPI.addChildKPI(maximalDependencyVulnerabilityKPI, 0.5) //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 @@ -104,7 +115,7 @@ class KPIService( ) rootKPI.addChildKPI(processTransparencyKPI, 0.25) rootKPI.addChildKPI(processComplianceKPI, 0.25) -// rootKPI.addChildKPI(securityKPI, 0.5) + rootKPI.addChildKPI(securityKPI, 0.5) return rootKPI } @@ -238,5 +249,4 @@ class KPIService( } } - } diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt deleted file mode 100644 index d4241779..00000000 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/TaskManager.kt +++ /dev/null @@ -1,173 +0,0 @@ -package de.fraunhofer.iem.dataprovider.taskManager - -import de.fraunhofer.iem.dataprovider.configuration.DirectoryPathsProperties -import de.fraunhofer.iem.dataprovider.configuration.OpenCodeGitlabApiProperties -import de.fraunhofer.iem.dataprovider.kpi.service.KPIService -import de.fraunhofer.iem.dataprovider.logger.getLogger -import de.fraunhofer.iem.dataprovider.repository.service.RepositoryService -import de.fraunhofer.iem.dataprovider.taskManager.events.Event -import de.fraunhofer.iem.dataprovider.tool.service.ToolService -import de.fraunhofer.iem.dataprovider.toolRun.service.ToolRunService -import jakarta.annotation.PostConstruct -import jakarta.annotation.PreDestroy -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.launch -import org.springframework.stereotype.Component - - -/** - * The Task Manager takes tasks and distributes them to - * underlying workers. Internally it uses a channel - * to manage incoming tasks. - */ -@Component -class TaskManager( - private val directoryPathsProperties: DirectoryPathsProperties, - private val openCodeGitlabConfiguration: OpenCodeGitlabApiProperties, - private val toolRunService: ToolRunService, - private val toolService: ToolService, - private val repositoryService: RepositoryService, - private val kpiService: KPIService, -) { - - // The used default dispatcher is ok for CPU-bound workloads. However, - // if they block for a long time it's better to use a custom thread - // pool solution. - private val worker = Worker("Worker") - - // Should be used for long-running tasks, which DON'T use CPU power and - // are non-blocking - private val ioWorker = Worker("IO-Worker", CoroutineScope(Dispatchers.IO)) - - private val mainScope = CoroutineScope(Dispatchers.Default) - private val channel: Channel<Event> = Channel() - - suspend fun addEvent(event: Event) { - channel.send(event) - } - - @PostConstruct - private fun start() { - mainScope.launch { - for (task in channel) { - onReceive(task) - } - } - } - - @PreDestroy - fun close() { - channel.close() - worker.close() - ioWorker.close() - } - - - private val logger = getLogger(javaClass) - private val groupTaskManager = GroupTaskManager(::onReceive) - suspend fun onReceive(event: Event) { - logger.info("[${Thread.currentThread().name}] add task called in Task Manager $event") -// -// when (event) { -// is RepoChangedEvent -> { -// ioWorker.addTask( -// GetGitlabProjectTask( -// event.repoId, -// openCodeGitlabConfiguration, -// ::addEvent, -// repositoryService, -// ) -// ) -// } -// -// is GetGitlabProjectDoneEvent -> { -// // TODO: we should replace the git clone task with the temporary OCCMD task, as only OCCMD -// -// val groupId = groupTaskManager.createTaskGroup(event.repoId) -// -//// val occmdTask = OccmdTask( -//// event.outputDirectory, -//// config.toolResultsTargetDirectory, -//// openCodeGitlabConfiguration, -//// repositoryService, -//// ::addEvent, -//// event.repoId, -//// groupId, -//// toolRunService -//// ) -// ioWorker.addTask( -// OrtApiTask( -// ::addEvent, -// event.repoId, -// toolService, -// repositoryService -// ) -// ) -// -//// groupTaskManager.addTaskToGroup(groupId, occmdTask.taskID) -//// -//// worker.addTask(occmdTask) -// } -// -// is GroupTaskDoneEvent -> { -// logger.info("GroupTaskDoneEvent received") -// groupTaskManager.taskInGroupFinished(event.groupId, event.taskId) -// } -// -// is GroupTasksDoneEvent -> { -// logger.info("Adding repository details task") -// worker.addTask( -// GetRepositoryDetailsTask( -// event.repoId, -// openCodeGitlabConfiguration, -// repositoryService, -// ::addEvent -// ) -// ) -// } -// -// is GetRepositoryDetailsDoneEvent -> { -// worker.addTask( -// MetricsTask( -// event.repoId, -// repositoryService, -// kpiService, -// ::addEvent, -// toolRunService -// ) -// ) -// } -// -// is RecalculateAllKpisEvent -> { -// repositoryService.getAllRepositories().forEach { repo -> -// worker.addTask( -// MetricsTask( -// repo.id!!, -// repositoryService, -// kpiService, -// ::addEvent, -// toolRunService -// ) -// ) -// } -// } -// -// is TaskFailedEvent -> { -// logger.info("task failed event received. ${event.throwable}") -// } -// -// is GroupTaskFailedEvent -> { -// logger.info("Group task failed event received. ${event.throwable} ") -// groupTaskManager.taskInGroupFinished(event.groupId, event.taskId) -// } -// -// else -> { -// logger.info("Received event without special handling associated $event") -// } -// } - logger.info("[${Thread.currentThread().name}] add task finished in Task Manager $event") - } - -} diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/OrtApiTask.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/OrtApiTask.kt index fad54c41..34ae9d41 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/OrtApiTask.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/OrtApiTask.kt @@ -3,8 +3,8 @@ package de.fraunhofer.iem.dataprovider.taskManager.tasks.tools.ort 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.tools.ort.json.OrtJson import de.fraunhofer.iem.dataprovider.tool.service.ToolService +import de.fraunhofer.iem.dataprovider.tools.ort.json.OrtJson import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.engine.cio.* diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/dto/VulnerabilityDto.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/dto/VulnerabilityDto.kt new file mode 100644 index 00000000..c26385a1 --- /dev/null +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/dto/VulnerabilityDto.kt @@ -0,0 +1,3 @@ +package de.fraunhofer.iem.dataprovider.tools.ort.dto + +data class VulnerabilityDto(val cveIdentifier: String, val packageName: String, val severity: Double) diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/DataJson.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/DataJson.kt similarity index 83% rename from src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/DataJson.kt rename to src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/DataJson.kt index dd84fd5c..6f6ba58c 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/DataJson.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/DataJson.kt @@ -1,4 +1,4 @@ -package de.fraunhofer.iem.dataprovider.taskManager.tasks.tools.ort.json +package de.fraunhofer.iem.dataprovider.tools.ort.json import kotlinx.serialization.SerialName diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/OrtJson.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/OrtJson.kt similarity index 76% rename from src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/OrtJson.kt rename to src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/OrtJson.kt index 2b211ec2..1173032f 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/OrtJson.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/OrtJson.kt @@ -1,4 +1,4 @@ -package de.fraunhofer.iem.dataprovider.taskManager.tasks.tools.ort.json +package de.fraunhofer.iem.dataprovider.tools.ort.json import kotlinx.serialization.SerialName diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/ReferenceJson.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/ReferenceJson.kt similarity index 80% rename from src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/ReferenceJson.kt rename to src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/ReferenceJson.kt index 19e5af82..58d3bd7f 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/ReferenceJson.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/ReferenceJson.kt @@ -1,4 +1,4 @@ -package de.fraunhofer.iem.dataprovider.taskManager.tasks.tools.ort.json +package de.fraunhofer.iem.dataprovider.tools.ort.json import kotlinx.serialization.SerialName diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/ResultJson.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/ResultJson.kt similarity index 89% rename from src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/ResultJson.kt rename to src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/ResultJson.kt index f551be03..de0edba9 100644 --- a/src/main/kotlin/de/fraunhofer/iem/dataprovider/taskManager/tasks/tools/ort/json/ResultJson.kt +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/json/ResultJson.kt @@ -1,4 +1,4 @@ -package de.fraunhofer.iem.dataprovider.taskManager.tasks.tools.ort.json +package de.fraunhofer.iem.dataprovider.tools.ort.json import kotlinx.serialization.SerialName @@ -24,4 +24,4 @@ data class ResultJson( val updatedAt: String?, @SerialName("version") val version: String? -) \ No newline at end of file +) diff --git a/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/service/OrtService.kt b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/service/OrtService.kt new file mode 100644 index 00000000..1b446dd5 --- /dev/null +++ b/src/main/kotlin/de/fraunhofer/iem/dataprovider/tools/ort/service/OrtService.kt @@ -0,0 +1,62 @@ +package de.fraunhofer.iem.dataprovider.tools.ort.service + +import de.fraunhofer.iem.dataprovider.configuration.OpenCodeApiProperties +import de.fraunhofer.iem.dataprovider.kpi.dto.KPICreateDto +import de.fraunhofer.iem.dataprovider.kpi.strategy.RawValueKPICalculationStrategy +import de.fraunhofer.iem.dataprovider.tools.ort.dto.VulnerabilityDto +import de.fraunhofer.iem.dataprovider.tools.ort.json.OrtJson +import io.ktor.client.* +import io.ktor.client.call.* +import io.ktor.client.engine.cio.* +import io.ktor.client.plugins.contentnegotiation.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.serialization.kotlinx.json.* +import kotlinx.serialization.json.Json +import org.springframework.stereotype.Service + +@Service +class OrtService(private val openCodeApiProperties: OpenCodeApiProperties) { + + val client = HttpClient(CIO) { + install(ContentNegotiation) { + json( + Json { ignoreUnknownKeys = true } + ) + } + } + + suspend fun getOrtResults(repoId: Long): List<VulnerabilityDto> { + val response: HttpResponse = client.get(getToolApiPath(repoId)) + val ortJson = response.body<OrtJson>() + client.close() + + if (ortJson.code == 200) { + return ortJson.result.mapNotNull { + if (it.cveId != null && it.packageName != null && it.severity != null) { + VulnerabilityDto(it.cveId, it.packageName, it.severity) + } else { + null + } + } + } + return emptyList() + } + + fun calculateVulnerabilityKpis(vulnerabilityDtos: List<VulnerabilityDto>): List<KPICreateDto> { + return vulnerabilityDtos.map { + KPICreateDto( + "Vulnerability ${it.cveIdentifier}", + "Affected package: ${it.packageName}", + false, + RawValueKPICalculationStrategy((it.severity * 10).toInt()), + displayScore = it.severity.toString() + ) + } + } + + private fun getToolApiPath(repoId: Long): String { + return "${openCodeApiProperties.basePath}106${openCodeApiProperties.ort}" + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b37ce441..7fbe091c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,9 +1,11 @@ spring.config.import=optional:classpath:.env[.properties] - # Config for the OpencoDE platform # Token can be an empty string to access public repositories only opencode.host=https://gitlab.opencode.de/ opencode.access-token=${OC_GL_APIKEY} +# Tool APIs +opencode.api.base-path=https://sl.dev.o4oe.de/api/v1/project/ +opencode.api.ort=/cve-result # DB Login data spring.datasource.url=jdbc:postgresql://${host}:26257/${DB_USER}?sslmode=${ssl_mode}&sslrootcert=${ca_crt}&sslcert=${ssl_cert}&sslkey=${ssl_key} @@ -14,7 +16,6 @@ security.api-key=${API_KEY} security.admin-password=${ADMIN_PASSWORD} directories.git-clone-target-directory=${GIT_CLONE_TARGET_DIRECTORY} directories.tool-results-target-directory=${TOOL_RESULTS_TARGET_DIRECTORY} - server.port=${PORT} # Generates db schema if it doesn't exist in db spring.jpa.generate-ddl=true -- GitLab