Skip to content

Commit

Permalink
updated for #2753
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremylong committed Aug 29, 2020
1 parent e175308 commit 8a3f952
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* This file is part of dependency-check-core.
*
* 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.
*
* Copyright (c) 2020 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update.cpe;

import com.google.common.base.Strings;
import java.util.HashMap;
import java.util.Map;
import org.owasp.dependencycheck.data.update.nvd.NvdCveParser;
import org.owasp.dependencycheck.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* @author Jeremy Long
*/
public final class CpeEcosystemCache {

private final static String MULTIPLE_ECOSYSTEMS_IDENTIFIED = "MULTIPLE";
private static Map<Pair<String, String>, String> cache = new HashMap<>();
private static Map<Pair<String, String>, String> changed = new HashMap<>();

private CpeEcosystemCache() {
//empty constructor for utiilty class
}
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(NvdCveParser.class);

public static synchronized String getEcosystem(String vendor, String product, String identifiedEcosystem) {
Pair<String, String> key = new Pair<>(vendor, product);
String current = cache.get(key);
String result = null;
if (current == null) {
if (!Strings.isNullOrEmpty(identifiedEcosystem)) {
cache.put(key, identifiedEcosystem);
changed.put(key, identifiedEcosystem);
result = identifiedEcosystem;
}
} else if (MULTIPLE_ECOSYSTEMS_IDENTIFIED.equals(current)) {
//do nothing - result is already null
} else if (current.equals(identifiedEcosystem) || identifiedEcosystem == null) {
result = current;
} else {
cache.put(key, MULTIPLE_ECOSYSTEMS_IDENTIFIED);
changed.put(key, MULTIPLE_ECOSYSTEMS_IDENTIFIED);
}
return result;
}

public static synchronized void setCache(Map<Pair<String, String>, String> cache) {
CpeEcosystemCache.cache = cache;
CpeEcosystemCache.changed = new HashMap<>();
}

public static synchronized Map<Pair<String, String>, String> getChanged() {
return CpeEcosystemCache.changed;
}

public static synchronized boolean isEmpty() {
return CpeEcosystemCache.cache.isEmpty();
}
}
9 changes: 5 additions & 4 deletions core/src/main/resources/data/dbStatements_mariadb.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

MERGE_PROPERTY=CALL save_property(?, ?)
CLEANUP_ORPHANS=call cleanup_orphans()
UPDATE_ECOSYSTEM=call update_ecosystems()
UPDATE_ECOSYSTEM2=call update_ecosystems2()
MERGE_PROPERTY=CALL save_property(?, ?);
CLEANUP_ORPHANS=call cleanup_orphans();
UPDATE_ECOSYSTEM=call update_ecosystems();
UPDATE_ECOSYSTEM2=call update_ecosystems2();
MERGE_CPE_ECOSYSTEM=call merge_ecosystem(?, ?, ?);
9 changes: 5 additions & 4 deletions core/src/main/resources/data/dbStatements_mysql.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

MERGE_PROPERTY=CALL save_property(?, ?)
CLEANUP_ORPHANS=call cleanup_orphans()
UPDATE_ECOSYSTEM=call update_ecosystems()
UPDATE_ECOSYSTEM2=call update_ecosystems2()
MERGE_PROPERTY=CALL save_property(?, ?);
CLEANUP_ORPHANS=call cleanup_orphans();
UPDATE_ECOSYSTEM=call update_ecosystems();
UPDATE_ECOSYSTEM2=call update_ecosystems2();
MERGE_CPE_ECOSYSTEM=call merge_ecosystem(?, ?, ?);
79 changes: 46 additions & 33 deletions core/src/main/resources/data/initialize_mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#DROP database dependencycheck;

#CREATE database dependencycheck;

USE dependencycheck;

DROP PROCEDURE IF EXISTS dependencycheck.save_property;
Expand All @@ -11,12 +12,14 @@ DROP PROCEDURE IF EXISTS dependencycheck.update_ecosystems2;
DROP PROCEDURE IF EXISTS dependencycheck.cleanup_orphans;
DROP PROCEDURE IF EXISTS dependencycheck.update_vulnerability;
DROP PROCEDURE IF EXISTS dependencycheck.insert_software;
DROP PROCEDURE IF EXISTS dependencycheck.merge_ecosystem;
DROP TABLE IF EXISTS software;
DROP TABLE IF EXISTS cpeEntry;
DROP TABLE IF EXISTS `reference`;
DROP TABLE IF EXISTS properties;
DROP TABLE IF EXISTS cweEntry;
DROP TABLE IF EXISTS vulnerability;
DROP TABLE IF EXISTS cpeEcosystemCache;

