Skip to content

Commit

Permalink
finalization
Browse files Browse the repository at this point in the history
  • Loading branch information
valentijnscholten committed Jan 26, 2025
1 parent 15f99a1 commit d2917df
Show file tree
Hide file tree
Showing 12 changed files with 593 additions and 100 deletions.
15 changes: 13 additions & 2 deletions src/main/java/org/dependencytrack/model/Repository.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ public class Repository implements Serializable {
@JsonDeserialize(using = TrimmedStringDeserializer.class)
private String identifier;

@Persistent
@Column(name = "DESCRIPTION")
@JsonDeserialize(using = TrimmedStringDeserializer.class)
private String description;

@Persistent
@Column(name = "URL")
@NotBlank
Expand Down Expand Up @@ -100,8 +105,6 @@ public class Repository implements Serializable {
@Column(name = "PASSWORD")
private String password;

//TODO VS Add Description field

@Persistent
@Column(name = "CONFIG", jdbcType = "CLOB")
@JsonDeserialize(using = TrimmedStringDeserializer.class)
Expand Down Expand Up @@ -138,6 +141,14 @@ public void setIdentifier(String identifier) {
this.identifier = identifier;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getUrl() {
return url;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,24 +214,24 @@ private List<Permission> getBadgesPermissions(final List<Permission> fullList) {
public void loadDefaultRepositories() {
try (QueryManager qm = new QueryManager()) {
LOGGER.info("Synchronizing default repositories to datastore");
qm.createRepository(RepositoryType.CPAN, "cpan-public-registry", "https://fastapi.metacpan.org/v1/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.GEM, "rubygems.org", "https://rubygems.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.HEX, "hex.pm", "https://hex.pm/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.HACKAGE, "hackage.haskell.org", "https://hackage.haskell.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "central", "https://repo1.maven.org/maven2/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "atlassian-public", "https://packages.atlassian.com/content/repositories/atlassian-public/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "jboss-releases", "https://repository.jboss.org/nexus/content/repositories/releases/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "clojars", "https://repo.clojars.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "google-android", "https://maven.google.com/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.NIXPKGS, "nixpkgs-unstable", "https://channels.nixos.org/nixpkgs-unstable/packages.json.br", true, false, false, null, null, null);
qm.createRepository(RepositoryType.NPM, "npm-public-registry", "https://registry.npmjs.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.PYPI, "pypi.org", "https://pypi.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.NUGET, "nuget-gallery", "https://api.nuget.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.COMPOSER, "packagist", "https://repo.packagist.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.COMPOSER, "drupal8", "https://packages.drupal.org/8", false, false, false, null, null, null);
qm.createRepository(RepositoryType.CARGO, "crates.io", "https://crates.io", true, false, false, null, null, null);
qm.createRepository(RepositoryType.GO_MODULES, "proxy.golang.org", "https://proxy.golang.org", true, false, false, null, null, null);
qm.createRepository(RepositoryType.GITHUB, "github.com", "https://github.com", true, false, false, null, null, null);
qm.createRepository(RepositoryType.CPAN, "cpan-public-registry", null, "https://fastapi.metacpan.org/v1/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.GEM, "rubygems.org", null, "https://rubygems.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.HEX, "hex.pm", null, "https://hex.pm/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.HACKAGE, "hackage.haskell.org", null, "https://hackage.haskell.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "central", null, "https://repo1.maven.org/maven2/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "atlassian-public", null, "https://packages.atlassian.com/content/repositories/atlassian-public/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "jboss-releases", null, "https://repository.jboss.org/nexus/content/repositories/releases/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "clojars", null, "https://repo.clojars.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.MAVEN, "google-android", null, "https://maven.google.com/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.NIXPKGS, "nixpkgs-unstable", null, "https://channels.nixos.org/nixpkgs-unstable/packages.json.br", true, false, false, null, null, null);
qm.createRepository(RepositoryType.NPM, "npm-public-registry", null, "https://registry.npmjs.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.PYPI, "pypi.org", null, "https://pypi.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.NUGET, "nuget-gallery", null, "https://api.nuget.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.COMPOSER, "packagist", null, "https://repo.packagist.org/", true, false, false, null, null, null);
qm.createRepository(RepositoryType.COMPOSER, "drupal8", null, "https://packages.drupal.org/8", false, false, false, null, null, null);
qm.createRepository(RepositoryType.CARGO, "crates.io", null, "https://crates.io", true, false, false, null, null, null);
qm.createRepository(RepositoryType.GO_MODULES, "proxy.golang.org", null, "https://proxy.golang.org", true, false, false, null, null, null);
qm.createRepository(RepositoryType.GITHUB, "github.com", null, "https://github.com", true, false, false, null, null, null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1225,12 +1225,12 @@ public boolean repositoryExist(RepositoryType type, String identifier) {
return getRepositoryQueryManager().repositoryExist(type, identifier);
}

public Repository createRepository(RepositoryType type, String identifier, String url, boolean enabled, boolean internal, boolean isAuthenticationRequired, String username, String password, String config) {
return getRepositoryQueryManager().createRepository(type, identifier, url, enabled, internal, isAuthenticationRequired, username, password, config);
public Repository createRepository(RepositoryType type, String identifier, String description, String url, boolean enabled, boolean internal, boolean isAuthenticationRequired, String username, String password, String config) {
return getRepositoryQueryManager().createRepository(type, identifier, description, url, enabled, internal, isAuthenticationRequired, username, password, config);
}

public Repository updateRepository(UUID uuid, String identifier, String url, boolean internal, boolean authenticationRequired, String username, String password, boolean enabled, String config) {
return getRepositoryQueryManager().updateRepository(uuid, identifier, url, internal, authenticationRequired, username, password, enabled, config);
public Repository updateRepository(UUID uuid, String identifier, String description, String url, boolean internal, boolean authenticationRequired, String username, String password, boolean enabled, String config) {
return getRepositoryQueryManager().updateRepository(uuid, identifier, description, url, internal, authenticationRequired, username, password, enabled, config);
}

public RepositoryMetaComponent getRepositoryMetaComponent(RepositoryType repositoryType, String namespace, String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,6 @@ public class RepositoryQueryManager extends QueryManager implements IQueryManage
super(pm, request);
}

//TODO VS remove getRepository?
/**
* Returns repository by identifier
*
* @return Repository
*/
public Repository getRepository(String identifier) {
final Query<Repository> query = pm.newQuery(Repository.class, "identifier == :identifier");
query.setParameters(identifier);
return executeAndCloseUnique(query);
}

/**
* Returns a list of all repositories.
*
Expand Down Expand Up @@ -148,6 +136,7 @@ public boolean repositoryExist(RepositoryType type, String identifier) {
*
* @param type the type of repository
* @param identifier a unique (to the type) identifier for the repo
* @param description description of the repository
* @param url the URL to the repository
* @param enabled if the repo is enabled or not
* @param internal if the repo is internal or not
Expand All @@ -156,7 +145,7 @@ public boolean repositoryExist(RepositoryType type, String identifier) {
* @param password the password to access the (authenticated) repository with
* @return the created Repository
*/
public Repository createRepository(RepositoryType type, String identifier, String url, boolean enabled, boolean internal, boolean isAuthenticationRequired, String username, String password, String config) {
public Repository createRepository(RepositoryType type, String identifier, String description, String url, boolean enabled, boolean internal, boolean isAuthenticationRequired, String username, String password, String config) {
if (repositoryExist(type, identifier)) {
return null;
}
Expand All @@ -172,6 +161,7 @@ public Repository createRepository(RepositoryType type, String identifier, Strin
final Repository repo = new Repository();
repo.setType(type);
repo.setIdentifier(identifier);
repo.setDescription(description);
repo.setUrl(url);
repo.setResolutionOrder(order + 1);
repo.setEnabled(enabled);
Expand All @@ -196,6 +186,7 @@ public Repository createRepository(RepositoryType type, String identifier, Strin
*
* @param uuid the uuid of the repository to update
* @param identifier the identifier of the repository
* @param description description of the repository
* @param url a url of the repository
* @param internal specifies if the repository is internal
* @param authenticationRequired if the repository needs authentication or not
Expand All @@ -204,9 +195,10 @@ public Repository createRepository(RepositoryType type, String identifier, Strin
* @param enabled specifies if the repository is enabled
* @return the updated Repository
*/
public Repository updateRepository(UUID uuid, String identifier, String url, boolean internal, boolean authenticationRequired, String username, String password, boolean enabled, String config) {
public Repository updateRepository(UUID uuid, String identifier, String description, String url, boolean internal, boolean authenticationRequired, String username, String password, boolean enabled, String config) {
final Repository repository = getObjectByUuid(Repository.class, uuid);
repository.setIdentifier(identifier);
repository.setDescription(description);
repository.setUrl(url);
repository.setInternal(internal);
repository.setAuthenticationRequired(authenticationRequired);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,12 @@ public Response createRepository(Repository jsonRepository) {

try (QueryManager qm = new QueryManager()) {
final boolean exists = qm.repositoryExist(jsonRepository.getType(), StringUtils.trimToNull(jsonRepository.getIdentifier()));
//TODO VS Add description to Frontend
if (!exists) {
final Repository repository = qm.createRepository(
jsonRepository.getType(),
StringUtils.trimToNull(jsonRepository.getIdentifier()),
StringUtils.trimToNull(jsonRepository.getDescription()),
StringUtils.trimToNull(jsonRepository.getUrl()),
jsonRepository.isEnabled(),
jsonRepository.isInternal(),
Expand Down Expand Up @@ -241,7 +243,7 @@ public Response updateRepository(Repository jsonRepository) {
? DataEncryption.encryptAsString(jsonRepository.getPassword())
: repository.getPassword();

repository = qm.updateRepository(jsonRepository.getUuid(), repository.getIdentifier(), url,
repository = qm.updateRepository(jsonRepository.getUuid(), repository.getIdentifier(), jsonRepository.getDescription(), url,
jsonRepository.isInternal(), jsonRepository.isAuthenticationRequired(), jsonRepository.getUsername(), updatedPassword, jsonRepository.isEnabled(), jsonRepository.getConfig());
return Response.ok(repository).build();
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,7 @@ protected List<VulnerableSoftware> mapVulnerabilityToVulnerableSoftware(final Qu
final PackageURL purl = generatePurlFromComposerAdvisory(advisory);
if (purl == null)
return null;
String versionStartIncluding = null;
String versionStartExcluding = null;
String versionEndIncluding = null;
String versionEndExcluding = null;

if (advisory.getAffectedVersions() != null) {
// regex splitters copied from Composer Version Parser
LOGGER.trace("Parsing version ranges for " + advisory.getPackageEcosystem() + " : "
Expand All @@ -343,6 +340,10 @@ protected List<VulnerableSoftware> mapVulnerabilityToVulnerableSoftware(final Qu
.map(String::trim).toArray(String[]::new);

for (String range : ranges) {
String versionStartIncluding = null;
String versionStartExcluding = null;
String versionEndIncluding = null;
String versionEndExcluding = null;
// Split by both ',' and ' '
String[] parts = Arrays.stream(range.split("(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)"))
.map(String::trim).toArray(String[]::new);
Expand All @@ -358,16 +359,15 @@ protected List<VulnerableSoftware> mapVulnerabilityToVulnerableSoftware(final Qu
} else if (part.startsWith("=")) {
versionStartIncluding = part.replace("=", "").trim();
versionEndIncluding = part.replace("=", "").trim();
} else if (part.trim().equals("*")) {
// Drupal sometimes uses * to indicate all versions are vulnerable for abandoned plugins
// Since we don't have a "deprecated" or "endoflife" or "unsupported" or "abandoned" flag, we do this:
versionEndExcluding = "999.999.999";
} else {
// TODO VS Try to support all version ranges seen in Drupal package repo. All
// from
// packagist are supported above.
/*
* "<5.25.0 || 6.0.0 || 6.0.1" (no = for exact version)
* "*" (all versions, plugin marked as unsupported)
*/
LOGGER.warn("Unable to determine version range of " + advisory.getPackageEcosystem()
+ " : " + advisory.getPackageName() + " : " + part);
// No operator, so it's a single version. Or garbage. But since none of the parts are checked for formatting, we don't check neither
// Drupal uses this, for example "8.1.0"
versionStartIncluding = part;
versionEndIncluding = part;
}
}
VulnerableSoftware vs = qm.getVulnerableSoftwareByPurl(purl.getType(), purl.getNamespace(),
Expand All @@ -379,6 +379,7 @@ protected List<VulnerableSoftware> mapVulnerabilityToVulnerableSoftware(final Qu
continue;
}
}

vs = new VulnerableSoftware();
vs.setVulnerable(true);
vs.setPurlType(purl.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public class ComposerAdvisoryParserTest {
]
}
""");
// TODO VS Test wildcardall versions

public final static JSONObject VULN_WILDCARD_ALL = new JSONObject("""
{
"advisoryId": "PKSA-n8hw-tywm-xrh7",
Expand Down Expand Up @@ -202,8 +202,7 @@ public class ComposerAdvisoryParserTest {
""");


//TODO VS Test NoOp version
public final static JSONObject VULN_NOOP_VERSION = new JSONObject("""
public final static JSONObject VULN_EXACT_VERSION = new JSONObject("""
{
"advisoryId": "PKSA-n8hw-tywm-xrh7",
"packageName": "drupal/core",
Expand Down Expand Up @@ -254,6 +253,8 @@ public void testParseNoErrors() throws IOException {
ComposerAdvisoryParser.parseAdvisory(VULN_FOP_CVE);
ComposerAdvisoryParser.parseAdvisory(VULN_FOP_NO_CVE);
ComposerAdvisoryParser.parseAdvisory(VULN_COMPOSER);
ComposerAdvisoryParser.parseAdvisory(VULN_WILDCARD_ALL);
ComposerAdvisoryParser.parseAdvisory(VULN_EXACT_VERSION);
}

}
Loading

0 comments on commit d2917df

Please sign in to comment.