|
43 | 43 |
|
44 | 44 | import java.util.Collections; |
45 | 45 | import java.util.List; |
| 46 | +import java.util.Map; |
46 | 47 | import java.util.concurrent.ConcurrentHashMap; |
47 | 48 | import java.util.concurrent.locks.Lock; |
48 | 49 |
|
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; |
59 | 52 | import static org.projectnessie.cel.Issues.newIssues; |
60 | 53 | import static org.projectnessie.cel.common.Source.newTextSource; |
61 | 54 |
|
@@ -151,48 +144,31 @@ private static MultiValuedMap<Type, String> analyzeRequirements(final CheckedExp |
151 | 144 | final var visitor = new CelPolicyScriptVisitor(expr.getTypeMapMap()); |
152 | 145 | visitor.visit(expr.getExpr()); |
153 | 146 |
|
154 | | - // Fields that are accessed directly are always a requirement. |
155 | 147 | final MultiValuedMap<Type, String> requirements = visitor.getAccessedFieldsByType(); |
156 | 148 |
|
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 | + } |
171 | 154 |
|
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()); |
190 | 158 | } |
191 | | - case FUNC_COMPARE_VERSION_DISTANCE -> |
192 | | - requirements.putAll(TYPE_COMPONENT, List.of("purl", "uuid", "version", "latest_version")); |
| 159 | + } |
| 160 | + } |
193 | 161 |
|
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 | + } |
195 | 168 |
|
| 169 | + final List<String> fields = funcRequirements.get(funcSignature.targetType()); |
| 170 | + if (fields != null) { |
| 171 | + requirements.putAll(funcSignature.targetType(), fields); |
196 | 172 | } |
197 | 173 | } |
198 | 174 |
|
|
0 commit comments