CREATE TABLE vulnerability (id int auto_increment PRIMARY KEY, cve VARCHAR(20) UNIQUE,
description VARCHAR(8000), v2Severity VARCHAR(20), v2ExploitabilityScore DECIMAL(3,1),
Expand Down Expand Up @@ -45,6 +48,9 @@ CREATE TABLE software (cveid INT, cpeEntryId INT, versionEndExcluding VARCHAR(50
CREATE TABLE cweEntry (cveid INT, cwe VARCHAR(20),
CONSTRAINT fkCweEntry FOREIGN KEY (cveid) REFERENCES vulnerability(id) ON DELETE CASCADE);

CREATE TABLE cpeEcosystemCache (vendor VARCHAR(255), product VARCHAR(255), ecosystem VARCHAR(255), PRIMARY KEY (vendor, product));
INSERT INTO cpeEcosystemCache (vendor, product, ecosystem) VALUES ('apache', 'zookeeper', 'MULTIPLE');

CREATE INDEX idxCwe ON cweEntry(cveid);
CREATE INDEX idxVulnerability ON vulnerability(cve);
CREATE INDEX idxReference ON `reference`(cveid);
Expand All @@ -69,45 +75,17 @@ DELIMITER ;

GRANT EXECUTE ON PROCEDURE dependencycheck.save_property TO 'dcuser';

DELIMITER //
CREATE PROCEDURE update_ecosystems()
BEGIN
SET @OLD_SQL_SAFE_UPDATES = (SELECT @@SQL_SAFE_UPDATES);
SET SQL_SAFE_UPDATES = 0;
UPDATE cpeEntry n INNER JOIN
(SELECT DISTINCT vendor, product, MIN(ecosystem) eco
FROM cpeEntry
WHERE ecosystem IS NOT NULL
GROUP BY vendor , product) e
ON e.vendor = n.vendor
AND e.product = n.product
SET n.ecosystem = e.eco
WHERE n.ecosystem IS NULL;
SET SQL_SAFE_UPDATES = @OLD_SQL_SAFE_UPDATES;
END //
DELIMITER ;

GRANT EXECUTE ON PROCEDURE dependencycheck.update_ecosystems TO 'dcuser';

DELIMITER //
CREATE PROCEDURE update_ecosystems2()
CREATE PROCEDURE merge_ecosystem
(IN p_vendor VARCHAR(255), IN p_product VARCHAR(255), IN p_ecosystem varchar(255))
BEGIN
SET @OLD_SQL_SAFE_UPDATES = (SELECT @@SQL_SAFE_UPDATES);
SET SQL_SAFE_UPDATES = 0;
UPDATE cpeEntry e SET e.ecosystem = NULL
WHERE e.id IN (SELECT * FROM
(SELECT DISTINCT entry.id FROM vulnerability v
INNER JOIN software s ON v.id = s.cveid
INNER JOIN cpeEntry r ON s.cpeentryid=r.id
INNER JOIN cpeEntry entry ON r.part = entry.part AND r.vendor = entry.vendor AND r.product = entry.product
WHERE description like '%bindings%' AND r.ecosystem is not null AND entry.ecosystem is not null
UNION ALL
SELECT z.id FROM cpeEntry z WHERE z.ecosystem is not null AND z.vendor = 'apache' AND z.product = 'zookeeper') x);
SET SQL_SAFE_UPDATES = @OLD_SQL_SAFE_UPDATES;
INSERT INTO cpeEcosystemCache (`vendor`, `product`, `ecosystem`) VALUES (p_vendor, p_product, p_ecosystem)
ON DUPLICATE KEY UPDATE `ecosystem`=p_ecosystem;
END //
DELIMITER ;

GRANT EXECUTE ON PROCEDURE dependencycheck.update_ecosystems2 TO 'dcuser';
GRANT EXECUTE ON PROCEDURE dependencycheck.merge_ecosystem TO 'dcuser';

DELIMITER //
CREATE PROCEDURE cleanup_orphans()
Expand Down Expand Up @@ -242,4 +220,39 @@ DELIMITER ;

GRANT EXECUTE ON PROCEDURE dependencycheck.insert_software TO 'dcuser';

DELIMITER //
CREATE PROCEDURE update_ecosystems()
BEGIN
SET @OLD_SQL_SAFE_UPDATES = (SELECT @@SQL_SAFE_UPDATES);
SET SQL_SAFE_UPDATES = 0;
UPDATE cpeEntry e INNER JOIN cpeEcosystemCache c
ON c.vendor=e.vendor
AND c.product=e.product
SET e.ecosystem=c.ecosystem
WHERE e.ecosystem IS NULL AND c.ecosystem<>'MULTIPLE';

SET SQL_SAFE_UPDATES = @OLD_SQL_SAFE_UPDATES;
END //
DELIMITER ;

GRANT EXECUTE ON PROCEDURE dependencycheck.update_ecosystems TO 'dcuser';

DELIMITER //
CREATE PROCEDURE update_ecosystems2()
BEGIN
SET @OLD_SQL_SAFE_UPDATES = (SELECT @@SQL_SAFE_UPDATES);
SET SQL_SAFE_UPDATES = 0;
UPDATE cpeEntry e INNER JOIN cpeEcosystemCache c
ON c.vendor=e.vendor
AND c.product=e.product
SET e.ecosystem=null
WHERE c.ecosystem='MULTIPLE'
AND e.ecosystem IS NOT NULL;

SET SQL_SAFE_UPDATES = @OLD_SQL_SAFE_UPDATES;
END //
DELIMITER ;

GRANT EXECUTE ON PROCEDURE dependencycheck.update_ecosystems2 TO 'dcuser';

INSERT INTO properties(id, value) VALUES ('version', '5.0');
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* This file is part of dependency-check-core.
*
* 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.
*
* Copyright (c) 2020 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update.cpe;

import java.util.HashMap;
import java.util.Map;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.utils.Pair;

/**
*
* @author Jeremy Long
*/
public class CpeEcosystemCacheTest {

@Before
public void setUp() {

}

@After
public void tearDown() {
}

/**
* Test of getEcosystem method, of class CpeEcosystemCache.
*/
@Test
public void testGetEcosystem() {
Pair<String, String> key = new Pair<>("apache", "zookeeper");
Map<Pair<String, String>, String> map = new HashMap<>();
map.put(key, "java");
CpeEcosystemCache.setCache(map);

String expected = "java";
String result = CpeEcosystemCache.getEcosystem("apache", "zookeeper", null);
assertEquals(expected, result);

expected = "MULTIPLE";
result = CpeEcosystemCache.getEcosystem("apache", "zookeeper", "c++");
assertEquals(expected, result);

result = CpeEcosystemCache.getEcosystem("pivotal", "spring-framework", null);
assertNull(result);

expected = "java";
result = CpeEcosystemCache.getEcosystem("pivotal", "spring-framework", "java");
assertEquals(expected, result);

expected = "java";
result = CpeEcosystemCache.getEcosystem("pivotal", "spring-framework", "java");
assertEquals(expected, result);

result = CpeEcosystemCache.getEcosystem("microsoft", "word", null );
assertNull(result);

result = CpeEcosystemCache.getEcosystem("microsoft", "word", null );
assertNull(result);

result = CpeEcosystemCache.getEcosystem("microsoft", "word", "" );
assertNull(result);
}

/**
* Test of setCache method, of class CpeEcosystemCache.
*/
@Test
public void testSetCache() {
Map<Pair<String, String>, String> map = new HashMap<>();
CpeEcosystemCache.setCache(map);
assertTrue(CpeEcosystemCache.isEmpty());

map = new HashMap<>();
Pair<String, String> key = new Pair<>("apache", "zookeeper");
map.put(key, "java");
CpeEcosystemCache.setCache(map);

assertFalse(CpeEcosystemCache.isEmpty());
}

/**
* Test of getChanged method, of class CpeEcosystemCache.
*/
@Test
public void testGetChanged() {
Pair<String, String> key = new Pair<>("apache", "zookeeper");
Map<Pair<String, String>, String> map = new HashMap<>();
map.put(key, "java");
CpeEcosystemCache.setCache(map);

Map<Pair<String, String>, String> result = CpeEcosystemCache.getChanged();
assertTrue(result.isEmpty());

CpeEcosystemCache.getEcosystem("apache", "zookeeper", "java");

result = CpeEcosystemCache.getChanged();
assertTrue(result.isEmpty());

CpeEcosystemCache.getEcosystem("apache", "zookeeper", null);

result = CpeEcosystemCache.getChanged();
assertTrue(result.isEmpty());

CpeEcosystemCache.getEcosystem("apache", "zookeeper", "c++");

result = CpeEcosystemCache.getChanged();
assertFalse(result.isEmpty());
}

/**
* Test of isEmpty method, of class CpeEcosystemCache.
*/
@Test
public void testIsEmpty() {
Map<Pair<String, String>, String> map = new HashMap<>();
CpeEcosystemCache.setCache(map);
boolean expResult = true;
boolean result = CpeEcosystemCache.isEmpty();
assertEquals(expResult, result);
map.put(new Pair<String, String>("apache", "zookeeper"), "MULTPILE");
expResult = false;
result = CpeEcosystemCache.isEmpty();
assertEquals(expResult, result);
}

}

0 comments on commit 8a3f952

Please # to comment.