Skip to content

Commit

Permalink
[Upstream] Add pgp in memory signing support (#1191)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: jchen <[email protected]>
  • Loading branch information
ThomasCJY and jchen-sc authored Aug 9, 2024
1 parent ba7310c commit 9a10cae
Show file tree
Hide file tree
Showing 7 changed files with 509 additions and 56 deletions.
2 changes: 2 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ maven.install(
"org.slf4j:log4j-over-slf4j:2.0.12",
"org.slf4j:slf4j-simple:2.0.12",
"software.amazon.awssdk:s3:2.26.12",
"org.bouncycastle:bcprov-jdk15on:1.68",
"org.bouncycastle:bcpg-jdk15on:1.68",
],
fail_if_repin_required = True,
fetch_sources = True,
Expand Down
12 changes: 12 additions & 0 deletions private/rules/maven_publish.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export MAVEN_REPO="${{MAVEN_REPO:-{maven_repo}}}"
export GPG_SIGN="${{GPG_SIGN:-{gpg_sign}}}"
export MAVEN_USER="${{MAVEN_USER:-{user}}}"
export MAVEN_PASSWORD="${{MAVEN_PASSWORD:-{password}}}"
export USE_IN_MEMORY_PGP_KEYS="${{USE_IN_MEMORY_PGP_KEYS:-{use_in_memory_pgp_keys}}}"
export PGP_SIGNING_KEY="${{PGP_SIGNING_KEY:-{pgp_signing_key}}}"
export PGP_SIGNING_PWD="${{PGP_SIGNING_PWD:-{pgp_signing_pwd}}}"
echo Uploading "{coordinates}" to "${{MAVEN_REPO}}"
{uploader} "{coordinates}" '{pom}' '{artifact}' '{classifier_artifacts}' $@
"""
Expand All @@ -29,6 +32,9 @@ def _maven_publish_impl(ctx):
gpg_sign = ctx.var.get("gpg_sign", "false")
user = ctx.var.get("maven_user", "")
password = ctx.var.get("maven_password", "")
use_in_memory_pgp_keys = ctx.var.get("use_in_memory_pgp_keys", "'false'")
pgp_signing_key = ctx.var.get("pgp_signing_key", "''")
pgp_signing_pwd = ctx.var.get("pgp_signing_pwd", "''")
if password:
print("WARNING: using --define to set maven_password is insecure. Set env var MAVEN_PASSWORD=xxx instead.")

Expand All @@ -55,6 +61,9 @@ def _maven_publish_impl(ctx):
gpg_sign = _escape_arg(gpg_sign),
maven_repo = _escape_arg(maven_repo),
password = _escape_arg(password),
use_in_memory_pgp_keys = _escape_arg(use_in_memory_pgp_keys),
pgp_signing_key = _escape_arg(pgp_signing_key),
pgp_signing_pwd = _escape_arg(pgp_signing_pwd),
user = _escape_arg(user),
pom = ctx.file.pom.short_path,
artifact = artifacts_short_path,
Expand Down Expand Up @@ -97,6 +106,9 @@ using `--define` or via environment variables (in all caps, e.g. `MAVEN_REPO`):
maven_repo: A URL for the repo to use. May be "https" or "file".
maven_user: The user name to use when uploading to the maven repository.
maven_password: The password to use when uploading to the maven repository.
use_in_memory_pgp_keys: Whether to sign artifacts using in memory PGP secrets
pgp_signing_key = The secret key to sign the artifact with
pgp_signing_pwd = Password for the secret key
When signing with GPG, the current default key is used.
""",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ load("@rules_jvm_external//:defs.bzl", "artifact")

java_binary(
name = "MavenPublisher",
srcs = ["MavenPublisher.java"],
srcs = ["MavenPublisher.java", "MavenSigning.java"],
main_class = "com.github.bazelbuild.rules_jvm_external.maven.MavenPublisher",
visibility = ["//visibility:public"],
deps = [
Expand Down Expand Up @@ -31,6 +31,14 @@ java_binary(
"software.amazon.awssdk:s3",
repository_name = "rules_jvm_external_deps",
),
artifact(
"org.bouncycastle:bcprov-jdk15on",
repository_name = "rules_jvm_external_deps",
),
artifact(
"org.bouncycastle:bcpg-jdk15on",
repository_name = "rules_jvm_external_deps",
),
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package com.github.bazelbuild.rules_jvm_external.maven;

import static com.github.bazelbuild.rules_jvm_external.maven.MavenSigning.in_memory_pgp_sign;
import static com.github.bazelbuild.rules_jvm_external.maven.MavenSigning.gpg_sign;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.MINUTES;
Expand Down Expand Up @@ -78,6 +80,11 @@ public static void main(String[] args)
boolean gpgSign = Boolean.parseBoolean(System.getenv("GPG_SIGN"));
Credentials credentials =
new BasicAuthCredentials(System.getenv("MAVEN_USER"), System.getenv("MAVEN_PASSWORD"));
boolean useInMemoryPgpKeys = Boolean.parseBoolean(System.getenv("USE_IN_MEMORY_PGP_KEYS"));
String signingKey = System.getenv("PGP_SIGNING_KEY");
String signingPassword = System.getenv("PGP_SIGNING_PWD");
MavenSigning.SigningMetadata signingMetadata =
new MavenSigning.SigningMetadata(gpgSign, useInMemoryPgpKeys, signingKey, signingPassword);

List<String> parts = Arrays.asList(args[0].split(":"));
if (parts.size() != 3) {
Expand All @@ -93,12 +100,12 @@ public static void main(String[] args)

try {
List<CompletableFuture<Void>> futures = new ArrayList<>();
futures.add(upload(repo, credentials, coords, ".pom", pom, gpgSign));
futures.add(upload(repo, credentials, coords, ".pom", pom, signingMetadata));

if (mainArtifact != null) {
String ext =
com.google.common.io.Files.getFileExtension(mainArtifact.getFileName().toString());
futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, gpgSign));
futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, signingMetadata));
}

if (args.length > 3 && !args[3].isEmpty()) {
Expand All @@ -115,7 +122,7 @@ public static void main(String[] args)
coords,
String.format("-%s.%s", classifier, ext),
artifact,
gpgSign));
signingMetadata));
}
}

