Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Analysis model to additionally hold rating overrides #472

Merged
merged 5 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/main/java/org/dependencytrack/model/Analysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import javax.jdo.annotations.Unique;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

/**
Expand Down Expand Up @@ -96,6 +97,41 @@ public class Analysis implements Serializable {
@JsonProperty(value = "isSuppressed")
private boolean suppressed;

@Persistent(defaultFetchGroup = "true")
@Column(name = "SEVERITY")
@JsonProperty(value = "severity")
private Severity severity;

@Persistent
@Column(name = "CVSSV2VECTOR")
@JsonProperty(value = "cvssV2Vector")
private String cvssV2Vector;

@Persistent
@Column(name = "CVSSV2SCORE")
@JsonProperty(value = "cvssV2Score")
private BigDecimal cvssV2Score;

@Persistent
@Column(name = "CVSSV3VECTOR")
@JsonProperty(value = "cvssV3Vector")
private String cvssV3Vector;

@Persistent
@Column(name = "CVSSV3SCORE")
@JsonProperty(value = "cvssV3Score")
private BigDecimal cvssV3Score;

@Persistent
@Column(name = "OWASPVECTOR")
@JsonProperty(value = "owaspVector")
private String owaspVector;

@Persistent
@Column(name = "OWASPSCORE")
@JsonProperty(value = "owaspScore")
private BigDecimal owaspScore;

public long getId() {
return id;
}
Expand Down Expand Up @@ -172,4 +208,60 @@ public boolean isSuppressed() {
public void setSuppressed(boolean suppressed) {
this.suppressed = suppressed;
}

public Severity getSeverity() {
return severity;
}

public void setSeverity(Severity severity) {
this.severity = severity;
}

public String getCvssV2Vector() {
return cvssV2Vector;
}

public void setCvssV2Vector(String cvssV2Vector) {
this.cvssV2Vector = cvssV2Vector;
}

public BigDecimal getCvssV2Score() {
return cvssV2Score;
}

public void setCvssV2Score(BigDecimal cvssV2Score) {
this.cvssV2Score = cvssV2Score;
}

public String getCvssV3Vector() {
return cvssV3Vector;
}

public void setCvssV3Vector(String cvssV3Vector) {
this.cvssV3Vector = cvssV3Vector;
}

public BigDecimal getCvssV3Score() {
return cvssV3Score;
}

public void setCvssV3Score(BigDecimal cvssV3Score) {
this.cvssV3Score = cvssV3Score;
}

public String getOwaspVector() {
return owaspVector;
}

public void setOwaspVector(String owaspVector) {
this.owaspVector = owaspVector;
}

public BigDecimal getOwaspScore() {
return owaspScore;
}

public void setOwaspScore(BigDecimal owaspScore) {
this.owaspScore = owaspScore;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
import org.dependencytrack.model.Component;
import org.dependencytrack.model.Finding;
import org.dependencytrack.model.Project;
import org.dependencytrack.model.RepositoryMetaComponent;
import org.dependencytrack.model.RepositoryType;
import org.dependencytrack.model.Vulnerability;
import org.dependencytrack.model.VulnerabilityAlias;
import org.dependencytrack.model.RepositoryType;
import org.dependencytrack.model.RepositoryMetaComponent;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
Expand All @@ -45,6 +45,7 @@ public class FindingsQueryManager extends QueryManager implements IQueryManager

/**
* Constructs a new QueryManager.
*
* @param pm a PersistenceManager object
*/
FindingsQueryManager(final PersistenceManager pm) {
Expand All @@ -53,7 +54,8 @@ public class FindingsQueryManager extends QueryManager implements IQueryManager

/**
* Constructs a new QueryManager.
* @param pm a PersistenceManager object
*
* @param pm a PersistenceManager object
* @param request an AlpineRequest object
*/
FindingsQueryManager(final PersistenceManager pm, final AlpineRequest request) {
Expand All @@ -64,6 +66,7 @@ public class FindingsQueryManager extends QueryManager implements IQueryManager
* Returns the number of audited findings for the portfolio.
* Findings that are suppressed or have been assigned the states {@link AnalysisState#NOT_SET} or {@link AnalysisState#IN_TRIAGE}
* do not count as audited. Suppressions are tracked separately.
*
* @return the total number of analysis decisions
*/
public long getAuditedCount() {
Expand All @@ -75,6 +78,7 @@ public long getAuditedCount() {
* Returns the number of audited findings for the specified Project.
* Findings that are suppressed or have been assigned the states {@link AnalysisState#NOT_SET} or {@link AnalysisState#IN_TRIAGE}
* do not count as audited. Suppressions are tracked separately.
*
* @param project the Project to retrieve audit counts for
* @return the total number of analysis decisions for the project
*/
Expand All @@ -87,6 +91,7 @@ public long getAuditedCount(Project project) {
* Returns the number of audited findings for the specified Component.
* Findings that are suppressed or have been assigned the states {@link AnalysisState#NOT_SET} or {@link AnalysisState#IN_TRIAGE}
* do not count as audited. Suppressions are tracked separately.
*
* @param component the Component to retrieve audit counts for
* @return the total number of analysis decisions for the component
*/
Expand All @@ -97,7 +102,8 @@ public long getAuditedCount(Component component) {

/**
* Returns the number of audited findings for the specified Project / Component.
* @param project the Project to retrieve audit counts for
*
* @param project the Project to retrieve audit counts for
* @param component the Component to retrieve audit counts for
* @return the total number of analysis decisions for the project / component
*/
Expand All @@ -108,6 +114,7 @@ public long getAuditedCount(Project project, Component component) {

/**
* Returns the number of suppressed vulnerabilities for the portfolio.
*
* @return the total number of suppressed vulnerabilities
*/
public long getSuppressedCount() {
Expand All @@ -117,6 +124,7 @@ public long getSuppressedCount() {

/**
* Returns the number of suppressed vulnerabilities for the specified Project
*
* @param project the Project to retrieve suppressed vulnerabilities of
* @return the total number of suppressed vulnerabilities for the project
*/
Expand All @@ -127,6 +135,7 @@ public long getSuppressedCount(Project project) {

/**
* Returns the number of suppressed vulnerabilities for the specified Component.
*
* @param component the Component to retrieve suppressed vulnerabilities of
* @return the total number of suppressed vulnerabilities for the component
*/
Expand All @@ -137,7 +146,8 @@ public long getSuppressedCount(Component component) {

/**
* Returns the number of suppressed vulnerabilities for the specified Project / Component.
* @param project the Project to retrieve suppressed vulnerabilities of
*
* @param project the Project to retrieve suppressed vulnerabilities of
* @param component the Component to retrieve suppressed vulnerabilities of
* @return the total number of suppressed vulnerabilities for the project / component
*/
Expand All @@ -148,6 +158,7 @@ public long getSuppressedCount(Project project, Component component) {

/**
* Returns a List Analysis for the specified Project.
*
* @param project the Project
* @return a List of Analysis objects, or null if not found
*/
Expand All @@ -159,7 +170,8 @@ List<Analysis> getAnalyses(Project project) {

/**
* Returns a Analysis for the specified Project, Component, and Vulnerability.
* @param component the Component
*
* @param component the Component
* @param vulnerability the Vulnerability
* @return a Analysis object, or null if not found
*/
Expand All @@ -172,7 +184,8 @@ public Analysis getAnalysis(Component component, Vulnerability vulnerability) {
/**
* Documents a new analysis. Creates a new Analysis object if one doesn't already exist and appends
* the specified comment along with a timestamp in the AnalysisComment trail.
* @param component the Component
*
* @param component the Component
* @param vulnerability the Vulnerability
* @return an Analysis object
*/
Expand Down Expand Up @@ -210,10 +223,66 @@ public Analysis makeAnalysis(Component component, Vulnerability vulnerability, A
return getAnalysis(analysis.getComponent(), analysis.getVulnerability());
}

public Analysis makeAnalysis(Component component, Vulnerability vulnerability, Analysis transientAnalysis) {
Analysis analysis = getAnalysis(component, vulnerability);
if (analysis == null) {
analysis = new Analysis();
analysis.setComponent(component);
analysis.setVulnerability(vulnerability);
}

if (transientAnalysis == null) {
analysis = persist(analysis);
return getAnalysis(analysis.getComponent(), analysis.getVulnerability());
}

// In case we're updating an existing analysis, setting any of the fields
// to null will wipe them. That is not the expected behavior when an AnalysisRequest
// has some fields unset (so they're null). If fields are not set, there shouldn't
// be any modifications to the existing data.
analysis.setSuppressed(transientAnalysis.isSuppressed());
if (transientAnalysis.getAnalysisState() != null) {
analysis.setAnalysisState(transientAnalysis.getAnalysisState());
}
if (transientAnalysis.getAnalysisJustification() != null) {
analysis.setAnalysisJustification(transientAnalysis.getAnalysisJustification());
}
if (transientAnalysis.getAnalysisResponse() != null) {
analysis.setAnalysisResponse(transientAnalysis.getAnalysisResponse());
}
if (transientAnalysis.getAnalysisDetails() != null) {
analysis.setAnalysisDetails(transientAnalysis.getAnalysisDetails());
}
if (transientAnalysis.getSeverity() != null) {
analysis.setSeverity(transientAnalysis.getSeverity());
}
if (transientAnalysis.getCvssV2Vector() != null) {
analysis.setCvssV2Vector(transientAnalysis.getCvssV2Vector());
}
if (transientAnalysis.getCvssV2Score() != null) {
analysis.setCvssV2Score(transientAnalysis.getCvssV2Score());
}
if (transientAnalysis.getCvssV3Vector() != null) {
analysis.setCvssV3Vector(transientAnalysis.getCvssV3Vector());
}
if (transientAnalysis.getCvssV3Score() != null) {
analysis.setCvssV3Score(transientAnalysis.getCvssV3Score());
}
if (transientAnalysis.getOwaspVector() != null) {
analysis.setOwaspVector(transientAnalysis.getOwaspVector());
}
if (transientAnalysis.getOwaspScore() != null) {
analysis.setOwaspScore(transientAnalysis.getOwaspScore());
}
analysis = persist(analysis);
return getAnalysis(analysis.getComponent(), analysis.getVulnerability());
}

/**
* Adds a new analysis comment to the specified analysis.
* @param analysis the analysis object to add a comment to
* @param comment the comment to make
*
* @param analysis the analysis object to add a comment to
* @param comment the comment to make
* @param commenter the name of the principal who wrote the comment
* @return a new AnalysisComment object
*/
Expand All @@ -231,6 +300,7 @@ public AnalysisComment makeAnalysisComment(Analysis analysis, String comment, St

/**
* Deleted all analysis and comments associated for the specified Component.
*
* @param component the Component to delete analysis for
*/
void deleteAnalysisTrail(Component component) {
Expand All @@ -240,6 +310,7 @@ void deleteAnalysisTrail(Component component) {

/**
* Deleted all analysis and comments associated for the specified Project.
*
* @param project the Project to delete analysis for
*/
void deleteAnalysisTrail(Project project) {
Expand All @@ -249,6 +320,7 @@ void deleteAnalysisTrail(Project project) {

/**
* Returns a List of Finding objects for the specified project.
*
* @param project the project to retrieve findings for
* @return a List of Finding objects
*/
Expand All @@ -259,7 +331,8 @@ public List<Finding> getFindings(Project project) {

/**
* Returns a List of Finding objects for the specified project.
* @param project the project to retrieve findings for
*
* @param project the project to retrieve findings for
* @param includeSuppressed determines if suppressed vulnerabilities should be included or not
* @return a List of Finding objects
*/
Expand All @@ -269,10 +342,10 @@ public List<Finding> getFindings(Project project, boolean includeSuppressed) {
query.setParameters(project.getId());
final List<Object[]> list = query.executeList();
final List<Finding> findings = new ArrayList<>();
for (final Object[] o: list) {
for (final Object[] o : list) {
final Finding finding = new Finding(project.getUuid(), o);
final Component component = getObjectByUuid(Component.class, (String)finding.getComponent().get("uuid"));
final Vulnerability vulnerability = getObjectByUuid(Vulnerability.class, (String)finding.getVulnerability().get("uuid"));
final Component component = getObjectByUuid(Component.class, (String) finding.getComponent().get("uuid"));
final Vulnerability vulnerability = getObjectByUuid(Vulnerability.class, (String) finding.getVulnerability().get("uuid"));
final Analysis analysis = getAnalysis(component, vulnerability);
final List<VulnerabilityAlias> aliases = detach(getVulnerabilityAliases(vulnerability));
finding.addVulnerabilityAliases(aliases);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,10 @@ public Analysis makeAnalysis(Component component, Vulnerability vulnerability, A
return getFindingsQueryManager().makeAnalysis(component, vulnerability, analysisState, analysisJustification, analysisResponse, analysisDetails, isSuppressed);
}

public Analysis makeAnalysis(Component component, Vulnerability vulnerability, Analysis analysis) {
return getFindingsQueryManager().makeAnalysis(component, vulnerability, analysis);
}

public AnalysisComment makeAnalysisComment(Analysis analysis, String comment, String commenter) {
return getFindingsQueryManager().makeAnalysisComment(analysis, comment, commenter);
}
Expand Down Expand Up @@ -1918,7 +1922,7 @@ public ComponentMetaInformation getMetaInformation(UUID uuid) {
if (resultSet.getString("INTEGRITY_CHECK_STATUS") != null) {
integrityMatchStatus = IntegrityMatchStatus.valueOf(resultSet.getString("INTEGRITY_CHECK_STATUS"));
}
if(resultSet.getString("REPOSITORY_URL") != null) {
if (resultSet.getString("REPOSITORY_URL") != null) {
integrityRepoUrl = String.valueOf(resultSet.getString("REPOSITORY_URL"));
}
return new ComponentMetaInformation(publishedDate, integrityMatchStatus, lastFetch, integrityRepoUrl);
Expand Down
14 changes: 14 additions & 0 deletions src/main/resources/migration/changelog-v5.3.0.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2353,4 +2353,18 @@
<column name="NAME"/>
</createIndex>
</changeSet>
<changeSet id="v5.3.0-6" author="sahibamittal">
<preConditions onFail="MARK_RAN">
<tableExists tableName="ANALYSIS"/>
</preConditions>
<addColumn tableName="ANALYSIS">
<column name="CVSSV2VECTOR" type="VARCHAR(255)"/>
<column name="CVSSV3SCORE" type="numeric"/>
<column name="OWASPSCORE" type="numeric"/>
<column name="CVSSV2SCORE" type="numeric"/>
<column name="OWASPVECTOR" type="VARCHAR(255)"/>
<column name="CVSSV3VECTOR" type="VARCHAR(255)"/>
<column name="SEVERITY" type="VARCHAR(255)"/>
</addColumn>
</changeSet>
</databaseChangeLog>
Loading