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

com.metaeffekt.artifact.enrichment.other.EolEnrichment 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.other;

import com.metaeffekt.artifact.analysis.utils.StringUtils;
import com.metaeffekt.artifact.analysis.vulnerability.enrichment.InventoryAttribute;
import com.metaeffekt.artifact.enrichment.InventoryEnricher;
import com.metaeffekt.artifact.enrichment.configurations.EolEnrichmentConfiguration;
import com.metaeffekt.mirror.contents.eol.EolCycle;
import com.metaeffekt.mirror.contents.eol.EolLifecycle;
import com.metaeffekt.mirror.contents.eol.export.CycleStateScenario;
import com.metaeffekt.mirror.contents.eol.export.ExportedCycleState;
import com.metaeffekt.mirror.download.documentation.DocRelevantMethods;
import com.metaeffekt.mirror.download.documentation.EnricherMetadata;
import com.metaeffekt.mirror.download.documentation.InventoryEnrichmentPhase;
import com.metaeffekt.mirror.query.EolIndexQuery;
import lombok.Setter;
import org.apache.commons.lang3.ObjectUtils;
import org.json.JSONArray;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.Inventory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 

Interpreting the data

*

The 6 values we actually use from the data source can either be a Boolean or a date:

*
    *
  • EOL (End of Life): Generally, whether something has reached the end-of-life state, i.e., both support and extended * support have expired.
  • *
  • Support: Whether the basic support is still valid.
  • *
  • Extended Support: Something like security support or similar, is usually either not set or equals the EOL date.
  • *
  • LTS (Long Term Support): If Boolean, whether the cycle is LTS; if Date, when the cycle becomes LTS.
  • *
  • Discontinued: Whether the cycle is explicitly marked as discontinued, is often not set.
  • *
  • Technical Guidance: When the technical guidance support ends, is often not set.
  • *
*

If the value ist a date, it always indicates when this state will be reached. Except for LTS, reaching this date is * always something negative.

*

We can differentiate the lifecycle state of a product based on whether extended support is available or not. Here are * the two scenarios:

*

Scenario 1: Extended Support is Available

*
    *
  1. Green: EOL has not been reached, both support and extended support are still valid.
  2. *
  3. Light Green: Support ends in less than X months (configurable, default is 6 months).
  4. *
  5. Yellow: Support is no longer valid, but extended support is still in effect.
  6. *
  7. Orange: Extended support ends in less than X months (configurable, default is 6 months).
  8. *
  9. Red: EOL has been reached, extended support is no longer valid.
  10. *
*

Scenario 2: Extended Support is Not Available

*

In this case, phases 3 and 4 are skipped and the cycle immediately reaches the end of life.

*
    *
  1. Green: EOL has not been reached, support is still valid.
  2. *
  3. Orange: Support ends in less than X months (configurable, default is 6 months).
  4. *
  5. Red: EOL has been reached, support is no longer valid.
  6. *
