Skip to content
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

Store key not found result in cache #336

Merged
merged 1 commit into from
Nov 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions src/it/noKeyFail/postbuild.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
def buildLog = new File( basedir, 'build.log' ).text


assert buildLog.contains('[ERROR] PGP key https://keyserver.ubuntu.com/pks/lookup?op=vindex&fingerprint=on&search=0x466583F9480EBE2462C46B309F1A263E15FD0AC9 not found on keyserver for artifact nl.dannyvanheumen:helloworld:jar:1.0')
assert buildLog.contains('[ERROR] PGP key https://keyserver.ubuntu.com/pks/lookup?op=vindex&fingerprint=on&search=0x466583F9480EBE2462C46B309F1A263E15FD0AC9 not found on keyserver for artifact nl.dannyvanheumen:helloworld:pom:1.0')
assert buildLog.contains('[ERROR] nl.dannyvanheumen:helloworld:jar:1.0 PGP key 0x466583F9480EBE2462C46B309F1A263E15FD0AC9 not found on keyserver')
assert buildLog.contains('[ERROR] nl.dannyvanheumen:helloworld:pom:1.0 PGP key 0x466583F9480EBE2462C46B309F1A263E15FD0AC9 not found on keyserver')
assert buildLog.contains('[INFO] BUILD FAILURE')
4 changes: 2 additions & 2 deletions src/it/noKeyOK/postbuild.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
*/
def buildLog = new File( basedir, 'build.log' ).text

assert buildLog.contains('[INFO] nl.dannyvanheumen:helloworld:jar:1.0 PGP key not found on keyserver, consistent with keys map.')
assert buildLog.contains('[INFO] nl.dannyvanheumen:helloworld:pom:1.0 PGP key not found on keyserver, consistent with keys map.')
assert buildLog.contains('[INFO] nl.dannyvanheumen:helloworld:jar:1.0 PGP key 0x466583F9480EBE2462C46B309F1A263E15FD0AC9 not found on keyserver, consistent with keys map.')
assert buildLog.contains('[INFO] nl.dannyvanheumen:helloworld:pom:1.0 PGP key 0x466583F9480EBE2462C46B309F1A263E15FD0AC9 not found on keyserver, consistent with keys map.')
assert buildLog.contains('[INFO] BUILD SUCCESS')
19 changes: 18 additions & 1 deletion src/main/java/org/simplify4u/plugins/AbstractPGPMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Parameter;
import org.simplify4u.plugins.keyserver.KeyCacheSettings;
import org.simplify4u.plugins.keyserver.KeyServerClientSettings;
import org.simplify4u.plugins.keyserver.PGPKeysCache;
import org.simplify4u.plugins.pgp.SignatureUtils;
Expand Down Expand Up @@ -63,6 +64,16 @@ public abstract class AbstractPGPMojo extends AbstractMojo {
defaultValue = "${settings.localRepository}/pgpkeys-cache")
private File pgpKeysCachePath;

/**
* When key not exist on keys servers such information will be store in cache.
* <p>
* Next checking for key existence will be done after specific hours remain.
*
* @since 1.15.0
*/
@Parameter(defaultValue = "24")
private int keyNotFoundRefreshHour;

/**
* PGP public key servers address.
*
Expand Down Expand Up @@ -139,9 +150,15 @@ protected void setupMojo() throws MojoFailureException {
.proxyName(proxyName)
.build();

KeyCacheSettings cacheSettings = KeyCacheSettings.builder()
.cachePath(pgpKeysCachePath)
.keyServers(pgpKeyServer)
.loadBalance(pgpKeyServerLoadBalance)
.notFoundRefreshHours(keyNotFoundRefreshHour)
.build();

try {
pgpKeysCache.init(pgpKeysCachePath, pgpKeyServer, pgpKeyServerLoadBalance, clientSettings);
pgpKeysCache.init(cacheSettings, clientSettings);
} catch (IOException e) {
throw new MojoFailureException(e.getMessage(), e);
}
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/simplify4u/plugins/CheckMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -294,14 +294,14 @@ protected VerificationResult processArtifactSignature(Artifact artifact, Artifac
break;
case KEY_NOT_FOUND:
if (keysMap.isKeyMissing(artifact)) {
logInfoWithQuiet("{} PGP key not found on keyserver, consistent with keys map.",
artifact::getId);
logInfoWithQuiet("{} PGP key {} not found on keyserver, consistent with keys map.",
artifact::getId, signatureCheckResult.getSignature()::getKeyId);
verificationResultBuilder.error(false);
break;
}

LOGGER.error("PGP key {} not found on keyserver for artifact {}",
signatureCheckResult.getKeyShowUrl(), artifact.getId());
LOGGER.error("{} PGP key {} not found on keyserver",
artifact.getId(), signatureCheckResult.getSignature().getKeyId());
verificationResultBuilder.error(true);
break;
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2021 Slawomir Jaranowski
*
* 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.simplify4u.plugins.keyserver;

import java.io.File;

import lombok.Builder;
import lombok.Value;

/**
* Provide settings for key cache.
*/
@Builder
@Value
public class KeyCacheSettings {

File cachePath;

String keyServers;

boolean loadBalance;

int notFoundRefreshHours;
}
62 changes: 53 additions & 9 deletions src/main/java/org/simplify4u/plugins/keyserver/PGPKeysCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import javax.inject.Named;

import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static org.simplify4u.plugins.utils.ExceptionUtils.getMessage;

import io.vavr.control.Try;
Expand All @@ -63,6 +64,7 @@ public class PGPKeysCache {
private static final Pattern KEY_SERVERS_SPLIT_PATTERN = Pattern.compile("[;,\\s]");

private File cachePath;
private int notFoundRefreshHours;
private KeyServerList keyServerList;

PGPKeysCache() {
Expand All @@ -71,23 +73,22 @@ public class PGPKeysCache {
/**
* Init Keys cache.
*
* @param cachePath a path where cache will be stored
* @param keyServers a list of key servers addresses
* @param loadBalance if use key servers list in balance mode
* @param cacheSettings a key cache settings
* @param clientSettings a kay server client settings
*
* @throws IOException in case of problems
*/
public void init(File cachePath, String keyServers, boolean loadBalance, KeyServerClientSettings clientSettings)
public void init(KeyCacheSettings cacheSettings, KeyServerClientSettings clientSettings)
throws IOException {
init(cachePath, prepareClients(keyServers, clientSettings), loadBalance);
init(cacheSettings, prepareClients(cacheSettings.getKeyServers(), clientSettings));
}

// used by test
void init(File cachePath, List<PGPKeysServerClient> pgpKeysServerClients, boolean loadBalance) throws IOException {
void init(KeyCacheSettings cacheSettings, List<PGPKeysServerClient> pgpKeysServerClients) throws IOException {

this.cachePath = cachePath;
this.keyServerList = createKeyServerList(pgpKeysServerClients, loadBalance);
this.cachePath = cacheSettings.getCachePath();
this.notFoundRefreshHours = cacheSettings.getNotFoundRefreshHours();
this.keyServerList = createKeyServerList(pgpKeysServerClients, cacheSettings.isLoadBalance());

LOGGER.info("Key server(s) - {}", keyServerList);

Expand Down Expand Up @@ -166,6 +167,8 @@ public PGPPublicKeyRing getKeyRing(KeyId keyID) throws IOException {

synchronized (LOCK) {

checkNotFoundCache(path);

if (keyFile.exists()) {
// load from cache
Optional<PGPPublicKeyRing> keyRing = loadKeyFromFile(keyFile, keyID);
Expand All @@ -175,7 +178,48 @@ public PGPPublicKeyRing getKeyRing(KeyId keyID) throws IOException {
}

// key not exists in cache or something wrong with cache, so receive from servers
return keyServerList.execute(keysServerClient -> receiveKey(keyFile, keyID, keysServerClient));
return Try.of(() -> keyServerList.execute(keysServerClient -> receiveKey(keyFile, keyID, keysServerClient)))
.onFailure(PGPKeyNotFound.class, e -> writeNotFoundCache(path))
.get();
}
}

private void writeNotFoundCache(String keyFilePath) {

File file = new File(cachePath, keyFilePath + ".404");

try {
Files.write(file.toPath(), String.valueOf(System.currentTimeMillis()).getBytes(US_ASCII));
} catch (IOException e) {
LOGGER.warn("Write file: {} exception: {}", file, getMessage(e));
deleteFile(file);
}
}

private void checkNotFoundCache(String keyFilePath) throws PGPKeyNotFound {

File file = new File(cachePath, keyFilePath + ".404");

if (file.isFile()) {

long markTime = Try.of(() -> {
byte[] cacheContent = Files.readAllBytes(file.toPath());
return Long.parseLong(new String(cacheContent, US_ASCII));
})
.onFailure(e -> LOGGER.warn("Read cache file: {}", file, e))
.getOrElse(0L);

Duration elapsedTime = Duration.ofMillis(System.currentTimeMillis() - markTime);

if (elapsedTime.toHours() > notFoundRefreshHours) {
LOGGER.debug("KeyNotFound remove cache {} - mark time: {} elapsed: {}",
file, markTime, elapsedTime);
deleteFile(file);
} else {
LOGGER.debug("KeyNotFound from cache {} - mark time: {} elapsed: {}",
file, markTime, elapsedTime);
throw new PGPKeyNotFound();
}
}
}

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

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
Expand Down Expand Up @@ -95,7 +93,7 @@ void shouldExecute() throws MojoFailureException, MojoExecutionException, IOExce

// then
verify(mojo).executeConfiguredMojo();
verify(pgpKeysCache).init(isNull(), isNull(), eq(false), any());
verify(pgpKeysCache).init(any(), any());
verifyNoInteractions(logger);
}
}
9 changes: 4 additions & 5 deletions src/test/java/org/simplify4u/plugins/ShowMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import static org.mockito.ArgumentMatchers.anyCollection;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
Expand Down Expand Up @@ -124,7 +123,7 @@ void shouldProcessArtifact() throws MojoFailureException, MojoExecutionException
verify(signatureUtils).checkSignature(artifact, artifactAsc, pgpKeysCache);
verify(signatureUtils).keyAlgorithmName(anyInt());

verify(pgpKeysCache).init(isNull(), isNull(), eq(false), any());
verify(pgpKeysCache).init(any(), any());

verifyNoMoreInteractions(artifactResolver, pgpKeysCache, signatureUtils, repositorySystem);
}
Expand All @@ -151,7 +150,7 @@ void shouldProcessArtifactWithPom() throws MojoFailureException, MojoExecutionEx
verify(artifactResolver).resolveSignatures(anyCollection());


verify(pgpKeysCache).init(isNull(), isNull(), eq(false), any());
verify(pgpKeysCache).init(any(), any());

verifyNoMoreInteractions(artifactResolver, pgpKeysCache, signatureUtils, repositorySystem);
}
Expand Down Expand Up @@ -189,7 +188,7 @@ void shouldFailForNotResolvedArtifact() throws IOException {

verify(signatureUtils).keyAlgorithmName(anyInt());

verify(pgpKeysCache).init(isNull(), isNull(), eq(false), any());
verify(pgpKeysCache).init(any(), any());

verifyNoMoreInteractions(artifactResolver, pgpKeysCache, signatureUtils, repositorySystem);
}
Expand Down Expand Up @@ -228,7 +227,7 @@ void shouldFailForNotResolvedSignature() throws MojoExecutionException, IOExcept

verify(signatureUtils).keyAlgorithmName(anyInt());

verify(pgpKeysCache).init(isNull(), isNull(), eq(false), any());
verify(pgpKeysCache).init(any(), any());

verifyNoMoreInteractions(artifactResolver, pgpKeysCache, signatureUtils, repositorySystem);
}
Expand Down
Loading