Skip to content

Commit d9c7f74

Browse files
authored
Merge pull request #1908 from DependencyTrack/simplify-cel-script-host
2 parents 709406e + a195aa9 commit d9c7f74

File tree

2 files changed

+43
-46
lines changed

2 files changed

+43
-46
lines changed

apiserver/src/main/java/org/dependencytrack/policy/cel/CelCommonPolicyLibrary.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import alpine.common.logging.Logger;
2222
import com.github.packageurl.MalformedPackageURLException;
2323
import com.github.packageurl.PackageURL;
24+
import com.google.api.expr.v1alpha1.Type;
2425
import io.github.nscuro.versatile.Vers;
2526
import io.github.nscuro.versatile.VersException;
2627
import jakarta.annotation.Nullable;
@@ -69,6 +70,7 @@
6970
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_COMPONENT;
7071
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_PROJECT;
7172
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_VERSION_DISTANCE;
73+
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_VULNERABILITY;
7274

7375
public class CelCommonPolicyLibrary implements Library {
7476

@@ -82,6 +84,25 @@ public class CelCommonPolicyLibrary implements Library {
8284
static final String FUNC_COMPARE_AGE = "compare_age";
8385
static final String FUNC_COMPARE_VERSION_DISTANCE = "version_distance";
8486

87+
static final Map<String, Map<Type, List<String>>> FUNCTION_FIELD_REQUIREMENTS = Map.ofEntries(
88+
Map.entry(FUNC_DEPENDS_ON, Map.of(TYPE_PROJECT, List.of("uuid"), TYPE_COMPONENT, List.of("uuid"))),
89+
Map.entry(FUNC_IS_DEPENDENCY_OF, Map.of(TYPE_COMPONENT, List.of("uuid"))),
90+
Map.entry(FUNC_IS_EXCLUSIVE_DEPENDENCY_OF, Map.of(TYPE_COMPONENT, List.of("uuid"))),
91+
Map.entry(FUNC_IS_DIRECT_DEPENDENCY_OF, Map.of(TYPE_COMPONENT, List.of("uuid"))),
92+
Map.entry(FUNC_MATCHES_RANGE, Map.of(TYPE_PROJECT, List.of("version"), TYPE_COMPONENT, List.of("version"))),
93+
Map.entry(FUNC_COMPARE_VERSION_DISTANCE, Map.of(TYPE_COMPONENT, List.of("purl", "uuid", "version", "latest_version"))),
94+
Map.entry(FUNC_COMPARE_AGE, Map.of(TYPE_COMPONENT, List.of("purl", "published_at"))));
95+
96+
static final Map<Type, Map<String, List<String>>> FIELD_EXPANSIONS = Map.of(
97+
TYPE_VULNERABILITY, Map.of(
98+
"severity", List.of(
99+
"cvssv2_base_score",
100+
"cvssv3_base_score",
101+
"cvssv4_score",
102+
"owasp_rr_likelihood_score",
103+
"owasp_rr_technical_impact_score",
104+
"owasp_rr_business_impact_score")));
105+
85106
@Override
86107
public List<EnvOption> getCompileOptions() {
87108
return List.of(

apiserver/src/main/java/org/dependencytrack/policy/cel/CelPolicyScriptHost.java

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,12 @@
4343

4444
import java.util.Collections;
4545
import java.util.List;
46+
import java.util.Map;
4647
import java.util.concurrent.ConcurrentHashMap;
4748
import java.util.concurrent.locks.Lock;
4849

49-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_COMPARE_AGE;
50-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_COMPARE_VERSION_DISTANCE;
51-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_DEPENDS_ON;
52-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_IS_DEPENDENCY_OF;
53-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_IS_DIRECT_DEPENDENCY_OF;
54-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_IS_EXCLUSIVE_DEPENDENCY_OF;
55-
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNC_MATCHES_RANGE;
56-
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_COMPONENT;
57-
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_PROJECT;
58-
import static org.dependencytrack.policy.cel.definition.CelPolicyTypes.TYPE_VULNERABILITY;
50+
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FIELD_EXPANSIONS;
51+
import static org.dependencytrack.policy.cel.CelCommonPolicyLibrary.FUNCTION_FIELD_REQUIREMENTS;
5952
import static org.projectnessie.cel.Issues.newIssues;
6053
import static org.projectnessie.cel.common.Source.newTextSource;
6154

@@ -151,48 +144,31 @@ private static MultiValuedMap<Type, String> analyzeRequirements(final CheckedExp
151144
final var visitor = new CelPolicyScriptVisitor(expr.getTypeMapMap());
152145
visitor.visit(expr.getExpr());
153146

154-
// Fields that are accessed directly are always a requirement.
155147
final MultiValuedMap<Type, String> requirements = visitor.getAccessedFieldsByType();
156148

157-
// Special case for vulnerability severity: The "true" severity may or may not be persisted
158-
// in the SEVERITY database column. To compute the actual severity, CVSSv2, CVSSv3, CVSSv4, and OWASP RR
159-
// scores may be required. See https://github.com/DependencyTrack/dependency-track/issues/2474
160-
if (requirements.containsKey(TYPE_VULNERABILITY)
161-
&& requirements.get(TYPE_VULNERABILITY).contains("severity")) {
162-
requirements.putAll(TYPE_VULNERABILITY, List.of(
163-
"cvssv2_base_score",
164-
"cvssv3_base_score",
165-
"cvssv4_score",
166-
"owasp_rr_likelihood_score",
167-
"owasp_rr_technical_impact_score",
168-
"owasp_rr_business_impact_score"
169-
));
170-
}
149+
for (final var expansion : FIELD_EXPANSIONS.entrySet()) {
150+
final Type type = expansion.getKey();
151+
if (!requirements.containsKey(type)) {
152+
continue;
153+
}
171154

172-
// Custom functions may access certain fields implicitly, in a way that is not visible
173-
// to the AST visitor. To compensate, we hardcode the functions' requirements here.
174-
// TODO: This should be restructured to be more generic.
175-
for (final FunctionSignature functionSignature : visitor.getUsedFunctionSignatures()) {
176-
switch (functionSignature.function()) {
177-
case FUNC_DEPENDS_ON, FUNC_IS_DEPENDENCY_OF, FUNC_IS_EXCLUSIVE_DEPENDENCY_OF, FUNC_IS_DIRECT_DEPENDENCY_OF -> {
178-
if (TYPE_PROJECT.equals(functionSignature.targetType())) {
179-
requirements.put(TYPE_PROJECT, "uuid");
180-
} else if (TYPE_COMPONENT.equals(functionSignature.targetType())) {
181-
requirements.put(TYPE_COMPONENT, "uuid");
182-
}
183-
}
184-
case FUNC_MATCHES_RANGE -> {
185-
if (TYPE_PROJECT.equals(functionSignature.targetType())) {
186-
requirements.put(TYPE_PROJECT, "version");
187-
} else if (TYPE_COMPONENT.equals(functionSignature.targetType())) {
188-
requirements.put(TYPE_COMPONENT, "version");
189-
}
155+
for (final var fieldExpansion : expansion.getValue().entrySet()) {
156+
if (requirements.get(type).contains(fieldExpansion.getKey())) {
157+
requirements.putAll(type, fieldExpansion.getValue());
190158
}
191-
case FUNC_COMPARE_VERSION_DISTANCE ->
192-
requirements.putAll(TYPE_COMPONENT, List.of("purl", "uuid", "version", "latest_version"));
159+
}
160+
}
193161

194-
case FUNC_COMPARE_AGE -> requirements.putAll(TYPE_COMPONENT, List.of("purl", "published_at"));
162+
for (final FunctionSignature funcSignature : visitor.getUsedFunctionSignatures()) {
163+
final Map<Type, List<String>> funcRequirements =
164+
FUNCTION_FIELD_REQUIREMENTS.get(funcSignature.function());
165+
if (funcRequirements == null) {
166+
continue;
167+
}
195168

169+
final List<String> fields = funcRequirements.get(funcSignature.targetType());
170+
if (fields != null) {
171+
requirements.putAll(funcSignature.targetType(), fields);
196172
}
197173
}
198174

0 commit comments

Comments
 (0)