*/ @EnricherMetadata( name = "EOL Date", phase = InventoryEnrichmentPhase.VULNERABILITY_PRIORITIZATION, intermediateFileSuffix = "eol-date", mavenPropertyName = "eolEnrichment" ) public class EolEnrichment extends InventoryEnricher { private static final Logger LOG = LoggerFactory.getLogger(EolEnrichment.class); @Setter private EolEnrichmentConfiguration configuration = new EolEnrichmentConfiguration(); private final EolIndexQuery eolIndexQuery; public EolEnrichment(File baseMirrorDirectory) { this.eolIndexQuery = new EolIndexQuery(baseMirrorDirectory); } @Override public EolEnrichmentConfiguration getConfiguration() { return configuration; } @Override @DocRelevantMethods({"EolEnrichment#performEnrichmentOnSingleArtifact"}) protected void performEnrichment(Inventory inventory) { int count = 0; final Map> matchedEolCyclesTracker = new HashMap<>(); for (Artifact artifact : inventory.getArtifacts()) { final Map> result = performEnrichmentOnSingleArtifact(artifact); if (result == null) continue; matchedEolCyclesTracker.putAll(result); count++; } LOG.info("Added EOL Information to [{}] artifacts for products: {}", count, matchedEolCyclesTracker.entrySet().stream().map(e -> e.getKey() + " (" + e.getValue().stream().map(EolCycle::getCycle).collect(Collectors.joining(", ")) + ")").collect(Collectors.joining(", "))); } public Map> performEnrichmentOnSingleArtifact(Artifact artifact) { if (!artifact.has(InventoryAttribute.EOL_ID.getKey())) { return null; } final String[] eolIds = artifact.get(InventoryAttribute.EOL_ID.getKey()).split(", "); final Map> matchedEolCyclesTracker = new HashMap<>(); for (String eolId : eolIds) { final EolLifecycle lifecycle = this.eolIndexQuery.findCyclesByProduct(eolId); if (lifecycle == null || lifecycle.getCycles().isEmpty()) { LOG.warn("No EOL information found for product: {}", eolId); continue; } final String cycleQueryVersion = ObjectUtils.firstNonNull( artifact.get(InventoryAttribute.EOL_OVERWRITE_CYCLE_QUERY_VERSION), artifact.get(Artifact.Attribute.VERSION) ); final String latestVersionQueryVersion = ObjectUtils.firstNonNull( artifact.get(InventoryAttribute.EOL_OVERWRITE_LATEST_VERSION_QUERY_VERSION), artifact.get(Artifact.Attribute.VERSION) ); final EolCycle currentCycle = lifecycle.findCycleFromVersion(cycleQueryVersion); if (currentCycle == null) { if (cycleQueryVersion == null) { LOG.warn("Lifecycle found for product [{}], artifact query version [{}] [{}] is null on artifact [{}]", eolId, cycleQueryVersion, latestVersionQueryVersion, artifact.get(Artifact.Attribute.ID)); } else { LOG.warn("Lifecycle found for product [{}], artifact query version [{}] [{}] on artifact [{}] cannot be found in cycle data", eolId, cycleQueryVersion, latestVersionQueryVersion, artifact.get(Artifact.Attribute.ID)); } continue; } this.performEnrichmentOnArtifactAndCycle(lifecycle, artifact, currentCycle, latestVersionQueryVersion); matchedEolCyclesTracker.computeIfAbsent(eolId, k -> new HashSet<>()).add(currentCycle); } return matchedEolCyclesTracker; } private void performEnrichmentOnArtifactAndCycle(EolLifecycle lifecycle, Artifact artifact, EolCycle cycle, String latestVersionQueryVersion) { final ExportedCycleState state = ExportedCycleState.from(cycle, artifact, latestVersionQueryVersion, lifecycle, configuration.getWarningThresholdMillisSupport(), configuration.getWarningThresholdMillisExtendedSupport()); if (StringUtils.isEmpty(artifact.get(InventoryAttribute.EOL_FULL_STATE.getKey()))) { artifact.set(InventoryAttribute.EOL_FULL_STATE.getKey(), new JSONArray().put(state.toJson()).toString()); } else { final JSONArray existing = new JSONArray(artifact.get(InventoryAttribute.EOL_FULL_STATE.getKey())); existing.put(state.toJson()); artifact.set(InventoryAttribute.EOL_FULL_STATE.getKey(), existing.toString()); } artifact.set(InventoryAttribute.EOL_RECOMMENDED_CYCLE_VERSION.getKey(), state.getLatestCycleVersion()); artifact.set(InventoryAttribute.EOL_RECOMMENDED_LIFECYCLE_VERSION.getKey(), state.getLatestLifecycleVersion()); artifact.set(InventoryAttribute.EOL_RECOMMENDED_NEXT_SUPPORTED_VERSION.getKey(), state.getNextSupportedVersion()); artifact.set(InventoryAttribute.EOL_RECOMMENDED_NEXT_SUPPORTED_EXTENDED_VERSION.getKey(), state.getNextSupportedExtendedVersion()); artifact.set(InventoryAttribute.EOL_RECOMMENDED_CLOSEST_SUPPORTED_LTS_VERSION.getKey(), state.getClosestActiveLtsVersion()); artifact.set(InventoryAttribute.EOL_RECOMMENDED_LATEST_SUPPORTED_LTS_VERSION.getKey(), state.getLatestActiveLtsVersion()); artifact.set(InventoryAttribute.EOL_IS_EOL.getKey(), String.valueOf(state.isEol())); artifact.set(InventoryAttribute.EOL_IS_SUPPORTED.getKey(), String.valueOf(state.isSupport())); artifact.set(InventoryAttribute.EOL_IS_SUPPORTED_EXTENDED.getKey(), String.valueOf(state.isExtendedSupport())); artifact.set(InventoryAttribute.EOL_RATING.getKey(), String.valueOf(state.getCycleStateScenario() == CycleStateScenario.EXTENDED_SUPPORT_NOT_PRESENT ? state.getCycleStateExtendedSupportUnavailable().getRating().getRating() : state.getCycleStateExtendedSupportAvailable().getRating().getRating())); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy