From 061ad4a9b3da45361743c22d1518b5dd436c887c Mon Sep 17 00:00:00 2001 From: Thomas Beekman Date: Tue, 4 Jul 2023 21:21:43 +0200 Subject: [PATCH 1/8] Prepare for next development iteration --- oc-sso-notificatie/pom.xml | 2 +- pom.xml | 2 +- release/pom.xml | 4 +-- .../docs/2.1.2-SNAPSHOT/release-notes.md | 28 +++++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md diff --git a/oc-sso-notificatie/pom.xml b/oc-sso-notificatie/pom.xml index 9c3b0f1..ae00156 100644 --- a/oc-sso-notificatie/pom.xml +++ b/oc-sso-notificatie/pom.xml @@ -19,7 +19,7 @@ oc-sso-notificatie-parent nl.kennisnet.services - 2.1.1 + 2.1.2-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index cbcb24a..0b3c048 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ nl.kennisnet.services oc-sso-notificatie-parent pom - 2.1.1 + 2.1.2-SNAPSHOT oc-sso-notificatie release diff --git a/release/pom.xml b/release/pom.xml index cc964e3..bf973e1 100644 --- a/release/pom.xml +++ b/release/pom.xml @@ -19,7 +19,7 @@ oc-sso-notificatie-parent nl.kennisnet.services - 2.1.1 + 2.1.2-SNAPSHOT 4.0.0 @@ -31,7 +31,7 @@ - 2.1.1,2.1.0,2.0.6,2.0.5,2.0.4,2.0.3,2.0.2,2.0.1,1.0.0 + 2.1.2-SNAPSHOT,2.1.1,2.1.0,2.0.6,2.0.5,2.0.4,2.0.3,2.0.2,2.0.1,1.0.0 false 2.8 3.8.2 diff --git a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md new file mode 100644 index 0000000..f4c3cd8 --- /dev/null +++ b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md @@ -0,0 +1,28 @@ +# OC SSO Notification Service - Release Notes + +| Field | Value | +|:--------------------------|:----------------------------| +| Application | OC SSO Notification Service | +| Version | 2.1.2-SNAPSHOT | +| Changes since version | 2.1.1 | +| Release date | dd-mm-yyyy (dd-mm-yyyy) | +| Delivery type | Full release | + +## Changes + + +| # | Description | +|:---------|:--------------------------------------------------------------| +| ENT-XXXX | | + + +## Configuration changes + +## Known vulnerabilities + +This version of the application consists of the following known vulnerabilities with a CVE of 8 or higher: + +### snakeyaml-1.33.jar: CVE-2022-1471 (9.8) + +This dependency is used by the latest version of Spring Boot (3.0.7) and yet unresolved. This vulnerability is a false +positive (see: https://github.com/spring-projects/spring-boot/issues/33457) and added to the ignore list. From 81c4506817cbdd49ecc5a5b604ee585d1e2e6078 Mon Sep 17 00:00:00 2001 From: Tim Poot Date: Tue, 25 Jul 2023 14:23:53 +0200 Subject: [PATCH 2/8] ENT-4722: Implement cache clear functionality --- .../services/web/config/CacheConfig.java | 2 - .../web/service/CacheHashService.java | 62 +++++++++++++++ .../jobs/DataServicesUpdateRunner.java | 75 ++++++++++++++++++ .../services/web/CacheHashServiceTest.java | 77 +++++++++++++++++++ .../jobs/DataServicesUpdateRunnerTest.java | 74 ++++++++++++++++++ .../src/test/resources/application.properties | 5 +- .../sample/config/application.properties | 6 +- .../docs/2.1.2-SNAPSHOT/release-notes.md | 14 +++- 8 files changed, 306 insertions(+), 9 deletions(-) create mode 100644 oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java create mode 100644 oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java create mode 100644 oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java create mode 100644 oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/jobs/DataServicesUpdateRunnerTest.java diff --git a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java index 66b29a7..b027419 100644 --- a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java +++ b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java @@ -24,7 +24,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; /** * Guava cache configuration. @@ -44,7 +43,6 @@ public CacheManager cacheManager() { } @CacheEvict(allEntries = true, cacheNames = { IDP_CACHE }) - @Scheduled(fixedDelayString = "#{ ${idp.cache.expiration.time.seconds} * 1000 }") public void cacheEvict() { LOGGER.info("Cache evicted"); } diff --git a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java new file mode 100644 index 0000000..b02e48a --- /dev/null +++ b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java @@ -0,0 +1,62 @@ +package nl.kennisnet.services.web.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +@Service +public class CacheHashService { + + private static final Logger LOGGER = LoggerFactory.getLogger(CacheHashService.class); + + @Value("${api.key.header.key}") + private String API_KEY_HEADER; + + @Value("${api.key.header.value}") + private String apiKeyHeaderValue; + + @Value("${api.endpoint.url.cacheHash}") + private String url; + + private final RestTemplate restTemplate; + + public CacheHashService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + public String fetchCacheHash() { + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.add(API_KEY_HEADER, apiKeyHeaderValue); + + HttpEntity httpEntity = new HttpEntity<>(requestHeaders); + + try { + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, + new ParameterizedTypeReference<>() {}); + + String result = response.getBody(); + if (null == result) { + LOGGER.warn("Received null from data-services cache-hash"); + return ""; + } + + return result; + } catch (HttpStatusCodeException htsce) { + LOGGER.error("Unexpected response received: " + htsce.getMessage()); + return ""; + } catch (RestClientException rce) { + LOGGER.error("Communication error occured: " + rce.getMessage()); + return ""; + } + } + +} \ No newline at end of file diff --git a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java new file mode 100644 index 0000000..cab3c1b --- /dev/null +++ b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java @@ -0,0 +1,75 @@ +package nl.kennisnet.services.web.service.jobs; + +import nl.kennisnet.services.web.config.CacheConfig; +import nl.kennisnet.services.web.service.CacheHashService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +@Component +public class DataServicesUpdateRunner implements Runnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(DataServicesUpdateRunner.class); + + private static final String ALREADY_RUNNING = "DataServicesUpdateRunner is already running"; + + private static final String UPDATE_FAILED = "Cache evicts failed: {}"; + + private static final String UPDATE_FINISHED = "Cache evicts finished"; + + private static final Lock execLock = new ReentrantLock(); + + private static boolean running = false; + + private static String lastDataServicesCacheHash = ""; + + private final CacheHashService cacheHashService; + + private final CacheConfig cacheConfig; + + public DataServicesUpdateRunner(CacheHashService cacheHashService, CacheConfig cacheConfig) { + this.cacheHashService = cacheHashService; + this.cacheConfig = cacheConfig; + } + + @Override + @Scheduled(cron = "${dataservices.fetchCacheHash.cronSchedule}") + public void run() { + if (running || !execLock.tryLock()) { + LOGGER.warn(ALREADY_RUNNING); + return; + } + + // Set the lock and execute the reaper + running = true; + // General exception to ensure that we do not create a deadlock for the scheduled runner + try { + execute(); + } catch (Error | Exception e) { + LOGGER.error(UPDATE_FAILED, e.getMessage()); + } + + // Release the lock + running = false; + execLock.unlock(); + } + + private void execute() { + String dataServicesCacheHash = cacheHashService.fetchCacheHash(); + if (dataServicesCacheHash.equals(lastDataServicesCacheHash) + || (!lastDataServicesCacheHash.isEmpty() && dataServicesCacheHash.isEmpty())) { + return; + } + + LOGGER.info("Changes since last update detected, evicting caches"); + cacheConfig.cacheEvict(); + lastDataServicesCacheHash = dataServicesCacheHash; + + LOGGER.info(UPDATE_FINISHED); + } + +} \ No newline at end of file diff --git a/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java b/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java new file mode 100644 index 0000000..b3faffa --- /dev/null +++ b/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java @@ -0,0 +1,77 @@ +package nl.kennisnet.services.web; + +import nl.kennisnet.services.web.service.CacheHashService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +@SpringBootTest +public class CacheHashServiceTest { + + @Mock + RestTemplate restTemplate; + + @InjectMocks + CacheHashService cacheHashService; + + @BeforeEach + void setUp() { + ReflectionTestUtils.setField(cacheHashService, "url", "sso-notification-url"); + ReflectionTestUtils.setField(cacheHashService, "API_KEY_HEADER", "api-key"); + } + + @Test + void fetchCacheHashTest() { + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), + any(ParameterizedTypeReference.class))).thenReturn(new ResponseEntity<>("HASH", HttpStatus.OK)); + + String result = cacheHashService.fetchCacheHash(); + + assertEquals("HASH", result); + } + + @Test + void fetchCacheNullReturnTest() { + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), + any(ParameterizedTypeReference.class))).thenReturn(new ResponseEntity<>(null, HttpStatus.OK)); + + String result = cacheHashService.fetchCacheHash(); + + assertEquals("", result); + } + + @Test + void fetchCacheHashHttpExceptionTest() { + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), + any(ParameterizedTypeReference.class))).thenThrow(new HttpClientErrorException(HttpStatus.FORBIDDEN)); + + String result = cacheHashService.fetchCacheHash(); + + assertEquals("", result); + } + + @Test + void fetchCacheRestClientExceptionTest() { + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), + any(ParameterizedTypeReference.class))).thenThrow(new RestClientException("ERROR")); + + String result = cacheHashService.fetchCacheHash(); + + assertEquals("", result); + } + +} \ No newline at end of file diff --git a/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/jobs/DataServicesUpdateRunnerTest.java b/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/jobs/DataServicesUpdateRunnerTest.java new file mode 100644 index 0000000..e480a85 --- /dev/null +++ b/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/jobs/DataServicesUpdateRunnerTest.java @@ -0,0 +1,74 @@ +package nl.kennisnet.services.web.jobs; + +import nl.kennisnet.services.web.config.CacheConfig; +import nl.kennisnet.services.web.service.CacheHashService; +import nl.kennisnet.services.web.service.jobs.DataServicesUpdateRunner; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.mockito.Mockito.*; + +@SpringBootTest +public class DataServicesUpdateRunnerTest { + + @Mock + CacheHashService cacheHashService; + + @Mock + CacheConfig cacheConfig; + + @InjectMocks + DataServicesUpdateRunner dataServicesUpdateRunner; + + @BeforeEach + void setup() { + ReflectionTestUtils.setField(dataServicesUpdateRunner, "lastDataServicesCacheHash", "HASH"); + } + + @Test + void runTest() { + ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", false); + + when(cacheHashService.fetchCacheHash()).thenReturn("NEW_HASH"); + + dataServicesUpdateRunner.run(); + + verify(cacheConfig, times(1)).cacheEvict(); + } + + @Test + void runSameHashTest() { + ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", false); + + when(cacheHashService.fetchCacheHash()).thenReturn("HASH"); + + dataServicesUpdateRunner.run(); + + verify(cacheConfig, times(0)).cacheEvict(); + } + + @Test + void runEmptyHashTest() { + ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", false); + + when(cacheHashService.fetchCacheHash()).thenReturn(""); + + dataServicesUpdateRunner.run(); + + verify(cacheConfig, times(0)).cacheEvict(); + } + + @Test + void canNotRunDouble() { + ReflectionTestUtils.setField(dataServicesUpdateRunner, "running", true); + + dataServicesUpdateRunner.run(); + + verify(cacheConfig, times(0)).cacheEvict(); + } + +} \ No newline at end of file diff --git a/oc-sso-notificatie/src/test/resources/application.properties b/oc-sso-notificatie/src/test/resources/application.properties index a87579e..305e9f7 100644 --- a/oc-sso-notificatie/src/test/resources/application.properties +++ b/oc-sso-notificatie/src/test/resources/application.properties @@ -23,6 +23,8 @@ api.key.header.key=api-key api.key.header.value=TESTTOKEN # The URL-suffix to fetch all SSO Notification data from the Data Service endpoint api.endpoint.url.all-suffix=/all +# The URL-suffix to fetch the cache-hash to see if the cache needs to be evicted +api.endpoint.url.cacheHash=/cache-hash # SSO Notification cookie settings # The domain to set for the notification cookie @@ -45,8 +47,7 @@ crypto.secure.key.algorithm=AES crypto.secure.salt=cQ_Jym5aH$Fqua#D # Caching settings -# The expiration time in seconds to invalidate the cached entries for the retrieved idp information. -idp.cache.expiration.time.seconds=300 +dataservices.fetchCacheHash.cronSchedule=0 * * * * * # log level for whole application logging.level.root=INFO diff --git a/release/src/main/resources/sample/config/application.properties b/release/src/main/resources/sample/config/application.properties index a35193c..d8e3e08 100644 --- a/release/src/main/resources/sample/config/application.properties +++ b/release/src/main/resources/sample/config/application.properties @@ -26,6 +26,9 @@ api.key.header.key= api.key.header.value= # The URL-suffix to fetch all SSO Notification data from the Data Service endpoint api.endpoint.url.all-suffix= +# The URL-suffix to fetch the cache-hash to see if the cache needs to be evicted +api.endpoint.url.cacheHash= + # The amount of seconds before a timeout connection.timeout.seconds=5 # The secondary endpoint to redirect to if a request fails. Can be used in a confederation setup @@ -53,8 +56,7 @@ crypto.secure.key.algorithm=AES crypto.secure.salt=cQ_Jym5aH$Fqua#D # Caching settings -# The expiration time in seconds to invalidate the cached entries for the retrieved idp information. -idp.cache.expiration.time.seconds=300 +dataservices.fetchCacheHash.cronSchedule=0 * * * * * # The admin user who can access the management information. spring.security.user.name=admin diff --git a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md index f4c3cd8..acba7a8 100644 --- a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md +++ b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md @@ -11,13 +11,21 @@ ## Changes -| # | Description | -|:---------|:--------------------------------------------------------------| -| ENT-XXXX | | +| # | Description | +|:---------|:------------------------------------| +| ENT-4722 | Implement cache clear functionality | ## Configuration changes +The newly exposed cache-hash endpoint should be added to the configs to fetch the cache-hash: + + api.endpoint.url.cacheHash=http://localhost:3000/api/cache-hash/sso-notification + +Furthermore, a cron schedule to retrieve the cache hash once a minute should also be added: + + dataservices.fetchCacheHash.cronSchedule=0 * * * * * + ## Known vulnerabilities This version of the application consists of the following known vulnerabilities with a CVE of 8 or higher: From 9a29b28645f3113b4c09f978c0ab402c8139a857 Mon Sep 17 00:00:00 2001 From: Tim Poot Date: Tue, 25 Jul 2023 15:49:23 +0200 Subject: [PATCH 3/8] ENT-4722: Implement cache clear functionality - make cache-hash configurable --- .../nl/kennisnet/services/web/config/CacheConfig.java | 2 ++ .../src/test/resources/application.properties | 5 ++++- readme.md | 11 +++++++++++ .../resources/sample/config/application.properties | 5 ++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java index b027419..66b29a7 100644 --- a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java +++ b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/config/CacheConfig.java @@ -24,6 +24,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; /** * Guava cache configuration. @@ -43,6 +44,7 @@ public CacheManager cacheManager() { } @CacheEvict(allEntries = true, cacheNames = { IDP_CACHE }) + @Scheduled(fixedDelayString = "#{ ${idp.cache.expiration.time.seconds} * 1000 }") public void cacheEvict() { LOGGER.info("Cache evicted"); } diff --git a/oc-sso-notificatie/src/test/resources/application.properties b/oc-sso-notificatie/src/test/resources/application.properties index 305e9f7..477a969 100644 --- a/oc-sso-notificatie/src/test/resources/application.properties +++ b/oc-sso-notificatie/src/test/resources/application.properties @@ -47,7 +47,10 @@ crypto.secure.key.algorithm=AES crypto.secure.salt=cQ_Jym5aH$Fqua#D # Caching settings -dataservices.fetchCacheHash.cronSchedule=0 * * * * * +# The expiration time in seconds to invalidate the cached entries for the retrieved idp information. +idp.cache.expiration.time.seconds=300 +# Polling schedule if central data-service is used, disabled by default +dataservices.fetchCacheHash.cronSchedule=- # log level for whole application logging.level.root=INFO diff --git a/readme.md b/readme.md index 9613c57..05bfa21 100644 --- a/readme.md +++ b/readme.md @@ -110,6 +110,17 @@ outage), the static file will NOT be used as a fallback. For a full example of the configurations, please refer to [Installation Manual](release/src/site/markdown/docs/installation-manual.md). +It is possible to configure SSO-Notification such that it runs more in sync with the data-source. If this is done, +SSO-Notification periodically polls a check-sum endpoint exposed on the original data-source. The cache is then evicted +if the check-sum has changed since the last time. To do this, the following configurations must be configured: + + api.endpoint.url.cacheHash= + dataservices.fetchCacheHash.cronSchedule=- + +Where `api.endpoint.url.cacheHash` is the url (including endpoint) where the check-sum is exposed, and +`dataservices.fetchCacheHash.cronSchedule` is the cron-schedule at which the above endpoint will be polled. This schedule +is set to `-` by default, which disables this polling feature. + ## Configuration of Engineblock Reading and processing SSO Notification cookies should be enabled in Engineblock. Furthermore, the encryption key diff --git a/release/src/main/resources/sample/config/application.properties b/release/src/main/resources/sample/config/application.properties index d8e3e08..add13a6 100644 --- a/release/src/main/resources/sample/config/application.properties +++ b/release/src/main/resources/sample/config/application.properties @@ -56,7 +56,10 @@ crypto.secure.key.algorithm=AES crypto.secure.salt=cQ_Jym5aH$Fqua#D # Caching settings -dataservices.fetchCacheHash.cronSchedule=0 * * * * * +# The expiration time in seconds to invalidate the cached entries for the retrieved idp information. +idp.cache.expiration.time.seconds=300 +# Polling schedule if central data-service is used, disabled by default +dataservices.fetchCacheHash.cronSchedule=- # The admin user who can access the management information. spring.security.user.name=admin From d5943ea5cbfc99d14d49c125d478f1d52f1f1dfe Mon Sep 17 00:00:00 2001 From: Tim Poot Date: Tue, 25 Jul 2023 15:53:10 +0200 Subject: [PATCH 4/8] ENT-4744: Update Institution Service & SSO-Notification cache to cache clear hash --- .../src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md index acba7a8..a71110e 100644 --- a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md +++ b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md @@ -11,9 +11,10 @@ ## Changes -| # | Description | -|:---------|:------------------------------------| -| ENT-4722 | Implement cache clear functionality | +| # | Description | +|:---------|:------------------------------------------------------------------------| +| ENT-4722 | Implement cache clear functionality | +| ENT-4744 | Update Institution Service & SSO-Notification cache to cache clear hash | ## Configuration changes From 7f9bd0c7d6d9a3ff63fd840c67c4d56e7fab49cc Mon Sep 17 00:00:00 2001 From: Vincent Jong Date: Thu, 3 Aug 2023 10:48:10 +0200 Subject: [PATCH 5/8] ENT-4744: Update Institution Service & SSO-Notification cache to cache clear hash - make cache hash configurations optional --- .../services/web/service/CacheHashService.java | 13 +++++++++---- .../web/service/jobs/DataServicesUpdateRunner.java | 4 ++-- .../services/web/CacheHashServiceTest.java | 12 ++++++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java index b02e48a..5b75f3f 100644 --- a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java +++ b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/CacheHashService.java @@ -24,7 +24,7 @@ public class CacheHashService { @Value("${api.key.header.value}") private String apiKeyHeaderValue; - @Value("${api.endpoint.url.cacheHash}") + @Value("${api.endpoint.url.cacheHash:#{null}}") private String url; private final RestTemplate restTemplate; @@ -34,6 +34,11 @@ public CacheHashService(RestTemplate restTemplate) { } public String fetchCacheHash() { + if (null == url) { + LOGGER.info("Cache hash endpoint not set, returning empty hash"); + return ""; + } + HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.add(API_KEY_HEADER, apiKeyHeaderValue); @@ -45,16 +50,16 @@ public String fetchCacheHash() { String result = response.getBody(); if (null == result) { - LOGGER.warn("Received null from data-services cache-hash"); + LOGGER.warn("Received null from data-services cache-hash, returning empty hash"); return ""; } return result; } catch (HttpStatusCodeException htsce) { - LOGGER.error("Unexpected response received: " + htsce.getMessage()); + LOGGER.error("Unexpected response received, returning empty hash. Error message: {}", htsce.getMessage()); return ""; } catch (RestClientException rce) { - LOGGER.error("Communication error occured: " + rce.getMessage()); + LOGGER.error("Communication error occurred, returning empty hash. Error message: {} ", rce.getMessage()); return ""; } } diff --git a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java index cab3c1b..e471a10 100644 --- a/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java +++ b/oc-sso-notificatie/src/main/java/nl/kennisnet/services/web/service/jobs/DataServicesUpdateRunner.java @@ -23,7 +23,7 @@ public class DataServicesUpdateRunner implements Runnable { private static final Lock execLock = new ReentrantLock(); - private static boolean running = false; + private static boolean running = false; private static String lastDataServicesCacheHash = ""; @@ -37,7 +37,7 @@ public DataServicesUpdateRunner(CacheHashService cacheHashService, CacheConfig c } @Override - @Scheduled(cron = "${dataservices.fetchCacheHash.cronSchedule}") + @Scheduled(cron = "${dataservices.fetchCacheHash.cronSchedule:-}") public void run() { if (running || !execLock.tryLock()) { LOGGER.warn(ALREADY_RUNNING); diff --git a/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java b/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java index b3faffa..185952c 100644 --- a/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java +++ b/oc-sso-notificatie/src/test/java/nl/kennisnet/services/web/CacheHashServiceTest.java @@ -54,6 +54,18 @@ void fetchCacheNullReturnTest() { assertEquals("", result); } + @Test + void fetchCacheNullUrlTest() { + ReflectionTestUtils.setField(cacheHashService, "url", null); + + when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), + any(ParameterizedTypeReference.class))).thenReturn(new ResponseEntity<>(null, HttpStatus.OK)); + + String result = cacheHashService.fetchCacheHash(); + + assertEquals("", result); + } + @Test void fetchCacheHashHttpExceptionTest() { when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), From b36c700561b6ae965619f15ce83443edcf2426c1 Mon Sep 17 00:00:00 2001 From: Thomas Beekman Date: Thu, 3 Aug 2023 12:13:55 +0200 Subject: [PATCH 6/8] ENT-4735: Build release SSO Notification Service 2.2.0 --- .github/workflows/develop.yml | 9 ++++ .github/workflows/master.yml | 9 ++++ oc-sso-notificatie/pom.xml | 3 +- .../src/test/resources/application.properties | 2 +- pom.xml | 17 ++++++-- release/pom.xml | 4 +- .../sample/config/application.properties | 2 +- .../docs/2.1.2-SNAPSHOT/release-notes.md | 37 ---------------- .../site/markdown/docs/2.2.0/release-notes.md | 43 +++++++++++++++++++ .../markdown/docs/release-notes-template.md | 7 +-- release/src/suppressions/ignore.xml | 9 ---- 11 files changed, 80 insertions(+), 62 deletions(-) delete mode 100644 release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md create mode 100644 release/src/site/markdown/docs/2.2.0/release-notes.md diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 05372bf..363eb92 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -22,6 +22,15 @@ jobs: java-version: '17' distribution: 'adopt' cache: maven + - name: Fail build if version contains SNAPSHOT + run: | + VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + if [[ "$VERSION" == *SNAPSHOT ]]; then + echo "Version contains SNAPSHOT, continuing the workflow." + else + echo "Version does not contain SNAPSHOT, failing the workflow!" + exit 1 + fi - name: Build with Maven run: mvn -B -U clean verify install -P release -Djdk.net.URLClassPath.disableClassPathURLCheck=true - run: echo "ARTIFACT_FILE_NAME=$(ls oc-sso-notificatie/target/*.jar | xargs basename | sed 's/\.[^.]*$//')" >> $GITHUB_ENV diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 423e206..90cb4ec 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -22,6 +22,15 @@ jobs: java-version: '17' distribution: 'adopt' cache: maven + - name: Fail build if version contains SNAPSHOT + run: | + VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + if [[ "$VERSION" == *SNAPSHOT ]]; then + echo "Version contains SNAPSHOT, failing the workflow!" + exit 1 + else + echo "Version is valid, continuing with the workflow." + fi - name: Build with Maven and publish package run: mvn -B -U clean verify install -P release deploy -Djdk.net.URLClassPath.disableClassPathURLCheck=true env: diff --git a/oc-sso-notificatie/pom.xml b/oc-sso-notificatie/pom.xml index ae00156..03644a8 100644 --- a/oc-sso-notificatie/pom.xml +++ b/oc-sso-notificatie/pom.xml @@ -19,7 +19,7 @@ oc-sso-notificatie-parent nl.kennisnet.services - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT 4.0.0 @@ -34,7 +34,6 @@ 3.1.0 5.3 1.18.20 - 6.3.2 11 false diff --git a/oc-sso-notificatie/src/test/resources/application.properties b/oc-sso-notificatie/src/test/resources/application.properties index 477a969..979e07d 100644 --- a/oc-sso-notificatie/src/test/resources/application.properties +++ b/oc-sso-notificatie/src/test/resources/application.properties @@ -49,7 +49,7 @@ crypto.secure.salt=cQ_Jym5aH$Fqua#D # Caching settings # The expiration time in seconds to invalidate the cached entries for the retrieved idp information. idp.cache.expiration.time.seconds=300 -# Polling schedule if central data-service is used, disabled by default +# Polling schedule if a central data-service is used, disabled by default dataservices.fetchCacheHash.cronSchedule=- # log level for whole application diff --git a/pom.xml b/pom.xml index 0b3c048..bef3bfc 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ nl.kennisnet.services oc-sso-notificatie-parent pom - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT oc-sso-notificatie release @@ -45,13 +45,13 @@ 2.5.3 3.1.1 3.7.0.1746 - 1.33 + 2.0 org.springframework.boot spring-boot-starter-parent - 3.0.7 + 3.1.2 @@ -156,7 +156,7 @@ ${dependency-check-maven.version} ALL - 8 + 7 release/src/suppressions/ignore.xml false @@ -209,6 +209,15 @@ Jong.Vincent@kpmg.nl + + poot01 + Tim Poot + KPMG Advisory N.V. + + Developer + + Poot.Tim@kpmg.nl + \ No newline at end of file diff --git a/release/pom.xml b/release/pom.xml index bf973e1..8cc1846 100644 --- a/release/pom.xml +++ b/release/pom.xml @@ -19,7 +19,7 @@ oc-sso-notificatie-parent nl.kennisnet.services - 2.1.2-SNAPSHOT + 2.2.0-SNAPSHOT 4.0.0 @@ -31,7 +31,7 @@ - 2.1.2-SNAPSHOT,2.1.1,2.1.0,2.0.6,2.0.5,2.0.4,2.0.3,2.0.2,2.0.1,1.0.0 + 2.2.0,2.1.1,2.1.0,2.0.6,2.0.5,2.0.4,2.0.3,2.0.2,2.0.1,1.0.0 false 2.8 3.8.2 diff --git a/release/src/main/resources/sample/config/application.properties b/release/src/main/resources/sample/config/application.properties index add13a6..b507aa2 100644 --- a/release/src/main/resources/sample/config/application.properties +++ b/release/src/main/resources/sample/config/application.properties @@ -58,7 +58,7 @@ crypto.secure.salt=cQ_Jym5aH$Fqua#D # Caching settings # The expiration time in seconds to invalidate the cached entries for the retrieved idp information. idp.cache.expiration.time.seconds=300 -# Polling schedule if central data-service is used, disabled by default +# Polling schedule if a central data-service is used, disabled by default dataservices.fetchCacheHash.cronSchedule=- # The admin user who can access the management information. diff --git a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md b/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md deleted file mode 100644 index a71110e..0000000 --- a/release/src/site/markdown/docs/2.1.2-SNAPSHOT/release-notes.md +++ /dev/null @@ -1,37 +0,0 @@ -# OC SSO Notification Service - Release Notes - -| Field | Value | -|:--------------------------|:----------------------------| -| Application | OC SSO Notification Service | -| Version | 2.1.2-SNAPSHOT | -| Changes since version | 2.1.1 | -| Release date | dd-mm-yyyy (dd-mm-yyyy) | -| Delivery type | Full release | - -## Changes - - -| # | Description | -|:---------|:------------------------------------------------------------------------| -| ENT-4722 | Implement cache clear functionality | -| ENT-4744 | Update Institution Service & SSO-Notification cache to cache clear hash | - - -## Configuration changes - -The newly exposed cache-hash endpoint should be added to the configs to fetch the cache-hash: - - api.endpoint.url.cacheHash=http://localhost:3000/api/cache-hash/sso-notification - -Furthermore, a cron schedule to retrieve the cache hash once a minute should also be added: - - dataservices.fetchCacheHash.cronSchedule=0 * * * * * - -## Known vulnerabilities - -This version of the application consists of the following known vulnerabilities with a CVE of 8 or higher: - -### snakeyaml-1.33.jar: CVE-2022-1471 (9.8) - -This dependency is used by the latest version of Spring Boot (3.0.7) and yet unresolved. This vulnerability is a false -positive (see: https://github.com/spring-projects/spring-boot/issues/33457) and added to the ignore list. diff --git a/release/src/site/markdown/docs/2.2.0/release-notes.md b/release/src/site/markdown/docs/2.2.0/release-notes.md new file mode 100644 index 0000000..ab87864 --- /dev/null +++ b/release/src/site/markdown/docs/2.2.0/release-notes.md @@ -0,0 +1,43 @@ +# OC SSO Notification Service - Release Notes + +| Field | Value | +|:--------------------------|:----------------------------| +| Application | OC SSO Notification Service | +| Version | 2.2.0 | +| Changes since version | 2.1.1 | +| Release date | 03-04-2023 (dd-mm-yyyy) | +| Delivery type | Full release | + +## Changes + +| # | Description | +|:---------|:------------------------------------------------------------------------| +| ENT-4722 | Implement cache clear functionality | +| ENT-4735 | Build release SSO Notification Service 2.2.0 | +| ENT-4744 | Update Institution Service & SSO-Notification cache to cache clear hash | + +## Configuration changes + +With the changes in this version of OC SSO Notification, it is possible to configure the application such that it runs +more in sync with the data-source. If this is done, OC SSO Notification periodically polls a check-sum endpoint exposed +on the original data-source. The cache is then evicted if the check-sum has changed since the last time. To do this, +the following configurations must be configured: + + api.endpoint.url.cacheHash= + dataservices.fetchCacheHash.cronSchedule=- + +Where `api.endpoint.url.cacheHash' is the url (including endpoint) where the check-sum is exposed, and +'dataservices.fetchCacheHash.cronSchedule' is the cron-schedule at which the above endpoint will be polled. This +schedule is set to '-' by default, which disables this polling feature. + +The newly exposed cache-hash endpoint should be added to the configs to fetch the cache-hash: + + api.endpoint.url.cacheHash=http://localhost:3000/api/cache-hash/sso-notification + +Furthermore, a cron schedule to retrieve the cache hash once a minute should also be added: + + dataservices.fetchCacheHash.cronSchedule=0 * * * * * + +## Known vulnerabilities + +At the time of release, this version of the application had no known vulnerabilities with a CVE of 7 or higher. diff --git a/release/src/site/markdown/docs/release-notes-template.md b/release/src/site/markdown/docs/release-notes-template.md index 8978f84..e809847 100644 --- a/release/src/site/markdown/docs/release-notes-template.md +++ b/release/src/site/markdown/docs/release-notes-template.md @@ -20,9 +20,4 @@ ## Known vulnerabilities -This version of the application consists of the following known vulnerabilities with a CVE of 8 or higher: - -### snakeyaml-1.33.jar: CVE-2022-1471 (9.8) - -This dependency is used by the latest version of Spring Boot (3.0.7) and yet unresolved. This vulnerability is a false -positive (see: https://github.com/spring-projects/spring-boot/issues/33457) and added to the ignore list. +At the time of release, this version of the application had no known vulnerabilities with a CVE of 7 or higher. diff --git a/release/src/suppressions/ignore.xml b/release/src/suppressions/ignore.xml index 1b4b15b..5aecb74 100644 --- a/release/src/suppressions/ignore.xml +++ b/release/src/suppressions/ignore.xml @@ -1,13 +1,4 @@ - - - ^pkg:maven/org\.yaml/snakeyaml@.*$ - CVE-2022-1471 - - From f005655aa9abad86af5e38d68e52012534ad4d98 Mon Sep 17 00:00:00 2001 From: Thomas Beekman Date: Thu, 3 Aug 2023 13:37:41 +0200 Subject: [PATCH 7/8] ENT-4735: Build release SSO Notification Service 2.2.0 --- oc-sso-notificatie/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/oc-sso-notificatie/pom.xml b/oc-sso-notificatie/pom.xml index 03644a8..8fd580c 100644 --- a/oc-sso-notificatie/pom.xml +++ b/oc-sso-notificatie/pom.xml @@ -34,7 +34,6 @@ 3.1.0 5.3 1.18.20 - 11 false From 33a7a3b74016aba9f99fe49e4c6915f7db7fa1ff Mon Sep 17 00:00:00 2001 From: Thomas Beekman Date: Thu, 3 Aug 2023 17:04:28 +0200 Subject: [PATCH 8/8] ENT-4735: Build release SSO Notification Service 2.2.0 --- oc-sso-notificatie/pom.xml | 2 +- pom.xml | 2 +- release/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/oc-sso-notificatie/pom.xml b/oc-sso-notificatie/pom.xml index 8fd580c..0374266 100644 --- a/oc-sso-notificatie/pom.xml +++ b/oc-sso-notificatie/pom.xml @@ -19,7 +19,7 @@ oc-sso-notificatie-parent nl.kennisnet.services - 2.2.0-SNAPSHOT + 2.2.0 4.0.0 diff --git a/pom.xml b/pom.xml index bef3bfc..d5931e7 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ nl.kennisnet.services oc-sso-notificatie-parent pom - 2.2.0-SNAPSHOT + 2.2.0 oc-sso-notificatie release diff --git a/release/pom.xml b/release/pom.xml index 8cc1846..dd8ff55 100644 --- a/release/pom.xml +++ b/release/pom.xml @@ -19,7 +19,7 @@ oc-sso-notificatie-parent nl.kennisnet.services - 2.2.0-SNAPSHOT + 2.2.0 4.0.0