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

com.metaeffekt.artifact.analysis.vulnerability.enrichment.warnings.InventoryWarnings 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.analysis.vulnerability.enrichment.warnings;

import com.metaeffekt.artifact.analysis.utils.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.metaeffekt.core.inventory.processor.model.Inventory;
import org.metaeffekt.core.inventory.processor.model.InventoryInfo;
import org.metaeffekt.core.inventory.processor.model.VulnerabilityMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

public class InventoryWarnings {

    private final static Logger LOG = LoggerFactory.getLogger(InventoryWarnings.class);

    public final static String CORRELATION_WARNINGS_INVENTORY_INFO_ROW_KEY = "correlation-warnings";
    public final static String CORRELATION_WARNINGS_INVENTORY_INFO_COL_WARNINGS_KEY = "Warnings";

    private final Inventory inventory;
    private final InventoryInfo inventoryInfo;

    private final List sourcelessWarnings = new ArrayList<>();
    private final List> artifactWarnings = new ArrayList<>();
    private final List> vulnerabilityWarnings = new ArrayList<>();

    private final static Map CACHE = new WeakHashMap<>();

    public static InventoryWarnings fromInventory(Inventory inventory) {
        if (CACHE.containsKey(inventory)) {
            return CACHE.get(inventory);
        }
        final InventoryWarnings warnings = new InventoryWarnings(inventory);
        CACHE.put(inventory, warnings);
        return warnings;
    }

    public InventoryWarnings(Inventory inventory) {
        if (CACHE.containsKey(inventory)) {
            LOG.warn("InventoryWarnings already initialized on inventory [{}]. Consider using fromInventory(Inventory) instead.", inventory);
        }
        this.inventory = inventory;
        this.inventoryInfo = inventory.findOrCreateInventoryInfo(CORRELATION_WARNINGS_INVENTORY_INFO_ROW_KEY);

        parse();
        applyChanges();
    }

    public boolean hasData() {
        return !artifactWarnings.isEmpty() || !vulnerabilityWarnings.isEmpty() || !sourcelessWarnings.isEmpty();
    }

    private void parse() {
        if (StringUtils.isEmpty(inventoryInfo.get(CORRELATION_WARNINGS_INVENTORY_INFO_COL_WARNINGS_KEY))) {
            applyChanges();
            return;
        }

        try {
            final JSONObject json = new JSONObject(inventoryInfo.get(CORRELATION_WARNINGS_INVENTORY_INFO_COL_WARNINGS_KEY));

            if (json.optJSONArray("artifactWarnings") != null) {
                final JSONArray artifactWarnings = json.getJSONArray("artifactWarnings");
                for (int i = 0; i < artifactWarnings.length(); i++) {
                    final JSONObject artifactWarning = artifactWarnings.getJSONObject(i);

                    final InventoryWarningEntry entry = InventoryWarningEntry.fromToJson(artifactWarning, inventory, InventoryWarningEntry.ARTIFACT_FINDABLE);
                    this.artifactWarnings.add(entry);
                }
            } else if (json.optJSONObject("artifactWarnings") != null) {
                LOG.warn("Artifact warnings are not an array. You cannot parse the legacy format. Please re-run enrichment pipeline for this inventory.");
            }

            if (json.optJSONArray("vulnerabilityWarnings") != null) {
                final JSONArray vulnerabilityWarnings = json.optJSONArray("vulnerabilityWarnings");
                for (int i = 0; i < vulnerabilityWarnings.length(); i++) {
                    final JSONObject vulnerabilityWarning = vulnerabilityWarnings.getJSONObject(i);

                    final InventoryWarningEntry entry = InventoryWarningEntry.fromToJson(vulnerabilityWarning, inventory, InventoryWarningEntry.VULNERABILITY_META_DATA_FINDABLE);
                    this.vulnerabilityWarnings.add(entry);
                }
            } else if (json.optJSONObject("vulnerabilityWarnings") != null) {
                LOG.warn("Vulnerability warnings are not an array. You cannot parse the legacy format. Please re-run enrichment pipeline for this inventory.");
            }

            if (json.optJSONArray("sourcelessWarnings") != null) {
                final JSONArray sourcelessWarnings = json.getJSONArray("sourcelessWarnings");
                for (int i = 0; i < sourcelessWarnings.length(); i++) {
                    final String warning = sourcelessWarnings.getString(i);
                    this.sourcelessWarnings.add(warning);
                }
            }

        } catch (Exception e) {
            LOG.error("Failed to parse correlation warnings.", e);
            throw new RuntimeException("Failed to parse correlation warnings from inventory: " + e.getMessage() + "\n" + inventoryInfo.get(CORRELATION_WARNINGS_INVENTORY_INFO_COL_WARNINGS_KEY), e);
        }
    }

    private void applyChanges() {
        if (!hasData()) {
            inventory.getInventoryInfo().remove(inventoryInfo);
            inventory.getInventoryInfo().removeIf(i -> i.get(InventoryInfo.Attribute.ID).equals(CORRELATION_WARNINGS_INVENTORY_INFO_ROW_KEY));
            return;
        } else if (!inventory.getInventoryInfo().contains(inventoryInfo)) {
            inventory.getInventoryInfo().add(inventoryInfo);
        }

        final JSONObject json = new JSONObject();

        final JSONArray artifactWarnings = new JSONArray();
        for (final InventoryWarningEntry entry : this.artifactWarnings) {
            artifactWarnings.put(entry.toJson());
        }
        json.put("artifactWarnings", artifactWarnings);

        final JSONArray vulnerabilityWarnings = new JSONArray();
        for (final InventoryWarningEntry entry : this.vulnerabilityWarnings) {
            vulnerabilityWarnings.put(entry.toJson());
        }
        json.put("vulnerabilityWarnings", vulnerabilityWarnings);

        json.put("sourcelessWarnings", sourcelessWarnings);

        inventoryInfo.set(CORRELATION_WARNINGS_INVENTORY_INFO_COL_WARNINGS_KEY, json.toString());
    }

    public void addSourcelessWarning(String warning) {
        sourcelessWarnings.add(warning);
        applyChanges();
    }

    public void addArtifactWarning(InventoryWarningEntry warning) {
        this.artifactWarnings.add(warning);
        applyChanges();
    }

    public void addVulnerabilityWarning(InventoryWarningEntry warning) {
        this.vulnerabilityWarnings.add(warning);
        applyChanges();
    }

    public List> getArtifactWarnings() {
        return artifactWarnings;
    }

    public List> getVulnerabilityWarnings() {
        return vulnerabilityWarnings;
    }

    public List getSourcelessWarnings() {
        return sourcelessWarnings;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy