New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MRESOLVER-301] Artifact generators SPI and GnuPG signature generator #432
Conversation
3fc4f4c
to
8fd2fe1
Compare
At first time looks a complicated a bit. I can test it in next weekend - I need more time for it. first questions:
By the way I think we should discuss such (for me big) architecture change on ML. |
Q1: checksums: they are tightly coupled into "basic connector". Historically, "connector" was the transport abstraction, but later "connector + transport" was introduced, and connector deals with checksums ONLY. Original issue was "deal with signatures as with checksums" but this is a no-go, as connector is (theoretically) swappable, while true, we have only "basic" connector and no other implementation. IMHO, we should eventually remove the abstraction from connector and accept that "basic" is THE connector we use. |
Also, "artifact generator" is one thing, and its use for "signing" is another. If we remain at "publishing to Central" domain, where PGP signature is enforced, and signing, I am not satisfied with any of existing solutions:
So I just "brought" the best of all here. At least, that was my intent. And yes, IMO, "signing" is natural fit for "artifact generator" and IMO we should not complicate our build/POMs for something that is an expected requirement (is like we'd need to add a plugin to POM to create checksums, something also required to publish to Central). Also, "signer" is extensible, so it does not have to get GnuPG, it could be something else as well... so in this way, it is not in Maven Core (wired in), but can progress and change, maybe as an extension. |
...tor-signer/src/main/java/org/eclipse/aether/generator/signer/gpg/GpgAgentPasswordLoader.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have any opinion and cannot object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave the decision to others.
febfac1
to
a41067a
Compare
@slawekjaranowski this is not "big architectural change" at all, just another option. I modified current PR to:
|
a41067a
to
1ad2b13
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly coding style issues
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
final class SignerArtifactGenerator implements ArtifactGenerator { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not public
instead of final
with a public constructor and protected fields ? Why would not people be allowed to extend it ?
@Named(GpgEnvPasswordLoader.NAME) | ||
@Priority(50) | ||
@SuppressWarnings("checkstyle:magicnumber") | ||
public final class GpgEnvPasswordLoader implements GpgSignerFactory.KeyPasswordLoader { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the final
keyword needed ?
@Singleton | ||
@Named(GpgFileRingMaterialLoader.NAME) | ||
@Priority(10) | ||
public final class GpgFileRingMaterialLoader implements GpgSignerFactory.KeyRingMaterialLoader { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
* GnuPG {@link Signer} implementation that is kept and reused across session. | ||
*/ | ||
@SuppressWarnings("checkstyle:magicnumber") | ||
public final class GpgSigner implements Signer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same...
}); | ||
} | ||
|
||
private void sign(InputStream content, OutputStream signature) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected
?
@@ -151,7 +162,23 @@ private DeployResult deploy(SyncContext syncContext, RepositorySystemSession ses | |||
throw new DeploymentException("Failed to deploy artifacts/metadata: " + e.getMessage(), e); | |||
} | |||
|
|||
final List<Artifact> artifacts = new ArrayList<>(request.getArtifacts()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how final
is useful. The static analysis very well knows if a variable is final or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -95,53 +106,96 @@ private InstallResult install(SyncContext syncContext, RepositorySystemSession s | |||
|
|||
RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); | |||
|
|||
List<? extends MetadataGenerator> generators = getMetadataGenerators(session, request); | |||
final List<Artifact> artifacts = new ArrayList<>(request.getArtifacts()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
1ad2b13
to
bec77d9
Compare
For other a general answer: I do agree with all your comments, but
So, yes, I agree, but this is why not IMO. |
Added UT for signer (for now does not assert much). Also verified locally the whole signing workflow along with agent, and it all works nicely, while verified produced signatures with The test on purpose use Ed25519 key, as that is where the future moves to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are many new Factories ... do we need all of them?
|
||
@Singleton | ||
@Named(SignerArtifactGeneratorFactory.NAME) | ||
public final class SignerArtifactGeneratorFactory implements ArtifactGeneratorFactory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is only one implementation of SignerArtifactGeneratorFactory
why we put it in new module ... maybe should be in maven-resolver-impl
* | ||
* @since 2.0.0 | ||
*/ | ||
public interface SignerFactory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
next factory similar to ArtifactGeneratorFactory
.map(a -> { | ||
HashMap<String, String> properties = new HashMap<>(a.getProperties()); | ||
properties.put( | ||
SignerArtifactGeneratorFactory.ARTIFACT_SIGNER_ID, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This property ARTIFACT_SIGNER_ID
is only used in this place .... why we add it?
try { | ||
List<Artifact> generatedArtifacts = new ArrayList<>(); | ||
for (ArtifactGenerator artifactGenerator : artifactGenerators) { | ||
Collection<? extends Artifact> generated = artifactGenerator.generate(generatedArtifacts); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generatedArtifacts
is an empty list at beginning - so how we discover artifacts to sign in artifactGenerator.generate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok - I see we heve materialized artifact list in org.eclipse.aether.generator.signer.SignerArtifactGenerator
It is look too complicated
<!-- To make Jetty + generator-signer work --> | ||
<javaVersion>17</javaVersion> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only see that UnixDomainSocketAddress
used in GpgAgentPasswordLoader
requres JDK 16+
so I don't see connections with Jetty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally it was 11 as Jetty 10.x we use as client and as server (in http-test) required 11, but now upped to 17.
Will change it: "jetty needs 11, generator-signer needs 17"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@Named(GpgSignerFactory.NAME) | ||
public final class GpgSignerFactory implements SignerFactory { | ||
public static final String NAME = GpgConfigurationKeys.NAME; | ||
private static final String SIGNER_KEY = GpgSignerFactory.class.getName() + ".signer"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused constant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
} | ||
|
||
Long keyId = null; | ||
String keyIdStr = ConfigUtils.getString(session, null, CONFIG_PROP_KEY_ID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keyId
should also be provided by environment value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, now only exists "loaders" (3 of them: env, conf and agent)
@slawekjaranowski general remark:
But also:
|
...generator-signer/src/main/java/org/eclipse/aether/generator/signer/gpg/GpgSignerFactory.java
Outdated
Show resolved
Hide resolved
fdea33b
to
eb5796c
Compare
@michael-o @slawekjaranowski @gnodet pls review again. Reworked, as layout was "improper" for signer (is transport and remote repository related). What was actually missing was the ArtifactPredicate (that recognizes artifact hashes and also configured extensions without hashes). This config was never per-remote repository, so it felt right to be moved to new component. Maven2 repo layout updated accordingly. Finally, this change revealed a (doc) bug: remote repo checksums ARE configurable per remote repository, but doco did not reflect that. |
So to recap, what I tried to explain to Slawek. This PR:
Naturally, as generators are ordered, signer generator is expected to be "among last" and sign not only artifacts in request (install/deploy) but also "so far generated artifacts" (if they are relevant). |
Now that you put it that way, I'm not really convinced we need a Signer SPI here. The code of the ArtifactGenerator which calls the signers is trivial, so it seems to me that the GpgSigner could directly implement the Artifact Generator SPI.
|
Agreed, will simplify it more, but the question begs: "generator-signer" module name becomes wrong, no? Should it be maybe "generator-gnupg (or gpg)" instead? |
Yes, I think that would make more sense. |
Collapsed code and renamed to generator-gnupg |
c5dd853
to
e3e9602
Compare
Artifact generators and one implementation: GnuPG Signer.
The "signer" generator is simple module for signing artifacts with GnuPG Signer.
https://issues.apache.org/jira/browse/MRESOLVER-301