diff --git a/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandler.java b/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandler.java index 10c7517bb0..9cead430a8 100644 --- a/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandler.java +++ b/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandler.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSVerifier; import com.nimbusds.jose.crypto.ECDSAVerifier; import com.nimbusds.jose.crypto.RSASSAVerifier; import com.nimbusds.jose.crypto.impl.ECDSA; @@ -33,6 +32,7 @@ import uk.gov.di.ipv.core.library.service.ConfigService; import uk.gov.di.ipv.core.reconcilemigratedvcs.domain.ReconciliationReport; import uk.gov.di.ipv.core.reconcilemigratedvcs.domain.Request; +import uk.gov.di.ipv.core.reconcilemigratedvcs.domain.VerifierAndUseCount; import java.text.ParseException; import java.util.ArrayList; @@ -42,6 +42,7 @@ import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import static com.nimbusds.jose.JWSAlgorithm.ES256; import static com.nimbusds.jose.jwk.KeyType.EC; @@ -73,7 +74,7 @@ public class ReconcileMigratedVcsHandler implements RequestHandler processedIdentities; private AtomicBoolean timeoutClose; private Map criIssuersMap; - private Map> historicSigningKeyVerifiers; + private Map> historicSigningKeyVerifiers; public ReconcileMigratedVcsHandler( ConfigService configService, @@ -174,6 +175,7 @@ public ReconciliationReport handleRequest(Request request, Context context) { unprocessedIdentities.removeAll(processedIdentities); reconciliationReport.setUnprocessedHashedUserIds( unprocessedIdentities.stream().map(DigestUtils::sha256Hex).toList()); + reconciliationReport.setVerifierUse(historicSigningKeyVerifiers); logReport(); } @@ -220,12 +222,12 @@ private void reconcileIdentity(String userId, Context context) { // Compare VCs if (!evcsVcsStrings.equals(tacticalVcsStrings)) { logVcDifferences(evcsVcsStrings, tacticalVcsStrings, hashedUserId); - reconciliationReport.incrementDifferenceInVcs(hashedUserId); + reconciliationReport.incrementIdentitiesWithDifferentVcs(hashedUserId); reconciliationReport.incrementIdentitiesFullyProcessed(); processedIdentities.add(userId); return; } else { - reconciliationReport.incrementVcsMatch(); + reconciliationReport.incrementIdentitiesWithMatchingVcs(evcsVcsStrings.size()); } if (reconciliationReport.isCheckSignatures() || reconciliationReport.isCheckP2()) { @@ -325,9 +327,9 @@ private synchronized void refreshEvcsClientIfNeeded() { private boolean validSignature(VerifiableCredential vc, String hashedUserId) throws JOSEException, ParseException { // try all known keys until VC is validated, or return false - for (var verifier : historicSigningKeyVerifiers.get(vc.getCri())) { + for (var verifierAndUseCount : historicSigningKeyVerifiers.get(vc.getCri())) { SignedJWT formattedVc; - if (verifier instanceof ECDSAVerifier) { + if (verifierAndUseCount.getVerifier() instanceof ECDSAVerifier) { try { formattedVc = transcodeSignatureIfDerFormat(vc.getSignedJwt()); } catch (JOSEException | ParseException e) { @@ -338,7 +340,8 @@ private boolean validSignature(VerifiableCredential vc, String hashedUserId) formattedVc = vc.getSignedJwt(); } - if (formattedVc.verify(verifier)) { + if (formattedVc.verify(verifierAndUseCount.getVerifier())) { + verifierAndUseCount.getUseCount().incrementAndGet(); return true; } } @@ -430,9 +433,9 @@ private void logReport() { } } - private Map> getHistoricSigningKeyVerifiers() + private Map> getHistoricSigningKeyVerifiers() throws ParseException, JOSEException { - Map> verifiers = new EnumMap<>(Cri.class); + Map> verifiers = new EnumMap<>(Cri.class); for (var cri : Cri.values()) { try { for (var publicKey : configService.getHistoricSigningKeys(cri.getId())) { @@ -440,9 +443,12 @@ private Map> getHistoricSigningKeyVerifiers() verifiers .computeIfAbsent(cri, k -> new ArrayList<>()) .add( - parsedJwk.getKeyType() == EC - ? new ECDSAVerifier(parsedJwk.toECKey()) - : new RSASSAVerifier(parsedJwk.toRSAKey())); + new VerifierAndUseCount( + parsedJwk.getKeyType() == EC + ? new ECDSAVerifier(parsedJwk.toECKey()) + : new RSASSAVerifier(parsedJwk.toRSAKey()), + publicKey, + new AtomicInteger(0))); } } catch (ConfigParameterNotFoundException e) { LOGGER.warn( diff --git a/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/ReconciliationReport.java b/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/ReconciliationReport.java index aed3d19322..ae169a8e43 100644 --- a/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/ReconciliationReport.java +++ b/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/ReconciliationReport.java @@ -3,10 +3,12 @@ import lombok.Getter; import lombok.Setter; import uk.gov.di.ipv.core.library.annotations.ExcludeFromGeneratedCoverageReport; +import uk.gov.di.ipv.core.library.domain.Cri; import uk.gov.di.ipv.core.library.domain.VerifiableCredential; import java.util.ArrayList; import java.util.List; +import java.util.Map; @Getter @ExcludeFromGeneratedCoverageReport @@ -16,8 +18,9 @@ public class ReconciliationReport { private final boolean checkP2; private final int batchSize; private int identitiesFullyProcessed; + private int identitiesWithMatchingVcs; private int vcsMatchedCount; - private int vcsDifferentCount; + private int identitiesWithDifferentVcsCount; private int identityWithValidSignaturesCount; private int identityWithInvalidSignaturesCount; private int invalidVcSignatureCount; @@ -35,8 +38,9 @@ public class ReconciliationReport { private final List identityWithAnyInvalidSignaturesHashedUserIds = new ArrayList<>(); private final List invalidVcSignatureHashedUserIdAndCri = new ArrayList<>(); private final List failedToAttainP2HashedUserIds = new ArrayList<>(); - private final List differenceInVcsHashedUserIds = new ArrayList<>(); + private final List identitiesWithDifferentVcsHashedUserIds = new ArrayList<>(); @Setter private List unprocessedHashedUserIds = new ArrayList<>(); + @Setter private Map> verifierUse; public ReconciliationReport(Request request) { batchId = request.batchId(); @@ -49,8 +53,14 @@ public synchronized void incrementIdentitiesFullyProcessed() { identitiesFullyProcessed++; } - public synchronized void incrementVcsMatch() { - vcsMatchedCount++; + public synchronized void incrementIdentitiesWithMatchingVcs(int vcCount) { + identitiesWithMatchingVcs++; + vcsMatchedCount += vcCount; + } + + public synchronized void incrementIdentitiesWithDifferentVcs(String hashedUserId) { + identitiesWithDifferentVcsCount++; + identitiesWithDifferentVcsHashedUserIds.add(hashedUserId); } public synchronized void incrementFailedEvcsRead(String hashedUserId) { @@ -99,9 +109,4 @@ public synchronized void incrementFailedToAttainP2(String hashedUserId) { public synchronized void incrementSuccessfullyMatchedP2Count() { successfullyAttainedP2Count++; } - - public synchronized void incrementDifferenceInVcs(String hashedUserId) { - vcsDifferentCount++; - differenceInVcsHashedUserIds.add(hashedUserId); - } } diff --git a/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/VerifierAndUseCount.java b/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/VerifierAndUseCount.java new file mode 100644 index 0000000000..f7655fae50 --- /dev/null +++ b/lambdas/reconcile-migrated-vcs/src/main/java/uk/gov/di/ipv/core/reconcilemigratedvcs/domain/VerifierAndUseCount.java @@ -0,0 +1,16 @@ +package uk.gov.di.ipv.core.reconcilemigratedvcs.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.nimbusds.jose.JWSVerifier; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.concurrent.atomic.AtomicInteger; + +@Getter +@AllArgsConstructor +public class VerifierAndUseCount { + @JsonIgnore private final JWSVerifier verifier; + private final String publicKey; + private final AtomicInteger useCount; +} diff --git a/lambdas/reconcile-migrated-vcs/src/test/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandlerTest.java b/lambdas/reconcile-migrated-vcs/src/test/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandlerTest.java index 0ef1776d09..6264228fda 100644 --- a/lambdas/reconcile-migrated-vcs/src/test/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandlerTest.java +++ b/lambdas/reconcile-migrated-vcs/src/test/java/uk/gov/di/ipv/core/reconcilemigratedvcs/ReconcileMigratedVcsHandlerTest.java @@ -91,8 +91,9 @@ void handlerShouldHandleMatchingVcs() throws Exception { assertEquals("vcs-match-batch-id", reconciliationReport.getBatchId()); assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); - assertEquals(1, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(1, reconciliationReport.getIdentitiesWithMatchingVcs()); + assertEquals(3, reconciliationReport.getVcsMatchedCount()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertFalse(reconciliationReport.isCheckSignatures()); assertFalse(reconciliationReport.isCheckP2()); } @@ -122,7 +123,7 @@ void handlerShouldHandleNonMatchingVcs() throws Exception { assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); assertEquals(0, reconciliationReport.getVcsMatchedCount()); - assertEquals(1, reconciliationReport.getVcsDifferentCount()); + assertEquals(1, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertFalse(reconciliationReport.isCheckSignatures()); assertFalse(reconciliationReport.isCheckP2()); } @@ -151,7 +152,7 @@ void handlerShouldHandleMissingVcs() throws Exception { assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); assertEquals(0, reconciliationReport.getVcsMatchedCount()); - assertEquals(1, reconciliationReport.getVcsDifferentCount()); + assertEquals(1, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertFalse(reconciliationReport.isCheckSignatures()); assertFalse(reconciliationReport.isCheckP2()); } @@ -193,8 +194,9 @@ void handlerShouldHandleValidateSignatures() throws Exception { assertEquals("vcs-valid-sig-batch-id", reconciliationReport.getBatchId()); assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); - assertEquals(1, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(1, reconciliationReport.getIdentitiesWithMatchingVcs()); + assertEquals(2, reconciliationReport.getVcsMatchedCount()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertEquals(1, reconciliationReport.getIdentityWithValidSignaturesCount()); assertEquals(0, reconciliationReport.getIdentityWithInvalidSignaturesCount()); assertEquals(0, reconciliationReport.getInvalidVcSignatureCount()); @@ -224,7 +226,7 @@ void handlerShouldHandleInvalidSignatures() throws Exception { assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); assertEquals(1, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertEquals(0, reconciliationReport.getIdentityWithValidSignaturesCount()); assertEquals(1, reconciliationReport.getIdentityWithInvalidSignaturesCount()); assertEquals(1, reconciliationReport.getInvalidVcSignatureCount()); @@ -254,7 +256,7 @@ void handlerShouldCheckSignaturesWithAllKeys() throws Exception { assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); assertEquals(1, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertEquals(1, reconciliationReport.getIdentityWithValidSignaturesCount()); assertEquals(0, reconciliationReport.getIdentityWithInvalidSignaturesCount()); assertEquals(0, reconciliationReport.getInvalidVcSignatureCount()); @@ -287,7 +289,7 @@ void handlerShouldHandleIdentityWithP2() throws Exception { assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); assertEquals(1, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertEquals(1, reconciliationReport.getIdentityWithValidSignaturesCount()); assertEquals(0, reconciliationReport.getIdentityWithInvalidSignaturesCount()); assertEquals(0, reconciliationReport.getInvalidVcSignatureCount()); @@ -317,7 +319,7 @@ void handlerShouldHandleIdentityWithNonP2() throws Exception { assertEquals(1, reconciliationReport.getBatchSize()); assertEquals(1, reconciliationReport.getIdentitiesFullyProcessed()); assertEquals(1, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertEquals(0, reconciliationReport.getIdentityWithValidSignaturesCount()); assertEquals(0, reconciliationReport.getIdentityWithInvalidSignaturesCount()); assertEquals(0, reconciliationReport.getInvalidVcSignatureCount()); @@ -344,8 +346,8 @@ void handlerShouldHandleLambdaTimeout() throws Exception { assertEquals("timeout-batch-id", reconciliationReport.getBatchId()); assertEquals(2, reconciliationReport.getBatchSize()); assertEquals(2, reconciliationReport.getIdentitiesFullyProcessed()); - assertEquals(2, reconciliationReport.getVcsMatchedCount()); - assertEquals(0, reconciliationReport.getVcsDifferentCount()); + assertEquals(2, reconciliationReport.getIdentitiesWithMatchingVcs()); + assertEquals(0, reconciliationReport.getIdentitiesWithDifferentVcsCount()); assertEquals("Lambda close to timeout", reconciliationReport.getExitReason()); }