-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from MSUSEL/ryan-nvd-and-ghsa-clients
Remove python port and replace with java-native data access
- Loading branch information
Showing
155 changed files
with
2,187 additions
and
520,481 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#!/bin/sh | ||
|
||
|
||
# Copyright 2024 Montana State University Software Engineering and Cybersecurity Laboratory | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining | ||
# a copy of this software and associated documentation files (the “Software”), | ||
# to deal in the Software without restriction, including without limitation | ||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
# and/or sell copies of the Software, and to permit persons to whom the Software | ||
# is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included | ||
# in all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, | ||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
# OTHER DEALINGS IN THE SOFTWARE. | ||
|
||
######################################################################## | ||
# Prepares Environment For PIQUE-Cloud and runs PIQUE on sample targets | ||
######################################################################## | ||
|
||
WORKDIR="$PWD" | ||
INPUT_MESSAGE="##############################################\n# INPUT NEEDED \n##############################################" | ||
PROGNAME=" | ||
██████╗ ██╗ ██████╗ ██╗ ██╗███████╗ | ||
██╔══██╗██║██╔═══██╗██║ ██║██╔════╝ | ||
██████╔╝██║██║ ██║██║ ██║█████╗ | ||
██╔═══╝ ██║██║▄▄ ██║██║ ██║██╔══╝ | ||
██║ ██║╚██████╔╝╚██████╔╝███████╗ | ||
╚═╝ ╚═╝ ╚══▀▀═╝ ╚═════╝ ╚══════╝ | ||
██████╗██╗ ██████╗ ██╗ ██╗██████╗ | ||
██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗ | ||
██║ ██║ ██║ ██║██║ ██║██║ ██║ | ||
██║ ██║ ██║ ██║██║ ██║██║ ██║ | ||
╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝ | ||
╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ | ||
------------------------------------------------------------------------ | ||
" | ||
printBanner() { | ||
COLUMNS=$(tput cols) | ||
# shellcheck disable=SC2002 | ||
if [ -f msu_logo_ascii.txt ] && [ -x /bin/perl ] && [ "$COLUMNS" -gt 100 ]; then | ||
cat msu_logo_ascii.txt | perl -pe 'select undef,undef,undef,.01555' | ||
printf "$PROGNAME" | perl -pe 'select undef,undef,undef,.01555' | ||
echo " " | perl -pe 'select undef,undef,undef,0.20000' | ||
else | ||
printf "$PROGNAME" | ||
fi | ||
} | ||
|
||
# Dependency Checks | ||
check_deps() { | ||
# Check that wget is installed | ||
printf "Checking dependencies...\n" | ||
[ -x "$(which wget)" ] || { printf "\u001b[31mERROR: wget is not installed. Please install wget on your system or perform manual installation of PIQUE-Cloud\nexit 1\n\u001b[0m"; exit 1; } | ||
printf "\twget is installed\n" | ||
|
||
# Check that docker is installed and user is logged in | ||
[ -x "$(which docker)" ] || { printf "\u001b[31mPlease ensure that docker is installed, running, and configured with your username and login.\u001b[0m\nexit 1\n"; exit 1; } | ||
printf "\tdocker is installed\n" | ||
|
||
# Check git is installed | ||
git --version >/dev/null 2>&1 || { printf "\u001b[31mgit is not installed. Please install git on your system to continue PIQUE-Cloud setup\u001b[0m\nexit 1\n"; exit 1; } | ||
printf "\tgit is installed\n" | ||
printf "\u001b[32mDependency check completed successfully\n\n\u001b[0m" | ||
} | ||
|
||
# Check for/create input, output, and subdirectories | ||
set_up_directories() { | ||
printf "Checking directory structure...\n" | ||
[ -d "$WORKDIR/input/keys" ] || { mkdir -p "$WORKDIR/input/keys"; } | ||
[ -d "$WORKDIR/output/" ] || { mkdir -p "$WORKDIR/output"; } | ||
printf "\u001b[32mDirectory check/setup complete\n\n\u001b[0m" | ||
} | ||
|
||
# Checks for existing keys. If they don't exist, prompt user to create them and paste into prompts | ||
get_authentication_keys() { | ||
printf "Checking authentication keys...\n" | ||
|
||
NVD_KEY_PATH="$WORKDIR/input/keys/nvd-api-key.txt" | ||
GITHUB_TOKEN_PATH="$WORKDIR/input/keys/github-token.txt" | ||
|
||
# Check if keys already exist and provide option to paste in keys | ||
# Future Work: Key validation | ||
[ -f "$NVD_KEY_PATH" ] || { printf "$INPUT_MESSAGE\n"; \ | ||
printf "\u001b[33mThis step asks you to paste an api key into the terminal. If you are concened about having a secure key in your clipboard or shell history,\n"; \ | ||
printf "type the letter 'n' in the prompt. The script will exit and you can manually generate WORKDIR/input/keys/nvd-api-key.txt. Then, rerun this script.\u001b[0m\n"; \ | ||
printf "Please generate an API key with the National Vulnerability Database here:\u001b[36m https://nvd.nist.gov/developers/request-an-api-key\u001b[0m\n"; \ | ||
printf "Be sure to save it somewhere secure. If you lose the key, you will need to generate a new one.\n\n"; \ | ||
printf "Once you have retrieved your key, enter it here: "; \ | ||
read nvd_key; \ | ||
[ "$nvd_key" = "n" ] && exit 1 || echo "$nvd_key" > $NVD_KEY_PATH; } | ||
printf "\tNVD Key setup complete\n" | ||
|
||
# Future Work: Key validation | ||
[ -f "$GITHUB_TOKEN_PATH" ] || { printf "$INPUT_MESSAGE\n"; \ | ||
printf "\u001b[33mThis step asks you to paste a personal access token into the terminal. If you are concened about having a secure key in your clipboard or shell \n"; \ | ||
printf "history, type the letter 'n' in the prompt. The script will exit and you can manually generate WORKDIR/input/keys/github-token.txt Then, rerun this script.\u001b[0m\n"; \ | ||
printf "Please generate a Github personal access token with ......permissions. More info:\u001b[36m https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\u001b[0m\n\n"; \ | ||
printf "Once you have generated or retrieved your token, paste it here: "; \ | ||
read -r github_key; \ | ||
[ "$github_key" = "n" ] && exit 1 || echo "$github_key" > "$GITHUB_TOKEN_PATH"; } | ||
printf "\tGithub token setup complete\n" | ||
printf "\u001b[32mAuthentication setup complete\u001b[0m\n\n" | ||
} | ||
|
||
run() { | ||
printBanner | ||
check_deps | ||
set_up_directories | ||
get_authentication_keys | ||
|
||
# docker run -it --rm -v "/var/run/docker.sock:/var/run/docker.sock:rw" -v "$WORKDIR"/input:/input -v "$WORKDIR"/output:/output msusel/pique-sbom-supply-chain-sec:latest | ||
docker-compose -f "$WORKDIR/src/main/java/data/nvdMirror/docker-compose.yml" up --detach | ||
} | ||
run | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package data; | ||
|
||
import data.baseClasses.BaseRequest; | ||
import data.handlers.SecurityAdvisoryMarshaller; | ||
import data.handlers.JsonResponseHandler; | ||
import org.apache.http.client.methods.CloseableHttpResponse; | ||
import org.apache.http.client.methods.HttpPost; | ||
import org.apache.http.client.utils.URIBuilder; | ||
import org.apache.http.entity.StringEntity; | ||
import org.apache.http.impl.client.CloseableHttpClient; | ||
import org.apache.http.impl.client.HttpClients; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.IOException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
|
||
public class GHSARequest extends BaseRequest { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(GHSARequest.class); | ||
private final JsonResponseHandler handler = new JsonResponseHandler(); | ||
private final String query; | ||
|
||
public GHSARequest(String httpMethod, String baseURI, List<String> headers, String query) { | ||
super(httpMethod, baseURI, headers); | ||
this.query = query; | ||
} | ||
|
||
@Override | ||
public GHSAResponse executeRequest() { | ||
return executeGHSARequest(); | ||
} | ||
|
||
private GHSAResponse executeGHSARequest() { | ||
URI uri; | ||
GHSAResponse ghsaResponse = new GHSAResponse(); | ||
SecurityAdvisoryMarshaller securityAdvisoryMarshaler = new SecurityAdvisoryMarshaller(); | ||
|
||
try { | ||
uri = new URIBuilder(baseURI).build(); | ||
} catch (URISyntaxException e) { | ||
LOGGER.error("Could not build URI with given inputs", e); | ||
throw new RuntimeException(e); | ||
} | ||
|
||
HttpPost request = new HttpPost(); | ||
request.setURI(uri); | ||
request.setHeaders(Utils.resolveHeaders(headers)); | ||
request.setEntity(new StringEntity(query, StandardCharsets.UTF_8)); | ||
|
||
try (CloseableHttpClient client = HttpClients.createDefault(); | ||
CloseableHttpResponse response = client.execute(request)) { | ||
|
||
int status = response.getStatusLine().getStatusCode(); | ||
if (status >= 200 && status < 300) { | ||
String json = handler.handleResponse(response); | ||
ghsaResponse.setSecurityAdvisory(securityAdvisoryMarshaler.unmarshallJson(json)); | ||
ghsaResponse.setStatus(status); | ||
} else { | ||
LOGGER.info("Response Status: {}", status); | ||
throw new IOException("Failed to execute request: " + response.getStatusLine()); | ||
} | ||
} catch ( IOException e) { | ||
LOGGER.info("Request failed", e); | ||
throw new RuntimeException(e); | ||
} | ||
|
||
return ghsaResponse; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package data; | ||
|
||
import data.baseClasses.BaseResponse; | ||
import data.ghsaData.SecurityAdvisory; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
public class GHSAResponse extends BaseResponse { | ||
private SecurityAdvisory securityAdvisory; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package data; | ||
|
||
public class GraphQlQueries { | ||
public static final String GHSA_SECURITY_ADVISORY_QUERY = "query { securityAdvisory(ghsaId: \"%s\") { ghsaId summary cwes(first : 1) { nodes { cweId } } } }"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package data; | ||
|
||
import com.mongodb.MongoClientException; | ||
import com.mongodb.MongoClientSettings; | ||
import com.mongodb.MongoCredential; | ||
import com.mongodb.ServerAddress; | ||
import com.mongodb.client.MongoClient; | ||
import com.mongodb.client.MongoClients; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import utilities.helperFunctions; | ||
|
||
import java.io.IOException; | ||
import java.util.*; | ||
|
||
/** | ||
* Creates and manages a Singleton Mongo Connection | ||
*/ | ||
public class MongoConnection { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoConnection.class); | ||
private static volatile MongoClient mongoClient = null; | ||
|
||
private MongoConnection() {} | ||
|
||
/** | ||
* Builds a MongoClient instance if one does not already exist. | ||
* This uses the MongoClient class to manage the connection pool. | ||
* | ||
* @return existing MongoClient or a new one if one does not already exist | ||
*/ | ||
public static MongoClient getInstance() { | ||
if (mongoClient == null) { | ||
synchronized (MongoClient.class) { | ||
if (mongoClient == null) { | ||
mongoClient = MongoClients.create("mongodb://localhost:27017"); | ||
} | ||
} | ||
} | ||
return mongoClient; | ||
} | ||
|
||
// public static MongoClient getInstance() { | ||
// String username, password, port, hostname, dbname; | ||
// Map<String, String> credentials; | ||
// | ||
// try { | ||
// credentials = helperFunctions.getMongoCredentials(); | ||
// } catch (IOException e) { | ||
// LOGGER.error("Could not read credentials file", e); | ||
// throw new RuntimeException(e); | ||
// } | ||
// | ||
// username = credentials.get("username"); | ||
// password = credentials.get("password"); | ||
// hostname = credentials.get("hostname"); | ||
// port = credentials.get("port"); | ||
// dbname = credentials.get("dbname"); | ||
// | ||
// if (mongoClient == null) { | ||
// synchronized (MongoClient.class) { | ||
// if (mongoClient == null) { | ||
// MongoCredential credential = MongoCredential.createCredential(username, dbname, password.toCharArray()); | ||
// try { | ||
// mongoClient = MongoClients.create( | ||
// MongoClientSettings.builder() | ||
// .applyToClusterSettings(builder -> | ||
// builder.hosts(Arrays.asList(new ServerAddress(hostname, Integer.parseInt(port))))) | ||
// .credential(credential) | ||
// .build()); | ||
// } catch (MongoClientException e) { | ||
// LOGGER.error(String.format("Could not connect to Mongo database: {%s}.", dbname), e); | ||
// throw new RuntimeException(e); | ||
// } | ||
// } | ||
// } | ||
// } | ||
// | ||
// return mongoClient; | ||
// } | ||
} |
Oops, something went wrong.