Skip to content

Commit

Permalink
feat(service): Add RuleViolationAPI
Browse files Browse the repository at this point in the history
Add API endpoint for rule violations list under
/runs/{run_id}/rule-violations.

Signed-off-by: Kamil Bielecki <[email protected]>
  • Loading branch information
Kamil Bielecki committed Sep 30, 2024
1 parent f4592f1 commit 6960b95
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 0 deletions.
18 changes: 18 additions & 0 deletions api/v1/mapping/src/commonMain/kotlin/Mappings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ import org.eclipse.apoapsis.ortserver.api.v1.model.ReporterJob as ApiReporterJob
import org.eclipse.apoapsis.ortserver.api.v1.model.ReporterJobConfiguration as ApiReporterJobConfiguration
import org.eclipse.apoapsis.ortserver.api.v1.model.Repository as ApiRepository
import org.eclipse.apoapsis.ortserver.api.v1.model.RepositoryType as ApiRepositoryType
import org.eclipse.apoapsis.ortserver.api.v1.model.RuleViolation as ApiRuleViolation
import org.eclipse.apoapsis.ortserver.api.v1.model.RuleViolationWithIdentifier as ApiRuleViolationWithIdentifier
import org.eclipse.apoapsis.ortserver.api.v1.model.ScannerJob as ApiScannerJob
import org.eclipse.apoapsis.ortserver.api.v1.model.ScannerJobConfiguration as ApiScannerJobConfiguration
import org.eclipse.apoapsis.ortserver.api.v1.model.Secret as ApiSecret
Expand Down Expand Up @@ -108,6 +110,7 @@ import org.eclipse.apoapsis.ortserver.model.ReporterJob
import org.eclipse.apoapsis.ortserver.model.ReporterJobConfiguration
import org.eclipse.apoapsis.ortserver.model.Repository
import org.eclipse.apoapsis.ortserver.model.RepositoryType
import org.eclipse.apoapsis.ortserver.model.RuleViolationWithIdentifier
import org.eclipse.apoapsis.ortserver.model.ScannerJob
import org.eclipse.apoapsis.ortserver.model.ScannerJobConfiguration
import org.eclipse.apoapsis.ortserver.model.Secret
Expand All @@ -123,6 +126,7 @@ import org.eclipse.apoapsis.ortserver.model.runs.RemoteArtifact
import org.eclipse.apoapsis.ortserver.model.runs.VcsInfo
import org.eclipse.apoapsis.ortserver.model.runs.advisor.Vulnerability
import org.eclipse.apoapsis.ortserver.model.runs.advisor.VulnerabilityReference
import org.eclipse.apoapsis.ortserver.model.runs.evaluator.RuleViolation
import org.eclipse.apoapsis.ortserver.model.util.ListQueryParameters
import org.eclipse.apoapsis.ortserver.model.util.ListQueryResult
import org.eclipse.apoapsis.ortserver.model.util.OptionalValue
Expand Down Expand Up @@ -477,6 +481,20 @@ fun VulnerabilityWithIdentifier.mapToApi() =

fun Vulnerability.mapToApi() = ApiVulnerability(externalId, summary, description, references.map { it.mapToApi() })

fun RuleViolationWithIdentifier.mapToApi() = ApiRuleViolationWithIdentifier(
ruleViolation.mapToApi(),
identifier.mapToApi()
)

fun RuleViolation.mapToApi() = ApiRuleViolation(
rule,
license,
licenseSource,
severity.mapToApi(),
message,
howToFix
)

fun Identifier.mapToApi() = ApiIdentifier(type, namespace, name, version)

