From e9f81b39db81d8eaec136a3b9770b64628a0d622 Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 17 Apr 2023 15:44:20 +0200 Subject: [PATCH 1/5] [SLS-26] Implemented idpCertData provider and storage --- .../consumer/idp/IdpCertProvider.java | 8 +- .../idp/impl/IdpCertProviderFactoryImpl.java | 42 +++++++ .../impl/IdpCertProviderFactoryImplStub.java | 18 --- .../idp/impl/IdpCertProviderImpl.java | 70 ++++++++++++ .../idp/impl/IdpCertProviderImplStub.java | 17 --- .../consumer/idp/storage/IdpCertStorage.java | 24 +++- .../idp/storage/IdpCertStorageConfig.java | 14 +++ .../idp/storage/IdpCertStorageProvider.java | 6 +- .../idp/storage/SimpleIdpCertStorage.java | 104 ++++++++++++++++++ .../storage/SimpleIdpCertStorageProvider.java | 19 ++++ gradle/verification-metadata.xml | 18 +-- 11 files changed, 280 insertions(+), 60 deletions(-) create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java delete mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java create mode 100644 core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java index 7aaed7a2..f2969e74 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/IdpCertProvider.java @@ -1,7 +1,13 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp; +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; + public interface IdpCertProvider { - boolean getIdpCertData(String assertionInstant, String entityId); + List getIdpCertData(String assertionInstant, String entityId) + throws CertDataTagListNotFoundException, CertDataNotFoundException; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java new file mode 100644 index 00000000..82ace7bf --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java @@ -0,0 +1,42 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.impl; + +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; +import javax.inject.Inject; + +/** + * Implementation of {@link IdpCertProviderFactory}, used to create instances of {@link + * IdpCertProviderImpl} + */ +public class IdpCertProviderFactoryImpl implements IdpCertProviderFactory { + + private IdpCertClientProvider idpCertClientProvider; + private IdpCertStorageProvider idpCertStorageProvider; + private final IdpCertStorageConfig storageConfig; + + @Inject + public IdpCertProviderFactoryImpl( + IdpCertStorageProvider idpCertStorageProvider, + IdpCertClientProvider idpCertClientProvider, + IdpCertStorageConfig storageConfig) { + this.idpCertClientProvider = idpCertClientProvider; + this.idpCertStorageProvider = idpCertStorageProvider; + this.storageConfig = storageConfig; + } + + /** + * Factory for creating an instance of {@link IdpCertProvider} + * + * @return an instance of {@link IdpCertProviderImpl} + */ + @Override + public IdpCertProvider create() { + return new IdpCertProviderImpl( + idpCertClientProvider.provideClient(), + idpCertStorageProvider.provideStorage(storageConfig)); + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java deleted file mode 100644 index c72c7da6..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImplStub.java +++ /dev/null @@ -1,18 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.impl; - -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; -import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; - -public class IdpCertProviderFactoryImplStub implements IdpCertProviderFactory { - - private IdpCertClientProvider idpCertClientProvider; - private IdpCertStorageProvider idpCertStorageProvider; - - @Override - public IdpCertProvider create() { - return null; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java new file mode 100644 index 00000000..e993f96d --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -0,0 +1,70 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.impl; + +import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; +import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; +import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; +import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; +import javax.inject.Inject; + +public class IdpCertProviderImpl implements IdpCertProvider { + + private IdpCertClient idpCertClient; + private IdpCertStorage idpCertStorage; + + @Inject + public IdpCertProviderImpl(IdpCertClient idpCertClient, IdpCertStorage idpCertStorage) { + this.idpCertClient = idpCertClient; + this.idpCertStorage = idpCertStorage; + } + + /** + * {@inheritDoc} + * + *

Retrieve the Identity Provider Certification Data, first looking in the storage if enabled + * ({@link IdpCertStorageConfig}) and then, if not found, through the client {@link + * IdpCertClient}. If the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will + * be stored, after being retrieved by the client. + * + * @param assertionInstant Assertion Issue Instant found in the xml + * @param entityId Entity ID of the identity provider found in the assertion + * @return List a list of idp cert data + * @throws CertDataTagListNotFoundException + * @throws CertDataNotFoundException + */ + @Override + public List getIdpCertData(String assertionInstant, String entityId) + throws CertDataTagListNotFoundException, CertDataNotFoundException { + if (assertionInstant == null + || assertionInstant.isBlank() + || entityId == null + || entityId.isBlank()) { + String errMsg = + String.format( + "Cannot retrieve the identity provider cert data, assertion instant" + + " [%s] or entity id [%s] missing", + assertionInstant, entityId); + throw new IllegalArgumentException(errMsg); + } + + List listIdpCertData = idpCertStorage.getIdpCertData(assertionInstant); + + if (listIdpCertData != null && listIdpCertData.size() > 0) { + return listIdpCertData; + } + + listIdpCertData = idpCertClient.getCertData(entityId, assertionInstant); + + if (listIdpCertData == null || listIdpCertData.size() > 0) { + return null; + } + + idpCertStorage.saveIdpCertData(assertionInstant, listIdpCertData); + + return listIdpCertData; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java deleted file mode 100644 index b6df7d6f..00000000 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImplStub.java +++ /dev/null @@ -1,17 +0,0 @@ -/* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.impl; - -import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; -import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; - -public class IdpCertProviderImplStub implements IdpCertProvider { - - private IdpCertClient idpCertClient; - private IdpCertStorage idpCertStorage; - - @Override - public boolean getIdpCertData(String assertionInstant, String entityId) { - return false; - } -} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java index 6226daf2..aa4425b6 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -4,13 +4,25 @@ import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; +/** + * Interface of the storage used for storing the identity provider certification data retrieved for + * validation + */ public interface IdpCertStorage { - List getTagList(); + /** + * Retrieve the idp cert data associated with the provided tag + * + * @param tag + * @return the list of idpCertData found + */ + List getIdpCertData(String tag); - void saveTagList(List tagList); - - IdpCertData getIdpCertData(String tag); - - void saveIdpCertData(String tag); + /** + * Store the provided idpCertData + * + * @param tag the idpCertData issue instance + * @param idpCertData + */ + void saveIdpCertData(String tag, List idpCertData); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java new file mode 100644 index 00000000..f6fe13a4 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageConfig.java @@ -0,0 +1,14 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.storage; + +import java.util.concurrent.TimeUnit; +import lombok.Data; + +/** Configuration class for the idpCertData storage */ +@Data +public class IdpCertStorageConfig { + + private boolean idpCertDataStorageEnabled = true; + private long storageEvictionDelay = 1L; + private TimeUnit storageEvictionDelayTimeUnit = TimeUnit.MINUTES; +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java index 3f045332..c73d835a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorageProvider.java @@ -1,7 +1,11 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.idp.storage; +/** Interface for the provider used to create instances of {@link IdpCertStorage} */ public interface IdpCertStorageProvider { - IdpCertStorage provideStorage(); + /** + * @return instance of {@link IdpCertStorage} + */ + IdpCertStorage provideStorage(IdpCertStorageConfig storageConfig); } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java new file mode 100644 index 00000000..f26d8184 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java @@ -0,0 +1,104 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.storage; + +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import javax.inject.Inject; + +/** + * Implementation of the {@link IdpCertStorage} interface as a simple in memory storage. + * + *

The storage can be configured via the {@link IdpCertStorageConfig} configuration class. + * + *

It store in a in memory {@link java.util.HashMap} the assertions and the associated scheduled + * eviction operations, every time an assertion is accessed the associated eviction operation is + * rescheduled. + */ +public class SimpleIdpCertStorage implements IdpCertStorage { + + private final Map> idpCertDataMap; + private final Map> scheduledEvictionsMap; + private final IdpCertStorageConfig storageConfig; + + @Inject + public SimpleIdpCertStorage( + Map> idpCertDataMap, + Map> scheduledEvictionsMap, + IdpCertStorageConfig storageConfig) { + this.idpCertDataMap = idpCertDataMap; + this.scheduledEvictionsMap = scheduledEvictionsMap; + this.storageConfig = storageConfig; + } + + /** + * Retrieve the idpCertData associated with the provided tag if the storage is enabled {@link + * IdpCertStorageConfig}, otherwise no operation is performed. + * + *

Before the list of idpCertData is returned the associated eviction operation is + * rescheduled with the delay configured via {@link IdpCertStorageConfig} + * + * @param tag the idpCertData issue instant + * @return the list of cert data if found, null if no cert data are present in the storage or + * the storage is disabled + */ + @Override + public List getIdpCertData(String tag) { + if (!storageConfig.isIdpCertDataStorageEnabled()) { + return null; + } + + List listIdpCertData = idpCertDataMap.get(tag); + if (listIdpCertData != null) { + delayEviction(tag); + } + return listIdpCertData; + } + + /** + * Store the idpCertData if the storage is enabled {@link IdpCertStorageConfig}, otherwise no + * operation is performed. + * + *

Once the idpCertData is stored an eviction operation is scheduled with a delay configured + * via {@link IdpCertStorageConfig} + * + * @param tag the idpCertData issue instant + * @param idpCertData + */ + @Override + public void saveIdpCertData(String tag, List idpCertData) { + if (!storageConfig.isIdpCertDataStorageEnabled()) { + return; + } + + idpCertDataMap.put(tag, idpCertData); + scheduleEviction(tag); + } + + private void scheduleEviction(String assertionRef) { + ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + ScheduledFuture schedule = + executorService.schedule( + getEvictionTask(assertionRef), + storageConfig.getStorageEvictionDelay(), + storageConfig.getStorageEvictionDelayTimeUnit()); + scheduledEvictionsMap.put(assertionRef, schedule); + } + + private void delayEviction(String tag) { + ScheduledFuture schedule = scheduledEvictionsMap.get(tag); + schedule.cancel(false); + scheduledEvictionsMap.remove(tag); + scheduleEviction(tag); + } + + private Runnable getEvictionTask(String tag) { + return () -> { + idpCertDataMap.remove(tag); + scheduledEvictionsMap.remove(tag); + }; + } +} diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java new file mode 100644 index 00000000..632ea668 --- /dev/null +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java @@ -0,0 +1,19 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.storage; + +import java.util.HashMap; + +/** Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of the */ +public class SimpleIdpCertStorageProvider implements IdpCertStorageProvider { + + /** + * {@inheritDoc} + * + * @param storageConfig the storage configuration + * @return an instance of {@link SimpleIdpCertStorage} + */ + @Override + public IdpCertStorage provideStorage(IdpCertStorageConfig storageConfig) { + return new SimpleIdpCertStorage(new HashMap<>(), new HashMap<>(), storageConfig); + } +} diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 5337fc06..2ce666da 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -245,14 +245,6 @@ - - - - - - - - @@ -345,14 +337,6 @@ - - - - - - - - @@ -377,9 +361,9 @@ + - From 2a2981132c43af5f5f8eb37cd75887006361cf03 Mon Sep 17 00:00:00 2001 From: svariant Date: Mon, 17 Apr 2023 17:25:15 +0200 Subject: [PATCH 2/5] [SLS-26] Moved identity provider storage implementation from core module to identity-service-rest-client-native --- .../idp/impl/IdpCertProviderImpl.java | 37 +++++++------------ .../consumer/idp/storage/IdpCertStorage.java | 5 +-- .../client/simple/IdpCertSimpleClient.java | 33 +++++++++++++++-- .../simple/IdpCertSimpleClientProvider.java | 8 +++- .../simple}/storage/SimpleIdpCertStorage.java | 19 +++++----- .../storage/SimpleIdpCertStorageProvider.java | 5 ++- .../java/simple/IdpCertSimpleClientTest.java | 9 ++++- 7 files changed, 73 insertions(+), 43 deletions(-) rename {core/src/main/java/it/pagopa/tech/lollipop/consumer/idp => identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple}/storage/SimpleIdpCertStorage.java (85%) rename {core/src/main/java/it/pagopa/tech/lollipop/consumer/idp => identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple}/storage/SimpleIdpCertStorageProvider.java (66%) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index e993f96d..3c952905 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -25,16 +25,19 @@ public IdpCertProviderImpl(IdpCertClient idpCertClient, IdpCertStorage idpCertSt /** * {@inheritDoc} * - *

Retrieve the Identity Provider Certification Data, first looking in the storage if enabled - * ({@link IdpCertStorageConfig}) and then, if not found, through the client {@link - * IdpCertClient}. If the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will - * be stored, after being retrieved by the client. + *

Retrieve the certification data of the given entityId issued in the same timeframe as the + * issue instant of the SAML assertion, first looking in the storage if enabled ({@link + * IdpCertStorageConfig}) and then, if not found, through the client {@link IdpCertClient}. If + * the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will be stored, after + * being retrieved by the client. * - * @param assertionInstant Assertion Issue Instant found in the xml - * @param entityId Entity ID of the identity provider found in the assertion - * @return List a list of idp cert data - * @throws CertDataTagListNotFoundException - * @throws CertDataNotFoundException + * @param entityId Identity Provider ID + * @param assertionInstant Assertion Issue Instant + * @return the certifications issued before and after the timestamp instant + * @throws CertDataTagListNotFoundException if an error occurred retrieving the list of tags or + * filtering the tags with the instant + * @throws CertDataNotFoundException if an error occurred retrieving the certification XML or if + * data for the given entityId were not found */ @Override public List getIdpCertData(String assertionInstant, String entityId) @@ -51,20 +54,6 @@ public List getIdpCertData(String assertionInstant, String entityId throw new IllegalArgumentException(errMsg); } - List listIdpCertData = idpCertStorage.getIdpCertData(assertionInstant); - - if (listIdpCertData != null && listIdpCertData.size() > 0) { - return listIdpCertData; - } - - listIdpCertData = idpCertClient.getCertData(entityId, assertionInstant); - - if (listIdpCertData == null || listIdpCertData.size() > 0) { - return null; - } - - idpCertStorage.saveIdpCertData(assertionInstant, listIdpCertData); - - return listIdpCertData; + return idpCertClient.getCertData(assertionInstant, entityId); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java index aa4425b6..ef2f827a 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/IdpCertStorage.java @@ -2,7 +2,6 @@ package it.pagopa.tech.lollipop.consumer.idp.storage; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import java.util.List; /** * Interface of the storage used for storing the identity provider certification data retrieved for @@ -16,7 +15,7 @@ public interface IdpCertStorage { * @param tag * @return the list of idpCertData found */ - List getIdpCertData(String tag); + IdpCertData getIdpCertData(String tag); /** * Store the provided idpCertData @@ -24,5 +23,5 @@ public interface IdpCertStorage { * @param tag the idpCertData issue instance * @param idpCertData */ - void saveIdpCertData(String tag, List idpCertData); + void saveIdpCertData(String tag, IdpCertData idpCertData); } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 1b62a68c..1c2ee31d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -9,6 +9,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.CertData; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntitiesDescriptor; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.model.EntityDescriptor; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.ArrayList; import java.util.Collections; @@ -20,16 +22,22 @@ public class IdpCertSimpleClient implements IdpCertClient { private final DefaultApi defaultApi; private final IdpCertSimpleClientConfig entityConfig; + private IdpCertStorage storage; @Inject - public IdpCertSimpleClient(ApiClient client, IdpCertSimpleClientConfig entityConfig) { + public IdpCertSimpleClient( + ApiClient client, IdpCertSimpleClientConfig entityConfig, IdpCertStorage storage) { this.defaultApi = new DefaultApi(client); this.entityConfig = entityConfig; + this.storage = storage; } /** * Retrieve the certification data of the given entityId issued in the same timeframe as the - * issue instant of the SAML assertion + * issue instant of the SAML assertion, first looking in the storage if enabled ({@link + * IdpCertStorageConfig}) and then, if not found, through the client {@link IdpCertClient}. If + * the storage is enabled ({@link IdpCertStorageConfig}) the IdpCertData will be stored, after + * being retrieved by the client. * * @param entityId Identity Provider ID * @param instant Assertion Issue Instant @@ -61,7 +69,14 @@ public List getCertData(String entityId, String instant) for (String tag : tagList) { try { - IdpCertData certData = getCIECertData(tag, entityId); + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(storageTag); + + if (certData == null) { + certData = getCIECertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); + } listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { @@ -85,8 +100,14 @@ public List getCertData(String entityId, String instant) for (String tag : tagList) { try { - IdpCertData certData = getSPIDCertData(tag, entityId); + String storageTag = codifyStorageTag(tag, entityId); + IdpCertData certData = storage.getIdpCertData(codifyStorageTag(tag, entityId)); + if (certData == null) { + certData = getSPIDCertData(tag, entityId); + } else { + storage.saveIdpCertData(storageTag, certData); + } listCertData.add(certData); } catch (ApiException | EntityIdNotFoundException e) { throw new CertDataNotFoundException( @@ -211,4 +232,8 @@ private List getTagsFromInstant(List tagList, String instant) return newTagList; } + + private String codifyStorageTag(String tag, String entityId) { + return tag + entityId; + } } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java index 6a292a71..6a9f5ba1 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientProvider.java @@ -4,6 +4,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import javax.inject.Inject; /** Provider class for retrieving an instance of {@link IdpCertSimpleClient} */ @@ -22,6 +24,10 @@ public IdpCertSimpleClientProvider(IdpCertSimpleClientConfig config) { */ @Override public IdpCertClient provideClient() { - return new IdpCertSimpleClient(new ApiClient(this.idpClientConfig), this.idpClientConfig); + SimpleIdpCertStorageProvider storageProvider = new SimpleIdpCertStorageProvider(); + return new IdpCertSimpleClient( + new ApiClient(this.idpClientConfig), + this.idpClientConfig, + storageProvider.provideStorage(new IdpCertStorageConfig())); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorage.java similarity index 85% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java rename to identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorage.java index f26d8184..69cc2826 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorage.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorage.java @@ -1,8 +1,9 @@ /* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.storage; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.storage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; -import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -20,13 +21,13 @@ */ public class SimpleIdpCertStorage implements IdpCertStorage { - private final Map> idpCertDataMap; + private final Map idpCertDataMap; private final Map> scheduledEvictionsMap; private final IdpCertStorageConfig storageConfig; @Inject public SimpleIdpCertStorage( - Map> idpCertDataMap, + Map idpCertDataMap, Map> scheduledEvictionsMap, IdpCertStorageConfig storageConfig) { this.idpCertDataMap = idpCertDataMap; @@ -46,16 +47,16 @@ public SimpleIdpCertStorage( * the storage is disabled */ @Override - public List getIdpCertData(String tag) { + public IdpCertData getIdpCertData(String tag) { if (!storageConfig.isIdpCertDataStorageEnabled()) { return null; } - List listIdpCertData = idpCertDataMap.get(tag); - if (listIdpCertData != null) { + IdpCertData idpCertData = idpCertDataMap.get(tag); + if (idpCertData != null) { delayEviction(tag); } - return listIdpCertData; + return idpCertData; } /** @@ -69,7 +70,7 @@ public List getIdpCertData(String tag) { * @param idpCertData */ @Override - public void saveIdpCertData(String tag, List idpCertData) { + public void saveIdpCertData(String tag, IdpCertData idpCertData) { if (!storageConfig.isIdpCertDataStorageEnabled()) { return; } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageProvider.java similarity index 66% rename from core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java rename to identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageProvider.java index 632ea668..710f5787 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/storage/SimpleIdpCertStorageProvider.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageProvider.java @@ -1,6 +1,9 @@ /* (C)2023 */ -package it.pagopa.tech.lollipop.consumer.idp.storage; +package it.pagopa.tech.lollipop.consumer.idp.client.simple.storage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import java.util.HashMap; /** Implementation of {@link IdpCertStorageProvider} interface. It provides an instance of the */ diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java index 20a12462..eee7c6a6 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java @@ -6,6 +6,8 @@ import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; +import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.time.Instant; import java.util.List; @@ -31,7 +33,12 @@ class IdpCertSimpleClientTest { public static void startServer() { entityConfig = Mockito.spy(IdpCertSimpleClientConfig.builder().build()); ApiClient client = new ApiClient(entityConfig); - idpCertSimpleClient = new IdpCertSimpleClient(client, entityConfig); + SimpleIdpCertStorageProvider storageProvider = new SimpleIdpCertStorageProvider(); + idpCertSimpleClient = + new IdpCertSimpleClient( + client, + entityConfig, + storageProvider.provideStorage(new IdpCertStorageConfig())); } @Test From 6f363c114a1dfd659200e4f60d492b3008c79355 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 18 Apr 2023 10:11:44 +0200 Subject: [PATCH 3/5] [SLS-26] Defined unit tests for SimpleIdpCertStorage - added 2 tests to IdpCertSimpleClientTest --- .../simple/IdpCertSimpleClientTest.java | 18 ++- .../storage/SimpleIdpCertStorageTest.java | 135 ++++++++++++++++++ 2 files changed, 150 insertions(+), 3 deletions(-) rename identity-service-rest-client-native/src/test/java/{ => it/pagopa/tech/lollipop/consumer/idp/client}/simple/IdpCertSimpleClientTest.java (86%) create mode 100644 identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java diff --git a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java similarity index 86% rename from identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java rename to identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index eee7c6a6..79427af9 100644 --- a/identity-service-rest-client-native/src/test/java/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -1,10 +1,8 @@ /* (C)2023 */ -package simple; +package it.pagopa.tech.lollipop.consumer.idp.client.simple; import it.pagopa.tech.lollipop.consumer.exception.CertDataNotFoundException; import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClient; -import it.pagopa.tech.lollipop.consumer.idp.client.simple.IdpCertSimpleClientConfig; import it.pagopa.tech.lollipop.consumer.idp.client.simple.internal.ApiClient; import it.pagopa.tech.lollipop.consumer.idp.client.simple.storage.SimpleIdpCertStorageProvider; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; @@ -75,4 +73,18 @@ void getCIECertDataWrongInstant() { CertDataTagListNotFoundException.class, () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, WRONG_INSTANT)); } + + @Test + void entityIdNull() { + Assertions.assertThrows( + IllegalArgumentException.class, + () -> idpCertSimpleClient.getCertData(null, WRONG_INSTANT)); + } + + @Test + void instantNull() { + Assertions.assertThrows( + IllegalArgumentException.class, + () -> idpCertSimpleClient.getCertData(CIE_ENTITY_ID, null)); + } } diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java new file mode 100644 index 00000000..e189d7eb --- /dev/null +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/storage/SimpleIdpCertStorageTest.java @@ -0,0 +1,135 @@ +/* (C)2023 */ +package it.pagopa.tech.lollipop.consumer.idp.client.simple.storage; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; +import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; +import it.pagopa.tech.lollipop.consumer.model.IdpCertData; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.*; +import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class SimpleIdpCertStorageTest { + + private static final long EVICTION_DELAY = 5000L; + private static IdpCertStorageConfig storageConfigMock; + private IdpCertStorage sut; + private static final String IDPCERTDATA_1 = "1680691737https://posteid.poste.it"; + + @BeforeEach + void setUp() { + storageConfigMock = mock(IdpCertStorageConfig.class); + doReturn(EVICTION_DELAY).when(storageConfigMock).getStorageEvictionDelay(); + doReturn(TimeUnit.MILLISECONDS).when(storageConfigMock).getStorageEvictionDelayTimeUnit(); + } + + @Test + void getExistingAssertionAndResetScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { + doReturn(true).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + Map idpCertDataMap = new HashMap<>(); + IdpCertData idpCertData = new IdpCertData(); + idpCertDataMap.put(IDPCERTDATA_1, idpCertData); + Map> scheduledEvictionsMap = new HashMap<>(); + ScheduledFuture scheduledFutureMock = mock(ScheduledFuture.class); + scheduledEvictionsMap.put(IDPCERTDATA_1, scheduledFutureMock); + + sut = new SimpleIdpCertStorage(idpCertDataMap, scheduledEvictionsMap, storageConfigMock); + + IdpCertData result = sut.getIdpCertData(IDPCERTDATA_1); + + assertNotNull(result); + assertEquals(idpCertData, result); + assertEquals(1, scheduledEvictionsMap.size()); + + CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); + assertEquals(true, future.get()); + assertEquals(0, idpCertDataMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + @Test + void getNotExistingAssertionWithStorageEnabled() { + doReturn(true).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + sut = new SimpleIdpCertStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + + IdpCertData result = sut.getIdpCertData(IDPCERTDATA_1); + + assertNull(result); + } + + @Test + void saveAssertionAndScheduleEvictionWithStorageEnabled() + throws InterruptedException, ExecutionException { + doReturn(true).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + Map idpCertDataMap = new HashMap<>(); + Map> scheduledEvictionsMap = new HashMap<>(); + + sut = new SimpleIdpCertStorage(idpCertDataMap, scheduledEvictionsMap, storageConfigMock); + IdpCertData idpCertData = new IdpCertData(); + + sut.saveIdpCertData(IDPCERTDATA_1, idpCertData); + + assertEquals(1, idpCertDataMap.size()); + assertEquals(1, scheduledEvictionsMap.size()); + assertEquals(idpCertData, idpCertDataMap.get(IDPCERTDATA_1)); + + CompletableFuture future = waitEvictionEnd(scheduledEvictionsMap); + assertEquals(true, future.get()); + assertEquals(0, idpCertDataMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + @Test + void getAssertionWithStorageDisabled() { + doReturn(false).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + sut = new SimpleIdpCertStorage(new HashMap<>(), new HashMap<>(), storageConfigMock); + + IdpCertData result = sut.getIdpCertData(IDPCERTDATA_1); + + assertNull(result); + } + + @Test + void savaAssertionWithStorageDisabled() { + doReturn(false).when(storageConfigMock).isIdpCertDataStorageEnabled(); + + Map idpCertDataMap = new HashMap<>(); + Map> scheduledEvictionsMap = new HashMap<>(); + + sut = new SimpleIdpCertStorage(idpCertDataMap, scheduledEvictionsMap, storageConfigMock); + + sut.saveIdpCertData(IDPCERTDATA_1, new IdpCertData()); + + assertEquals(0, idpCertDataMap.size()); + assertEquals(0, scheduledEvictionsMap.size()); + } + + private CompletableFuture waitEvictionEnd( + Map> scheduledEvictionsMap) { + CompletableFuture future = new CompletableFuture<>(); + ExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + executorService.submit( + new Runnable() { + @SneakyThrows + @Override + public void run() { + ScheduledFuture scheduledFuture = + scheduledEvictionsMap.get(IDPCERTDATA_1); + scheduledFuture.get(); + future.complete(true); + } + }); + return future; + } +} From 9de2940a8b37d80210c24b28541bdb0071d03255 Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 18 Apr 2023 16:05:53 +0200 Subject: [PATCH 4/5] [SLS-26] Removed storage injection from IdpCertProvider --- .../idp/impl/IdpCertProviderFactoryImpl.java | 17 +++-------------- .../consumer/idp/impl/IdpCertProviderImpl.java | 5 +---- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java index 82ace7bf..121da224 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderFactoryImpl.java @@ -4,8 +4,6 @@ import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProviderFactory; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClientProvider; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageProvider; import javax.inject.Inject; /** @@ -14,18 +12,11 @@ */ public class IdpCertProviderFactoryImpl implements IdpCertProviderFactory { - private IdpCertClientProvider idpCertClientProvider; - private IdpCertStorageProvider idpCertStorageProvider; - private final IdpCertStorageConfig storageConfig; + private final IdpCertClientProvider idpCertClientProvider; @Inject - public IdpCertProviderFactoryImpl( - IdpCertStorageProvider idpCertStorageProvider, - IdpCertClientProvider idpCertClientProvider, - IdpCertStorageConfig storageConfig) { + public IdpCertProviderFactoryImpl(IdpCertClientProvider idpCertClientProvider) { this.idpCertClientProvider = idpCertClientProvider; - this.idpCertStorageProvider = idpCertStorageProvider; - this.storageConfig = storageConfig; } /** @@ -35,8 +26,6 @@ public IdpCertProviderFactoryImpl( */ @Override public IdpCertProvider create() { - return new IdpCertProviderImpl( - idpCertClientProvider.provideClient(), - idpCertStorageProvider.provideStorage(storageConfig)); + return new IdpCertProviderImpl(idpCertClientProvider.provideClient()); } } diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java index 3c952905..8e269ca3 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/idp/impl/IdpCertProviderImpl.java @@ -5,7 +5,6 @@ import it.pagopa.tech.lollipop.consumer.exception.CertDataTagListNotFoundException; import it.pagopa.tech.lollipop.consumer.idp.IdpCertProvider; import it.pagopa.tech.lollipop.consumer.idp.client.IdpCertClient; -import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorage; import it.pagopa.tech.lollipop.consumer.idp.storage.IdpCertStorageConfig; import it.pagopa.tech.lollipop.consumer.model.IdpCertData; import java.util.List; @@ -14,12 +13,10 @@ public class IdpCertProviderImpl implements IdpCertProvider { private IdpCertClient idpCertClient; - private IdpCertStorage idpCertStorage; @Inject - public IdpCertProviderImpl(IdpCertClient idpCertClient, IdpCertStorage idpCertStorage) { + public IdpCertProviderImpl(IdpCertClient idpCertClient) { this.idpCertClient = idpCertClient; - this.idpCertStorage = idpCertStorage; } /** From 89f1bd81190b82b03454acd921786cc4900c2cbf Mon Sep 17 00:00:00 2001 From: svariant Date: Tue, 18 Apr 2023 16:44:48 +0200 Subject: [PATCH 5/5] [SLS-26] Handled multiple idp certificate signatures - added unit test --- .../lollipop/consumer/model/IdpCertData.java | 3 +- .../client/simple/IdpCertSimpleClient.java | 2 +- .../internal/model/EntityDescriptor.java | 66 +++++++++++++------ .../simple/IdpCertSimpleClientTest.java | 11 ++++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java index 6c0aaa2e..12d0c7ab 100644 --- a/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java +++ b/core/src/main/java/it/pagopa/tech/lollipop/consumer/model/IdpCertData.java @@ -1,6 +1,7 @@ /* (C)2023 */ package it.pagopa.tech.lollipop.consumer.model; +import java.util.List; import lombok.Getter; import lombok.Setter; @@ -10,5 +11,5 @@ public class IdpCertData { private String entityId; private String tag; - private String certData; + private List certData; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java index 1c2ee31d..e30a4a4a 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClient.java @@ -168,7 +168,7 @@ private IdpCertData getEntityData(EntitiesDescriptor data, String tag, String en if (entity.getEntityID().equals(entityId)) { newData.setEntityId(entityId); newData.setTag(tag); - newData.setCertData(entity.getSignature()); + newData.setCertData(entity.getSignatureList()); return newData; } diff --git a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java index f54361ce..8e8b7d1d 100644 --- a/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java +++ b/identity-service-rest-client-native/src/main/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/internal/model/EntityDescriptor.java @@ -3,10 +3,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; import lombok.Getter; /** EntityDescriptor */ @@ -21,7 +19,7 @@ public class EntityDescriptor { @JsonProperty("entityID") private String entityID; - private String signature; + private List signatureList; /** * Methods that obtains the signature used for verify the user's assertion from a series of @@ -32,24 +30,52 @@ public class EntityDescriptor { @SuppressWarnings("unchecked") @JsonProperty("IDPSSODescriptor") private void unpackNestedSignature(Map signature) { - Map keyDescriptor = new HashMap<>(); + List> keyDescriptorsList = new ArrayList<>(); if (signature.get(KEY_DESCRIPTOR) instanceof List) { - List> listDescriptors = - (List>) signature.get(KEY_DESCRIPTOR); - Optional> optionalFirst = - listDescriptors.stream() - .filter(el -> el.get("use").equals("signing")) - .findFirst(); - - if (optionalFirst.isPresent()) { - keyDescriptor = optionalFirst.get(); - } + + keyDescriptorsList = + ((List>) signature.get(KEY_DESCRIPTOR)) + .stream() + .filter(el -> el.get("use").equals("signing")) + .collect(Collectors.toList()); } else { - keyDescriptor = (Map) signature.get(KEY_DESCRIPTOR); + Map keyDescriptorFound = + (Map) signature.get(KEY_DESCRIPTOR); + + if (keyDescriptorFound.get("use").equals("signing")) { + keyDescriptorsList.add(keyDescriptorFound); + } + } + + List> keyInfosList = new ArrayList<>(); + for (Map keyDescriptor : keyDescriptorsList) { + if (keyDescriptor.get(KEY_INFO) instanceof List) { + keyInfosList = (List>) keyDescriptor.get(KEY_INFO); + } else { + Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); + + keyInfosList.add(keyInfo); + } + } + + List> listX509Data = new ArrayList<>(); + for (Map keyInfo : keyInfosList) { + if (keyInfo.get(X_509_DATA) instanceof List) { + listX509Data = (List>) keyInfo.get(X_509_DATA); + } else { + listX509Data.add((Map) keyInfo.get(X_509_DATA)); + } + } + + List signatureList = new ArrayList<>(); + for (Map x509Data : listX509Data) { + if (x509Data.get(X_509_CERTIFICATE) instanceof List) { + signatureList = (List) x509Data.get(X_509_CERTIFICATE); + } else { + signatureList.add((String) x509Data.get(X_509_CERTIFICATE)); + } } - Map keyInfo = (Map) keyDescriptor.get(KEY_INFO); - Map x509Data = (Map) keyInfo.get(X_509_DATA); - this.signature = (String) x509Data.get(X_509_CERTIFICATE); + this.signatureList = signatureList; } } diff --git a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java index 79427af9..e4617299 100644 --- a/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java +++ b/identity-service-rest-client-native/src/test/java/it/pagopa/tech/lollipop/consumer/idp/client/simple/IdpCertSimpleClientTest.java @@ -21,6 +21,7 @@ class IdpCertSimpleClientTest { private static final String INSTANT = String.valueOf(Instant.now().getEpochSecond()); private static final String SPID_ENTITY_ID = "https://posteid.poste.it"; + private static final String SPID_ENTITY_ID_MULTIPLE_SIGNATURE = "https://loginspid.aruba.it"; private static final String CIE_ENTITY_ID = "https://idserver.servizicie.interno.gov.it/idp/profile/SAML2/POST/SSO"; @@ -46,6 +47,16 @@ void certSPIDDataFound() throws CertDataTagListNotFoundException, CertDataNotFou Assertions.assertNotNull(response); } + @Test + void certSPIDDataFoundMultipleSignature() + throws CertDataTagListNotFoundException, CertDataNotFoundException { + List response = + idpCertSimpleClient.getCertData(SPID_ENTITY_ID_MULTIPLE_SIGNATURE, INSTANT); + + Assertions.assertNotNull(response); + Assertions.assertTrue(response.get(0).getCertData().size() > 1); + } + @Test void certCIEDataFound() throws CertDataTagListNotFoundException, CertDataNotFoundException { List response = idpCertSimpleClient.getCertData(CIE_ENTITY_ID, INSTANT);