All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.metaeffekt.artifact.enrichment.configurations.VadDetailLevelConfiguration Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * 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
 *
 *     http://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.
 */
package com.metaeffekt.artifact.enrichment.configurations;

import com.metaeffekt.artifact.analysis.vulnerability.enrichment.InventoryAttribute;
import com.metaeffekt.mirror.contents.store.AdvisoryTypeIdentifier;
import org.metaeffekt.core.inventory.processor.configuration.ProcessConfiguration;
import org.metaeffekt.core.inventory.processor.configuration.ProcessMisconfiguration;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.report.configuration.CentralSecurityPolicyConfiguration;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * Configures elements to hide from the dashboard, such as:
 * 
    *
  • timeline
  • *
  • advisors *
      *
    • different types of advisories (notice, ...)
    • *
    • by advisory providers (CERT-FR, ...)
    • *
    *
  • *
  • references
  • *
*/ public class VadDetailLevelConfiguration extends ProcessConfiguration { public final static VadDetailLevelConfiguration DEFAULT_DETAIL_LEVEL = new VadDetailLevelConfiguration(); private VadDetailLevelMatcher matcher = new VadDetailLevelMatcher(); private boolean timeline = true; private boolean advisoriesGlobal = true; private boolean advisoriesReferences = true; private boolean references = true; private boolean eolDate = true; // FIXME: Implement handler once http://ae-server:7990/projects/AE/repos/metaeffekt-artifact-analysis/pull-requests/82/overview is merged private List advisoryByTypes = new ArrayList<>(); private List advisoryByProviders = new ArrayList<>(); public VadDetailLevelConfiguration() { advisoryByTypes.add("any"); advisoryByProviders.add("any"); } public VadDetailLevelConfiguration setMatcher(VadDetailLevelMatcher matcher) { this.matcher = matcher; return this; } public VadDetailLevelMatcher getMatcher() { return matcher; } public boolean isTimeline() { return timeline; } public boolean isAdvisoriesGlobal() { return advisoriesGlobal; } public boolean isAdvisoriesReferences() { return advisoriesReferences; } public List getAdvisoryByTypes() { return advisoryByTypes; } public boolean isAdvisoryTypeEnabled(String advisoryType) { return advisoriesGlobal && (advisoryByTypes.contains(advisoryType) || CentralSecurityPolicyConfiguration.isAny(advisoryType) || CentralSecurityPolicyConfiguration.containsAny(advisoryByTypes)); } public List getAdvisoryByProviders() { return advisoryByProviders; } public boolean isAdvisoryProviderEnabled(String advisoryProvider) { return advisoriesGlobal && (advisoryByProviders.contains(advisoryProvider) || CentralSecurityPolicyConfiguration.isAny(advisoryProvider) || CentralSecurityPolicyConfiguration.containsAny(advisoryByProviders)); } public boolean isAdvisoryProviderEnabled(AdvisoryTypeIdentifier advisoryProvider) { return isAdvisoryProviderEnabled(advisoryProvider.name()) || isAdvisoryProviderEnabled(advisoryProvider.getWellFormedName()); } public boolean isReferences() { return references; } public boolean isEolDate() { return eolDate; } public VadDetailLevelConfiguration setTimeline(boolean timeline) { this.timeline = timeline; return this; } public VadDetailLevelConfiguration setAdvisoriesGlobal(boolean advisoriesGlobal) { this.advisoriesGlobal = advisoriesGlobal; return this; } public VadDetailLevelConfiguration setAdvisoriesReferences(boolean advisoriesReferences) { this.advisoriesReferences = advisoriesReferences; return this; } public VadDetailLevelConfiguration setAdvisoryByTypes(List advisoryByTypes) { this.advisoryByTypes = advisoryByTypes; return this; } public VadDetailLevelConfiguration setAdvisoryByProviders(List advisoryByProviders) { this.advisoryByProviders = advisoryByProviders; return this; } public VadDetailLevelConfiguration setReferences(boolean references) { this.references = references; return this; } public void setEolDate(boolean eolDate) { this.eolDate = eolDate; } @Override public LinkedHashMap getProperties() { LinkedHashMap properties = new LinkedHashMap<>(); properties.put("matcher", matcher == null ? null : matcher.getProperties()); properties.put("timeline", timeline); properties.put("references", references); properties.put("advisoriesGlobal", advisoriesGlobal); properties.put("advisoriesReferences", advisoriesReferences); properties.put("advisoryByTypes", advisoryByTypes); properties.put("advisoryByProviders", advisoryByProviders); properties.put("eolDate", eolDate); return properties; } @Override public void setProperties(LinkedHashMap properties) { super.loadBooleanProperty(properties, "timeline", this::setTimeline); super.loadBooleanProperty(properties, "references", this::setReferences); super.loadBooleanProperty(properties, "advisoriesGlobal", this::setAdvisoriesGlobal); super.loadBooleanProperty(properties, "advisoriesReferences", this::setAdvisoriesReferences); super.loadBooleanProperty(properties, "eolDate", this::setEolDate); super.loadListProperty(properties, "advisoryByTypes", String::valueOf, this::setAdvisoryByTypes); super.loadListProperty(properties, "advisoryByProviders", String::valueOf, this::setAdvisoryByProviders); if (properties.containsKey("matcher")) { matcher = new VadDetailLevelMatcher(); matcher.setProperties((LinkedHashMap) properties.get("matcher")); } super.loadSubConfiguration(properties, "matcher", VadDetailLevelMatcher::new, this::setMatcher); } @Override protected void collectMisconfigurations(List misconfigurations) { if (matcher == null) { misconfigurations.add(new ProcessMisconfiguration("matcher", "matcher is not set")); } else { matcher.collectMisconfigurations(misconfigurations); } } public static List fromArtifacts(Set artifacts) { return artifacts.stream() .map(VadDetailLevelConfiguration::fromArtifact) .flatMap(Collection::stream) .collect(Collectors.toList()); } public static List fromArtifact(Artifact artifact) { final String configString = artifact.getComplete(InventoryAttribute.VAD_DETAIL_LEVEL_CONFIGURATIONS.getKey()); if (configString == null) { return new ArrayList<>(); } return fromConfigurationString(configString); } /** * These strings may be used in the correlation files. They are used to create {@link VadDetailLevelMatcher} and * {@link VadDetailLevelConfiguration} instances.
* Every detail level is represented by two lines, the first specifying the matcher and the second specifying the * configuration.
* Example: *
     * matcher: status = "in review"; anyCpe = "cpe:/a:linux:kernel"
     * detail: timeline = "false"; advisoriesGlobal = "false"
     *  ... further detail levels
     * 
*

* If a value is not specified, the default value is used. * * @param configString The string representation of the configuration. * @return The list of detail level configurations. */ public static List fromConfigurationString(String configString) { final List lines = Arrays.stream(configString.split("\n")) .map(String::trim) .filter(line -> !line.isEmpty()) .collect(Collectors.toList()); final List configurations = new ArrayList<>(); final StringBuilder matcherBuilder = new StringBuilder(" "); final StringBuilder detailsBuilder = new StringBuilder(" "); final List matcherLines = new ArrayList<>(); final List detailsLines = new ArrayList<>(); boolean inMatcher = true; for (int i = 0; i < lines.size(); i++) { final String line = lines.get(i); if (line.startsWith("matcher:")) { inMatcher = true; matcherBuilder.append(line); if (detailsBuilder.length() > 1) { detailsLines.add(detailsBuilder.toString()); detailsBuilder.setLength(0); } } else if (line.startsWith("detail:")) { inMatcher = false; detailsBuilder.append(line); if (matcherBuilder.length() > 1) { matcherLines.add(matcherBuilder.toString()); matcherBuilder.setLength(0); } } else { if (inMatcher) { matcherBuilder.append(line); } else { detailsBuilder.append(line); } } } if (matcherBuilder.length() > 1) { matcherLines.add(matcherBuilder.toString()); } if (detailsBuilder.length() > 1) { detailsLines.add(detailsBuilder.toString()); } if (matcherLines.size() != detailsLines.size()) { throw new IllegalArgumentException("Invalid configuration string, number of matcher lines (" + matcherLines.size() + ") does not match number of detail lines (" + detailsLines.size() + ")"); } for (int i = 0; i < matcherLines.size(); i++) { final String matcherLine = matcherLines.get(i).trim(); final String detailsLine = detailsLines.get(i).trim(); if (!detailsLine.startsWith("detail:")) { throw new IllegalArgumentException("Invalid configuration string, expected 'detail:' but got '" + detailsLine + "'"); } final String trimmedPropertiesString = detailsLine.substring("detail:".length()).trim(); final Map properties = extractPropertiesFromConfigLine(trimmedPropertiesString); final VadDetailLevelConfiguration configuration = new VadDetailLevelConfiguration(); final VadDetailLevelMatcher matcher = VadDetailLevelMatcher.fromConfigurationString(matcherLine); configuration.setMatcher(matcher); setBooleanProperty(properties, "timeline", configuration::setTimeline); setBooleanProperty(properties, "references", configuration::setReferences); setBooleanProperty(properties, "advisoriesGlobal", configuration::setAdvisoriesGlobal); setBooleanProperty(properties, "advisoriesReferences", configuration::setAdvisoriesReferences); setBooleanProperty(properties, "eolDate", configuration::setEolDate); if (properties.containsKey("advisoryByTypes")) { configuration.setAdvisoryByTypes(Arrays.asList(properties.get("advisoryByTypes").split(", "))); } if (properties.containsKey("advisoryByProviders")) { configuration.setAdvisoryByProviders(Arrays.asList(properties.get("advisoryByProviders").split(", "))); } configurations.add(configuration); } return configurations; } private static void setBooleanProperty(Map properties, String propertyName, Consumer setter) { if (properties.containsKey(propertyName)) { setter.accept(Boolean.parseBoolean(properties.get(propertyName))); } } protected static Map extractPropertiesFromConfigLine(String configLine) { final Map properties = new HashMap<>(); // go character by character to prevent matching ";" inside strings. // the only escape sequence is \". final StringBuilder key = new StringBuilder(); final StringBuilder value = new StringBuilder(); boolean inKey = true; boolean inString = false; for (int i = 0; i < configLine.length(); i++) { final char c = configLine.charAt(i); if (inString) { if (c == '"') { inString = false; } else if (c == '\\' && i + 1 < configLine.length() && configLine.charAt(i + 1) == '"') { value.append('"'); i++; } else { value.append(c); } } else { if (c == '"') { inString = true; } else if (c == ' ') { // ignore } else if (c == '=') { inKey = false; } else if (c == ';') { properties.put(key.toString().trim(), value.toString().trim()); key.setLength(0); value.setLength(0); inKey = true; } else { if (inKey) { key.append(c); } else { value.append(c); } } } } if (inKey && !configLine.endsWith(";")) { throw new IllegalArgumentException("Invalid configuration string, string ended with unterminated key '" + configLine + "'"); } if (inString) { throw new IllegalArgumentException("Invalid configuration string, string ended with unterminated string value '" + configLine + "'"); } if (key.length() > 0) { properties.put(key.toString().trim(), value.toString().trim()); } return properties; } public static VadDetailLevelConfiguration computeEffective(Collection levels) { if (levels == null || levels.isEmpty()) { return DEFAULT_DETAIL_LEVEL; } final VadDetailLevelConfiguration effective = new VadDetailLevelConfiguration(); for (VadDetailLevelConfiguration level : levels) { effective.setTimeline(effective.isTimeline() && level.isTimeline()); effective.setReferences(effective.isReferences() && level.isReferences()); effective.setAdvisoriesGlobal(effective.isAdvisoriesGlobal() && level.isAdvisoriesGlobal()); effective.setAdvisoriesReferences(effective.isAdvisoriesReferences() && level.isAdvisoriesReferences()); effective.setEolDate(effective.isEolDate() && level.isEolDate()); effective.getAdvisoryByTypes().retainAll(level.getAdvisoryByTypes()); effective.getAdvisoryByProviders().retainAll(level.getAdvisoryByProviders()); } return effective; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy