Skip to content

Commit 0bc448b

Browse files
committed
feat: Add table for storing vulnerability resolution definitions
The vulnerability resolution definitions will be used to allow users to make vulnerability resolutions on the server, after which they will be injected into repository configuration for runs. In the first implementation, the scope of the resolutions will be the repository. The definition allows to add multiple ID matchers in case the same vulnerability is found with different external IDs from different advisors. Relates to #1009. Signed-off-by: Johanna Lamppu <[email protected]>
1 parent 4b3cba5 commit 0bc448b

File tree

4 files changed

+237
-0
lines changed

4 files changed

+237
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright (C) 2025 The ORT Server Authors (See <https://github.com/eclipse-apoapsis/ort-server/blob/main/NOTICE>)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
package org.eclipse.apoapsis.ortserver.dao.tables
21+
22+
import org.eclipse.apoapsis.ortserver.dao.repositories.repository.RepositoriesTable
23+
import org.eclipse.apoapsis.ortserver.dao.utils.jsonb
24+
import org.eclipse.apoapsis.ortserver.model.ChangeEventEntityType
25+
import org.eclipse.apoapsis.ortserver.model.RepositoryId
26+
import org.eclipse.apoapsis.ortserver.model.VulnerabilityResolutionDefinition
27+
import org.eclipse.apoapsis.ortserver.model.VulnerabilityResolutionReason
28+
import org.eclipse.apoapsis.ortserver.model.util.OptionalValue
29+
30+
import org.jetbrains.exposed.dao.id.LongIdTable
31+
import org.jetbrains.exposed.sql.ResultRow
32+
import org.jetbrains.exposed.sql.insertAndGetId
33+
import org.jetbrains.exposed.sql.update
34+
35+
/**
36+
* A table to store definitions of vulnerability resolutions.
37+
*/
38+
object VulnerabilityResolutionDefinitionsTable : LongIdTable("vulnerability_resolution_definitions") {
39+
val repositoryId = reference("repository_id", RepositoriesTable)
40+
41+
val contextRunId = long("context_run_id")
42+
val idMatchers = jsonb<List<String>>("id_matchers")
43+
val reason = text("reason")
44+
val comment = text("comment")
45+
val archived = bool("archived").default(false)
46+
47+
fun insert(
48+
hierarchyId: RepositoryId,
49+
runIdInput: Long,
50+
idMatchersInput: List<String>,
51+
reasonInput: VulnerabilityResolutionReason,
52+
commentInput: String
53+
): Long {
54+
return insertAndGetId {
55+
it[repositoryId] = hierarchyId.value
56+
it[contextRunId] = runIdInput
57+
it[idMatchers] = idMatchersInput
58+
it[reason] = reasonInput.name
59+
it[comment] = commentInput
60+
}.value
61+
}
62+
63+
fun get(definitionId: Long): VulnerabilityResolutionDefinition {
64+
return select(columns)
65+
.where { id eq definitionId }
66+
.single()
67+
.toVulnerabilityResolutionDefinition()
68+
}
69+
70+
fun getOrNull(definitionId: Long): VulnerabilityResolutionDefinition? {
71+
val row = select(columns)
72+
.where { id eq definitionId }
73+
.singleOrNull() ?: return null
74+
75+
return row.toVulnerabilityResolutionDefinition()
76+
}
77+
78+
fun updateDefinition(
79+
definitionId: Long,
80+
idMatchersInput: OptionalValue<List<String>> = OptionalValue.Absent,
81+
reasonInput: OptionalValue<VulnerabilityResolutionReason> = OptionalValue.Absent,
82+
commentInput: OptionalValue<String> = OptionalValue.Absent,
83+
archivedInput: OptionalValue<Boolean> = OptionalValue.Absent
84+
) {
85+
update({ id eq definitionId }) { stmt ->
86+
idMatchersInput.ifPresent { stmt[idMatchers] = it }
87+
reasonInput.ifPresent { stmt[reason] = it.name }
88+
commentInput.ifPresent { stmt[comment] = it }
89+
archivedInput.ifPresent { stmt[archived] = it }
90+
}
91+
}
92+
93+
fun ResultRow.toVulnerabilityResolutionDefinition() = VulnerabilityResolutionDefinition(
94+
this[id].value,
95+
RepositoryId(this[repositoryId].value),
96+
this[idMatchers],
97+
VulnerabilityResolutionReason.valueOf(this[reason]),
98+
this[comment],
99+
this[archived],
100+
ChangeLogTable.getAllByEntityTypeAndId(
101+
ChangeEventEntityType.VULNERABILITY_RESOLUTION_DEFINITION,
102+
this[id].value.toString()
103+
)
104+
)
105+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CREATE TABLE vulnerability_resolution_definitions
2+
(
3+
id bigserial PRIMARY KEY,
4+
repository_id bigint REFERENCES repositories NOT NULL,
5+
context_run_id bigint NOT NULL,
6+
id_matchers jsonb NOT NULL,
7+
reason text NOT NULL,
8+
comment text NOT NULL,
9+
archived boolean DEFAULT FALSE NOT NULL
10+
);
11+
12+
CREATE INDEX IF NOT EXISTS idx_vulnerability_resolution_definitions_repository_id
13+
ON vulnerability_resolution_definitions(repository_id);
14+
15+
CREATE INDEX IF NOT EXISTS idx_vulnerability_resolution_definitions_context_run_id
16+
ON vulnerability_resolution_definitions(context_run_id);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (C) 2025 The ORT Server Authors (See <https://github.com/eclipse-apoapsis/ort-server/blob/main/NOTICE>)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
package org.eclipse.apoapsis.ortserver.model
21+
22+
/*
23+
* A data class representing a vulnerability resolution definition.
24+
*/
25+
data class VulnerabilityResolutionDefinition(
26+
/** The unique identifier of the vulnerability resolution definition. */
27+
val id: Long,
28+
29+
/**
30+
* The ID of the hierarchy to which this vulnerability resolution definition is scoped to. In the initial
31+
* implementation this is always the repository level.
32+
*/
33+
val hierarchyId: RepositoryId,
34+
35+
/** The list of vulnerability ID matchers (regular expressions) to match the ids of the vulnerability to resolve. */
36+
val idMatchers: List<String>,
37+
38+
/** The reason why the vulnerability is resolved. */
39+
val reason: VulnerabilityResolutionReason,
40+
41+
/** A comment to further explain why the [reason] is applicable here. */
42+
val comment: String,
43+
44+
/** Whether the vulnerability resolution definition is archived. */
45+
val archived: Boolean,
46+
47+
/** The list of change events associated with this vulnerability resolution definition. */
48+
val changes: List<ChangeEvent>
49+
)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (C) 2025 The ORT Server Authors (See <https://github.com/eclipse-apoapsis/ort-server/blob/main/NOTICE>)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
package org.eclipse.apoapsis.ortserver.model
21+
22+
/**
23+
* Possible reasons for resolving an [Vulnerability] using a [VulnerabilityResolution].
24+
*/
25+
enum class VulnerabilityResolutionReason {
26+
/**
27+
* No remediation is available for this vulnerability, e.g., because it requires a change to be made
28+
* by a third party that is not responsive.
29+
*/
30+
CANT_FIX_VULNERABILITY,
31+
32+
/**
33+
* The code in which the vulnerability was found is neither invoked in the project's code nor indirectly
34+
* via another open source component.
35+
*/
36+
INEFFECTIVE_VULNERABILITY,
37+
38+
/**
39+
* The vulnerability is irrelevant due to a tooling or database mismatch, e.g., the package version used
40+
* does not match the version for which the vulnerability provider has reported a vulnerability.
41+
*/
42+
INVALID_MATCH_VULNERABILITY,
43+
44+
/**
45+
* The vulnerability is valid but has been mitigated, e.g., measures have been taken to ensure
46+
* this vulnerability can not be exploited.
47+
*/
48+
MITIGATED_VULNERABILITY,
49+
50+
/**
51+
* The vulnerability was reported, and got a CVE assigned. However, the CVE was later deemed to not be a
52+
* vulnerability.
53+
*/
54+
NOT_A_VULNERABILITY,
55+
56+
/**
57+
* This vulnerability will never be fixed, e.g., because the package which is affected is orphaned,
58+
* declared end-of-life, or otherwise deprecated.
59+
*/
60+
WILL_NOT_FIX_VULNERABILITY,
61+
62+
/**
63+
* The vulnerability is valid but a temporary workaround has been put in place to avoid exposure
64+
* to the vulnerability.
65+
*/
66+
WORKAROUND_FOR_VULNERABILITY
67+
}

0 commit comments

Comments
 (0)