Skip to content

Commit

Permalink
Merge branch 'DependencyTrack:master' into feat/add-team-selection-in…
Browse files Browse the repository at this point in the history
…-create-proect-button
  • Loading branch information
Gepardgame authored Sep 18, 2024
2 parents 3822462 + e582e9d commit 58106f8
Show file tree
Hide file tree
Showing 684 changed files with 2,867 additions and 2,220 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/_meta-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # tag=v4.1.7

- name: Set up JDK
uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # tag=v4.2.2
uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # tag=v4.3.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down Expand Up @@ -145,6 +145,6 @@ jobs:

- name: Upload Trivy Scan Results to GitHub Security Tab
if: ${{ inputs.publish-container }}
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # tag=v3.26.6
uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # tag=v3.26.7
with:
sarif_file: 'trivy-results.sarif'
2 changes: 1 addition & 1 deletion .github/workflows/ci-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # tag=v4.1.7

- name: Set up JDK
uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # tag=v4.2.2
uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # tag=v4.3.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # tag=v4.1.7

- name: Set up JDK
uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # tag=v4.2.2
uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # tag=v4.3.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down
5 changes: 3 additions & 2 deletions dev/docker-compose.mssql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ services:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "DTrack1234#"
healthcheck:
test: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -Q "SELECT 1" -b -o /dev/null
test: /opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -Q "SELECT 1" -b -o /dev/null
interval: 15s
timeout: 3s
retries: 10
Expand All @@ -51,7 +51,8 @@ services:
mssql:
condition: service_healthy
command:
- /opt/mssql-tools/bin/sqlcmd
- /opt/mssql-tools18/bin/sqlcmd
- -C
- -S
- mssql
- -U
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
<lib.open-vulnerability-clients.version>6.2.0</lib.open-vulnerability-clients.version>
<lib.packageurl.version>1.5.0</lib.packageurl.version>
<lib.pebble.version>3.2.2</lib.pebble.version>
<lib.protobuf-java.version>4.28.0</lib.protobuf-java.version>
<lib.protobuf-java.version>4.28.1</lib.protobuf-java.version>
<lib.resilience4j.version>2.2.0</lib.resilience4j.version>
<lib.swagger-parser.version>2.1.22</lib.swagger-parser.version>
<lib.system-rules.version>1.19.0</lib.system-rules.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public enum ConfigPropertyConstants {
BOM_VALIDATION_TAGS_INCLUSIVE("artifact", "bom.validation.tags.inclusive", "[]", PropertyType.STRING, "JSON array of tags for which BOM validation shall be performed"),
BOM_VALIDATION_TAGS_EXCLUSIVE("artifact", "bom.validation.tags.exclusive", "[]", PropertyType.STRING, "JSON array of tags for which BOM validation shall NOT be performed"),
WELCOME_MESSAGE("general", "welcome.message.html", "%20%3Chtml%3E%3Ch1%3EYour%20Welcome%20Message%3C%2Fh1%3E%3C%2Fhtml%3E", PropertyType.STRING, "Custom HTML Code that is displayed before login", true),
IS_WELCOME_MESSAGE("general", "welcome.message.enabled", "false", PropertyType.BOOLEAN, "Bool that says wheter to show the welcome message or not", true);
IS_WELCOME_MESSAGE("general", "welcome.message.enabled", "false", PropertyType.BOOLEAN, "Bool that says wheter to show the welcome message or not", true),
DEFAULT_LANGUAGE("general", "default.locale", null, PropertyType.STRING, "Determine the default Language to use", true);

private final String groupName;
private final String propertyName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
import java.util.function.Consumer;
import java.util.function.Function;

import static java.util.Objects.requireNonNullElse;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim;
import static org.apache.commons.lang3.StringUtils.trimToNull;
Expand Down Expand Up @@ -167,7 +168,7 @@ public static Component convertComponent(final org.cyclonedx.model.Component cdx
component.setSupplier(convert(cdxComponent.getSupplier()));
component.setClassifier(convertClassifier(cdxComponent.getType()).orElse(Classifier.LIBRARY));
component.setGroup(trimToNull(cdxComponent.getGroup()));
component.setName(trimToNull(cdxComponent.getName()));
component.setName(requireNonNullElse(trimToNull(cdxComponent.getName()), "-"));
component.setVersion(trimToNull(cdxComponent.getVersion()));
component.setDescription(trimToNull(cdxComponent.getDescription()));
component.setCopyright(trimToNull(cdxComponent.getCopyright()));
Expand Down Expand Up @@ -325,7 +326,7 @@ public static ServiceComponent convertService(final org.cyclonedx.model.Service
final var service = new ServiceComponent();
service.setBomRef(useOrGenerateRandomBomRef(cdxService.getBomRef()));
service.setGroup(trimToNull(cdxService.getGroup()));
service.setName(trimToNull(cdxService.getName()));
service.setName(requireNonNullElse(trimToNull(cdxService.getName()), "-"));
service.setVersion(trimToNull(cdxService.getVersion()));
service.setDescription(trimToNull(cdxService.getDescription()));
service.setAuthenticated(cdxService.getAuthenticated());
Expand Down Expand Up @@ -708,7 +709,7 @@ public static org.cyclonedx.model.Metadata createMetadata(final Project project)
cycloneComponent.setGroup(StringUtils.trimToNull(project.getGroup()));
cycloneComponent.setName(StringUtils.trimToNull(project.getName()));
if (StringUtils.trimToNull(project.getVersion()) == null) {
cycloneComponent.setVersion("SNAPSHOT"); // Version is required per CycloneDX spec
cycloneComponent.setVersion(""); // Version is required per CycloneDX spec
} else {
cycloneComponent.setVersion(StringUtils.trimToNull(project.getVersion()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -863,11 +863,32 @@ public void synchronizeComponentProperties(final Component component, final List

// Group properties by group, name, and value. Because CycloneDX supports duplicate
// property names, uniqueness can only be determined by also considering the value.
final var existingPropertyIdentitiesSeen = new HashSet<ComponentProperty.Identity>();
final var existingDuplicateProperties = new HashSet<ComponentProperty>();
final var existingPropertiesByIdentity = component.getProperties().stream()
// The legacy BOM processing in <= 4.11.x allowed duplicates to be persisted.
// Collectors#toMap fails upon encounter of duplicate keys.
// Prevent existing duplicates from breaking this.
// https://github.com/DependencyTrack/dependency-track/issues/4027
.filter(property -> {
final var identity = new ComponentProperty.Identity(property);
final boolean isUnique = existingPropertyIdentitiesSeen.add(identity);
if (!isUnique) {
existingDuplicateProperties.add(property);
}

return isUnique;
})
.collect(Collectors.toMap(ComponentProperty.Identity::new, Function.identity()));
final var incomingPropertyIdentitiesSeen = new HashSet<ComponentProperty.Identity>();
final var incomingPropertiesByIdentity = properties.stream()
.filter(property -> incomingPropertyIdentitiesSeen.add(new ComponentProperty.Identity(property)))
.collect(Collectors.toMap(ComponentProperty.Identity::new, Function.identity()));

if (!existingDuplicateProperties.isEmpty()) {
pm.deletePersistentAll(existingDuplicateProperties);
}

final var propertyIdentities = new HashSet<ComponentProperty.Identity>();
propertyIdentities.addAll(existingPropertiesByIdentity.keySet());
propertyIdentities.addAll(incomingPropertiesByIdentity.keySet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@

import alpine.common.validation.RegexSequence;
import alpine.common.validation.ValidationTask;
import alpine.model.LdapUser;
import alpine.model.ManagedUser;
import alpine.model.OidcUser;
import alpine.model.ApiKey;
import alpine.model.Team;
import alpine.model.UserPrincipal;
import alpine.server.auth.PermissionRequired;
import alpine.server.resources.AlpineResource;
Expand All @@ -35,6 +34,10 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
import io.swagger.v3.oas.annotations.tags.Tag;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.dependencytrack.auth.Permissions;
import org.dependencytrack.model.Analysis;
Expand Down Expand Up @@ -166,8 +169,13 @@ public Response updateAnalysis(AnalysisRequest request) {
}

String commenter = null;
if (getPrincipal() instanceof LdapUser || getPrincipal() instanceof ManagedUser || getPrincipal() instanceof OidcUser) {
commenter = ((UserPrincipal) getPrincipal()).getUsername();
if (getPrincipal() instanceof UserPrincipal principal) {
commenter = principal.getUsername();
} else if (getPrincipal() instanceof ApiKey apiKey) {
List<Team> teams = apiKey.getTeams();
List<String> teamNames = new ArrayList<String>();
teams.forEach(team -> teamNames.add(team.getName()));
commenter = String.join(", ", teamNames);
}

boolean analysisStateChange = false;
Expand Down
128 changes: 124 additions & 4 deletions src/main/java/org/dependencytrack/upgrade/v4120/v4120Updater.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import alpine.server.util.DbUtil;
import org.dependencytrack.model.BomValidationMode;

import jakarta.json.Json;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
Expand All @@ -46,6 +47,8 @@ public void executeUpgrade(final AlpineQueryManager qm, final Connection connect
removeExperimentalBomUploadProcessingV2ConfigProperty(connection);
migrateBomValidationConfigProperty(connection);
extendTeamNameColumnMaxLength(connection);
migrateAuthorToAuthors(connection);
dropAuthorColumns(connection);
}

private static void removeExperimentalBomUploadProcessingV2ConfigProperty(final Connection connection) throws SQLException {
Expand Down Expand Up @@ -156,13 +159,130 @@ private void extendTeamNameColumnMaxLength(final Connection connection) throws S
""");
} else if (DbUtil.isMysql()) {
stmt.executeUpdate("""
ALTER TABLE "TEAM" MODIFY "NAME" VARCHAR(255) NOT NULL
""");
ALTER TABLE "TEAM" MODIFY "NAME" VARCHAR(255) NOT NULL
""");
} else {
stmt.executeUpdate("""
ALTER TABLE "TEAM" ALTER COLUMN "NAME" TYPE VARCHAR(255)
""");
ALTER TABLE "TEAM" ALTER COLUMN "NAME" TYPE VARCHAR(255)
""");
}
}
}

private void migrateAuthorToAuthors(final Connection connection) throws SQLException {
LOGGER.info("Migrating PROJECT.AUTHOR and COMPONENT.AUTHOR to PROJECT.AUTHORS and COMPONENT.AUTHORS");

// MSSQL did not have native JSON functions until version 2022.
// Since we have to support versions earlier than that, the migration
// requires a more procedural approach.
if (DbUtil.isMssql()) {
migrateAuthorToAuthorsMssql(connection);
return;
}

try (final Statement stmt = connection.createStatement()) {
if (DbUtil.isH2()) {
stmt.executeUpdate("""
UPDATE "PROJECT"
SET "AUTHORS" = JSON_ARRAY(JSON_OBJECT('name': "AUTHOR"))
WHERE "AUTHOR" IS NOT NULL
""");
stmt.executeUpdate("""
UPDATE "COMPONENT"
SET "AUTHORS" = JSON_ARRAY(JSON_OBJECT('name': "AUTHOR"))
WHERE "AUTHOR" IS NOT NULL
""");
} else if (DbUtil.isMysql()) {
stmt.executeUpdate("""
UPDATE "PROJECT"
SET "AUTHORS" = JSON_ARRAY(JSON_OBJECT('name', "AUTHOR"))
WHERE "AUTHOR" IS NOT NULL
""");
stmt.executeUpdate("""
UPDATE "COMPONENT"
SET "AUTHORS" = JSON_ARRAY(JSON_OBJECT('name', "AUTHOR"))
WHERE "AUTHOR" IS NOT NULL
""");
} else if (DbUtil.isPostgreSQL()) {
stmt.executeUpdate("""
UPDATE "PROJECT"
SET "AUTHORS" = JSON_BUILD_ARRAY(JSON_BUILD_OBJECT('name', "AUTHOR"))::TEXT
WHERE "AUTHOR" IS NOT NULL
""");
stmt.executeUpdate("""
UPDATE "COMPONENT"
SET "AUTHORS" = JSON_BUILD_ARRAY(JSON_BUILD_OBJECT('name', "AUTHOR"))::TEXT
WHERE "AUTHOR" IS NOT NULL
""");
} else {
throw new IllegalStateException("Unrecognized database type");
}
}
}

private void migrateAuthorToAuthorsMssql(final Connection connection) throws SQLException {
migrateAuthorToAuthorsMssqlForTable(connection, "PROJECT");
migrateAuthorToAuthorsMssqlForTable(connection, "COMPONENT");
}

private void migrateAuthorToAuthorsMssqlForTable(
final Connection connection,
final String tableName) throws SQLException {
try (final PreparedStatement selectStatement = connection.prepareStatement("""
SELECT "ID"
, "AUTHOR"
FROM "%s"
WHERE "AUTHOR" IS NOT NULL
AND "AUTHORS" IS NULL
""".formatted(tableName));
final PreparedStatement updateStatement = connection.prepareStatement("""
UPDATE "%s"
SET "AUTHORS" = ?
WHERE "ID" = ?
""".formatted(tableName))) {
int batchSize = 0, numBatches = 0, numUpdates = 0;
final ResultSet rs = selectStatement.executeQuery();
while (rs.next()) {
final long id = rs.getLong(1);
final String author = rs.getString(2);
final String authors = Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("name", author))
.build()
.toString();

updateStatement.setString(1, authors);
updateStatement.setLong(2, id);
updateStatement.addBatch();
if (++batchSize == 500) {
updateStatement.executeBatch();
numUpdates += batchSize;
numBatches++;
batchSize = 0;
}
}

if (batchSize > 0) {
updateStatement.executeBatch();
numUpdates += batchSize;
numBatches++;
}

LOGGER.info("Updated %d %s records in %d batches"
.formatted(numUpdates, tableName, numBatches));
}
}

private void dropAuthorColumns(final Connection connection) throws SQLException {
LOGGER.info("Dropping PROJECT.AUTHOR and COMPONENT.AUTHOR columns");

try (final Statement stmt = connection.createStatement()) {
stmt.executeUpdate("""
ALTER TABLE "PROJECT" DROP COLUMN "AUTHOR"
""");
stmt.executeUpdate("""
ALTER TABLE "COMPONENT" DROP COLUMN "AUTHOR"
""");
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/license-list-data/json/details/0BSD.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"url": "https://opensource.org/licenses/0BSD",
"isValid": true,
"isLive": false,
"timestamp": "2024-05-22T17:29:17Z",
"timestamp": "2024-08-19T17:47:27Z",
"isWayBackLink": false,
"order": 1
},
Expand All @@ -19,7 +19,7 @@
"url": "http://landley.net/toybox/license.html",
"isValid": true,
"isLive": true,
"timestamp": "2024-05-22T17:29:18Z",
"timestamp": "2024-08-19T17:47:28Z",
"isWayBackLink": false,
"order": 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@
"licenseId": "3D-Slicer-1.0",
"crossRef": [
{
"match": "false",
"url": "https://slicer.org/LICENSE",
"match": "true",
"url": "https://github.com/Slicer/Slicer/blob/main/License.txt",
"isValid": true,
"isLive": true,
"timestamp": "2024-05-22T17:20:08Z",
"timestamp": "2024-08-19T17:43:03Z",
"isWayBackLink": false,
"order": 0
"order": 1
},
{
"match": "true",
"url": "https://github.com/Slicer/Slicer/blob/main/License.txt",
"match": "false",
"url": "https://slicer.org/LICENSE",
"isValid": true,
"isLive": true,
"timestamp": "2024-05-22T17:20:09Z",
"timestamp": "2024-08-19T17:43:04Z",
"isWayBackLink": false,
"order": 1
"order": 0
}
],
"seeAlso": [
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/license-list-data/json/details/AAL.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"url": "https://opensource.org/licenses/attribution",
"isValid": true,
"isLive": false,
"timestamp": "2024-05-22T17:24:39Z",
"timestamp": "2024-08-19T17:37:36Z",
"isWayBackLink": false,
"order": 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"url": "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense",
"isValid": true,
"isLive": true,
"timestamp": "2024-05-22T17:26:16Z",
"timestamp": "2024-08-19T17:46:39Z",
"isWayBackLink": false,
"order": 0
}
Expand Down
Loading

0 comments on commit 58106f8

Please sign in to comment.