Skip to content

Commit

Permalink
Merge pull request #336 from s4u/fix-313
Browse files Browse the repository at this point in the history
Store key not found result in cache
  • Loading branch information
slawekjaranowski authored Nov 12, 2021
2 parents 9068a12 + c843271 commit 93f19a0
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 32 deletions.
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

0 comments on commit 93f19a0

Please sign in to comment.