fun VulnerabilityReference.mapToApi() = ApiVulnerabilityReference(url, scoringSystem, severity, score, vector)
Expand Down
32 changes: 32 additions & 0 deletions api/v1/model/src/commonMain/kotlin/RuleViolation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2024 The ORT Server Authors (See <https://github.com/eclipse-apoapsis/ort-server/blob/main/NOTICE>)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

package org.eclipse.apoapsis.ortserver.api.v1.model

import kotlinx.serialization.Serializable

@Serializable
data class RuleViolation(
val rule: String,
val license: String?,
val licenseSource: String?,
val severity: Severity,
val message: String,
val howToFix: String
)
28 changes: 28 additions & 0 deletions api/v1/model/src/commonMain/kotlin/RuleViolationWithIdentifier.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2024 The ORT Server Authors (See <https://github.com/eclipse-apoapsis/ort-server/blob/main/NOTICE>)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

package org.eclipse.apoapsis.ortserver.api.v1.model

import kotlinx.serialization.Serializable

@Serializable
data class RuleViolationWithIdentifier(
val ruleViolation: RuleViolation,
val identifier: Identifier
)
21 changes: 21 additions & 0 deletions core/src/main/kotlin/api/RunsRoute.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import org.eclipse.apoapsis.ortserver.core.apiDocs.getLogsByRunId
import org.eclipse.apoapsis.ortserver.core.apiDocs.getOrtRunById
import org.eclipse.apoapsis.ortserver.core.apiDocs.getPackagesByRunId
import org.eclipse.apoapsis.ortserver.core.apiDocs.getReportByRunIdAndFileName
import org.eclipse.apoapsis.ortserver.core.apiDocs.getRuleViolationsByRunId
import org.eclipse.apoapsis.ortserver.core.apiDocs.getVulnerabilitiesByRunId
import org.eclipse.apoapsis.ortserver.core.authorization.requirePermission
import org.eclipse.apoapsis.ortserver.core.utils.pagingOptions
Expand All @@ -53,13 +54,15 @@ import org.eclipse.apoapsis.ortserver.logaccess.LogFileService
import org.eclipse.apoapsis.ortserver.logaccess.LogLevel
import org.eclipse.apoapsis.ortserver.logaccess.LogSource
import org.eclipse.apoapsis.ortserver.model.OrtRun
import org.eclipse.apoapsis.ortserver.model.RuleViolationWithIdentifier
import org.eclipse.apoapsis.ortserver.model.VulnerabilityWithIdentifier
import org.eclipse.apoapsis.ortserver.model.authorization.RepositoryPermission
import org.eclipse.apoapsis.ortserver.model.repositories.OrtRunRepository
import org.eclipse.apoapsis.ortserver.model.runs.Package
import org.eclipse.apoapsis.ortserver.services.PackageService
import org.eclipse.apoapsis.ortserver.services.ReportStorageService
import org.eclipse.apoapsis.ortserver.services.RepositoryService
import org.eclipse.apoapsis.ortserver.services.RuleViolationService
import org.eclipse.apoapsis.ortserver.services.VulnerabilityService

import org.koin.ktor.ext.inject
Expand All @@ -71,6 +74,7 @@ fun Route.runs() = route("runs/{runId}") {
val ortRunRepository by inject<OrtRunRepository>()
val repositoryService by inject<RepositoryService>()
val vulnerabilityService by inject<VulnerabilityService>()
val ruleViolationService by inject<RuleViolationService>()
val packageService by inject<PackageService>()

get(getOrtRunById) { _ ->
Expand Down Expand Up @@ -132,6 +136,23 @@ fun Route.runs() = route("runs/{runId}") {
}
}

route("rule-violations") {
get(getRuleViolationsByRunId) {
call.forRun(ortRunRepository) { ortRun ->
requirePermission(RepositoryPermission.READ_ORT_RUNS.roleName(ortRun.repositoryId))

val pagingOptions = call.pagingOptions(SortProperty("external_id", SortDirection.ASCENDING))

val ruleViolationsForOrtRun =
ruleViolationService.listForOrtRunId(ortRun.id, pagingOptions.mapToModel())

val pagedResponse = ruleViolationsForOrtRun.mapToApi(RuleViolationWithIdentifier::mapToApi)

call.respond(HttpStatusCode.OK, pagedResponse)
}
}
}

route("packages") {
get(getPackagesByRunId) {
call.forRun(ortRunRepository) { ortRun ->
Expand Down
86 changes: 86 additions & 0 deletions core/src/main/kotlin/apiDocs/RunsDocs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ import org.eclipse.apoapsis.ortserver.api.v1.model.PagedResponse
import org.eclipse.apoapsis.ortserver.api.v1.model.PagingData
import org.eclipse.apoapsis.ortserver.api.v1.model.ProcessedDeclaredLicense
import org.eclipse.apoapsis.ortserver.api.v1.model.RemoteArtifact
import org.eclipse.apoapsis.ortserver.api.v1.model.RuleViolation
import org.eclipse.apoapsis.ortserver.api.v1.model.RuleViolationWithIdentifier
import org.eclipse.apoapsis.ortserver.api.v1.model.Severity
import org.eclipse.apoapsis.ortserver.api.v1.model.SortDirection
import org.eclipse.apoapsis.ortserver.api.v1.model.SortProperty
import org.eclipse.apoapsis.ortserver.api.v1.model.VcsInfo
Expand Down Expand Up @@ -205,6 +208,89 @@ val getVulnerabilitiesByRunId: OpenApiRoute.() -> Unit = {
}
}

val getRuleViolationsByRunId: OpenApiRoute.() -> Unit = {
operationId = "GetRuleViolationsByRunId"
summary = "Get the rules violations found in an ORT run."
tags = listOf("RuleViolations")

request {
pathParameter<Long>("runId") {
description = "The ID of the ORT run."
}

standardListQueryParameters()
}

response {
HttpStatusCode.OK to {
description = "Success."
jsonBody<PagedResponse<RuleViolationWithIdentifier>> {
example("Get vulnerabilities for an ORT run") {
value = PagedResponse(
listOf(
RuleViolationWithIdentifier(
RuleViolation(
"OCaaS Policy C1 Strict Copyleft",
"GPL-1.0-or-later",
"DETECTED",
Severity.ERROR,
"License GPL-1.0-or-later found for package 'Maven:org.glassfish.jersey." +
"media:jersey-media-jaxb:2.42' is categorized as strict-copyleft which " +
"must not be used for BT05 Client application applications.",
"Find more information about the [strict-copyleft](https://inside-" +
"docupedia.bosch.com/confluence/x/2gNahg) and the [strict-copyleft-with-saas]" +
"(https://inside-docupedia.bosch.com/confluence/x/4ANahg) categories.\n" +
"Information about this policy and how to fix this issue can be found " +
"[here](https://inside-docupedia.bosch.com/confluence/x/pdOXc).\n\n" +
"If this is a false-positive or ineffective finding, it can be fixed in your " +
"`.ort.yml` file:\n\n" +
"```yaml\n" +
"---\n" +
"package_configurations:\n" +
"- id: \"Maven:org.glassfish.jersey.media:jersey-media-jaxb:2.42\"\n" +
" source_artifact_url: \"https://repo.maven.apache.org/maven2/org/glassfish/" +
"jersey/media/jersey-media-jaxb/2.42/jersey-media-jaxb-2.42-sources.jar\"\n" +
" license_finding_curations:\n" +
" - path: \"META-INF/NOTICE.md\"\n" +
" start_lines: \"84\"\n" +
" line_count: 1\n" +
" detected_license: \"GPL-1.0-or-later\"\n" +
" concluded_license: <Insert correct license.>\n" +
" reason: <Choose one of the reason from the list [CODE, DATA_OF, " +
"DOCUMENTATION_OF, INCORRECT, NOT_DETECTED, REFERENCE].>\n" +
" comment: \"<Describe the reason for the license finding curation.>\"\n" +
"\n" +
"```\n" +
"Documentation how to configure package configurations in the `.ort.yml` " +
"file can be found\n" +
"[here](https://oss-review-toolkit.org/ort/docs/configuration/ort-yml" +
"#curating-project-license-findings)."
),
Identifier(
"Maven",
"org.glassfish.jersey.media",
"jersey-media-jaxb",
"2.42"
)
)
),
PagingData(
limit = 20,
offset = 0,
totalCount = 1,
sortProperties = listOf(SortProperty("packageUrl", SortDirection.ASCENDING))
)
)
}
}
}

HttpStatusCode.NotFound to {
description = "The ORT run does not exist."
}
}
}

val getPackagesByRunId: OpenApiRoute.() -> Unit = {
operationId = "GetPackagesByRunId"
summary = "Get the packages found in an ORT run."
Expand Down

0 comments on commit 6960b95

Please sign in to comment.