Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
1074cbc
Add `build-attestation` target
ppkarwasz Mar 30, 2026
54e34b7
Add documentation of `buildType`
ppkarwasz Mar 30, 2026
f005ea1
Temporarily change version to publish snapshot
ppkarwasz Apr 2, 2026
5167d73
fix: output attestation in JSON Line format
ppkarwasz Apr 3, 2026
1ace65c
fix: disable Jackson auto-close option
ppkarwasz Apr 3, 2026
02ad5af
fix: adapt to Commons Code API change
ppkarwasz Apr 12, 2026
16f776f
feat: add support for DSSE signing
ppkarwasz Apr 15, 2026
c1644fa
fix: Javadoc of the model
ppkarwasz Apr 16, 2026
722edc0
fix: Javadoc of `DsseUtils`
ppkarwasz Apr 16, 2026
ec90db8
fix: Javadoc of `BuildAttestationMojo`
ppkarwasz Apr 16, 2026
2ad0751
fix: add sign test
ppkarwasz Apr 16, 2026
f8876c4
fix: build errors
ppkarwasz Apr 16, 2026
affb0a7
fix: base tests on already existing test resources
ppkarwasz Apr 16, 2026
3e4deda
fix: refactor external parameters from BuildAttestationMojo
ppkarwasz Apr 16, 2026
f519b36
fix: remove usage of AssertJ (and Hamcrest)
ppkarwasz Apr 20, 2026
c82977f
fix: add attestation example and use in tests
ppkarwasz Apr 20, 2026
595fbdc
fix: add Maven invocation parameters
ppkarwasz Apr 20, 2026
51df3bb
Merge remote-tracking branch 'apache/master' into feat/slsa
ppkarwasz Apr 20, 2026
2d3146d
fix: failures due to different set of JVM properties
ppkarwasz Apr 20, 2026
e633bc1
fix: `props` to `singletonProperties`
ppkarwasz Apr 20, 2026
d0ca534
fix: getter gets
ppkarwasz Apr 20, 2026
c8855e3
fix: fix `getFileName` Javadoc
ppkarwasz Apr 20, 2026
28f0b57
fix: add support for multiple checksum algorithms
ppkarwasz Apr 20, 2026
86a4401
fix: improve `BuildDefinitions.commandLine`
ppkarwasz Apr 20, 2026
c3cff4d
fix: add final everywhere
ppkarwasz Apr 20, 2026
db99b3c
fix: indentation
ppkarwasz Apr 20, 2026
717bc2c
fix: sort members
ppkarwasz Apr 20, 2026
b457710
fix: allow for setter chaining
ppkarwasz Apr 20, 2026
ad63bc7
fix: use `jackson-bom`
ppkarwasz Apr 20, 2026
89d61d2
fix: `internal` Javadoc
ppkarwasz Apr 20, 2026
d64965b
fix: improve documentation
ppkarwasz Apr 20, 2026
2cac4bd
fix: sort Java properties
ppkarwasz Apr 20, 2026
92c9d69
fix: buildType URL
ppkarwasz Apr 20, 2026
2cf85f1
fix: builder.id resolves to commons-release-plugin version
ppkarwasz Apr 20, 2026
9d8dc45
fix: latin abbreviations
ppkarwasz Apr 20, 2026
8118ebb
fix: clarify usage of JSON
ppkarwasz Apr 20, 2026
11eb6cb
Merge remote-tracking branch 'apache/codec-1.22.0' into feat/slsa
ppkarwasz Apr 20, 2026
33b1c2e
fix: remove unused method
ppkarwasz Apr 21, 2026
286e021
fix: clean-up after signature
ppkarwasz Apr 21, 2026
9b008bc
fix: add tests for `GitUtils`
ppkarwasz Apr 21, 2026
a654a98
fix: filter possibly sensitive use properties
ppkarwasz Apr 21, 2026
21ad673
fix: lower-case key id
ppkarwasz Apr 21, 2026
476ac4f
fix: `_type` property of attestation
ppkarwasz Apr 21, 2026
b7fbbf6
Apply suggestions from code review
ppkarwasz Apr 21, 2026
1f9bb30
Apply suggestions from code review (2)
ppkarwasz Apr 21, 2026
cfd3b97
fix: document attestation examples
ppkarwasz Apr 21, 2026
095d93f
fix: add documentation of the `build-attestation` goal
ppkarwasz Apr 21, 2026
9f69d2e
fix: remove dependency on ScmManager
ppkarwasz Apr 21, 2026
d74eb3e
fix: use temporary files for signing
ppkarwasz Apr 21, 2026
8102f34
fix: remove unnecessary `pom.xml` changes
ppkarwasz Apr 21, 2026
2dec90f
fix: clean-up public API
ppkarwasz Apr 21, 2026
0247724
fix: document checksum choice
ppkarwasz Apr 21, 2026
d92845a
fix: strengthen signature verification in test
ppkarwasz Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
<module name="UpperEll" />
<module name="ImportOrder">
<property name="option" value="top"/>
<property name="groups" value="java,javax,org"/>
<property name="groups" value="java,javax"/>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should not be required.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC this is inconsistent with other Commons projects, where com.* and org.* imports are in the same group. Is there any reason to group them separately?

