From 38061283e8b00617360efd328824d18df6a2e819 Mon Sep 17 00:00:00 2001 From: Slawomir Jaranowski Date: Sun, 28 Mar 2021 00:04:30 +0100 Subject: [PATCH] detect and merge duplicate items in keysMap --- pom.xml | 14 +- src/it/sigOkKeysMap/keysmap.list | 6 +- .../keysmap.list | 2 +- src/it/sigOkKeysMapWithPlugins/keysmap.list | 2 +- .../plugins/keysmap/ArtifactData.java | 21 +-- ...ArtifactInfo.java => ArtifactPattern.java} | 44 +++---- .../simplify4u/plugins/keysmap/KeyInfo.java | 95 -------------- .../{KeyInfoItem.java => KeyItem.java} | 9 +- ...InfoItemAnyKey.java => KeyItemAnyKey.java} | 18 ++- ...emBrokenSig.java => KeyItemBrokenSig.java} | 17 ++- ...foItemKey.java => KeyItemFingerprint.java} | 41 +++--- ...eyInfoItemNoKey.java => KeyItemNoKey.java} | 17 ++- ...eyInfoItemNoSig.java => KeyItemNoSig.java} | 17 ++- .../simplify4u/plugins/keysmap/KeyItems.java | 122 ++++++++++++++++++ .../simplify4u/plugins/keysmap/KeysMap.java | 92 +++++++------ .../plugins/keysmap/KeysMapContext.java | 40 ++++++ .../simplify4u/plugins/utils/HexUtils.java | 39 +++++- ...InfoTest.java => ArtifactPatternTest.java} | 23 ++-- .../plugins/keysmap/KeyItemAnyKeyTest.java | 33 +++++ .../plugins/keysmap/KeyItemBrokenSigTest.java | 33 +++++ .../keysmap/KeyItemFingerprintTest.java | 48 +++++++ .../plugins/keysmap/KeyItemNoKeyTest.java | 34 +++++ .../plugins/keysmap/KeyItemNoSigTest.java | 34 +++++ .../{KeyInfoTest.java => KeyItemsTest.java} | 34 ++--- .../plugins/keysmap/KeysMapMultiTest.java | 2 +- .../plugins/keysmap/KeysMapTest.java | 31 +++++ src/test/resources/keysMap.list | 7 +- 27 files changed, 626 insertions(+), 249 deletions(-) rename src/main/java/org/simplify4u/plugins/keysmap/{ArtifactInfo.java => ArtifactPattern.java} (87%) delete mode 100644 src/main/java/org/simplify4u/plugins/keysmap/KeyInfo.java rename src/main/java/org/simplify4u/plugins/keysmap/{KeyInfoItem.java => KeyItem.java} (91%) rename src/main/java/org/simplify4u/plugins/keysmap/{KeyInfoItemAnyKey.java => KeyItemAnyKey.java} (71%) rename src/main/java/org/simplify4u/plugins/keysmap/{KeyInfoItemBrokenSig.java => KeyItemBrokenSig.java} (70%) rename src/main/java/org/simplify4u/plugins/keysmap/{KeyInfoItemKey.java => KeyItemFingerprint.java} (65%) rename src/main/java/org/simplify4u/plugins/keysmap/{KeyInfoItemNoKey.java => KeyItemNoKey.java} (71%) rename src/main/java/org/simplify4u/plugins/keysmap/{KeyInfoItemNoSig.java => KeyItemNoSig.java} (70%) create mode 100644 src/main/java/org/simplify4u/plugins/keysmap/KeyItems.java create mode 100644 src/main/java/org/simplify4u/plugins/keysmap/KeysMapContext.java rename src/test/java/org/simplify4u/plugins/keysmap/{ArtifactInfoTest.java => ArtifactPatternTest.java} (83%) create mode 100644 src/test/java/org/simplify4u/plugins/keysmap/KeyItemAnyKeyTest.java create mode 100644 src/test/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSigTest.java create mode 100644 src/test/java/org/simplify4u/plugins/keysmap/KeyItemFingerprintTest.java create mode 100644 src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoKeyTest.java create mode 100644 src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoSigTest.java rename src/test/java/org/simplify4u/plugins/keysmap/{KeyInfoTest.java => KeyItemsTest.java} (75%) diff --git a/pom.xml b/pom.xml index e98d743d..f10c32a0 100644 --- a/pom.xml +++ b/pom.xml @@ -497,6 +497,16 @@ + + org.simplify4u.plugins + sign-maven-plugin + + + + pre-integration-test + + + org.apache.maven.plugins maven-failsafe-plugin @@ -581,7 +591,9 @@ ${maven.test.skip} true - org.simplify4u:slf4j-mock:jar:* + + org.simplify4u:slf4j-mock:jar:* + diff --git a/src/it/sigOkKeysMap/keysmap.list b/src/it/sigOkKeysMap/keysmap.list index caa3ae83..2f5e967a 100644 --- a/src/it/sigOkKeysMap/keysmap.list +++ b/src/it/sigOkKeysMap/keysmap.list @@ -16,10 +16,10 @@ org.hamcrest:hamcrest-core:1.3 = 0x4DB1A49729B053CAF015CEE9A6ADFC93EF34893E # sub key test -junit:junit:4.12 = 0xEFE8086F9E93774E +junit:junit:4.12 = 0xEFE8086F9E93774E, 0xEFE8086F9E93774E -commons-chain:commons-chain:1.2 = 0xB95BBD3FA43C4492, \ - 0x1861C322C56014B2 +commons-chain:commons-chain:1.2 = 0xB95BBD3FA43C4492 +commons-chain:commons-chain:1.2 = 0x1861C322C56014B2 # master key test ognl = 0xE157EEB8D208EEB23F5723AC06F21382801CEF5F diff --git a/src/it/sigOkKeysMapWithPluginDependencies/keysmap.list b/src/it/sigOkKeysMapWithPluginDependencies/keysmap.list index 483cb586..72733248 100644 --- a/src/it/sigOkKeysMapWithPluginDependencies/keysmap.list +++ b/src/it/sigOkKeysMapWithPluginDependencies/keysmap.list @@ -20,7 +20,7 @@ junit:junit:4.12=0xEFE8086F9E93774E commons-chain:commons-chain:1.2=0xB95BBD3FA43C4492,0x1861C322C56014B2 # # Plugins: -org.simplify4u.plugins:pgpverify-maven-plugin:*= +org.simplify4u.plugins:pgpverify-maven-plugin = noSig, 0x57EB3F12030A57BAA31CAAD5BE3E2A5CB80794EE # # Transitive dependencies of plugins: antlr:antlr:2.7.2 = diff --git a/src/it/sigOkKeysMapWithPlugins/keysmap.list b/src/it/sigOkKeysMapWithPlugins/keysmap.list index 6c257635..27ff0d6c 100644 --- a/src/it/sigOkKeysMapWithPlugins/keysmap.list +++ b/src/it/sigOkKeysMapWithPlugins/keysmap.list @@ -19,7 +19,7 @@ junit:junit:4.12=0xEFE8086F9E93774E commons-chain:commons-chain:1.2=0xB95BBD3FA43C4492,0x1861C322C56014B2 # # Plugins: -org.simplify4u.plugins:pgpverify-maven-plugin = noSig, 0x6636274B2E8BEA9D15A61143F8484389379ACEAC +org.simplify4u.plugins:pgpverify-maven-plugin = noSig, 0x57EB3F12030A57BAA31CAAD5BE3E2A5CB80794EE org.apache.maven.plugins = \ 0x6A814B1F869C2BBEAB7CB7271A2A1C94BDE89688, \ diff --git a/src/main/java/org/simplify4u/plugins/keysmap/ArtifactData.java b/src/main/java/org/simplify4u/plugins/keysmap/ArtifactData.java index cf8fa579..e95f1f58 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/ArtifactData.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/ArtifactData.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Slawomir Jaranowski + * 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. @@ -17,6 +17,7 @@ import java.util.Locale; +import lombok.Getter; import org.apache.maven.artifact.Artifact; /** @@ -26,6 +27,7 @@ * * @author Slawomir Jaranowski. */ +@Getter class ArtifactData { private final String groupId; @@ -34,26 +36,9 @@ class ArtifactData { private final String version; ArtifactData(Artifact artifact) { - groupId = artifact.getGroupId().toLowerCase(Locale.US); artifactId = artifact.getArtifactId().toLowerCase(Locale.US); type = artifact.getType().toLowerCase(Locale.US); version = artifact.getVersion().toLowerCase(Locale.US); } - - public String getGroupId() { - return groupId; - } - - public String getArtifactId() { - return artifactId; - } - - public String getType() { - return type; - } - - public String getVersion() { - return version; - } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/ArtifactInfo.java b/src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java similarity index 87% rename from src/main/java/org/simplify4u/plugins/keysmap/ArtifactInfo.java rename to src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java index e955bd99..36e2ef80 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/ArtifactInfo.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/ArtifactPattern.java @@ -21,33 +21,38 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import lombok.EqualsAndHashCode; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; -import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.openpgp.PGPPublicKeyRing; /** * Store information about artifact definition from KeysMap file. * * @author Slawomir Jaranowski. */ -class ArtifactInfo { +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +class ArtifactPattern { - private final KeyInfo keyInfo; + private static final Pattern DOT_REPLACE = Pattern.compile("\\."); + private static final Pattern STAR_REPLACE = Pattern.compile("\\*"); + private static final Pattern PACKAGING = Pattern.compile("^[a-zA-Z]+$"); + + /** + * Original pattern from keysMap. Used to compare if object is equal to another. + */ + @EqualsAndHashCode.Include + private final String pattern; private final Pattern groupIdPattern; private final Pattern artifactIdPattern; private final Pattern packagingPattern; private final Function versionMatch; - private static final Pattern DOT_REPLACE = Pattern.compile("\\."); - private static final Pattern STAR_REPLACE = Pattern.compile("\\*"); - private static final Pattern PACKAGING = Pattern.compile("^[a-zA-Z]+$"); - - public ArtifactInfo(String strArtifact, KeyInfo keyInfo) { + public ArtifactPattern(String pattern) { - String[] split = strArtifact.split(":"); + this.pattern = pattern; + String[] split = this.pattern.split(":"); String groupId = split.length > 0 ? split[0].trim().toLowerCase(Locale.US) : ""; String artifactId = split.length > 1 ? split[1].trim().toLowerCase(Locale.US) : ""; @@ -75,9 +80,8 @@ public ArtifactInfo(String strArtifact, KeyInfo keyInfo) { packagingPattern = Pattern.compile(patternPrepare(packaging)); versionMatch = versionMatchPrepare(version); } catch (InvalidVersionSpecificationException | PatternSyntaxException e) { - throw new IllegalArgumentException("Invalid artifact definition: " + strArtifact, e); + throw new IllegalArgumentException("Invalid artifact definition: " + pattern, e); } - this.keyInfo = keyInfo; } private static String patternPrepare(String str) { @@ -146,20 +150,4 @@ private static boolean isMatchPattern(Pattern pattern, String str) { Matcher m = pattern.matcher(str); return m.matches(); } - - public boolean isKeyMatch(PGPPublicKey key, PGPPublicKeyRing keyRing) { - return keyInfo.isKeyMatch(key, keyRing); - } - - public boolean isNoSignature() { - return keyInfo.isNoSignature(); - } - - public boolean isBrokenSignature() { - return keyInfo.isBrokenSignature(); - } - - public boolean isKeyMissing() { - return keyInfo.isKeyMissing(); - } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfo.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyInfo.java deleted file mode 100644 index ccc4e9a6..00000000 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfo.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2020 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.keysmap; - -import java.util.AbstractMap.SimpleEntry; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.bouncycastle.openpgp.PGPPublicKey; -import org.bouncycastle.openpgp.PGPPublicKeyRing; - -/** - * Store info about key numbers. - * - * @author Slawomir Jaranowski. - */ -class KeyInfo { - - private static final Map SPECIAL_KEYS = Stream.of( - new SimpleEntry<>("*", new KeyInfoItemAnyKey()), - new SimpleEntry<>("any", new KeyInfoItemAnyKey()), - new SimpleEntry<>("badSig", new KeyInfoItemBrokenSig()), - new SimpleEntry<>("noKey", new KeyInfoItemNoKey()), - new SimpleEntry<>("noSig", new KeyInfoItemNoSig()) - ).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - - private final List keys = new ArrayList<>(); - - - public KeyInfo(String strKeys) { - - if (strKeys == null) { - throw new IllegalArgumentException("null key not allowed"); - } - - // compatibility behavior - if (strKeys.trim().isEmpty()) { - keys.add(new KeyInfoItemNoSig()); - return; - } - - Arrays.stream(strKeys.split(",")) - .map(String::trim) - .forEach(key -> { - - if (key.startsWith("0x")) { - keys.add(new KeyInfoItemKey(key)); - } else { - - Optional keyInfoItem = SPECIAL_KEYS.entrySet().stream() - .filter(entry -> entry.getKey().equalsIgnoreCase(key)) - .map(Entry::getValue) - .findFirst(); - keys.add(keyInfoItem.orElseThrow(() - -> new IllegalArgumentException("Invalid keyID " + key + " must start with 0x " - + "or be any of " + SPECIAL_KEYS.keySet()))); - } - }); - } - - public boolean isKeyMatch(PGPPublicKey pgpPublicKey, PGPPublicKeyRing pgpPublicKeyRing) { - return keys.stream().anyMatch(keyInfoItem -> keyInfoItem.isKeyMatch(pgpPublicKey, pgpPublicKeyRing)); - } - - public boolean isNoSignature() { - return keys.stream().anyMatch(KeyInfoItem::isNoSignature); - } - - public boolean isKeyMissing() { - return keys.stream().anyMatch(KeyInfoItem::isKeyMissing); - } - - public boolean isBrokenSignature() { - return keys.stream().anyMatch(KeyInfoItem::isBrokenSignature); - } -} diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItem.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItem.java similarity index 91% rename from src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItem.java rename to src/main/java/org/simplify4u/plugins/keysmap/KeyItem.java index be93eb53..decfb842 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItem.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItem.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Slawomir Jaranowski + * 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. @@ -18,7 +18,10 @@ import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; -public interface KeyInfoItem { +/** + * Describe single key item in keysMap. + */ +interface KeyItem { /** * Artifact can has no signature. @@ -50,7 +53,7 @@ default boolean isKeyMissing() { /** * Check if current key mach with given key. * - * @param pgpPublicKey key to test + * @param pgpPublicKey key to test * @param pgpPublicKeyRing keys ring to find master key * * @return key matching status diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemAnyKey.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemAnyKey.java similarity index 71% rename from src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemAnyKey.java rename to src/main/java/org/simplify4u/plugins/keysmap/KeyItemAnyKey.java index abd80822..e749614e 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemAnyKey.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemAnyKey.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Slawomir Jaranowski + * 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. @@ -15,13 +15,27 @@ */ package org.simplify4u.plugins.keysmap; +import lombok.EqualsAndHashCode; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; -public class KeyInfoItemAnyKey implements KeyInfoItem { +/** + * Special key value. + *

+ * Given artifact pattern can has any kay. + */ +@EqualsAndHashCode +class KeyItemAnyKey implements KeyItem { + + public static final String DESC = "any"; @Override public boolean isKeyMatch(PGPPublicKey pgpPublicKey, PGPPublicKeyRing pgpPublicKeyRing) { return true; } + + @Override + public String toString() { + return DESC; + } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemBrokenSig.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSig.java similarity index 70% rename from src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemBrokenSig.java rename to src/main/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSig.java index 5625f5d6..eb690380 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemBrokenSig.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSig.java @@ -15,10 +15,25 @@ */ package org.simplify4u.plugins.keysmap; -public class KeyInfoItemBrokenSig implements KeyInfoItem { +import lombok.EqualsAndHashCode; + +/** + * Special key value. + *

+ * Given artifact pattern can has broken signature. + */ +@EqualsAndHashCode +class KeyItemBrokenSig implements KeyItem { + + public static final String DESC = "badSig"; @Override public boolean isBrokenSignature() { return true; } + + @Override + public String toString() { + return DESC; + } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemKey.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemFingerprint.java similarity index 65% rename from src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemKey.java rename to src/main/java/org/simplify4u/plugins/keysmap/KeyItemFingerprint.java index af4eeb3b..4573be0c 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemKey.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemFingerprint.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Slawomir Jaranowski + * 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. @@ -17,18 +17,24 @@ import java.util.Optional; +import static org.simplify4u.plugins.utils.HexUtils.stringToFingerprint; + +import lombok.EqualsAndHashCode; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; -import org.bouncycastle.util.encoders.DecoderException; -import org.bouncycastle.util.encoders.Hex; +import org.simplify4u.plugins.utils.HexUtils; import org.simplify4u.plugins.utils.PublicKeyUtils; -public class KeyInfoItemKey implements KeyInfoItem { +/** + * Represent key as fingerprint for given artifact pattern. + */ +@EqualsAndHashCode +class KeyItemFingerprint implements KeyItem { private final byte[] fingerPrint; - public KeyInfoItemKey(String key) { - fingerPrint = strKeyToBytes(key); + public KeyItemFingerprint(String key) { + fingerPrint = stringToFingerprint(key); } @Override @@ -42,24 +48,6 @@ public boolean isKeyMatch(PGPPublicKey pgpPublicKey, PGPPublicKeyRing pgpPublicK return masterKey.filter(publicKey -> isKeyMatch(publicKey, pgpPublicKeyRing)).isPresent(); } - private static byte[] strKeyToBytes(String key) { - byte[] bytes; - - try { - bytes = Hex.decode(key.substring(2)); - } catch (DecoderException e) { - throw new IllegalArgumentException("Malformed keyID hex string " + key, e); - } - - if (bytes.length < 8 || bytes.length > 20) { - throw new IllegalArgumentException( - String.format("Key length for = %s is %d bits, should be between 64 and 160 bits", - key, bytes.length * 8)); - } - - return bytes; - } - private static boolean compareArrays(byte[] keyBytes, byte[] fingerprint) { for (int i = 1; i <= keyBytes.length && i <= fingerprint.length; i++) { @@ -69,4 +57,9 @@ private static boolean compareArrays(byte[] keyBytes, byte[] fingerprint) { } return true; } + + @Override + public String toString() { + return HexUtils.fingerprintToString(fingerPrint); + } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemNoKey.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemNoKey.java similarity index 71% rename from src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemNoKey.java rename to src/main/java/org/simplify4u/plugins/keysmap/KeyItemNoKey.java index 59d8f714..59adbfa3 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemNoKey.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemNoKey.java @@ -15,10 +15,25 @@ */ package org.simplify4u.plugins.keysmap; -public class KeyInfoItemNoKey implements KeyInfoItem { +import lombok.EqualsAndHashCode; + +/** + * Special key value. + *

+ * Given artifact pattern can has no key. + */ +@EqualsAndHashCode +class KeyItemNoKey implements KeyItem { + + public static final String DESC = "noKey"; @Override public boolean isKeyMissing() { return true; } + + @Override + public String toString() { + return DESC; + } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemNoSig.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemNoSig.java similarity index 70% rename from src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemNoSig.java rename to src/main/java/org/simplify4u/plugins/keysmap/KeyItemNoSig.java index 5f923adb..5283e925 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeyInfoItemNoSig.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItemNoSig.java @@ -15,10 +15,25 @@ */ package org.simplify4u.plugins.keysmap; -public class KeyInfoItemNoSig implements KeyInfoItem { +import lombok.EqualsAndHashCode; + +/** + * Special key value. + *

+ * Given artifact pattern can has no signature. + */ +@EqualsAndHashCode +class KeyItemNoSig implements KeyItem { + + public static final String DESC = "noSig"; @Override public boolean isNoSignature() { return true; } + + @Override + public String toString() { + return DESC; + } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeyItems.java b/src/main/java/org/simplify4u/plugins/keysmap/KeyItems.java new file mode 100644 index 00000000..3a2e243d --- /dev/null +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeyItems.java @@ -0,0 +1,122 @@ +/* + * 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.keysmap; + +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPPublicKeyRing; + +/** + * Store list of fingerprints and special key value for given artifact pattern in keysMap. + * + * @author Slawomir Jaranowski. + */ +@Slf4j +class KeyItems { + + private static final Map SPECIAL_KEYS = Stream.of( + new SimpleEntry<>("*", new KeyItemAnyKey()), + new SimpleEntry<>(KeyItemAnyKey.DESC, new KeyItemAnyKey()), + new SimpleEntry<>(KeyItemBrokenSig.DESC, new KeyItemBrokenSig()), + new SimpleEntry<>(KeyItemNoKey.DESC, new KeyItemNoKey()), + new SimpleEntry<>(KeyItemNoSig.DESC, new KeyItemNoSig()) + ).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + + private final List keys = new ArrayList<>(); + + /** + * Add new keys to current list. + * + * @param strKeys a keys definition from keysMap + * @param keysMapContext a context of current processing + * + * @return a current object instance + */ + public KeyItems addKeys(String strKeys, KeysMapContext keysMapContext) { + + if (strKeys == null) { + throw new IllegalArgumentException("null key not allowed in " + keysMapContext); + } + + // compatibility behavior + if (strKeys.trim().isEmpty()) { + LOGGER.warn("Empty value for key is deprecated - please provide some value - now assume as noSig in: {}", + keysMapContext); + addKey(SPECIAL_KEYS.get(KeyItemNoSig.DESC), keysMapContext); + return this; + } + + Arrays.stream(strKeys.split(",")) + .map(String::trim) + .forEach(key -> { + + if (key.startsWith("0x")) { + addKey(new KeyItemFingerprint(key), keysMapContext); + } else { + + KeyItem keyInfoItem = SPECIAL_KEYS.entrySet().stream() + .filter(entry -> entry.getKey().equalsIgnoreCase(key)) + .map(Entry::getValue) + .findFirst() + .orElseThrow(() + -> new IllegalArgumentException("Invalid keyID " + key + " must start with 0x " + + "or be any of " + SPECIAL_KEYS.keySet())); + addKey(keyInfoItem, keysMapContext); + } + }); + + return this; + } + + /** + * Add key to list only if not exist. + * + * @param keyItem a key to add + * @param keysMapContext a context of current processing + */ + private void addKey(KeyItem keyItem, KeysMapContext keysMapContext) { + if (!keys.contains(keyItem)) { + keys.add(keyItem); + } else { + LOGGER.warn("Duplicate key item: {} in: {}", keyItem, keysMapContext); + } + } + + public boolean isKeyMatch(PGPPublicKey pgpPublicKey, PGPPublicKeyRing pgpPublicKeyRing) { + return keys.stream().anyMatch(keyInfoItem -> keyInfoItem.isKeyMatch(pgpPublicKey, pgpPublicKeyRing)); + } + + public boolean isNoSignature() { + return keys.stream().anyMatch(KeyItem::isNoSignature); + } + + public boolean isKeyMissing() { + return keys.stream().anyMatch(KeyItem::isKeyMissing); + } + + public boolean isBrokenSignature() { + return keys.stream().anyMatch(KeyItem::isBrokenSignature); + } +} diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeysMap.java b/src/main/java/org/simplify4u/plugins/keysmap/KeysMap.java index 8e16c925..12fb8021 100644 --- a/src/main/java/org/simplify4u/plugins/keysmap/KeysMap.java +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeysMap.java @@ -21,29 +21,30 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; import javax.inject.Named; +import lombok.extern.slf4j.Slf4j; import org.apache.maven.artifact.Artifact; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.codehaus.plexus.resource.ResourceManager; import org.codehaus.plexus.resource.loader.ResourceNotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** + * Store and manage information loaded from keysMap file. + * * @author Slawomir Jaranowski. */ +@Slf4j @Named public class KeysMap { - private static final Logger LOG = LoggerFactory.getLogger(KeysMap.class); - private ResourceManager resourceManager; - private final ArrayList keysMapList = new ArrayList<>(); + private final Map items = new HashMap<>(); @Inject KeysMap(ResourceManager resourceManager) { @@ -53,11 +54,11 @@ public class KeysMap { public void load(String locale) throws ResourceNotFoundException, IOException { if (locale != null && !locale.trim().isEmpty()) { try (final InputStream inputStream = resourceManager.getResourceAsInputStream(locale)) { - loadKeysMap(inputStream); + loadKeysMap(inputStream, new KeysMapContext(locale)); } } - if (keysMapList.isEmpty()) { - LOG.warn("No keysmap specified in configuration or keysmap contains no entries. PGPVerify will only " + + if (items.isEmpty()) { + LOGGER.warn("No keysmap specified in configuration or keysmap contains no entries. PGPVerify will only " + "check artifacts against their signature. File corruption will be detected. However, without a " + "keysmap as a reference for trust, valid signatures of any public key will be accepted."); } @@ -66,10 +67,10 @@ public void load(String locale) throws ResourceNotFoundException, IOException { /** * Indicate whether some keysmap entries are actually loaded. * - * @return Returns true iff at least one entry exists in the keysmap, or false otherwise. + * @return Returns true if at least one entry exists in the keysmap, or false otherwise. */ public boolean isEmpty() { - return keysMapList.isEmpty(); + return items.isEmpty(); } /** @@ -83,9 +84,9 @@ public boolean isNoSignature(Artifact artifact) { ArtifactData artifactData = new ArtifactData(artifact); - return keysMapList.stream() - .filter(artifactInfo -> artifactInfo.isMatch(artifactData)) - .anyMatch(ArtifactInfo::isNoSignature); + return items.entrySet().stream() + .filter(entry -> entry.getKey().isMatch(artifactData)) + .anyMatch(entry -> entry.getValue().isNoSignature()); } /** @@ -99,9 +100,9 @@ public boolean isBrokenSignature(Artifact artifact) { ArtifactData artifactData = new ArtifactData(artifact); - return keysMapList.stream() - .filter(artifactInfo -> artifactInfo.isMatch(artifactData)) - .anyMatch(ArtifactInfo::isBrokenSignature); + return items.entrySet().stream() + .filter(entry -> entry.getKey().isMatch(artifactData)) + .anyMatch(entry -> entry.getValue().isBrokenSignature()); } /** @@ -115,44 +116,61 @@ public boolean isKeyMissing(Artifact artifact) { ArtifactData artifactData = new ArtifactData(artifact); - return keysMapList.stream() - .filter(artifactInfo -> artifactInfo.isMatch(artifactData)) - .anyMatch(ArtifactInfo::isKeyMissing); + return items.entrySet().stream() + .filter(entry -> entry.getKey().isMatch(artifactData)) + .anyMatch(entry -> entry.getValue().isKeyMissing()); } public boolean isWithKey(Artifact artifact) { ArtifactData artifactData = new ArtifactData(artifact); - for (ArtifactInfo artifactInfo : keysMapList) { - if (artifactInfo.isMatch(artifactData)) { - return !artifactInfo.isNoSignature(); - } - } - return false; + return items.entrySet().stream() + .filter(entry -> entry.getKey().isMatch(artifactData)) + .anyMatch(entry -> !entry.getValue().isNoSignature()); } public boolean isValidKey(Artifact artifact, PGPPublicKey key, PGPPublicKeyRing keyRing) { - if (keysMapList.isEmpty()) { + if (items.isEmpty()) { return true; } ArtifactData artifactData = new ArtifactData(artifact); - return keysMapList.stream() - .filter(artifactInfo -> artifactInfo.isMatch(artifactData)) - .anyMatch(artifactInfo -> artifactInfo.isKeyMatch(key, keyRing)); + return items.entrySet().stream() + .filter(entry -> entry.getKey().isMatch(artifactData)) + .anyMatch(entry -> entry.getValue().isKeyMatch(key, keyRing)); } - private void loadKeysMap(final InputStream inputStream) throws IOException { - BufferedReader mapReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.US_ASCII)); + private void loadKeysMap(final InputStream inputStream, KeysMapContext keysMapContext) throws IOException { + + BufferedReader mapReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.US_ASCII)) { + + @Override + public String readLine() throws IOException { + keysMapContext.incLineNumber(); + return super.readLine(); + } + }; + String currentLine; while ((currentLine = getNextLine(mapReader)) != null) { + String[] parts = currentLine.split("=", 2); - ArtifactInfo artifactInfo = createArtifactInfo(parts[0], parts.length == 1 ? "" : parts[1]); - keysMapList.add(artifactInfo); + String artifactPatternStr = parts[0].trim(); + String keyItemsStr = parts.length == 1 ? "" : parts[1].trim(); + + ArtifactPattern artifactPattern = new ArtifactPattern(artifactPatternStr); + + if (items.containsKey(artifactPattern)) { + LOGGER.debug("Existing artifact pattern: {} - only update key items in {}", + artifactPatternStr, keysMapContext); + items.get(artifactPattern).addKeys(keyItemsStr, keysMapContext); + } else { + items.put(artifactPattern, new KeyItems().addKeys(keyItemsStr, keysMapContext)); + } } } @@ -198,13 +216,9 @@ private static String stripComments(String line) { return hashIndex >= 0 ? line.substring(0, hashIndex).trim() : line; } - private static ArtifactInfo createArtifactInfo(String strArtifact, String strKeys) { - return new ArtifactInfo(strArtifact.trim(), new KeyInfo(strKeys.trim())); - } - // for testing purpose int size() { - return keysMapList.size(); + return items.size(); } } diff --git a/src/main/java/org/simplify4u/plugins/keysmap/KeysMapContext.java b/src/main/java/org/simplify4u/plugins/keysmap/KeysMapContext.java new file mode 100644 index 00000000..98fe851f --- /dev/null +++ b/src/main/java/org/simplify4u/plugins/keysmap/KeysMapContext.java @@ -0,0 +1,40 @@ +/* + * 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.keysmap; + +/** + * Store information about current location in keysMap during processing. + * + * @author Slawomir Jaranowski + */ +class KeysMapContext { + + String name; + int lineNumber; + + KeysMapContext(String name) { + this.name = name; + } + + void incLineNumber() { + lineNumber++; + } + + @Override + public String toString() { + return "keysMap: " + name + " lineNumber: " + lineNumber; + } +} diff --git a/src/main/java/org/simplify4u/plugins/utils/HexUtils.java b/src/main/java/org/simplify4u/plugins/utils/HexUtils.java index 18a6c4ae..e6e26f4f 100644 --- a/src/main/java/org/simplify4u/plugins/utils/HexUtils.java +++ b/src/main/java/org/simplify4u/plugins/utils/HexUtils.java @@ -15,11 +15,21 @@ */ package org.simplify4u.plugins.utils; -public final class HexUtils { +import lombok.experimental.UtilityClass; +import org.bouncycastle.util.encoders.DecoderException; +import org.bouncycastle.util.encoders.Hex; - private HexUtils() { - } +/** + * Utility for converting finger to / from string + */ +@UtilityClass +public class HexUtils { + /** + * Convert byte array of fingerprint to string of hex + * @param bytes fingerprint + * @return fingerprint as string + */ public static String fingerprintToString(byte[] bytes) { StringBuilder ret = new StringBuilder(); ret.append("0x"); @@ -28,4 +38,27 @@ public static String fingerprintToString(byte[] bytes) { } return ret.toString(); } + + /** + * Convert fingerprint in string format to byte array. + * @param key fingerprint as string + * @return fingerprint as byte array + */ + public static byte[] stringToFingerprint(String key) { + byte[] bytes; + + try { + bytes = Hex.decode(key.substring(2)); + } catch (DecoderException e) { + throw new IllegalArgumentException("Malformed keyID hex string " + key, e); + } + + if (bytes.length < 8 || bytes.length > 20) { + throw new IllegalArgumentException( + String.format("Key length for = %s is %d bits, should be between 64 and 160 bits", + key, bytes.length * 8)); + } + + return bytes; + } } diff --git a/src/test/java/org/simplify4u/plugins/keysmap/ArtifactInfoTest.java b/src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java similarity index 83% rename from src/test/java/org/simplify4u/plugins/keysmap/ArtifactInfoTest.java rename to src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java index d7156ebe..e6c362a6 100644 --- a/src/test/java/org/simplify4u/plugins/keysmap/ArtifactInfoTest.java +++ b/src/test/java/org/simplify4u/plugins/keysmap/ArtifactPatternTest.java @@ -27,9 +27,7 @@ /** * @author Slawomir Jaranowski. */ -public class ArtifactInfoTest { - - private static final KeyInfo ANY_KEY = new KeyInfo("*"); +public class ArtifactPatternTest { @DataProvider(name = "lists") public Object[][] artifactsList() { @@ -64,15 +62,14 @@ public Object[][] artifactsList() { @Test(dataProvider = "lists") public void testMatchArtifact(String pattern, Artifact artifact, boolean match) { - ArtifactInfo artifactInfo = new ArtifactInfo(pattern, ANY_KEY); - assertThat(artifactInfo.isMatch(new ArtifactData(artifact))).isEqualTo(match); - assertThat(artifactInfo.isKeyMatch(null, null)).isTrue(); + ArtifactPattern artifactPattern = new ArtifactPattern(pattern); + assertThat(artifactPattern.isMatch(new ArtifactData(artifact))).isEqualTo(match); } @Test public void asteriskInVersionThrowException() { - assertThatCode(() -> new ArtifactInfo("test.group:test:1.0.*", ANY_KEY)) + assertThatCode(() -> new ArtifactPattern("test.group:test:1.0.*")) .isExactlyInstanceOf(IllegalArgumentException.class) .hasMessage("Invalid artifact definition: test.group:test:1.0.*") .hasCauseExactlyInstanceOf(InvalidVersionSpecificationException.class) @@ -82,11 +79,21 @@ public void asteriskInVersionThrowException() { @Test public void wrongVersionThrowException() { - assertThatCode(() -> new ArtifactInfo("test.group:test:[1.0.0", ANY_KEY)) + assertThatCode(() -> new ArtifactPattern("test.group:test:[1.0.0")) .isExactlyInstanceOf(IllegalArgumentException.class) .hasMessage("Invalid artifact definition: test.group:test:[1.0.0") .hasCauseExactlyInstanceOf(InvalidVersionSpecificationException.class) .hasRootCauseMessage("Unbounded range: [1.0.0"); } + @Test + public void twoInstanceWithTheSamePatternShouldBeEqual() { + ArtifactPattern artifactPattern1 = new ArtifactPattern("test.group.*:test*"); + ArtifactPattern artifactPattern2 = new ArtifactPattern("test.group.*:test*"); + + assertThat(artifactPattern1) + .isNotSameAs(artifactPattern2) + .isEqualTo(artifactPattern2) + .hasSameHashCodeAs(artifactPattern2); + } } diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeyItemAnyKeyTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemAnyKeyTest.java new file mode 100644 index 00000000..07e7cb15 --- /dev/null +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemAnyKeyTest.java @@ -0,0 +1,33 @@ +/* + * 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.keysmap; + +import org.assertj.core.api.Assertions; +import org.testng.annotations.Test; + +public class KeyItemAnyKeyTest { + + @Test + public void twoInstanceShouldBeEqual() { + KeyItemAnyKey keyItemAnyKey1 = new KeyItemAnyKey(); + KeyItemAnyKey keyItemAnyKey2 = new KeyItemAnyKey(); + + Assertions.assertThat(keyItemAnyKey1) + .isNotSameAs(keyItemAnyKey2) + .isEqualTo(keyItemAnyKey2) + .hasSameHashCodeAs(keyItemAnyKey2); + } +} diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSigTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSigTest.java new file mode 100644 index 00000000..bae7fecb --- /dev/null +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemBrokenSigTest.java @@ -0,0 +1,33 @@ +/* + * 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.keysmap; + +import org.assertj.core.api.Assertions; +import org.testng.annotations.Test; + +public class KeyItemBrokenSigTest { + + @Test + public void twoInstanceShouldBeEqual() { + KeyItemBrokenSig keyItemBrokenSig1 = new KeyItemBrokenSig(); + KeyItemBrokenSig keyItemBrokenSig2 = new KeyItemBrokenSig(); + + Assertions.assertThat(keyItemBrokenSig1) + .isNotSameAs(keyItemBrokenSig2) + .isEqualTo(keyItemBrokenSig2) + .hasSameHashCodeAs(keyItemBrokenSig2); + } +} diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeyItemFingerprintTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemFingerprintTest.java new file mode 100644 index 00000000..ccac8911 --- /dev/null +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemFingerprintTest.java @@ -0,0 +1,48 @@ +/* + * 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.keysmap; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.testng.annotations.Test; + +public class KeyItemFingerprintTest { + + private static final String FINGERPRINT_1 = "0x9ABC DEF0 1234 5678 9ABC DEF0 1234 5678 9ABC DEF0"; + private static final String FINGERPRINT_2 = "0x9ABC DEF0 1234 5678 9ABC DEF0 1234 5678 9ABC 0000"; + + @Test + public void twoInstanceForTheSameKeyShouldBeEqual() { + KeyItemFingerprint keyItemFingerprint1 = new KeyItemFingerprint(FINGERPRINT_1); + KeyItemFingerprint keyItemFingerprint2 = new KeyItemFingerprint(FINGERPRINT_1); + + assertThat(keyItemFingerprint1) + .isNotSameAs(keyItemFingerprint2) + .isEqualTo(keyItemFingerprint2) + .hasSameHashCodeAs(keyItemFingerprint2); + } + + @Test + public void twoInstanceForTheDifferentKeyShouldNotBeEqual() { + KeyItemFingerprint keyItemFingerprint1 = new KeyItemFingerprint(FINGERPRINT_1); + KeyItemFingerprint keyItemFingerprint2 = new KeyItemFingerprint(FINGERPRINT_2); + + assertThat(keyItemFingerprint1) + .isNotSameAs(keyItemFingerprint2) + .isNotEqualTo(keyItemFingerprint2) + .doesNotHaveSameHashCodeAs(keyItemFingerprint2); + } +} diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoKeyTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoKeyTest.java new file mode 100644 index 00000000..601158c6 --- /dev/null +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoKeyTest.java @@ -0,0 +1,34 @@ +/* + * 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.keysmap; + +import org.assertj.core.api.Assertions; +import org.testng.annotations.Test; + +public class KeyItemNoKeyTest { + + @Test + public void twoInstanceShouldBeEqual() { + KeyItemNoKey keyItemNoKey1 = new KeyItemNoKey(); + KeyItemNoKey keyItemNoKey2 = new KeyItemNoKey(); + + Assertions.assertThat(keyItemNoKey1) + .isNotSameAs(keyItemNoKey2) + .isEqualTo(keyItemNoKey2) + .hasSameHashCodeAs(keyItemNoKey2); + } + +} diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoSigTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoSigTest.java new file mode 100644 index 00000000..4bc210c5 --- /dev/null +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemNoSigTest.java @@ -0,0 +1,34 @@ +/* + * 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.keysmap; + +import org.assertj.core.api.Assertions; +import org.testng.annotations.Test; + +public class KeyItemNoSigTest { + + @Test + public void twoInstanceShouldBeEqual() { + KeyItemNoSig keyItemNoSig1 = new KeyItemNoSig(); + KeyItemNoSig keyItemNoSig2 = new KeyItemNoSig(); + + Assertions.assertThat(keyItemNoSig1) + .isNotSameAs(keyItemNoSig2) + .isEqualTo(keyItemNoSig2) + .hasSameHashCodeAs(keyItemNoSig2); + } + +} diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeyInfoTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemsTest.java similarity index 75% rename from src/test/java/org/simplify4u/plugins/keysmap/KeyInfoTest.java rename to src/test/java/org/simplify4u/plugins/keysmap/KeyItemsTest.java index e754a5db..33a86995 100644 --- a/src/test/java/org/simplify4u/plugins/keysmap/KeyInfoTest.java +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeyItemsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 Slawomir Jaranowski + * 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. @@ -32,7 +32,7 @@ /** * @author Slawomir Jaranowski. */ -public class KeyInfoTest { +public class KeyItemsTest { @DataProvider(name = "keys") public Object[][] keys() { @@ -58,36 +58,36 @@ public Object[][] keys() { @Test(dataProvider = "keys") public void testIsKeyMatch(String strKeys, long key, boolean match) throws Exception { - KeyInfo keyInfo = new KeyInfo(strKeys); - assertThat(keyInfo.isKeyMatch(getPGPgpPublicKey(key), null)).as("isKeyMatch").isEqualTo(match); + KeyItems keyItems = new KeyItems().addKeys(strKeys, null); + assertThat(keyItems.isKeyMatch(getPGPgpPublicKey(key), null)).as("isKeyMatch").isEqualTo(match); } - @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "null key not allowed") + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "null key not allowed in keysMap: test.map lineNumber: 0") public void nullKeyShouldThrowsException() { - - new KeyInfo(null); + new KeyItems().addKeys(null, new KeysMapContext("test.map")); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Invalid keyID xxxx must start with 0x or be any of .*") public void invalidKeyShouldThrowsException() { - new KeyInfo("xxxx"); + new KeyItems().addKeys("xxxx", null); } @Test public void testIsNoSignature() { - KeyInfo keyInfo = new KeyInfo(""); - assertThat(keyInfo.isNoSignature()).isTrue(); + KeyItems keyItems = new KeyItems().addKeys("", null); + assertThat(keyItems.isNoSignature()).isTrue(); } @Test public void testIsNoSignatureIncorrect() { - KeyInfo keyInfo = new KeyInfo("0x123456789abcdef0"); - assertThat(keyInfo.isNoSignature()).isFalse(); + KeyItems keyItems = new KeyItems().addKeys("0x123456789abcdef0", null); + assertThat(keyItems.isNoSignature()).isFalse(); } @Test @@ -98,10 +98,10 @@ public void testSubKeyMach() throws IOException, PGPException { assertThat(aPublicKeyRing) .hasValueSatisfying(publicKeyRing -> { - // keyInfo with master key fingerprint - KeyInfo keyInfo = new KeyInfo(PublicKeyUtils.fingerprint(publicKeyRing.getPublicKey())); + // keyItems with master key fingerprint + KeyItems keyItems = new KeyItems().addKeys(PublicKeyUtils.fingerprint(publicKeyRing.getPublicKey()), null); - assertThat(keyInfo.isKeyMatch(publicKeyRing.getPublicKey(0xEFE8086F9E93774EL), publicKeyRing)) + assertThat(keyItems.isKeyMatch(publicKeyRing.getPublicKey(0xEFE8086F9E93774EL), publicKeyRing)) .isTrue(); }); } @@ -110,13 +110,13 @@ public void testSubKeyMach() throws IOException, PGPException { @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Malformed keyID hex string 0x123456789abcdef") public void oddHexStringShouldThrowException() { - new KeyInfo("0x123456789abcdef"); + new KeyItems().addKeys("0x123456789abcdef", null); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Malformed keyID hex string 0xINVALID") public void invalidHexStringShouldThrowException() { - new KeyInfo("0xINVALID"); + new KeyItems().addKeys("0xINVALID", null); } } diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeysMapMultiTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeysMapMultiTest.java index 94c8a927..a0eb9038 100644 --- a/src/test/java/org/simplify4u/plugins/keysmap/KeysMapMultiTest.java +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeysMapMultiTest.java @@ -58,7 +58,7 @@ public void loadMultipleKeysMapShouldContainsAllItems() throws ResourceNotFoundE keysMap.load("/keysMapMulti1.list"); keysMap.load("/keysMapMulti2.list"); - assertThat(keysMap.size()).isEqualTo(15); + assertThat(keysMap.size()).isEqualTo(9); } @DataProvider diff --git a/src/test/java/org/simplify4u/plugins/keysmap/KeysMapTest.java b/src/test/java/org/simplify4u/plugins/keysmap/KeysMapTest.java index bc31186e..92908ead 100644 --- a/src/test/java/org/simplify4u/plugins/keysmap/KeysMapTest.java +++ b/src/test/java/org/simplify4u/plugins/keysmap/KeysMapTest.java @@ -16,10 +16,14 @@ package org.simplify4u.plugins.keysmap; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.simplify4u.plugins.TestArtifactBuilder.testArtifact; import static org.simplify4u.plugins.TestUtils.getPGPgpPublicKey; @@ -28,6 +32,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; +import org.slf4j.Logger; import org.testng.annotations.Listeners; import org.testng.annotations.Test; @@ -40,6 +45,12 @@ public class KeysMapTest { @Mock private ResourceManager resourceManager; + @Mock(name = "org.simplify4u.plugins.keysmap.KeysMap") + private Logger loggerKeysMap; + + @Mock(name = "org.simplify4u.plugins.keysmap.KeyItems") + private Logger loggerKeyItems; + @InjectMocks private KeysMap keysMap; @@ -208,4 +219,24 @@ public void shortKeyShouldThrownException() throws Exception { .isExactlyInstanceOf(IllegalArgumentException.class) .hasMessage("Key length for = 0x10 is 8 bits, should be between 64 and 160 bits"); } + + @Test + public void properLogShouldBeGeneratedForProcessingItems() throws Exception { + doAnswer(invocation -> getClass().getResourceAsStream(invocation.getArgument(0))) + .when(resourceManager).getResourceAsInputStream(anyString()); + + keysMap.load("/keysMap.list"); + + assertThat(keysMap.size()).isEqualTo(10); + + verify(loggerKeysMap) + .debug(eq("Existing artifact pattern: {} - only update key items in {}"), anyString(), any(KeysMapContext.class)); + verifyNoMoreInteractions(loggerKeysMap); + + verify(loggerKeyItems, times(3)) + .warn(eq("Duplicate key item: {} in: {}"), any(KeyItem.class), any(KeysMapContext.class)); + verify(loggerKeyItems) + .warn(eq("Empty value for key is deprecated - please provide some value - now assume as noSig in: {}"), any(KeysMapContext.class)); + verifyNoMoreInteractions(loggerKeyItems); + } } diff --git a/src/test/resources/keysMap.list b/src/test/resources/keysMap.list index 0c619772..08480e64 100644 --- a/src/test/resources/keysMap.list +++ b/src/test/resources/keysMap.list @@ -21,7 +21,7 @@ testlong : fingerprint = 0x9ABC DEF0 1234 5678 9ABC DEF0 1234 5678 9A test.* = any test2:test-package = 0xA6ADFC93EF34893F -test2 = 0xA6ADFC93EF34893E +test2 = 0xA6ADFC93EF34893E, 0xA6ADFC93EF34893E # duplicate key # noSig test @@ -35,7 +35,10 @@ noSig:test2 = noSig noSig:test3 = noSig, 0x123456789abcdef0 # badSig -badSig:test = badSig +badSig:test = badSig, badSig # duplicate special value # noKey noKey:test = noKey + +# duplicate artifact pattern with duplicate value +noKey:test = noKey