diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 0000000..a274581 --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1 @@ +-Daether.checksums.omitChecksumsForExtensions=.asc,.sigstore \ No newline at end of file diff --git a/pgp-keys-map.list b/pgp-keys-map.list index c1ea3db..7e322a7 100644 --- a/pgp-keys-map.list +++ b/pgp-keys-map.list @@ -33,3 +33,34 @@ org.slf4j:slf4j-api = 0x475F3B8E59E6E63AA78067482C7B12F2A511E325 org.sonatype.plexus:plexus-cipher = 0x9FFED7A118D45A44E4A1E47130E6F80434A72A7F org.sonatype.plexus:plexus-sec-dispatcher = 0x2BCBDD0F23EA1CAFCC11D4860374CF2E8DD1BDFD org.sonatype.sisu = 0xBA926F64CA647B6D853A38672E2010F8A7FF4A41 + +dev.sigstore = 0xF6B17CDEEE2BB5BB7D04667D4BE41A4907BCD034 +# sigstore signature https://repo.maven.apache.org/maven2/dev/sigstore/sigstore-java/0.4.0/sigstore-java-0.4.0.jar.sigstore +# decoded with https://search.sigstore.dev/?logIndex=16039467 +# Subject Alternative Name (critical): +# email: +# - appu@google.com +# OIDC Issuer: https://accounts.google.com + +com.google.http-client = 0x47504B76CF89C15C0512D9AFE16AB52D79FD224F +io.opencensus = 0x600EA202B1EC682F4A788E5AAC7A514BC9F9BB70 +commons-logging:commons-logging = 0x0CC641C3A62453AB390066C4A41F13C999945293 +org.apache.httpcomponents = 0x0785B3EFF60B1B1BEA94E0BB7C25280EAE63EBE5 +io.github.erdtman:java-json-canonicalization = 0x4556208EBE484FBA3984DC3D3D4FA1A9DB2FB4F4 +com.google.api.grpc:proto-google-common-protos = 0x47504B76CF89C15C0512D9AFE16AB52D79FD224F +com.google.protobuf = 0x2E5B73C6EFD2EB453104C2EAE6EC76B4C6D3AE8E +com.google.code.findbugs = 0x7616EB882DAF57A11477AAF559A252FB1199D873 +com.google.errorprone:error_prone_annotations = 0xE77417AC194160A3FABD04969A259C7EE636C5ED +com.google.guava:guava = 0xBDB5FA4FE719D787FB3D3197F6D4A1D411E9D1AE +com.google.guava:failureaccess = 0x56ED3B4843DAACC79DE555557457CA33C3CE9E15 +com.google.guava:listenablefuture = 0xBDB5FA4FE719D787FB3D3197F6D4A1D411E9D1AE +org.checkerframework:checker-qual = 0x19BEAB2D799C020F17C69126B16698A4ADF4D638 +com.google.j2objc:j2objc-annotations = 0xB801E2F8EF035068EC1139CC29579F18FA8FD93B +io.grpc = 0xB02335AA54CCF21E52BBF9ABD9C565AA72BA2FDD +commons-codec:commons-codec = 0xBC87A3FD0A54480F0BADBEBD21939FF0CA2A6567 +com.google.code.gson:gson = 0xC7BE5BCC9FEC15518CFDA882B0F3710FA64900E7 +org.bouncycastle = 0x08F0AAB4D0C1A4BDDE340765B341DDB020FCB6AB +com.google.oauth-client = 0x47504B76CF89C15C0512D9AFE16AB52D79FD224F +io.perfmark:perfmark-api = 0xC6F7D1C804C821F49AF3BFC13AD93C3C677A106E +com.google.android:annotations = 0x0F07D1201BDDAB67CFB84EB479752DB6C966F0B8 +org.codehaus.mojo:animal-sniffer-annotations = 0xF254B35617DC255D9344BCFA873A8E86B4372146 diff --git a/pom.xml b/pom.xml index d730397..f48e827 100644 --- a/pom.xml +++ b/pom.xml @@ -61,12 +61,24 @@ under the License. 3.2.5 - 8 + 11 + ${javaVersion} 2023-05-03T01:33:44Z @ + + dev.sigstore + sigstore-java + 0.4.0 + + + com.google.protobuf + protobuf-java + 3.22.0 + runtime + org.apache.maven maven-plugin-api @@ -249,6 +261,15 @@ under the License. + + org.apache.rat + apache-rat-plugin + + + .mvn/maven.config + + + @@ -305,5 +326,37 @@ under the License. + + + apache-release + + + + + org.apache.maven.plugins + maven-gpg-plugin + ${project.version} + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + true + + + + sigstore-sign-release-artifacts + + sigstore + + + + + + + diff --git a/src/main/java/org/apache/maven/plugins/sigstore/SigstoreSignAttachedMojo.java b/src/main/java/org/apache/maven/plugins/sigstore/SigstoreSignAttachedMojo.java new file mode 100644 index 0000000..b26826a --- /dev/null +++ b/src/main/java/org/apache/maven/plugins/sigstore/SigstoreSignAttachedMojo.java @@ -0,0 +1,157 @@ +/* + * 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 + * + * http://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.maven.plugins.sigstore; + +/* + * 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 + * + * http://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. + */ + +import java.io.File; +import java.security.cert.X509Certificate; +import java.util.List; + +import dev.sigstore.KeylessSignature; +import dev.sigstore.KeylessSigner; +import dev.sigstore.bundle.BundleFactory; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.gpg.FilesCollector; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; +import org.codehaus.plexus.util.FileUtils; + +/** + * Sign project artifact, the POM, and attached artifacts with sigstore for deployment. + * + * @since 3.1.1 + */ +@Mojo(name = "sigstore", defaultPhase = LifecyclePhase.VERIFY, threadSafe = true) +public class SigstoreSignAttachedMojo extends AbstractMojo { + + /** + * Skip doing the gpg signing. + */ + @Parameter(property = "sigstore.skip", defaultValue = "false") + private boolean skip; + + /** + * A list of files to exclude from being signed. Can contain Ant-style wildcards and double wildcards. The default + * excludes are **/*.md5 **/*.sha1 **/*.sha256 **/*.sha512 **/*.asc **/*.sigstore. + */ + @Parameter + private String[] excludes; + + /** + * Use public staging {@code sigstage.dev} instead of public default {@code sigstore.dev}. + */ + @Parameter(defaultValue = "false", property = "public-staging") + private boolean publicStaging; + + /** + * The Maven project. + */ + @Parameter(defaultValue = "${project}", readonly = true) + private MavenProject project; + + /** + * Maven ProjectHelper + */ + @Component + private MavenProjectHelper projectHelper; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + if (skip) { + // We're skipping the signing stuff + return; + } + + // ---------------------------------------------------------------------------- + // Collect files to sign + // ---------------------------------------------------------------------------- + + FilesCollector collector = new FilesCollector(project, excludes, getLog()); + List items = collector.collect(); + + // ---------------------------------------------------------------------------- + // Sign the filesToSign and attach all the signatures + // ---------------------------------------------------------------------------- + + getLog().info("Signing " + items.size() + " file" + ((items.size() > 1) ? "s" : "") + "."); + + try { + KeylessSigner signer; + + if (publicStaging) { + signer = KeylessSigner.builder().sigstoreStagingDefaults().build(); + } else { + signer = KeylessSigner.builder().sigstorePublicDefaults().build(); + } + + for (FilesCollector.Item item : items) { + File fileToSign = item.getFile(); + + getLog().info("Signing " + fileToSign); + long start = System.currentTimeMillis(); + KeylessSignature signature = signer.signFile(fileToSign.toPath()); + + // sigstore signature in bundle format (json string) + String sigstoreBundle = BundleFactory.createBundle(signature); + + File signatureFile = new File(fileToSign + ".sigstore"); + FileUtils.fileWrite(signatureFile, "UTF-8", sigstoreBundle); + + long duration = System.currentTimeMillis() - start; + getLog().info(" > " + signatureFile.getName() + " in " + duration + " ms"); + + projectHelper.attachArtifact( + project, item.getExtension() + ".sigstore", item.getClassifier(), signatureFile); + + getLog().info(" Rekor logIndex: " + + signature.getEntry().get().getLogIndex()); + X509Certificate cert = (X509Certificate) + signature.getCertPath().getCertificates().get(0); + getLog().info(" Certificate Issuer DN: " + cert.getIssuerDN()); + getLog().info(" Subject Alternative Names: " + cert.getSubjectAlternativeNames()); + } + } catch (Exception e) { + throw new MojoExecutionException("Error while signing with sigstore", e); + } + } +}