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

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

import com.metaeffekt.artifact.analysis.utils.CustomCollectors;
import com.metaeffekt.artifact.analysis.utils.StringUtils;
import com.metaeffekt.artifact.analysis.vulnerability.enrichment.InventoryAttribute;
import com.metaeffekt.mirror.contents.store.AdvisoryTypeIdentifier;
import com.metaeffekt.mirror.contents.store.AdvisoryTypeStore;
import com.metaeffekt.mirror.contents.store.ContentIdentifierStore;
import com.metaeffekt.mirror.contents.vulnerability.Vulnerability;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.ObjectUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.metaeffekt.core.inventory.processor.model.VulnerabilityMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Getter
public class VulnerabilityStatusReviewedEntry implements Cloneable {

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

    private final String id;
    @Setter
    private String comment;
    private final AdvisoryTypeIdentifier advisor;

    public VulnerabilityStatusReviewedEntry(String id, String comment, AdvisoryTypeIdentifier type) {
        this.id = id;
        this.comment = comment;


        if (type == null) {
            final Optional>> response = AdvisoryTypeStore.get().fromEntryIdentifier(id);
            if (!response.isPresent()) {
                LOG.warn("VulnerabilityStatusReviewedEntry: Unable to parse advisor from id [{}]", id);
                this.advisor = null;
            } else {
                this.advisor = response.get().getIdentifier();
            }
        } else {
            this.advisor = type;
        }

        if (id == null) {
            LOG.warn("VulnerabilityStatusReviewedEntry: Id is null (comment: {}; type: {})", comment, type);
        }
    }

    public VulnerabilityStatusReviewedEntry(String id, String comment) {
        this(id, comment, null);
    }

    public VulnerabilityStatusReviewedEntry(String id) {
        this(id, null, null);
    }

    @Override
    public String toString() {
        return id + (comment != null && !comment.isEmpty() ? " (" + comment + ")" : "");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        VulnerabilityStatusReviewedEntry that = (VulnerabilityStatusReviewedEntry) o;
        return Objects.equals(id, that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public VulnerabilityStatusReviewedEntry clone() {
        return new VulnerabilityStatusReviewedEntry(id, comment, advisor);
    }

    /**
     * Parses a list of entries that are either a Map or a String.
* [{
* "advisor": "MSRC", // or 'cert' as legacy key
* "comment": "This MSRC alert has been reviewed.",
* "id": "MSRC-CVE-2021-44228"
* },
* "MSRC-CVE-2021-44228 (comment)",
* "MSRC-CVE-2021-44228"]
* * @param entries The entries to parse. * @return The parsed entries. */ public static List fromMultipleFormattedStringOrMapEntries(List entries) { try { final List parsed = new ArrayList<>(); for (final Object entry : entries) { if (entry instanceof String) { parsed.add(fromFormattedString(entry.toString())); } else if (entry instanceof Map) { parsed.add(fromMap((Map) entry)); } } return parsed; } catch (Exception e) { throw new RuntimeException("Unable to parse Vulnerability Status Reviewed Advisory Entries from List of Objects: " + entries, e); } } public static VulnerabilityStatusReviewedEntry fromFormattedString(String entry) { final String id; final String comment; final Pattern valueWithOptionalParenthesisPattern = Pattern.compile("^([^(]+)(?: \\(([^)]+)\\))?$"); final Matcher matcher = valueWithOptionalParenthesisPattern.matcher(entry); if (matcher.matches()) { id = matcher.group(1); comment = matcher.groupCount() == 2 ? matcher.group(2) : null; } else { id = null; comment = null; } return new VulnerabilityStatusReviewedEntry(id, comment); } public JSONObject toJson() { JSONObject json = new JSONObject(); json.put("id", this.id); if (advisor != null) { json.put("advisor", advisor.getName()); json.put("advisor-implementation", advisor.getImplementation()); } if (comment != null) { json.put("comment", comment); } return json; } public static VulnerabilityStatusReviewedEntry fromMap(Map entry) { final String id = entry.containsKey("id") ? String.valueOf(entry.get("id")) : null; final String comment = entry.containsKey("comment") ? String.valueOf(entry.get("comment")) : null; final Object advisor = ObjectUtils.firstNonNull( entry.get("advisor"), entry.get("cert") ); final Object advisorImplementation = entry.get("advisor-implementation"); final AdvisoryTypeIdentifier advisory; if (advisor == null || StringUtils.isEmpty(String.valueOf(advisor))) { final Optional>> response = AdvisoryTypeStore.get().fromEntryIdentifier(id); if (!response.isPresent()) { LOG.warn("VulnerabilityStatusReviewedEntry: Unable to parse advisor from id [{}]", id); advisory = null; } else { advisory = response.get().getIdentifier(); } } else { advisory = AdvisoryTypeStore.get().fromNameAndImplementation(String.valueOf(advisor), advisorImplementation == null ? null : String.valueOf(advisorImplementation)); } return new VulnerabilityStatusReviewedEntry(id, comment, advisory); } public static List fromJsonArray(JSONArray jsonArray) { List entries = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); entries.add(fromMap(jsonObject.toMap())); } return entries; } public static List fromVulnerabilityMetaData(VulnerabilityMetaData vmd) { if (vmd.has(InventoryAttribute.REVIEWED_ADVISORIES.getKey())) { return fromJsonArray(new JSONArray(vmd.get(InventoryAttribute.REVIEWED_ADVISORIES.getKey()))); } else { return new ArrayList<>(); } } public static List fromVulnerability(Vulnerability vulnerability) { if (vulnerability.getAdditionalAttributes().containsKey(InventoryAttribute.REVIEWED_ADVISORIES.getKey())) { return fromJsonArray(new JSONArray(vulnerability.getAdditionalAttribute(InventoryAttribute.REVIEWED_ADVISORIES.getKey()))); } else { return new ArrayList<>(); } } public static JSONArray toJsonArray(List entries) { return entries.stream() .map(VulnerabilityStatusReviewedEntry::toJson) .collect(CustomCollectors.toJsonArray()); } public static JSONArray toJsonArray(VulnerabilityStatusReviewedEntry... entries) { return toJsonArray(Arrays.asList(entries)); } public static void appendToVulnerabilityMetaData(VulnerabilityMetaData vmd, List entries) { final List parsed = fromVulnerabilityMetaData(vmd); parsed.addAll(entries); vmd.set(InventoryAttribute.REVIEWED_ADVISORIES.getKey(), toJsonArray(parsed).toString()); } public static void appendToVulnerability(Vulnerability vulnerability, List entries) { final List parsed = fromVulnerability(vulnerability); parsed.addAll(entries); vulnerability.setAdditionalAttribute(InventoryAttribute.REVIEWED_ADVISORIES, toJsonArray(parsed).toString()); } public static boolean isReviewedEntry(@NonNull String id, List advisories) { return advisories.stream().anyMatch(a -> id.equals(a.getId())); } public static VulnerabilityStatusReviewedEntry findReviewedEntry(@NonNull String id, List advisories) { return advisories.stream().filter(a -> id.equals(a.getId())).findFirst().orElse(null); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy