diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/VulnerabilitiesFromGitHubAdvisories.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/VulnerabilitiesFromGitHubAdvisories.java new file mode 100644 index 000000000..3a31bf8d7 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/VulnerabilitiesFromGitHubAdvisories.java @@ -0,0 +1,169 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental; + +import static com.sap.sgs.phosphor.fosstars.model.other.Utils.date; +import static com.sap.sgs.phosphor.fosstars.model.value.Vulnerability.UNKNOWN_INTRODUCED_DATE; + +import com.sap.sgs.phosphor.fosstars.data.github.CachedSingleFeatureGitHubDataProvider; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.GitHubAdvisories; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.Advisory; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.AdvisoryReference; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.Node; +import com.sap.sgs.phosphor.fosstars.model.Feature; +import com.sap.sgs.phosphor.fosstars.model.Value; +import com.sap.sgs.phosphor.fosstars.model.feature.oss.VulnerabilitiesInProject; +import com.sap.sgs.phosphor.fosstars.model.value.CVSS; +import com.sap.sgs.phosphor.fosstars.model.value.PackageManager; +import com.sap.sgs.phosphor.fosstars.model.value.Reference; +import com.sap.sgs.phosphor.fosstars.model.value.Vulnerabilities; +import com.sap.sgs.phosphor.fosstars.model.value.Vulnerability; +import com.sap.sgs.phosphor.fosstars.model.value.Vulnerability.Resolution; +import com.sap.sgs.phosphor.fosstars.tool.github.GitHubProject; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.kohsuke.github.GHContent; +import org.kohsuke.github.GHFileNotFoundException; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GitHub; + +/** + * This data provider looks for vulnerabilities in {@link GitHubAdvisories} which are not present in + * {@link NVD}. + */ +public class VulnerabilitiesFromGitHubAdvisories extends CachedSingleFeatureGitHubDataProvider { + + /** + * A feature that holds info about vulnerabilities in the GitHub Advisory Database. + */ + public static final Feature VULNERABILITIES_IN_ADVISORIES = + new VulnerabilitiesInProject(); + + /** + * An interface to the GitHub Advisory database. + */ + private final GitHubAdvisories gitHubAdvisories; + + /** + * Initializes a data provider. + * + * @param github An interface to the GitHub API. + * @param gitHubToken The token to access GitHub API. + */ + public VulnerabilitiesFromGitHubAdvisories(GitHub github, String gitHubToken) { + super(github); + this.gitHubAdvisories = new GitHubAdvisories(gitHubToken); + } + + @Override + protected Feature supportedFeature() { + return VULNERABILITIES_IN_ADVISORIES; + } + + @Override + protected Value fetchValueFor(GitHubProject project) throws IOException { + logger.info("Looking for vulnerabilities from GitHub Advisory ..."); + + Vulnerabilities vulnerabilities = new Vulnerabilities(); + // TODO: Make this method recursively loop and gather all config files present in the project + // and gather the identifiers to pull all possible advisories for the project. More information + // can be found here https://github.com/SAP/fosstars-rating-core/issues/144 + Optional artifact = artifactFor(gitHubDataFetcher().repositoryFor(project, github)); + + if (artifact.isPresent()) { + for (Node node : gitHubAdvisories.advisoriesFor(PackageManager.MAVEN, artifact.get())) { + vulnerabilities.add(vulnerabilityFrom(node)); + } + } + return VULNERABILITIES_IN_ADVISORIES.value(vulnerabilities); + } + + /** + * Gathers groupId:artifactId identifier from the GitHub repository. + * + * @param repository The project's repository. + * @return The artifact identifier. + * @throws IOException if something goes wrong. + */ + private Optional artifactFor(GHRepository repository) throws IOException { + GHContent content; + try { + content = repository.getFileContent("pom.xml"); + } catch (GHFileNotFoundException e) { + logger.warn("Could not find pom.xml!"); + return Optional.empty(); + } + + Model model = readModel(content); + + String groupId = + model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId(); + String artifactId = model.getArtifactId(); + + return Optional.ofNullable(String.format("%s:%s", groupId, artifactId)); + } + + /** + * Parses a pom.xml file. + * + * @param content The content of the pom.xml file. + * @return A {@link Model} which represents the pom.xml file. + * @throws IOException If something went wrong. + */ + private static Model readModel(GHContent content) throws IOException { + try (InputStream is = content.read()) { + try { + return new MavenXpp3Reader().read(is); + } catch (XmlPullParserException e) { + throw new IOException(e); + } + } + } + + /** + * Convert List of {@link AdvisoryReference} to List of {@link Reference}. + * + * @param references List of type {@link AdvisoryReference}. + * @return List of {@link Reference}. + */ + private List referencesFrom(List references) { + List referenceList = new ArrayList<>(); + for (AdvisoryReference r : references) { + try { + referenceList.add(new Reference(null, new URL(r.getUrl()))); + } catch (MalformedURLException e) { + System.out.println("Could not parse a URL from a reference in NVD"); + } + } + return referenceList; + } + + /** + * Converts an {@link Node} to a {@link Vulnerability}. + * + * @param entry The {@link Node} to be converted. + * @return An instance of {@link Vulnerability}. + */ + private Vulnerability vulnerabilityFrom(Node node) { + Advisory advisory = node.getAdvisory(); + + String id = advisory.getGhsaId(); + String description = advisory.getDescription(); + CVSS cvss = CVSS.UNKNOWN; + List references = referencesFrom(advisory.getReferences()); + + Resolution resolution = + node.getFirstPatchedVersion() != null ? Resolution.PATCHED : Resolution.UNPATCHED; + + Date fixed = date(advisory.getPublishedAt()); + return new Vulnerability(id, description, cvss, references, resolution, UNKNOWN_INTRODUCED_DATE, + fixed); + } +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/GitHubAdvisories.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/GitHubAdvisories.java new file mode 100644 index 000000000..d029a6a15 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/GitHubAdvisories.java @@ -0,0 +1,247 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.Advisory; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.GitHubAdvisoryEntry; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.Identifier; +import com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data.Node; +import com.sap.sgs.phosphor.fosstars.model.value.PackageManager; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpHeaders; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; + +/** + * This class offers an interface to GitHub security advisories using GrahhQL APIs exposed by + * GitHub. + * + * @see GitHub + * Security Advisory + */ +public class GitHubAdvisories { + + /** + * An template used to query for Security Advisories. This is the template to use for the first + * run. + */ + private static final String GRAPHQL_FIRST_RUN_TEMPLATE = "first_run_template"; + + /** + * An template used to query for Security Advisories. This is the template to be used for page + * traversing. + */ + private static final String GRAPHQL_NEXT_PAGE_RUN_TEMPLATE = "next_page_run_template"; + + /** + * First n advisories per page. + */ + private static final int FIRST_N_ADVISORIES = 100; + + /** + * An {@link ObjectMapper} for serialization and deserialization. + */ + private static final ObjectMapper MAPPER = new ObjectMapper(); + + /** + * The token to access GitHub API. + */ + private final String gitHubToken; + + /** + * Initializes a data provider. + * + * @param gitHubToken GitHub Token. + */ + public GitHubAdvisories(String gitHubToken) { + this.gitHubToken = Objects.requireNonNull(gitHubToken, "The GitHub token cannot be null!"); + } + + /** + * Get the all the advisories for the given artifact and the package manager which are not present + * in NVD database. This is done by checking if the advisory has a CVE associated to it. + * + * @param ecosystem The GitHub project package management used. + * @param artifact The artifact identifier for the GitHub project (E.g MAVEN for Java, NPM for + * JavaScript packages). + * @return List of type {@link Node}. Each {@link Node} is an {@link Advisory}. + * @throws IOException if something goes wrong. + */ + public List advisoriesFor(PackageManager ecosystem, String artifact) throws IOException { + List advisories = new ArrayList<>(); + for (Node node : download(ecosystem.name(), artifact)) { + // TODO: This check needs to be removed to allow it to gather all possible advisories from the + // Security Advisory Database https://github.com/SAP/fosstars-rating-core/issues/143 + if (!hasCve(node.getAdvisory())) { + advisories.add(node); + } + } + + return Collections.unmodifiableList(advisories); + } + + /** + * Downloads the advisories related to the input parameters from GitHub Security Advisory + * Database. + * + * @param ecosystem The GitHub project package management used. + * @param artifact The artifact identifier for the GitHub project (E.g MAVEN for Java, NPM for + * JavaScript packages). + * @return List of type {@link Node}. Each {@link Node} is an {@link Advisory}. + * @throws IOException if something goes wrong. + */ + private List download(String ecosystem, String artifact) throws IOException { + List advisories = new ArrayList<>(); + + String jsonEntity = String.format("{\"query\" : \"%s\"}", + String.format(load(GRAPHQL_FIRST_RUN_TEMPLATE), FIRST_N_ADVISORIES, ecosystem, artifact)); + + boolean nextPage = true; + + do { + GitHubAdvisoryEntry entry = httpRequest(gitHubToken, jsonEntity); + + advisories.addAll(nodes(entry)); + + nextPage = hasNextPage(entry); + jsonEntity = String.format("{\"query\" : \"%s\"}", String + .format(load(GRAPHQL_NEXT_PAGE_RUN_TEMPLATE), FIRST_N_ADVISORIES, endCursor(entry), + ecosystem, artifact)); + } while (nextPage); + + return advisories; + } + + /** + * Does a REST API call to public URL GitHub GraphQL + * API to list all the security advisories from GitHub Security Advisory. + * + * @param githHubToken is the GitHub Token. + * @param jsonEntity is the query which needs to used to call GraphQL API. + * @return The {@link GitHubAdvisoryEntry} object. + * @throws IOException #{@link HttpClient} may throw an exception during GraphQL call. + */ + private GitHubAdvisoryEntry httpRequest(String gitHubToken, String jsonEntity) + throws IOException { + try (CloseableHttpClient client = httpClient()) { + HttpPost httpPostRequest = buildRequest(gitHubToken, jsonEntity); + try (CloseableHttpResponse response = client.execute(httpPostRequest)) { + return MAPPER.readValue(response.getEntity().getContent(), GitHubAdvisoryEntry.class); + } + } + } + + /** + * Builds a {@link HttpPost} request. + * + * @param githHubToken is the GitHub Token. + * @param jsonEntity is the query which needs to used to call GraphQL API. + * @return The {@link HttpPost} object. + * @throws UnsupportedEncodingException if something is wrong. + */ + private HttpPost buildRequest(String gitHubToken, String jsonEntity) + throws UnsupportedEncodingException { + String url = "https://api.github.com/graphql"; + + HttpPost httpPostRequest = new HttpPost(url); + if (StringUtils.isNotEmpty(gitHubToken)) { + httpPostRequest.addHeader(HttpHeaders.AUTHORIZATION, String.format("bearer %s", gitHubToken)); + } + httpPostRequest.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType()); + httpPostRequest.setEntity(new StringEntity(jsonEntity)); + return httpPostRequest; + } + + /** + * Returns an HTTP client. + */ + CloseableHttpClient httpClient() { + return HttpClients.createDefault(); + } + + /** + * Loads the GraphQL template, used as query to call GraphQL API. + * + * @param file name of the template. + * @return String content of the template. + * @throws IOException if something goes wrong. + */ + private String load(String file) throws IOException { + try (final InputStream is = getClass().getResourceAsStream(file)) { + return IOUtils.toString(is, "UTF-8").replaceAll("(\\r|\\n)", StringUtils.EMPTY); + } + } + + /** + * Get the last index of the first n elements. + * + * @param entry object of the type of {@link GitHubAdvisoryEntry}. + * @return The last index. + */ + private String endCursor(GitHubAdvisoryEntry entry) { + return entry.getData().getSecurityVulnerabilities().getPageInfo().getEndCursor(); + } + + /** + * Get the next page flag. + * + * @param entry object of the type of {@link GitHubAdvisoryEntry}. + * @return true if there is a next page. Otherwise false. + */ + private boolean hasNextPage(GitHubAdvisoryEntry entry) { + return entry.getData().getSecurityVulnerabilities().getPageInfo().getHasNextPage() + .booleanValue(); + } + + /** + * Extract all the advisories from the data {@link GitHubAdvisoryEntry}. + * + * @param entry object of the type of {@link GitHubAdvisoryEntry}. + * @return List o type {@link Node}. + */ + private List nodes(GitHubAdvisoryEntry entry) { + return entry.getData().getSecurityVulnerabilities().getNodes(); + } + + /** + * Check if the advisory has a CVE associated to it. + * + * @param advisory of object type {@link Advisory}. + * @return true if the {@link Advisory} has a CVE. Otherwise false. + */ + private boolean hasCve(Advisory advisory) { + for (Identifier identifier : advisory.getIdentifiers()) { + if (identifier.getType().equals("CVE")) { + return true; + } + } + return false; + } + + /** + * This is for testing purpose only. + * + * @throws IOException if something goes wrong. + */ + public static void main(String... args) throws IOException { + String token = "ded11dc9aa3c023d03074287f6d13b54fd6d1144";// System.getenv("TOKEN"); + GitHubAdvisories gitHubAdvisories = new GitHubAdvisories(token); + List advisories = + gitHubAdvisories.advisoriesFor(PackageManager.MAVEN, + "com.fasterxml.jackson.core:jackson-databind"); + System.out.println("Total count :" + advisories.size()); + } +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Advisory.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Advisory.java new file mode 100644 index 000000000..7a067f4c7 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Advisory.java @@ -0,0 +1,200 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"identifiers", "databaseId", "description", "ghsaId", "id", "origin", + "permalink", "publishedAt", "references", "severity", "summary", "updatedAt", "withdrawnAt"}) +public class Advisory { + + @JsonProperty("identifiers") + private List identifiers = null; + + @JsonProperty("databaseId") + private Integer databaseId; + + @JsonProperty("description") + private String description; + + @JsonProperty("ghsaId") + private String ghsaId; + + @JsonProperty("id") + private String id; + + @JsonProperty("origin") + private String origin; + + @JsonProperty("permalink") + private String permalink; + + @JsonProperty("publishedAt") + private String publishedAt; + + @JsonProperty("references") + private List references = null; + + @JsonProperty("severity") + private String severity; + + @JsonProperty("summary") + private String summary; + + @JsonProperty("updatedAt") + private String updatedAt; + + @JsonProperty("withdrawnAt") + private Object withdrawnAt; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("identifiers") + public List getIdentifiers() { + return identifiers; + } + + @JsonProperty("identifiers") + public void setIdentifiers(List identifiers) { + this.identifiers = identifiers; + } + + @JsonProperty("databaseId") + public Integer getDatabaseId() { + return databaseId; + } + + @JsonProperty("databaseId") + public void setDatabaseId(Integer databaseId) { + this.databaseId = databaseId; + } + + @JsonProperty("description") + public String getDescription() { + return description; + } + + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + @JsonProperty("ghsaId") + public String getGhsaId() { + return ghsaId; + } + + @JsonProperty("ghsaId") + public void setGhsaId(String ghsaId) { + this.ghsaId = ghsaId; + } + + @JsonProperty("id") + public String getId() { + return id; + } + + @JsonProperty("id") + public void setId(String id) { + this.id = id; + } + + @JsonProperty("origin") + public String getOrigin() { + return origin; + } + + @JsonProperty("origin") + public void setOrigin(String origin) { + this.origin = origin; + } + + @JsonProperty("permalink") + public String getPermalink() { + return permalink; + } + + @JsonProperty("permalink") + public void setPermalink(String permalink) { + this.permalink = permalink; + } + + @JsonProperty("publishedAt") + public String getPublishedAt() { + return publishedAt; + } + + @JsonProperty("publishedAt") + public void setPublishedAt(String publishedAt) { + this.publishedAt = publishedAt; + } + + @JsonProperty("references") + public List getReferences() { + return references; + } + + @JsonProperty("references") + public void setReferences(List references) { + this.references = references; + } + + @JsonProperty("severity") + public String getSeverity() { + return severity; + } + + @JsonProperty("severity") + public void setSeverity(String severity) { + this.severity = severity; + } + + @JsonProperty("summary") + public String getSummary() { + return summary; + } + + @JsonProperty("summary") + public void setSummary(String summary) { + this.summary = summary; + } + + @JsonProperty("updatedAt") + public String getUpdatedAt() { + return updatedAt; + } + + @JsonProperty("updatedAt") + public void setUpdatedAt(String updatedAt) { + this.updatedAt = updatedAt; + } + + @JsonProperty("withdrawnAt") + public Object getWithdrawnAt() { + return withdrawnAt; + } + + @JsonProperty("withdrawnAt") + public void setWithdrawnAt(Object withdrawnAt) { + this.withdrawnAt = withdrawnAt; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/AdvisoryReference.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/AdvisoryReference.java new file mode 100644 index 000000000..c54632f32 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/AdvisoryReference.java @@ -0,0 +1,47 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"url"}) +public class AdvisoryReference { + + @JsonProperty("url") + private String url; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("url") + public String getUrl() { + return url; + } + + @JsonProperty("url") + public void setUrl(String url) { + this.url = url; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + @Override + public String toString() { + return url; + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Data.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Data.java new file mode 100644 index 000000000..378cb4406 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Data.java @@ -0,0 +1,42 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"securityVulnerabilities"}) +public class Data { + + @JsonProperty("securityVulnerabilities") + private SecurityVulnerabilities securityVulnerabilities; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("securityVulnerabilities") + public SecurityVulnerabilities getSecurityVulnerabilities() { + return securityVulnerabilities; + } + + @JsonProperty("securityVulnerabilities") + public void setSecurityVulnerabilities(SecurityVulnerabilities securityVulnerabilities) { + this.securityVulnerabilities = securityVulnerabilities; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/GitHubAdvisoryEntry.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/GitHubAdvisoryEntry.java new file mode 100644 index 000000000..0d8b6ed5b --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/GitHubAdvisoryEntry.java @@ -0,0 +1,42 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"data"}) +public class GitHubAdvisoryEntry { + + @JsonProperty("data") + private Data data; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("data") + public Data getData() { + return data; + } + + @JsonProperty("data") + public void setData(Data data) { + this.data = data; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Identifier.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Identifier.java new file mode 100644 index 000000000..d7e83a6c7 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Identifier.java @@ -0,0 +1,55 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"value", "type"}) +public class Identifier { + + @JsonProperty("value") + private String value; + + @JsonProperty("type") + private String type; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("value") + public String getValue() { + return value; + } + + @JsonProperty("value") + public void setValue(String value) { + this.value = value; + } + + @JsonProperty("type") + public String getType() { + return type; + } + + @JsonProperty("type") + public void setType(String type) { + this.type = type; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Node.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Node.java new file mode 100644 index 000000000..e6e4342ad --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Node.java @@ -0,0 +1,108 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"advisory", "firstPatchedVersion", "package", "severity", "updatedAt", + "vulnerableVersionRange"}) +public class Node { + + @JsonProperty("advisory") + private Advisory advisory; + + @JsonProperty("firstPatchedVersion") + private Object firstPatchedVersion; + + @JsonProperty("package") + private Package packageManager; + + @JsonProperty("severity") + private String severity; + + @JsonProperty("updatedAt") + private String updatedAt; + + @JsonProperty("vulnerableVersionRange") + private String vulnerableVersionRange; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("advisory") + public Advisory getAdvisory() { + return advisory; + } + + @JsonProperty("advisory") + public void setAdvisory(Advisory advisory) { + this.advisory = advisory; + } + + @JsonProperty("firstPatchedVersion") + public Object getFirstPatchedVersion() { + return firstPatchedVersion; + } + + @JsonProperty("firstPatchedVersion") + public void setFirstPatchedVersion(Object firstPatchedVersion) { + this.firstPatchedVersion = firstPatchedVersion; + } + + @JsonProperty("package") + public Package getPackage() { + return packageManager; + } + + @JsonProperty("package") + public void setPackage(Package packageManager) { + this.packageManager = packageManager; + } + + @JsonProperty("severity") + public String getSeverity() { + return severity; + } + + @JsonProperty("severity") + public void setSeverity(String severity) { + this.severity = severity; + } + + @JsonProperty("updatedAt") + public String getUpdatedAt() { + return updatedAt; + } + + @JsonProperty("updatedAt") + public void setUpdatedAt(String updatedAt) { + this.updatedAt = updatedAt; + } + + @JsonProperty("vulnerableVersionRange") + public String getVulnerableVersionRange() { + return vulnerableVersionRange; + } + + @JsonProperty("vulnerableVersionRange") + public void setVulnerableVersionRange(String vulnerableVersionRange) { + this.vulnerableVersionRange = vulnerableVersionRange; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Package.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Package.java new file mode 100644 index 000000000..8823ee8ce --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/Package.java @@ -0,0 +1,55 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"name", "ecosystem"}) +public class Package { + + @JsonProperty("name") + private String name; + + @JsonProperty("ecosystem") + private String ecosystem; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("ecosystem") + public String getEcosystem() { + return ecosystem; + } + + @JsonProperty("ecosystem") + public void setEcosystem(String ecosystem) { + this.ecosystem = ecosystem; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/PageInfo.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/PageInfo.java new file mode 100644 index 000000000..46f397cf8 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/PageInfo.java @@ -0,0 +1,55 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"endCursor", "hasNextPage"}) +public class PageInfo { + + @JsonProperty("endCursor") + private String endCursor; + + @JsonProperty("hasNextPage") + private Boolean hasNextPage; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("endCursor") + public String getEndCursor() { + return endCursor; + } + + @JsonProperty("endCursor") + public void setEndCursor(String endCursor) { + this.endCursor = endCursor; + } + + @JsonProperty("hasNextPage") + public Boolean getHasNextPage() { + return hasNextPage; + } + + @JsonProperty("hasNextPage") + public void setHasNextPage(Boolean hasNextPage) { + this.hasNextPage = hasNextPage; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/SecurityAdvisories.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/SecurityAdvisories.java new file mode 100644 index 000000000..4424c6ec8 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/SecurityAdvisories.java @@ -0,0 +1,69 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"pageInfo", "totalCount", "nodes"}) +public class SecurityAdvisories { + + @JsonProperty("pageInfo") + private PageInfo pageInfo; + + @JsonProperty("totalCount") + private Integer totalCount; + + @JsonProperty("nodes") + private List nodes = null; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("pageInfo") + public PageInfo getPageInfo() { + return pageInfo; + } + + @JsonProperty("pageInfo") + public void setPageInfo(PageInfo pageInfo) { + this.pageInfo = pageInfo; + } + + @JsonProperty("totalCount") + public Integer getTotalCount() { + return totalCount; + } + + @JsonProperty("totalCount") + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } + + @JsonProperty("nodes") + public List getNodes() { + return nodes; + } + + @JsonProperty("nodes") + public void setNodes(List nodes) { + this.nodes = nodes; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/SecurityVulnerabilities.java b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/SecurityVulnerabilities.java new file mode 100644 index 000000000..9a091d5c5 --- /dev/null +++ b/src/main/java/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/data/SecurityVulnerabilities.java @@ -0,0 +1,56 @@ +package com.sap.sgs.phosphor.fosstars.data.github.experimental.graphql.data; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"pageInfo", "nodes"}) +public class SecurityVulnerabilities { + + @JsonProperty("pageInfo") + private PageInfo pageInfo; + + @JsonProperty("nodes") + private List nodes = null; + + @JsonIgnore + private Map additionalProperties = new HashMap(); + + @JsonProperty("pageInfo") + public PageInfo getPageInfo() { + return pageInfo; + } + + @JsonProperty("pageInfo") + public void setPageInfo(PageInfo pageInfo) { + this.pageInfo = pageInfo; + } + + @JsonProperty("nodes") + public List getNodes() { + return nodes; + } + + @JsonProperty("nodes") + public void setNodes(List nodes) { + this.nodes = nodes; + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/src/main/resources/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/first_run_template b/src/main/resources/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/first_run_template new file mode 100644 index 000000000..309aca07f --- /dev/null +++ b/src/main/resources/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/first_run_template @@ -0,0 +1,40 @@ +{ + securityVulnerabilities(first: %s, ecosystem: %s, package: \"%s\") { + pageInfo { + endCursor + hasNextPage + } + nodes { + firstPatchedVersion { + identifier + } + package { + name + ecosystem + } + severity + updatedAt + vulnerableVersionRange + advisory { + identifiers { + value + type + } + databaseId + description + ghsaId + id + origin + permalink + publishedAt + references { + url + } + severity + summary + updatedAt + withdrawnAt + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/next_page_run_template b/src/main/resources/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/next_page_run_template new file mode 100644 index 000000000..f5d6b9c80 --- /dev/null +++ b/src/main/resources/com/sap/sgs/phosphor/fosstars/data/github/experimental/graphql/next_page_run_template @@ -0,0 +1,40 @@ +{ + securityVulnerabilities(first: %s, after: \"%s\", ecosystem: %s, package: \"%s\") { + pageInfo { + endCursor + hasNextPage + } + nodes { + firstPatchedVersion { + identifier + } + package { + name + ecosystem + } + severity + updatedAt + vulnerableVersionRange + advisory { + identifiers { + value + type + } + databaseId + description + ghsaId + id + origin + permalink + publishedAt + references { + url + } + severity + summary + updatedAt + withdrawnAt + } + } + } +} \ No newline at end of file