Expand Down Expand Up @@ -149,7 +156,7 @@ private static CompletableFuture<Void> upload(
Coordinates coords,
String append,
Path item,
boolean gpgSign)
MavenSigning.SigningMetadata signingMetadata)
throws IOException, InterruptedException {

String base =
Expand All @@ -174,10 +181,27 @@ private static CompletableFuture<Void> upload(
uploads.add(upload(String.format("%s%s.md5", base, append), credentials, md5));
uploads.add(upload(String.format("%s%s.sha1", base, append), credentials, sha1));

if (gpgSign) {
uploads.add(upload(String.format("%s%s.asc", base, append), credentials, sign(item)));
uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, sign(md5)));
uploads.add(upload(String.format("%s%s.sha1.asc", base, append), credentials, sign(sha1)));
MavenSigning.SigningMethod signingMethod = signingMetadata.signingMethod;
if (signingMethod.equals(MavenSigning.SigningMethod.GPG)) {
uploads.add(upload(String.format("%s%s.asc", base, append), credentials, gpg_sign(item)));
uploads.add(upload(String.format("%s%s.md5.asc", base, append), credentials, gpg_sign(md5)));
uploads.add(upload(String.format("%s%s.sha1.asc", base, append), credentials, gpg_sign(sha1)));
} else if (signingMethod.equals(MavenSigning.SigningMethod.PGP)) {
uploads.add(upload(
String.format("%s%s.asc", base, append),
credentials,
in_memory_pgp_sign(item, signingMetadata.signingKey, signingMetadata.signingPassword)
));
uploads.add(upload(
String.format("%s%s.md5.asc", base, append),
credentials,
in_memory_pgp_sign(md5, signingMetadata.signingKey, signingMetadata.signingPassword)
));
uploads.add(upload(
String.format("%s%s.sha1.asc", base, append),
credentials,
in_memory_pgp_sign(sha1, signingMetadata.signingKey, signingMetadata.signingPassword)
));
}

return CompletableFuture.allOf(uploads.toArray(new CompletableFuture<?>[0]));
Expand Down Expand Up @@ -335,51 +359,6 @@ private static Callable<Void> arUpload(String targetUrl, Path toUpload) {
};
}

private static Path sign(Path toSign) throws IOException, InterruptedException {
LOG.info("Signing " + toSign);

// Ideally, we'd use BouncyCastle for this, but for now brute force by assuming
// the gpg binary is on the path

Path dir = Files.createTempDirectory("maven-sign");
Path file = dir.resolve(toSign.getFileName() + ".asc");

Process gpg =
new ProcessBuilder(
"gpg",
"--use-agent",
"--armor",
"--detach-sign",
"--no-tty",
"-o",
file.toAbsolutePath().toString(),
toSign.toAbsolutePath().toString())
.inheritIO()
.start();
gpg.waitFor();
if (gpg.exitValue() != 0) {
throw new IllegalStateException("Unable to sign: " + toSign);
}

// Verify the signature
Process verify =
new ProcessBuilder(
"gpg",
"--verify",
"--verbose",
"--verbose",
file.toAbsolutePath().toString(),
toSign.toAbsolutePath().toString())
.inheritIO()
.start();
verify.waitFor();
if (verify.exitValue() != 0) {
throw new IllegalStateException("Unable to verify signature of " + toSign);
}

return file;
}

private static class Coordinates {
private final String groupId;
private final String artifactId;
Expand Down
Loading

0 comments on commit 9a10cae

Please sign in to comment.