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

com.metaeffekt.artifact.enrichment.vulnerability.CpeDerivationEnrichment 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.vulnerability;

import com.metaeffekt.artifact.analysis.utils.StringUtils;
import com.metaeffekt.artifact.analysis.vulnerability.enrichment.InventoryAttribute;
import com.metaeffekt.artifact.analysis.vulnerability.enrichment.warnings.InventoryWarningEntry;
import com.metaeffekt.artifact.analysis.vulnerability.enrichment.warnings.InventoryWarnings;
import com.metaeffekt.artifact.enrichment.InventoryEnricher;
import com.metaeffekt.artifact.enrichment.configurations.CpeDerivationEnrichmentConfiguration;
import com.metaeffekt.mirror.download.documentation.EnricherMetadata;
import com.metaeffekt.mirror.download.documentation.InventoryEnrichmentPhase;
import lombok.Setter;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.Constants;
import org.metaeffekt.core.inventory.processor.model.Inventory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 

CPE URIs are vendor-product pairs that apply to single (or sometimes to multiple) components. * In order to derive them for each artifact, the certain artifact attributes are used to search for vendors/products. * These CPEs are then appended to the Derived CPE URIs of the artifacts. * This step is based on the principle of allowing more false positives than false negatives, since it is more important to identify all potential vulnerabilities which can be filtered out in later steps * either manually or automatically than to potentially miss critical vulnerabilities.

*

Example:

*
    *
  • Artifact with Id=gdk-pixbuf2-2.36.12, Component=gdk-pixbuf2, Version=2.36.12
  • *
  • derives these aliases: * gdk_pixbuf, gdk_pixbuf2, gdkpixbuf2, gdkpixbuf, gdk pixbuf2, gdk-pixbuf2, gdk pixbuf, gdk-pixbuf
  • *
  • finding these products → vendors: gdk_pixbuf -> [redhat], gdkpixbuf -> [gnome], gdk-pixbuf -> [gnome]
  • *
  • which maps to these CPEs: cpe:/a:gnome:gdk-pixbuf, cpe:/a:gnome:gdkpixbuf, cpe:/a:redhat:gdk_pixbuf
  • *
*/ @EnricherMetadata( name = "CPE URI derivation", phase = InventoryEnrichmentPhase.PRODUCT_IDENTIFICATION, intermediateFileSuffix = "cpe-derived", mavenPropertyName = "cpeDerivationEnrichment" ) public class CpeDerivationEnrichment extends InventoryEnricher { private final static Logger LOG = LoggerFactory.getLogger(CpeDerivationEnrichment.class); @Setter private CpeDerivationEnrichmentConfiguration configuration = new CpeDerivationEnrichmentConfiguration(); private CpeDerivationUtilities cpeDerivationUtilities; public CpeDerivationEnrichment(File baseMirrorDirectory) { super.executor.setSize(16); this.cpeDerivationUtilities = new CpeDerivationUtilities(baseMirrorDirectory); } @Override public CpeDerivationEnrichmentConfiguration getConfiguration() { return configuration; } @Override protected void performEnrichment(Inventory inventory) { final AtomicInteger progress = new AtomicInteger(0); final AtomicInteger skippedArtifacts = new AtomicInteger(0); this.cpeDerivationUtilities.setConfiguration(this.configuration); final List artifacts = inventory.getArtifacts(); final Map startTimes = new HashMap<>(); for (final Artifact artifact : artifacts) { if (!artifact.is(InventoryAttribute.ACTIVATE_CPE_URI_DERIVATION.getKey(), true)) { skippedArtifacts.incrementAndGet(); continue; } if (!isValidForEnrichment(artifact)) { LOG.info("Missing required information on artifact [{}], skipping CPE URI derivation", artifact.getId()); new InventoryWarnings(inventory).addArtifactWarning(new InventoryWarningEntry<>(artifact, "Cannot perform CPE URI derivation, missing required information.", this.getEnrichmentName() )); skippedArtifacts.incrementAndGet(); continue; } super.executor.submit(() -> { final int currentElement = progress.incrementAndGet(); if (currentElement % 100 == 0 && currentElement > 0) { LOG.info("Deriving CPE URIs for artifact [{} / {}]", currentElement, inventory.getArtifacts().size()); } synchronized (startTimes) { startTimes.put(artifact, System.currentTimeMillis()); } this.cpeDerivationUtilities.deriveCpeUris(inventory, artifact); synchronized (startTimes) { startTimes.remove(artifact); } }); } final TimerTask checkArtifactTimerTask = new TimerTask() { @Override public void run() { final long currentTime = System.currentTimeMillis(); synchronized (startTimes) { final List> longRunningArtifacts = startTimes.entrySet().stream() .filter(e -> currentTime - e.getValue() >= 30000) .sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())) .collect(Collectors.toList()); if (!longRunningArtifacts.isEmpty()) { LOG.warn("CPE URI derivation is taking longer than 30 seconds for [{}] artifacts: {}", longRunningArtifacts.size(), longRunningArtifacts.stream().map(Map.Entry::getKey).map(Artifact::getId).collect(Collectors.joining(", "))); } } } }; final Timer checkArtifactTimer = new Timer(); checkArtifactTimer.schedule(checkArtifactTimerTask, 30000, 30000); super.executor.start(); try { super.executor.join(); } catch (InterruptedException e) { throw new RuntimeException("Interrupted while waiting for CPE URI derivation to finish", e); } checkArtifactTimer.cancel(); if (skippedArtifacts.get() > 0) { LOG.info("Skipped [{}] artifacts due to missing required information or deactivation via [{}]", skippedArtifacts.get(), InventoryAttribute.ACTIVATE_CPE_URI_DERIVATION.getKey()); } } private boolean isValidForEnrichment(Artifact artifact) { return StringUtils.hasText(artifact.getId()) || StringUtils.hasText(artifact.getComponent()) || StringUtils.hasText(artifact.get(Constants.KEY_ORGANIZATION)) || Constants.ASTERISK.equalsIgnoreCase(artifact.getVersion()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy