Skip to content

Commit

Permalink
Update Javadocs
Browse files Browse the repository at this point in the history
  • Loading branch information
spyrkob committed Aug 2, 2024
1 parent 52d404a commit ba523d7
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 92 deletions.
11 changes: 6 additions & 5 deletions core/src/main/java/org/wildfly/channel/ChannelImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import org.wildfly.channel.spi.MavenVersionsResolver;
import org.wildfly.channel.spi.SignatureResult;
import org.wildfly.channel.spi.SignatureValidator;
import org.wildfly.channel.spi.ValidationResource;
import org.wildfly.channel.spi.ArtifactIdentifier;
import org.wildfly.channel.version.VersionMatcher;

/**
Expand Down Expand Up @@ -77,6 +77,7 @@ public ChannelImpl(Channel channelDefinition) {
*
* @param factory
* @param channels
* @param signatureValidator - the validator used to check the signatures of resolved artifacts
* @throws UnresolvedRequiredManifestException - if a required manifest cannot be resolved either via maven coordinates or in the list of channels
* @throws CyclicDependencyException - if the required manifests form a cyclic dependency
*/
Expand Down Expand Up @@ -407,7 +408,7 @@ ResolveArtifactResult resolveArtifact(String groupId, String artifactId, String

private void validateGpgSignature(String groupId, String artifactId, String extension, String classifier,
String version, File artifact) {
final ValidationResource mavenArtifact = new ValidationResource.MavenResource(groupId, artifactId, extension,
final ArtifactIdentifier mavenArtifact = new ArtifactIdentifier.MavenResource(groupId, artifactId, extension,
classifier, version);
try {
final File signature = resolver.resolveArtifact(groupId, artifactId, extension + SIGNATURE_FILE_SUFFIX,
Expand All @@ -426,7 +427,7 @@ mavenArtifact, new FileInputStream(artifact), new FileInputStream(signature),

private void validateGpgSignature(URL artifactFile, URL signature) throws IOException {
final SignatureResult signatureResult = signatureValidator.validateSignature(
new ValidationResource.UrlResource(artifactFile),
new ArtifactIdentifier.UrlResource(artifactFile),
artifactFile.openStream(), signature.openStream(),
channelDefinition.getGpgUrls()
);
Expand All @@ -448,7 +449,7 @@ List<ResolveArtifactResult> resolveArtifacts(List<ArtifactCoordinate> coordinate
for (int i = 0; i < resolvedArtifacts.size(); i++) {
final File artifact = resolvedArtifacts.get(i);
final ArtifactCoordinate c = coordinates.get(i);
final ValidationResource.MavenResource mavenArtifact = new ValidationResource.MavenResource(c.getGroupId(), c.getArtifactId(),
final ArtifactIdentifier.MavenResource mavenArtifact = new ArtifactIdentifier.MavenResource(c.getGroupId(), c.getArtifactId(),
c.getExtension(), c.getClassifier(), c.getVersion());
final File signature = signatures.get(i);
try {
Expand All @@ -464,7 +465,7 @@ List<ResolveArtifactResult> resolveArtifacts(List<ArtifactCoordinate> coordinate
}
}
} catch (ArtifactTransferException e) {
final ValidationResource.MavenResource artifact = new ValidationResource.MavenResource(e.getUnresolvedArtifacts().stream().findFirst().get());
final ArtifactIdentifier.MavenResource artifact = new ArtifactIdentifier.MavenResource(e.getUnresolvedArtifacts().stream().findFirst().get());
throw new SignatureValidator.SignatureException(String.format("Unable to find required signature for %s:%s:%s",
artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()),
SignatureResult.noSignature(artifact));
Expand Down
11 changes: 10 additions & 1 deletion core/src/main/java/org/wildfly/channel/ChannelSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class ChannelSession implements AutoCloseable {
private final int versionResolutionParallelism;

/**
* Create a ChannelSession.
* Create a ChannelSession with a default rejecting signature validator.
*
* @param channelDefinitions the list of channels to resolve Maven artifact
* @param factory Factory to create {@code MavenVersionsResolver} that are performing the actual Maven resolution.
Expand All @@ -64,6 +64,15 @@ public ChannelSession(List<Channel> channelDefinitions, MavenVersionsResolver.Fa
this(channelDefinitions, factory, DEFAULT_SPLIT_ARTIFACT_PARALLELISM, SignatureValidator.REJECTING_VALIDATOR);
}

/**
* Create a ChannelSession with a default rejecting signature validator.
*
* @param channelDefinitions the list of channels to resolve Maven artifact
* @param factory Factory to create {@code MavenVersionsResolver} that are performing the actual Maven resolution.
* @param signatureValidator Validator to verify signatures of downloaded artifacts
* @throws UnresolvedRequiredManifestException - if a required manifest cannot be resolved either via maven coordinates or in the list of channels
* @throws CyclicDependencyException - if the required manifests form a cyclic dependency
*/
public ChannelSession(List<Channel> channelDefinitions, MavenVersionsResolver.Factory factory, SignatureValidator signatureValidator) {
this(channelDefinitions, factory, DEFAULT_SPLIT_ARTIFACT_PARALLELISM, signatureValidator);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@

import org.wildfly.channel.ArtifactCoordinate;

public interface ValidationResource {
/**
* An identifier of an artifact being validated. It can be either a Maven coordinate or an URL.
*/
public interface ArtifactIdentifier {

class UrlResource implements ValidationResource {
private URL resourceUrl;
class UrlResource implements ArtifactIdentifier {
private final URL resourceUrl;

public UrlResource(URL resourceUrl) {
this.resourceUrl = resourceUrl;
Expand All @@ -34,7 +37,7 @@ public URL getResourceUrl() {
}
}

class MavenResource extends ArtifactCoordinate implements ValidationResource {
class MavenResource extends ArtifactCoordinate implements ArtifactIdentifier {

public MavenResource(String groupId, String artifactId, String extension, String classifier, String version) {
super(groupId, artifactId, extension, classifier, version);
Expand Down
28 changes: 20 additions & 8 deletions core/src/main/java/org/wildfly/channel/spi/SignatureResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,41 @@
*/
package org.wildfly.channel.spi;

/**
* Represents a result of artifact verification
*/
public class SignatureResult {

private ValidationResource resource;
/**
* Identifier of the artifact that was being verified.
*/
private ArtifactIdentifier resource;
/**
* Identifier of the certificate used to verify the artifact.
*/
private String keyId;
/**
* Optional message with details of validation.
*/
private String message;

public static SignatureResult noMatchingCertificate(ValidationResource resource, String keyID) {
public static SignatureResult noMatchingCertificate(ArtifactIdentifier resource, String keyID) {
return new SignatureResult(Result.NO_MATCHING_CERT, resource, keyID, null);
}

public static SignatureResult revoked(ValidationResource resource, String keyID, String revocationReason) {
public static SignatureResult revoked(ArtifactIdentifier resource, String keyID, String revocationReason) {
return new SignatureResult(Result.REVOKED, resource, keyID, revocationReason);
}

public static SignatureResult expired(ValidationResource resource, String keyID) {
public static SignatureResult expired(ArtifactIdentifier resource, String keyID) {
return new SignatureResult(Result.EXPIRED, resource, keyID, null);
}

public static SignatureResult noSignature(ValidationResource resource) {
public static SignatureResult noSignature(ArtifactIdentifier resource) {
return new SignatureResult(Result.NO_SIGNATURE, resource, null, null);
}

public static SignatureResult invalid(ValidationResource resource) {
public static SignatureResult invalid(ArtifactIdentifier resource) {
return new SignatureResult(Result.INVALID, resource, null, null);
}

Expand All @@ -48,7 +60,7 @@ public static SignatureResult ok() {
return new SignatureResult(Result.OK, null, null, null);
}

private SignatureResult(Result result, ValidationResource resource, String keyID, String message) {
private SignatureResult(Result result, ArtifactIdentifier resource, String keyID, String message) {
this.result = result;
this.resource = resource;
this.keyId = keyID;
Expand All @@ -59,7 +71,7 @@ public Result getResult() {
return result;
}

public ValidationResource getResource() {
public ArtifactIdentifier getResource() {
return resource;
}

Expand Down
16 changes: 12 additions & 4 deletions core/src/main/java/org/wildfly/channel/spi/SignatureValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,29 @@
* Called to validate detached signatures of artifacts resolved in the channel
*/
public interface SignatureValidator {
/**
* A default validator, rejecting all artifacts
*/
SignatureValidator REJECTING_VALIDATOR = (artifactSource, artifactStream, signatureStream, gpgUrls) -> {
throw new SignatureException("Not implemented", SignatureResult.noSignature(artifactSource));
};

/**
* validates a signature of {@code artifact}. The locally downloaded {@code signature} has to be an armour encoded GPG signature.
* validates a signature of an artifact. The locally downloaded {@code signature} has to be an armour encoded GPG signature.
*
* @param artifact - {@code MavenArtifact} to validate. Includes a full GAV and the local artifact file.
* @param signature - local file containing armour encoded detached GPG signature for the {@code artifact}.
* @param artifactId - an identifier of the resource to be validated.
* @param artifactStream - an {@code InputStream} of the artifact to be verified.
* @param signatureStream - an {@code InputStream} of the armour encoded detached GPG signature for the artifact.
* @param gpgUrls - URLs of the keys defined in the channel. Empty collection if channel does not define any signatures.
* @return {@link SignatureResult} with the result of validation
* @throws SignatureException - if an unexpected error occurred when handling the keys.
*/
SignatureResult validateSignature(ValidationResource artifactSource, InputStream artifactStream, InputStream signatureStream, List<String> gpgUrls) throws SignatureException;
SignatureResult validateSignature(ArtifactIdentifier artifactId, InputStream artifactStream,
InputStream signatureStream, List<String> gpgUrls) throws SignatureException;

/**
* An exception signifying issue with an artifact signature validation.
*/
class SignatureException extends RuntimeException {
private final SignatureResult signatureResult;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
import org.wildfly.channel.spi.MavenVersionsResolver;
import org.wildfly.channel.spi.SignatureResult;
import org.wildfly.channel.spi.SignatureValidator;
import org.wildfly.channel.spi.ValidationResource;
import org.wildfly.channel.spi.ArtifactIdentifier;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
Expand Down Expand Up @@ -442,7 +441,7 @@ public void invalidSignatureCausesError() throws Exception {
when(resolver.resolveArtifact("test.channels", "base-manifest",
ChannelManifest.EXTENSION + SIGNATURE_FILE_SUFFIX, ChannelManifest.CLASSIFIER, "1.0.0"))
.thenReturn(tempDir.resolve("test-manifest.yaml.asc").toFile());
when(signatureValidator.validateSignature(any(), any(), any(), any())).thenReturn(SignatureResult.invalid(mock(ValidationResource.class)));
when(signatureValidator.validateSignature(any(), any(), any(), any())).thenReturn(SignatureResult.invalid(mock(ArtifactIdentifier.class)));
assertThrows(SignatureValidator.SignatureException.class, () -> new ChannelSession(channels, factory));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.wildfly.channel.spi.MavenVersionsResolver;
import org.wildfly.channel.spi.SignatureResult;
import org.wildfly.channel.spi.SignatureValidator;
import org.wildfly.channel.spi.ValidationResource;

public class ChannelSessionTestCase {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.wildfly.channel;

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -26,14 +42,14 @@
import org.wildfly.channel.spi.MavenVersionsResolver;
import org.wildfly.channel.spi.SignatureResult;
import org.wildfly.channel.spi.SignatureValidator;
import org.wildfly.channel.spi.ValidationResource;
import org.wildfly.channel.spi.ArtifactIdentifier;

public class ChannelSessionWithSignatureValidationTestCase {

private static final ValidationResource.MavenResource ARTIFACT = new ValidationResource.MavenResource(
private static final ArtifactIdentifier.MavenResource ARTIFACT = new ArtifactIdentifier.MavenResource(
"org.wildfly", "wildfly-ee-galleon-pack", "zip", null, "25.0.1.Final");

private static final ValidationResource.MavenResource MANIFEST = new ValidationResource.MavenResource(
private static final ArtifactIdentifier.MavenResource MANIFEST = new ArtifactIdentifier.MavenResource(
"org.channels", "test-manifest", ChannelManifest.EXTENSION, ChannelManifest.CLASSIFIER, "1.0.0");

@TempDir
Expand Down Expand Up @@ -141,7 +157,7 @@ public void failedSignatureValidationThrowsException() throws Exception {
ARTIFACT.classifier, ARTIFACT.version))
.thenReturn(signatureFile);
// simulate a valid signature of the channel manifest, and invalid signature of the artifact
when(signatureValidator.validateSignature(eq(new ValidationResource.MavenResource(
when(signatureValidator.validateSignature(eq(new ArtifactIdentifier.MavenResource(
MANIFEST.groupId, MANIFEST.artifactId, MANIFEST.extension, MANIFEST.classifier, MANIFEST.version)),
any(), any(), any())).thenReturn(SignatureResult.ok());
when(signatureValidator.validateSignature(eq(ARTIFACT),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,27 @@

import java.util.List;

/**
* Local store of trusted public keys.
*
* Note: the keystore can reject a public key being added. In such case, the {@code GpgSignatureValidator} has to reject this key.
*/
public interface GpgKeystore {

/**
* resolve a public key from the store.
*
* @param keyID - a HEX form of the key ID
* @return - the resolved public key or {@code null} if the key was not found
*/
PGPPublicKey get(String keyID);

/**
* records the public keys in the store for future use.
*
* @param publicKey - list of trusted public keys
* @return true if the public keys have been added succesfully
* false otherwise.
*/
boolean add(List<PGPPublicKey> publicKey);
}
Loading

0 comments on commit ba523d7

Please sign in to comment.