<property name="ordered" value="true"/>
<property name="separated" value="true"/>
</module>
Expand Down
5 changes: 5 additions & 0 deletions fb-excludes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">

<!-- Mutable objects are not passed to untrusted methods, so we exclude these checks -->
<Match>
Comment on lines +21 to +22
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SpotBugs filter disables EI_EXPOSE_REP/EI_EXPOSE_REP2 globally for the entire project. That hides real findings outside the new SLSA model classes. Please scope the suppression to the specific package/classes that intentionally expose mutable state (e.g., the slsa.v1_2 models) rather than suppressing the patterns unconditionally.

Suggested change
<!-- Mutable objects are not passed to untrusted methods, so we exclude these checks -->
<Match>
<!-- Mutable objects are intentionally exposed only by the SLSA v1_2 model classes -->
<Match>
<Class name="~.*\.slsa\.v1_2\..*" />

Copilot uses AI. Check for mistakes.
<Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2" />
</Match>

<!-- Omit junit tests -->
<Match>
<Class name="~.*\.*Test.*"/>
Expand Down
97 changes: 95 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
</parent>
<artifactId>commons-release-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.9.3-SNAPSHOT</version>
<!-- Temporary version change to publish independent snapshot -->
<version>1.9.3.slsa-SNAPSHOT</version>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version should be a new minor version: 1.10.0, which can be done later and this comment can serve as a reminder.

Comment on lines +29 to +30
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project version is changed to 1.9.3.slsa-SNAPSHOT with a note that it is temporary. If this PR is intended to land on the main development line, this will change the published coordinates and may break downstream consumers/CI expecting 1.9.3-SNAPSHOT. Consider reverting the version change (or moving it to a separate, non-merged branch/workflow).

Copilot uses AI. Check for mistakes.
<name>Apache Commons Release Plugin</name>
<description>
Apache Maven Mojo for Apache Commons Release tasks.
Expand Down Expand Up @@ -113,7 +114,29 @@
<!-- Until Maven plugins used here don't fail the Moditect plugin -->
<moditect.skip>true</moditect.skip>
<japicmp.skip>true</japicmp.skip>
<!-- Dependency versions -->
<commons.jackson.version>2.21.2</commons.jackson.version>
<commons.slf4j.version>2.0.17</commons.slf4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-bom</artifactId>
<version>${commons.slf4j.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>${commons.jackson.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
Expand Down Expand Up @@ -171,6 +194,29 @@
<artifactId>commons-compress</artifactId>
<version>1.28.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
Expand All @@ -188,11 +234,34 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit</artifactId>
<version>2.40.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.6.0</version>
<scope>test</scope>
</dependency>
<!-- A bit of jar-hell requires this to come last. -->
<dependency>
<groupId>org.apache.maven</groupId>
Expand Down Expand Up @@ -223,6 +292,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean verify apache-rat:check checkstyle:check spotbugs:check javadoc:javadoc site</defaultGoal>
Expand All @@ -240,6 +314,25 @@
</includes>
</resource>
</resources>
<testResources>
<!-- Filter the attestation fixture and plugin coordinate file so they carry the current plugin version. -->
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
<includes>
<include>attestations/**</include>
<include>plugin.properties</include>
</includes>
</testResource>
<testResource>
<directory>src/test/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>attestations/**</exclude>
<exclude>plugin.properties</exclude>
</excludes>
</testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
Expand Down Expand Up @@ -532,7 +625,7 @@
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
</plugin>
</plugin>
</plugins>
</reporting>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* https://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.
*/
package org.apache.commons.release.plugin.internal;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.release.plugin.slsa.v1_2.ResourceDescriptor;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;

/**
* Utilities to convert {@link Artifact} from and to other types.
*/
public final class ArtifactUtils {

/**
* Maps standard JDK {@link java.security.MessageDigest} algorithm names to the in-toto digest names used in SLSA {@link ResourceDescriptor} digest sets.
*
* <p>JDK algorithms that have no in-toto equivalent (such as {@code MD2}) are omitted.</p>
*
* @see <a href="https://docs.oracle.com/en/java/javase/25/docs/specs/security/standard-names.html#messagedigest-algorithms">
* JDK standard {@code MessageDigest} algorithm names</a>
* @see <a href="https://github.com/in-toto/attestation/blob/main/spec/v1/digest_set.md">
* in-toto digest set specification</a>
*/
private static final Map<String, String> IN_TOTO_DIGEST_NAMES;

static {
final Map<String, String> m = new HashMap<>();
m.put("MD5", "md5");
m.put("SHA-1", "sha1");
m.put("SHA-224", "sha224");
m.put("SHA-256", "sha256");
m.put("SHA-384", "sha384");
m.put("SHA-512", "sha512");
m.put("SHA-512/224", "sha512_224");
m.put("SHA-512/256", "sha512_256");
m.put("SHA3-224", "sha3_224");
m.put("SHA3-256", "sha3_256");
m.put("SHA3-384", "sha3_384");
m.put("SHA3-512", "sha3_512");
IN_TOTO_DIGEST_NAMES = Collections.unmodifiableMap(m);
}

/**
* Gets a map of checksum algorithm names to hex-encoded digest values for the given artifact file.
*
* @param artifact A Maven artifact.
* @param algorithms JSSE names of algorithms to use
* @return A map of checksum algorithm names to hex-encoded digest values.
* @throws IOException If an I/O error occurs reading the artifact file.
* @throws IllegalArgumentException If any of the algorithms is not supported.
*/
private static Map<String, String> getChecksums(final Artifact artifact, final String... algorithms) throws IOException {
final Map<String, String> checksums = new HashMap<>();
for (final String algorithm : algorithms) {
final String key = IN_TOTO_DIGEST_NAMES.get(algorithm);
if (key == null) {
throw new IllegalArgumentException("Invalid algorithm name for in-toto attestation: " + algorithm);
}
final DigestUtils digest = new DigestUtils(DigestUtils.getDigest(algorithm));
final String checksum = digest.digestAsHex(artifact.getFile());
checksums.put(key, checksum);
}
return checksums;
}

/**
* Gets the filename of an artifact in the default Maven repository layout, using the specified extension.
*
* @param artifact A Maven artifact.
* @param extension The file name extension.
* @return A filename.
*/
public static String getFileName(final Artifact artifact, final String extension) {
final StringBuilder fileName = new StringBuilder();
fileName.append(artifact.getArtifactId()).append("-").append(artifact.getVersion());
if (artifact.getClassifier() != null) {
fileName.append("-").append(artifact.getClassifier());
}
fileName.append(".").append(extension);
return fileName.toString();
}

/**
* Gets the filename of an artifact in the default Maven repository layout.
*
* @param artifact A Maven artifact.
* @return A filename.
*/
public static String getFileName(final Artifact artifact) {
return getFileName(artifact, artifact.getArtifactHandler().getExtension());
}

/**
* Gets the Package URL corresponding to this artifact.
*
* @param artifact A maven artifact.
* @return A PURL for the given artifact.
*/
public static String getPackageUrl(final Artifact artifact) {
final StringBuilder sb = new StringBuilder();
sb.append("pkg:maven/").append(artifact.getGroupId()).append("/").append(artifact.getArtifactId()).append("@").append(artifact.getVersion())
.append("?");
final String classifier = artifact.getClassifier();
if (classifier != null) {
sb.append("classifier=").append(classifier).append("&");
}
sb.append("type=").append(artifact.getType());
return sb.toString();
}

/**
* Converts a Maven artifact to a SLSA {@link ResourceDescriptor}.
*
* @param artifact A Maven artifact.
* @param algorithms A comma-separated list of checksum algorithms to use.
* @return A SLSA resource descriptor.
* @throws MojoExecutionException If an I/O error occurs retrieving the artifact.
*/
public static ResourceDescriptor toResourceDescriptor(final Artifact artifact, final String algorithms) throws MojoExecutionException {
final ResourceDescriptor descriptor = new ResourceDescriptor()
.setName(getFileName(artifact))
.setUri(getPackageUrl(artifact));
if (artifact.getFile() != null) {
try {
descriptor.setDigest(getChecksums(artifact, StringUtils.split(algorithms, ",")));
} catch (final IOException e) {
throw new MojoExecutionException("Unable to compute hash for artifact file: " + artifact.getFile(), e);
}
}
return descriptor;
}

/** No instances. */
private ArtifactUtils() {
// prevent instantiation
}
}
Loading
Loading