diff --git a/pom.xml b/pom.xml
index d14539e6..d5cfb251 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
6.5.3
5.6.2
1.18.22
- 4.8.0
+ 4.9.0
1.6.6
1.4.2.Final
4.3.1
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/config/DgcConfigProperties.java b/src/main/java/eu/europa/ec/dgc/gateway/config/DgcConfigProperties.java
index d836ce2d..898d0ea1 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/config/DgcConfigProperties.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/config/DgcConfigProperties.java
@@ -39,6 +39,8 @@ public class DgcConfigProperties {
private Revocation revocation = new Revocation();
+ private SignerInformation signerInformation = new SignerInformation();
+
@Getter
@Setter
public static class JrcConfig {
@@ -85,4 +87,10 @@ public static class HeaderFields {
public static class Revocation {
private int deleteThreshold = 14;
}
+
+ @Getter
+ @Setter
+ public static class SignerInformation {
+ private int deleteThreshold = 14;
+ }
}
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/entity/SignerInformationEntity.java b/src/main/java/eu/europa/ec/dgc/gateway/entity/SignerInformationEntity.java
index 864c6978..825e48f7 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/entity/SignerInformationEntity.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/entity/SignerInformationEntity.java
@@ -53,6 +53,9 @@ public class SignerInformationEntity {
@Column(name = "created_at", nullable = false)
private ZonedDateTime createdAt = ZonedDateTime.now();
+ @Column(name = "deleted_at")
+ private ZonedDateTime deletedAt;
+
/**
* ISO 3166 Alpha-2 Country Code
* (plus code "EU" for administrative European Union entries).
@@ -75,7 +78,7 @@ public class SignerInformationEntity {
/**
* Signature of the TrustAnchor.
*/
- @Column(name = "signature", nullable = false, length = 6000)
+ @Column(name = "signature", length = 6000)
String signature;
/**
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/repository/SignerInformationRepository.java b/src/main/java/eu/europa/ec/dgc/gateway/repository/SignerInformationRepository.java
index f8b97916..d1f1536e 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/repository/SignerInformationRepository.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/repository/SignerInformationRepository.java
@@ -21,23 +21,75 @@
package eu.europa.ec.dgc.gateway.repository;
import eu.europa.ec.dgc.gateway.entity.SignerInformationEntity;
+import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;
import javax.transaction.Transactional;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
public interface SignerInformationRepository extends JpaRepository {
+ String SELECT_SINCE =
+ "SELECT s FROM SignerInformationEntity s WHERE s.createdAt >= :since OR s.deletedAt >= :since";
+ String SELECT_BY_TYPE_SINCE =
+ "SELECT s FROM SignerInformationEntity s WHERE s.certificateType = :certType AND (s.createdAt >= :since "
+ + " OR s.deletedAt >= :since)";
+ String SELECT_BY_TYPE_AND_COUNTRY_SINCE =
+ "SELECT s FROM SignerInformationEntity s"
+ + " WHERE s.certificateType = :certType AND s.country = :country AND (s.createdAt >= :since"
+ + " OR s.deletedAt >= :since)";
+
Optional getFirstByThumbprint(String thumbprint);
Optional getFirstByThumbprintStartsWith(String thumbprintStart);
@Transactional
- void deleteByThumbprint(String thumbprint);
+ @Modifying
+ @Query("DELETE FROM SignerInformationEntity s WHERE s.deletedAt < :threshold")
+ int deleteDeletedSignerInformationOlderThan(@Param("threshold") ZonedDateTime threshold);
+
+ List getByCertificateType(SignerInformationEntity.CertificateType type,
+ Pageable pageable);
List getByCertificateType(SignerInformationEntity.CertificateType type);
+ List getByCertificateTypeAndCountry(
+ SignerInformationEntity.CertificateType type, String countryCode,
+ Pageable pageable);
+
List getByCertificateTypeAndCountry(
SignerInformationEntity.CertificateType type, String countryCode);
+ @Query(SELECT_SINCE)
+ List getIsSince(@Param("since")ZonedDateTime since);
+
+ @Query(SELECT_SINCE)
+ List getIsSince(@Param("since")ZonedDateTime since, Pageable pageable);
+
+ @Query(SELECT_BY_TYPE_SINCE)
+ List getByCertificateTypeIsSince(
+ @Param("certType")SignerInformationEntity.CertificateType type,
+ @Param("since")ZonedDateTime since);
+
+ @Query(SELECT_BY_TYPE_SINCE)
+ List getByCertificateTypeIsSince(
+ @Param("certType")SignerInformationEntity.CertificateType type,
+ @Param("since")ZonedDateTime since, Pageable pageable);
+
+ @Query(SELECT_BY_TYPE_AND_COUNTRY_SINCE)
+ List getByCertificateTypeAndCountryIsSince(
+ @Param("certType")SignerInformationEntity.CertificateType type,
+ @Param("country")String countryCode,
+ @Param("since")ZonedDateTime since);
+
+ @Query(SELECT_BY_TYPE_AND_COUNTRY_SINCE)
+ List getByCertificateTypeAndCountryIsSince(
+ @Param("certType")SignerInformationEntity.CertificateType type,
+ @Param("country")String countryCode,
+ @Param("since")ZonedDateTime since, Pageable pageable);
+
}
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/repository/TrustedPartyRepository.java b/src/main/java/eu/europa/ec/dgc/gateway/repository/TrustedPartyRepository.java
index 101f1358..18e4f1c0 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/repository/TrustedPartyRepository.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/repository/TrustedPartyRepository.java
@@ -21,13 +21,22 @@
package eu.europa.ec.dgc.gateway.repository;
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
+import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
public interface TrustedPartyRepository extends JpaRepository {
+ String SELECT_SINCE = "SELECT t FROM TrustedPartyEntity t WHERE t.createdAt >= :since";
+ String SELECT_BY_TYPE_SINCE =
+ "SELECT t FROM TrustedPartyEntity t WHERE t.certificateType = :certType AND t.createdAt >= :since";
+ String SELECT_BY_TYPE_AND_COUNTRY_SINCE =
+ "SELECT t FROM TrustedPartyEntity t"
+ + " WHERE t.certificateType = :certType AND t.country = :country AND t.createdAt >= :since";
+
List getByCountryAndCertificateType(String country, TrustedPartyEntity.CertificateType type);
List getByCertificateType(TrustedPartyEntity.CertificateType type);
@@ -41,4 +50,18 @@ Optional getFirstByThumbprintAndCertificateType(
@Query("SELECT DISTINCT t.country FROM TrustedPartyEntity t")
List getCountryCodeList();
+ @Query(SELECT_SINCE)
+ List getIsSince(@Param("since") ZonedDateTime since);
+
+ @Query(SELECT_BY_TYPE_SINCE)
+ List getByCertificateTypeIsSince(
+ @Param("certType")TrustedPartyEntity.CertificateType type,
+ @Param("since")ZonedDateTime since);
+
+ @Query(SELECT_BY_TYPE_AND_COUNTRY_SINCE)
+ List getByCountryAndCertificateTypeIsSince(
+ @Param("country")String countryCode,
+ @Param("certType")TrustedPartyEntity.CertificateType type,
+ @Param("since")ZonedDateTime since);
+
}
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListController.java b/src/main/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListController.java
index 227b5925..9e4c594e 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListController.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListController.java
@@ -42,6 +42,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import java.time.ZonedDateTime;
import java.util.List;
import java.util.Locale;
import javax.validation.Valid;
@@ -49,12 +50,15 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -91,13 +95,43 @@ public class TrustListController {
},
summary = "Returns the full list of trusted certificates.",
tags = {"Trust Lists"},
+ parameters = {
+ @Parameter(
+ in = ParameterIn.HEADER,
+ name = HttpHeaders.IF_MODIFIED_SINCE,
+ description = "Defines if only updated certificates since the given date should be returned.",
+ required = false,
+ schema = @Schema(implementation = String.class),
+ example = "Wed, 21 Oct 2015 07:28:00 GMT"),
+ @Parameter(
+ in = ParameterIn.QUERY,
+ name = "page",
+ description = "Page index, must NOT be negative.",
+ required = false,
+ schema = @Schema(implementation = Integer.class),
+ example = "0"),
+ @Parameter(
+ in = ParameterIn.QUERY,
+ description = "Number of certificates in a page to be returned, must be greater than 0.",
+ required = false,
+ schema = @Schema(implementation = Integer.class),
+ example = "10")
+ },
responses = {
@ApiResponse(
responseCode = "200",
- description = "Returns the full list of trusted parties.",
+ description = "Returns the full list of trusted parties. Optional the download can be paginated"
+ + " and a delta download will be enabled by the header parameter 'If-Modified-Since'.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = TrustListDto.class)))),
+ @ApiResponse(
+ responseCode = "400",
+ description = "Bad request. Invalid date in HTTP header 'If-Modified-Since'.",
+ content = @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = ProblemReportDto.class)
+ )),
@ApiResponse(
responseCode = "401",
description = "Unauthorized. No Access to the system. (Client Certificate not present or whitelisted)",
@@ -107,10 +141,20 @@ public class TrustListController {
))
})
public ResponseEntity> downloadTrustList(
+ @RequestHeader(value = HttpHeaders.IF_MODIFIED_SINCE, required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime ifModifiedSince,
+ @RequestParam(value = "page", required = false) Integer page,
+ @RequestParam(value = "pagesize", required = false) Integer size,
@RequestAttribute(CertificateAuthenticationFilter.REQUEST_PROP_COUNTRY) String downloaderCountryCode
) {
- List trustList = trustListMapper.trustListToTrustListDto(trustListService.getTrustList());
-
+ List trustList;
+ if (isPaginationRequired(page,size)) {
+ trustList = trustListMapper.trustListToTrustListDto(
+ trustListService.getTrustList(ifModifiedSince, page, size));
+ } else {
+ trustList = trustListMapper.trustListToTrustListDto(
+ trustListService.getTrustList(ifModifiedSince, null, null));
+ }
DgcMdc.put(MDC_PROP_DOWNLOAD_KEYS_COUNT, trustList.size());
DgcMdc.put(MDC_PROP_DOWNLOAD_KEYS_COUNTRY, downloaderCountryCode);
@@ -137,18 +181,41 @@ public ResponseEntity> downloadTrustList(
name = "type",
description = "Certificate Type to filter for",
required = true,
- schema = @Schema(implementation = CertificateTypeDto.class))
+ schema = @Schema(implementation = CertificateTypeDto.class)),
+ @Parameter(
+ in = ParameterIn.HEADER,
+ name = HttpHeaders.IF_MODIFIED_SINCE,
+ description = "Defines if only updated certificates since the given date should be returned.",
+ required = false,
+ schema = @Schema(implementation = String.class),
+ example = "Wed, 21 Oct 2015 07:28:00 GMT"),
+ @Parameter(
+ in = ParameterIn.QUERY,
+ name = "page",
+ description = "Page index, must NOT be negative.",
+ required = false,
+ schema = @Schema(implementation = Integer.class),
+ example = "0"),
+ @Parameter(
+ in = ParameterIn.QUERY,
+ name = "pagesize",
+ description = "Number of certificates in a page to be returned, must be greater than 0.",
+ required = false,
+ schema = @Schema(implementation = Integer.class),
+ example = "10")
},
responses = {
@ApiResponse(
responseCode = "200",
- description = "Returns a filtered list of trusted certificates.",
+ description = "Returns a filtered list of trusted certificates. Optional the download can be paginated"
+ + " and a delta download will be enabled by the header parameter 'If-Modified-Since'.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = TrustListDto.class)))),
@ApiResponse(
responseCode = "400",
- description = "Bad request. Unknown Certificate Type.",
+ description = "Bad request. Unknown Certificate Type or invalid date in "
+ + "HTTP header 'If-Modified-Since'.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ProblemReportDto.class)
@@ -163,13 +230,22 @@ public ResponseEntity> downloadTrustList(
})
public ResponseEntity> downloadTrustListFilteredByType(
@Valid @PathVariable("type") CertificateTypeDto type,
+ @RequestHeader(value = HttpHeaders.IF_MODIFIED_SINCE, required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime ifModifiedSince,
+ @RequestParam(value = "page", required = false) Integer page,
+ @RequestParam(value = "pagesize", required = false) Integer size,
@RequestAttribute(CertificateAuthenticationFilter.REQUEST_PROP_COUNTRY) String downloaderCountryCode
) {
TrustListType mappedType = trustListMapper.certificateTypeDtoToTrustListType(type);
-
- List trustList = trustListMapper.trustListToTrustListDto(
- trustListService.getTrustList(mappedType));
+ List trustList;
+ if (isPaginationRequired(page,size)) {
+ trustList = trustListMapper.trustListToTrustListDto(
+ trustListService.getTrustList(mappedType, ifModifiedSince, page, size));
+ } else {
+ trustList = trustListMapper.trustListToTrustListDto(
+ trustListService.getTrustList(mappedType, ifModifiedSince, null, null));
+ }
DgcMdc.put(MDC_PROP_DOWNLOAD_KEYS_COUNT, trustList.size());
DgcMdc.put(MDC_PROP_DOWNLOAD_KEYS_TYPE, type.name());
@@ -204,18 +280,41 @@ public ResponseEntity> downloadTrustListFilteredByType(
name = "country",
description = "2-Digit Country Code to filter for",
example = "EU",
- required = true)
+ required = true),
+ @Parameter(
+ in = ParameterIn.HEADER,
+ name = HttpHeaders.IF_MODIFIED_SINCE,
+ description = "Defines if only updated certificates since the given date should be returned.",
+ required = false,
+ schema = @Schema(implementation = String.class),
+ example = "Wed, 21 Oct 2015 07:28:00 GMT"),
+ @Parameter(
+ in = ParameterIn.QUERY,
+ name = "page",
+ description = "Page index, must NOT be negative.",
+ required = false,
+ schema = @Schema(implementation = Integer.class),
+ example = "0"),
+ @Parameter(
+ in = ParameterIn.QUERY,
+ name = "pagesize",
+ description = "Number of certificates in a page to be returned, must be greater than 0.",
+ required = false,
+ schema = @Schema(implementation = Integer.class),
+ example = "10")
},
responses = {
@ApiResponse(
responseCode = "200",
- description = "Returns a filtered list of trusted certificates.",
+ description = "Returns a filtered list of trusted certificates. Optional the download can be paginated"
+ + " and a delta download will be enabled by the header parameter 'If-Modified-Since'.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = TrustListDto.class)))),
@ApiResponse(
responseCode = "400",
- description = "Bad request. Unknown Certificate Type or invalid country code.",
+ description = "Bad request. Unknown Certificate Type or invalid country code or "
+ + "invalid date in HTTP header 'If-Modified-Since'.",
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ProblemReportDto.class)
@@ -231,14 +330,24 @@ public ResponseEntity> downloadTrustListFilteredByType(
public ResponseEntity> downloadTrustListFilteredByCountryAndType(
@Valid @PathVariable("type") CertificateTypeDto type,
@Valid @Size(max = 2, min = 2) @PathVariable("country") String countryCode,
+ @RequestHeader(value = HttpHeaders.IF_MODIFIED_SINCE, required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime ifModifiedSince,
+ @RequestParam(value = "page", required = false) Integer page,
+ @RequestParam(value = "pagesize", required = false) Integer size,
@RequestAttribute(CertificateAuthenticationFilter.REQUEST_PROP_COUNTRY) String downloaderCountryCode
) {
TrustListType mappedType = trustListMapper.certificateTypeDtoToTrustListType(type);
countryCode = countryCode.toUpperCase(Locale.ROOT);
- List trustList = trustListMapper.trustListToTrustListDto(
- trustListService.getTrustList(mappedType, countryCode));
+ List trustList;
+ if (isPaginationRequired(page,size)) {
+ trustList = trustListMapper.trustListToTrustListDto(
+ trustListService.getTrustList(mappedType, countryCode, ifModifiedSince, page, size));
+ } else {
+ trustList = trustListMapper.trustListToTrustListDto(
+ trustListService.getTrustList(mappedType, countryCode, ifModifiedSince, null, null));
+ }
DgcMdc.put(MDC_PROP_DOWNLOAD_KEYS_COUNT, trustList.size());
DgcMdc.put(MDC_PROP_DOWNLOAD_KEYS_TYPE, type.name());
@@ -297,6 +406,9 @@ public ResponseEntity> getTrustedIssuersByCountry(
return ResponseEntity.ok(trustedIssuerMapper.trustedIssuerEntityToTrustedIssuerDto(
trustedIssuerService.getAllIssuers()));
}
+ }
+ private boolean isPaginationRequired(Integer page, Integer size) {
+ return page != null && size != null && page >= 0 && size > 0;
}
}
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationCleanUpService.java b/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationCleanUpService.java
new file mode 100644
index 00000000..c7ade469
--- /dev/null
+++ b/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationCleanUpService.java
@@ -0,0 +1,56 @@
+/*-
+ * ---license-start
+ * EU Digital Green Certificate Gateway Service / dgc-gateway
+ * ---
+ * Copyright (C) 2021 - 2022 T-Systems International GmbH and all other contributors
+ * ---
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ---license-end
+ */
+
+package eu.europa.ec.dgc.gateway.service;
+
+import eu.europa.ec.dgc.gateway.config.DgcConfigProperties;
+import eu.europa.ec.dgc.gateway.repository.SignerInformationRepository;
+import java.time.ZonedDateTime;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class SignerInformationCleanUpService {
+
+ private final SignerInformationRepository signerInformationRepository;
+
+ private final DgcConfigProperties configProperties;
+
+ /**
+ * Delete SignerInformationEntity which are flagged for deletion.
+ */
+ @Scheduled(cron = "@daily")
+ @SchedulerLock(name = "signer_information_cleanup")
+ public void cleanup() {
+ log.info("Starting SignerInformation Cleanup Job.");
+
+ int affectedRowsDeleted = signerInformationRepository.deleteDeletedSignerInformationOlderThan(
+ ZonedDateTime.now().minusDays(configProperties.getSignerInformation().getDeleteThreshold())
+ );
+ log.info("Deleted {} SignerInformation.", affectedRowsDeleted);
+
+ log.info("Completed SignerInformation Cleanup Job.");
+ }
+}
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationService.java b/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationService.java
index 3353a40b..62127c16 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationService.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/service/SignerInformationService.java
@@ -28,6 +28,7 @@
import eu.europa.ec.dgc.utils.CertificateUtils;
import java.io.IOException;
import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
@@ -43,6 +44,7 @@
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.RuntimeOperatorException;
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
+import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
@Service
@@ -91,6 +93,84 @@ public List getSignerInformation(
return signerInformationRepository.getByCertificateTypeAndCountry(type, countryCode);
}
+ /**
+ * Finds a list of SignerInformation.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param ifModifiedSince since timestamp for filtering SignerInformation.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return list of SignerInformation
+ */
+ public List getSignerInformation(ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+ if (ifModifiedSince != null && page != null && size != null) {
+ return signerInformationRepository.getIsSince(ifModifiedSince, PageRequest.of(page, size));
+ } else if (ifModifiedSince != null) {
+ return signerInformationRepository.getIsSince(ifModifiedSince);
+ } else if (page != null && size != null) {
+ return signerInformationRepository.findAll(PageRequest.of(page, size)).toList();
+ } else {
+ return getSignerInformation();
+ }
+ }
+
+ /**
+ * Finds a list of SignerInformation filtered by type.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param type type to filter for
+ * @param ifModifiedSince since timestamp for filtering SignerInformation.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of SignerInformation
+ */
+ public List getSignerInformation(SignerInformationEntity.CertificateType type,
+ ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+ if (ifModifiedSince != null && page != null && size != null) {
+ return signerInformationRepository.getByCertificateTypeIsSince(type,
+ ifModifiedSince, PageRequest.of(page, size));
+ } else if (ifModifiedSince != null) {
+ return signerInformationRepository.getByCertificateTypeIsSince(type, ifModifiedSince);
+ } else if (page != null && size != null) {
+ return signerInformationRepository.getByCertificateType(type,
+ PageRequest.of(page, size));
+ } else {
+ return signerInformationRepository.getByCertificateType(type);
+ }
+ }
+
+ /**
+ * Finds a list of SignerInformation filtered by type and country.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param countryCode 2-digit country Code to filter for.
+ * @param type type to filter for
+ * @param ifModifiedSince since timestamp for filtering SignerInformation.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of SignerInformation
+ */
+ public List getSignerInformation(
+ String countryCode,
+ SignerInformationEntity.CertificateType type,
+ ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+ if (ifModifiedSince != null && page != null && size != null) {
+ return signerInformationRepository.getByCertificateTypeAndCountryIsSince(type, countryCode,
+ ifModifiedSince, PageRequest.of(page, size));
+ } else if (ifModifiedSince != null) {
+ return signerInformationRepository.getByCertificateTypeAndCountryIsSince(type, countryCode,
+ ifModifiedSince);
+ } else if (page != null && size != null) {
+ return signerInformationRepository.getByCertificateTypeAndCountry(type, countryCode,
+ PageRequest.of(page, size));
+ } else {
+ return signerInformationRepository.getByCertificateTypeAndCountry(type, countryCode);
+ }
+ }
+
/**
* Adds a new Trusted Signer Certificate to TrustStore DB.
*
@@ -143,7 +223,7 @@ public SignerInformationEntity addSignerCertificate(
/**
* Update a CMS package.
*
- * @param id The entity to update
+ * @param id The entity to update
* @param uploadedCertificate the certificate to add
* @param signerCertificate the certificate which was used to sign the message
* @param signature the detached signature of cms message
@@ -152,11 +232,11 @@ public SignerInformationEntity addSignerCertificate(
* a reason property with detailed information why the validation has failed.
*/
public SignerInformationEntity updateSignerCertificate(
- Long id,
- X509CertificateHolder uploadedCertificate,
- X509CertificateHolder signerCertificate,
- String signature,
- String authenticatedCountryCode
+ Long id,
+ X509CertificateHolder uploadedCertificate,
+ X509CertificateHolder signerCertificate,
+ String signature,
+ String authenticatedCountryCode
) throws SignerCertCheckException {
final SignerInformationEntity signerInformationEntity = signerInformationRepository.findById(id).orElseThrow(
@@ -206,12 +286,14 @@ public void deleteSignerCertificate(
contentCheckUploaderCertificate(signerCertificate, authenticatedCountryCode);
contentCheckCountryOfOrigin(uploadedCertificate, authenticatedCountryCode);
- contentCheckExists(uploadedCertificate);
+ SignerInformationEntity signerInformationEntity = contentCheckExists(uploadedCertificate);
log.info("Revoking SignerInformation Entity");
- // All checks passed --> Delete from DB
- signerInformationRepository.deleteByThumbprint(certificateUtils.getCertThumbprint(uploadedCertificate));
+ // All checks passed --> Delete from DB, set fields to null
+ signerInformationEntity.setDeletedAt(ZonedDateTime.now());
+ signerInformationEntity.setSignature(null);
+ signerInformationRepository.save(signerInformationEntity);
DgcMdc.remove(MDC_PROP_UPLOAD_CERT_THUMBPRINT);
}
@@ -224,10 +306,10 @@ public void deleteSignerCertificate(
*/
public List getCmsPackage(String country) {
return signerInformationRepository
- .getByCertificateTypeAndCountry(SignerInformationEntity.CertificateType.DSC, country)
- .stream()
- .map(it -> new CmsPackageDto(it.getSignature(), it.getId(), CmsPackageDto.CmsPackageTypeDto.DSC))
- .collect(Collectors.toList());
+ .getByCertificateTypeAndCountry(SignerInformationEntity.CertificateType.DSC, country)
+ .stream()
+ .map(it -> new CmsPackageDto(it.getSignature(), it.getId(), CmsPackageDto.CmsPackageTypeDto.DSC))
+ .collect(Collectors.toList());
}
private void contentCheckUploaderCertificate(
@@ -323,16 +405,16 @@ private void contentCheckKidAlreadyExists(X509CertificateHolder uploadedCertific
}
}
- private void contentCheckExists(X509CertificateHolder uploadedCertificate) throws SignerCertCheckException {
+ private SignerInformationEntity contentCheckExists(X509CertificateHolder uploadedCertificate)
+ throws SignerCertCheckException {
String uploadedCertificateThumbprint = certificateUtils.getCertThumbprint(uploadedCertificate);
Optional signerInformationEntity =
signerInformationRepository.getFirstByThumbprint(uploadedCertificateThumbprint);
- if (signerInformationEntity.isEmpty()) {
- throw new SignerCertCheckException(SignerCertCheckException.Reason.EXIST_CHECK_FAILED,
- "Uploaded certificate does not exists");
- }
+ return signerInformationEntity.orElseThrow(
+ () -> new SignerCertCheckException(SignerCertCheckException.Reason.EXIST_CHECK_FAILED,
+ "Uploaded certificate does not exists"));
}
private boolean certificateSignedByCa(X509CertificateHolder certificate, TrustedPartyEntity caCertificateEntity) {
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/service/TrustListService.java b/src/main/java/eu/europa/ec/dgc/gateway/service/TrustListService.java
index 3639b86e..b91f708d 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/service/TrustListService.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/service/TrustListService.java
@@ -24,7 +24,9 @@
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
import eu.europa.ec.dgc.gateway.model.TrustList;
import eu.europa.ec.dgc.gateway.model.TrustListType;
+import eu.europa.ec.dgc.gateway.utils.ListUtils;
import eu.europa.ec.dgc.utils.CertificateUtils;
+import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -78,7 +80,7 @@ public List getTrustList(TrustListType type) {
}
/**
- * Get a TrustList with TrustList Entries filtered by countriy and type.
+ * Get a TrustList with TrustList Entries filtered by country and type.
*
* @param type the type to filter for.
* @param countryCode the 2-Digit country code to filter for.
@@ -98,6 +100,124 @@ public List getTrustList(TrustListType type, String countryCode) {
}
}
+ /**
+ * Finds a list of TrustList.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param ifModifiedSince since timestamp for filtering TrustList.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of {@link TrustList} ordered by KID
+ */
+ public List getTrustList(ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+
+ List fullTrustLists;
+
+ if (ifModifiedSince == null) {
+ fullTrustLists = mergeAndConvert(
+ trustedPartyService.getCertificates(),
+ signerInformationService.getSignerInformation());
+ } else {
+ fullTrustLists = mergeAndConvert(
+ trustedPartyService.getCertificates(ifModifiedSince, null, null),
+ signerInformationService.getSignerInformation(ifModifiedSince, null, null)
+ );
+ }
+ if (page != null && size != null) {
+ return ListUtils.getPage(fullTrustLists, page, size);
+ } else {
+ return fullTrustLists;
+ }
+ }
+
+ /**
+ * Finds a list of TrustList filtered by type.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param type the type to filter for.
+ * @param ifModifiedSince since timestamp for filtering TrustList.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of {@link TrustList} ordered by KID
+ */
+ public List getTrustList(TrustListType type,
+ ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+ List trustListsByType;
+
+ if (ifModifiedSince == null) {
+ if (type == TrustListType.DSC) {
+ trustListsByType = mergeAndConvert(Collections.emptyList(),
+ signerInformationService.getSignerInformation(SignerInformationEntity.CertificateType.DSC));
+ } else {
+ trustListsByType = mergeAndConvert(trustedPartyService.getCertificates(map(type)),
+ Collections.emptyList());
+ }
+ } else {
+ if (type == TrustListType.DSC) {
+ trustListsByType = mergeAndConvert(Collections.emptyList(),
+ signerInformationService.getSignerInformation(SignerInformationEntity.CertificateType.DSC,
+ ifModifiedSince, null, null));
+ } else {
+ trustListsByType = mergeAndConvert(trustedPartyService.getCertificates(map(type),
+ ifModifiedSince, null, null),
+ Collections.emptyList());
+ }
+ }
+ if (page != null && size != null) {
+ return ListUtils.getPage(trustListsByType, page, size);
+ } else {
+ return trustListsByType;
+ }
+ }
+
+ /**
+ * Finds a list of TrustList filtered by country and type.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param type the type to filter for.
+ * @param countryCode the 2-Digit country code to filter for.
+ * @param ifModifiedSince since timestamp for filtering TrustList.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of {@link TrustList} ordered by KID
+ */
+ public List getTrustList(TrustListType type, String countryCode,
+ ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+ List trustListsByTypeAndCountry;
+
+ if (ifModifiedSince == null) {
+ if (type == TrustListType.DSC) {
+ trustListsByTypeAndCountry = mergeAndConvert(Collections.emptyList(),
+ signerInformationService.getSignerInformation(countryCode,
+ SignerInformationEntity.CertificateType.DSC));
+ } else {
+ trustListsByTypeAndCountry = mergeAndConvert(
+ trustedPartyService.getCertificates(countryCode, map(type)),
+ Collections.emptyList());
+ }
+ } else {
+ if (type == TrustListType.DSC) {
+ trustListsByTypeAndCountry = mergeAndConvert(Collections.emptyList(),
+ signerInformationService.getSignerInformation(countryCode,
+ SignerInformationEntity.CertificateType.DSC,
+ ifModifiedSince, null, null));
+ } else {
+ trustListsByTypeAndCountry = mergeAndConvert(
+ trustedPartyService.getCertificates(countryCode, map(type),
+ ifModifiedSince, null, null),
+ Collections.emptyList());
+ }
+ }
+ if (page != null && size != null) {
+ return ListUtils.getPage(trustListsByTypeAndCountry, page, size);
+ } else {
+ return trustListsByTypeAndCountry;
+ }
+ }
+
private List mergeAndConvert(
List trustedPartyList,
List signerInformationList) {
@@ -130,7 +250,7 @@ private TrustList convert(SignerInformationEntity signerInformationEntity) {
map(signerInformationEntity.getCertificateType()),
signerInformationEntity.getThumbprint(),
signerInformationEntity.getSignature(),
- signerInformationEntity.getRawData()
+ signerInformationEntity.getDeletedAt() == null ? signerInformationEntity.getRawData() : null
);
}
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/service/TrustedPartyService.java b/src/main/java/eu/europa/ec/dgc/gateway/service/TrustedPartyService.java
index a6fde010..1f2e6066 100644
--- a/src/main/java/eu/europa/ec/dgc/gateway/service/TrustedPartyService.java
+++ b/src/main/java/eu/europa/ec/dgc/gateway/service/TrustedPartyService.java
@@ -24,6 +24,7 @@
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
import eu.europa.ec.dgc.gateway.repository.TrustedPartyRepository;
import eu.europa.ec.dgc.gateway.utils.DgcMdc;
+import eu.europa.ec.dgc.gateway.utils.ListUtils;
import eu.europa.ec.dgc.signing.SignedCertificateMessageParser;
import eu.europa.ec.dgc.signing.SignedMessageParser;
import eu.europa.ec.dgc.utils.CertificateUtils;
@@ -32,6 +33,7 @@
import java.security.KeyStoreException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
@@ -95,6 +97,117 @@ public List getCertificates(String country, TrustedPartyEnti
.collect(Collectors.toList());
}
+ /**
+ * Finds a list of Certificates.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param ifModifiedSince since timestamp for filtering Certificate.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of certificates.
+ */
+ public List getCertificates(ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+
+ List trustedPartyEntityFullList;
+
+ if (ifModifiedSince == null) {
+ trustedPartyEntityFullList = trustedPartyRepository.findAll()
+ .stream()
+ .filter(this::validateCertificateIntegrity)
+ .collect(Collectors.toList());
+
+ } else {
+ trustedPartyEntityFullList =
+ trustedPartyRepository.getIsSince(ifModifiedSince)
+ .stream()
+ .filter(this::validateCertificateIntegrity)
+ .collect(Collectors.toList());
+ }
+ if (page != null && size != null) {
+ return ListUtils.getPage(trustedPartyEntityFullList, page, size);
+ } else {
+ return trustedPartyEntityFullList;
+ }
+ }
+
+ /**
+ * Finds a list of Certificates by type.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param type type to filter for.
+ * @param ifModifiedSince since timestamp for filtering Certificate.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of certificates.
+ */
+ public List getCertificates(TrustedPartyEntity.CertificateType type,
+ ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+
+ List trustedPartyEntityByTypeList;
+
+ if (ifModifiedSince == null) {
+ trustedPartyEntityByTypeList = trustedPartyRepository.getByCertificateType(type)
+ .stream()
+ .filter(this::validateCertificateIntegrity)
+ .collect(Collectors.toList());
+
+ } else {
+ trustedPartyEntityByTypeList =
+ trustedPartyRepository.getByCertificateTypeIsSince(
+ type, ifModifiedSince)
+ .stream()
+ .filter(this::validateCertificateIntegrity)
+ .collect(Collectors.toList());
+ }
+ if (page != null && size != null) {
+ return ListUtils.getPage(trustedPartyEntityByTypeList, page, size);
+ } else {
+ return trustedPartyEntityByTypeList;
+ }
+ }
+
+ /**
+ * Finds a list of Certificates by country and type.
+ * Optional the list can be filtered by a timestamp and paginated.
+ *
+ * @param country country of certificate.
+ * @param type type to filter for.
+ * @param ifModifiedSince since timestamp for filtering Certificate.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return List of certificates.
+ */
+ public List getCertificates(String country,
+ TrustedPartyEntity.CertificateType type,
+ ZonedDateTime ifModifiedSince,
+ Integer page, Integer size) {
+
+ List trustedPartyEntityByTypeAndCountryList;
+
+ if (ifModifiedSince == null) {
+ trustedPartyEntityByTypeAndCountryList =
+ trustedPartyRepository.getByCountryAndCertificateType(country, type)
+ .stream()
+ .filter(this::validateCertificateIntegrity)
+ .collect(Collectors.toList());
+
+ } else {
+ trustedPartyEntityByTypeAndCountryList =
+ trustedPartyRepository.getByCountryAndCertificateTypeIsSince(country,
+ type, ifModifiedSince)
+ .stream()
+ .filter(this::validateCertificateIntegrity)
+ .collect(Collectors.toList());
+ }
+ if (page != null && size != null) {
+ return ListUtils.getPage(trustedPartyEntityByTypeAndCountryList, page, size);
+ } else {
+ return trustedPartyEntityByTypeAndCountryList;
+ }
+ }
+
/**
* Method to query the db for a certificate.
*
@@ -119,6 +232,7 @@ public List getCountryList() {
return trustedPartyRepository.getCountryCodeList();
}
+
private boolean validateCertificateIntegrity(TrustedPartyEntity trustedPartyEntity) {
DgcMdc.put(MDC_PROP_CERT_THUMBPRINT, trustedPartyEntity.getThumbprint());
diff --git a/src/main/java/eu/europa/ec/dgc/gateway/utils/ListUtils.java b/src/main/java/eu/europa/ec/dgc/gateway/utils/ListUtils.java
new file mode 100644
index 00000000..64e9cf64
--- /dev/null
+++ b/src/main/java/eu/europa/ec/dgc/gateway/utils/ListUtils.java
@@ -0,0 +1,55 @@
+/*-
+ * ---license-start
+ * EU Digital Green Certificate Gateway Service / dgc-gateway
+ * ---
+ * Copyright (C) 2021 - 2022 T-Systems International GmbH and all other contributors
+ * ---
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ---license-end
+ */
+
+package eu.europa.ec.dgc.gateway.utils;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ListUtils {
+
+ private ListUtils(){
+ }
+
+ /**
+ * Returns a sublist of a list of objects based on page index and size.
+ *
+ * @param list list for sublist.
+ * @param page zero-based page index, must NOT be negative.
+ * @param size number of items in a page to be returned, must be greater than 0.
+ * @return sublist of a list of objects.
+ */
+ public static List getPage(List list, int page, int size) {
+
+ if (page < 0) {
+ throw new IllegalArgumentException("Page index must not be less than zero!");
+ }
+ if (size <= 0) {
+ throw new IllegalArgumentException("Page size must not be less than one!");
+ }
+
+ int fromIndex = (page) * size;
+ if (list == null || list.size() < fromIndex) {
+ return Collections.emptyList();
+ }
+ return list.subList(fromIndex, Math.min(fromIndex + size, list.size()));
+ }
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index e5a86f2a..d1b249f3 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -45,6 +45,8 @@ dgc:
distinguished-name: X-SSL-Client-DN
revocation:
delete-threshold: 14
+ signer-information:
+ delete-threshold: 14
springdoc:
api-docs:
enabled: false
diff --git a/src/main/resources/db/changelog.xml b/src/main/resources/db/changelog.xml
index 824ed78c..3d1b6f1b 100644
--- a/src/main/resources/db/changelog.xml
+++ b/src/main/resources/db/changelog.xml
@@ -16,4 +16,5 @@
+
diff --git a/src/main/resources/db/changelog/alter-signer-information-for-deletion.xml b/src/main/resources/db/changelog/alter-signer-information-for-deletion.xml
new file mode 100644
index 00000000..70ae0d52
--- /dev/null
+++ b/src/main/resources/db/changelog/alter-signer-information-for-deletion.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/CertificateMigrationControllerTest.java b/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/CertificateMigrationControllerTest.java
index 29009cd4..3d81967e 100644
--- a/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/CertificateMigrationControllerTest.java
+++ b/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/CertificateMigrationControllerTest.java
@@ -621,7 +621,7 @@ void testUpdateRevocationWrongCountry() throws Exception {
private void createSignerInfo(final String cmsBase64, final X509Certificate certDscEu, final String signature) {
signerInformationRepository.save(new SignerInformationEntity(
- null, ZonedDateTime.now(), countryCode, certificateUtils.getCertThumbprint(certDscEu),
+ null, ZonedDateTime.now(), null, countryCode, certificateUtils.getCertThumbprint(certDscEu),
cmsBase64, signature, SignerInformationEntity.CertificateType.DSC
));
}
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListIntegrationTest.java b/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListIntegrationTest.java
index 7c30dd60..e2e9af44 100644
--- a/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListIntegrationTest.java
+++ b/src/test/java/eu/europa/ec/dgc/gateway/restapi/controller/TrustListIntegrationTest.java
@@ -20,17 +20,11 @@
package eu.europa.ec.dgc.gateway.restapi.controller;
-import static org.hamcrest.Matchers.hasSize;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import eu.europa.ec.dgc.gateway.config.DgcConfigProperties;
-import eu.europa.ec.dgc.gateway.entity.SignerInformationEntity;
-import eu.europa.ec.dgc.gateway.entity.TrustedIssuerEntity;
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
import eu.europa.ec.dgc.gateway.repository.SignerInformationRepository;
import eu.europa.ec.dgc.gateway.repository.TrustedIssuerRepository;
@@ -39,6 +33,7 @@
import eu.europa.ec.dgc.gateway.restapi.dto.TrustListDto;
import eu.europa.ec.dgc.gateway.testdata.CertificateTestUtils;
import eu.europa.ec.dgc.gateway.testdata.DgcTestKeyStore;
+import eu.europa.ec.dgc.gateway.testdata.SignerInformationTestHelper;
import eu.europa.ec.dgc.gateway.testdata.TrustedIssuerTestHelper;
import eu.europa.ec.dgc.gateway.testdata.TrustedPartyTestHelper;
import eu.europa.ec.dgc.utils.CertificateUtils;
@@ -46,10 +41,12 @@
import java.security.KeyPairGenerator;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
+import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
+import static org.hamcrest.Matchers.hasSize;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -61,6 +58,10 @@
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
@@ -78,6 +79,9 @@ class TrustListIntegrationTest {
@Autowired
TrustedPartyTestHelper trustedPartyTestHelper;
+ @Autowired
+ SignerInformationTestHelper signerInformationTestHelper;
+
@Autowired
TrustedIssuerTestHelper trustedIssuerTestHelper;
@@ -95,8 +99,14 @@ class TrustListIntegrationTest {
private static final String countryCode = "EU";
private static final String authCertSubject = "C=" + countryCode;
+ private static final String IF_MODIFIED_SINCE_HEADER = "If-Modified-Since";
+ private static final ZoneId gmt = ZoneId.of("GMT");
+ private static final ZonedDateTime now = ZonedDateTime.now(gmt);
+ private static final ZonedDateTime nowMinusOneMinute = ZonedDateTime.now(gmt).minusMinutes(1);
+ private static final ZonedDateTime nowMinusOneHour = ZonedDateTime.now(gmt).minusHours(1);
- X509Certificate certUploadDe, certUploadEu, certCscaDe, certCscaEu, certAuthDe, certAuthEu, certDscDe, certDscEu;
+ X509Certificate certUploadDe, certUploadEu, certCscaDe, certCscaEu, certAuthDe, certAuthEu, certDscDe, certDscEu,
+ certUploadDe2, certUploadEu2, certCscaDe2, certCscaEu2, certAuthDe2, certAuthEu2, certDscDe2, certDscEu2, certDscEuDeleted;
@BeforeEach
void testData() throws Exception {
@@ -115,33 +125,197 @@ void testData() throws Exception {
certDscDe = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "DE", "Test");
certDscEu = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "EU", "Test");
- signerInformationRepository.save(new SignerInformationEntity(
- null,
- ZonedDateTime.now(),
- "DE",
- certificateUtils.getCertThumbprint(certDscDe),
- Base64.getEncoder().encodeToString(certDscDe.getEncoded()),
- "sig1",
- SignerInformationEntity.CertificateType.DSC
- ));
-
- signerInformationRepository.save(new SignerInformationEntity(
- null,
- ZonedDateTime.now(),
- "EU",
- certificateUtils.getCertThumbprint(certDscEu),
- Base64.getEncoder().encodeToString(certDscEu.getEncoded()),
- "sig2",
- SignerInformationEntity.CertificateType.DSC
- ));
+ signerInformationTestHelper.createSignerInformationInDB("DE", "sig1", certDscDe, now);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig2", certDscEu, now);
trustedIssuerRepository.saveAll(List.of(
- trustedIssuerTestHelper.createTrustedIssuer("EU"),
- trustedIssuerTestHelper.createTrustedIssuer("DE"),
- trustedIssuerTestHelper.createTrustedIssuer("AT")
+ trustedIssuerTestHelper.createTrustedIssuer("EU"),
+ trustedIssuerTestHelper.createTrustedIssuer("DE"),
+ trustedIssuerTestHelper.createTrustedIssuer("AT")
));
}
+ @Test
+ void testTrustListDownloadNoFilterIsSince() throws Exception {
+ prepareTestCertsCreatedAtNowMinusOneHour();
+ String authCertHash = trustedPartyTestHelper.getHash(TrustedPartyEntity.CertificateType.AUTHENTICATION, countryCode);
+
+ mockMvc.perform(get("/trustList")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneHour)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListItem(c, certDscDe, "DE", CertificateTypeDto.DSC, "sig1"))
+ .andExpect(c -> assertTrustListItem(c, certDscEu, "EU", CertificateTypeDto.DSC, "sig2"))
+ .andExpect(c -> assertTrustListItem(c, certDscDe2, "DE", CertificateTypeDto.DSC, "sig3"))
+ .andExpect(c -> assertTrustListItem(c, certDscEu2, "EU", CertificateTypeDto.DSC, "sig4"))
+ .andExpect(c -> assertTrustListItem(c, certDscEuDeleted, "EU", CertificateTypeDto.DSC, null, true))
+ .andExpect(c -> assertTrustListItem(c, certCscaDe, "DE", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certCscaEu, "EU", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadDe, "DE", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadEu, "EU", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthEu, "EU", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certCscaDe2, "DE", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certCscaEu2, "EU", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadDe2, "DE", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadEu2, "EU", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe2, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthEu2, "EU", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListLength(c, 17));
+
+ mockMvc.perform(get("/trustList")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneMinute)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 8));
+ }
+ @Test
+ void testTrustListDownloadNoFilterPageable() throws Exception {
+ prepareTestCertsCreatedAtNowMinusOneHour();
+ String authCertHash = trustedPartyTestHelper.getHash(TrustedPartyEntity.CertificateType.AUTHENTICATION, countryCode);
+
+ mockMvc.perform(get("/trustList?page=0&pagesize=100")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListItem(c, certDscDe, "DE", CertificateTypeDto.DSC, "sig1"))
+ .andExpect(c -> assertTrustListItem(c, certDscEu, "EU", CertificateTypeDto.DSC, "sig2"))
+ .andExpect(c -> assertTrustListItem(c, certDscDe2, "DE", CertificateTypeDto.DSC, "sig3"))
+ .andExpect(c -> assertTrustListItem(c, certDscEu2, "EU", CertificateTypeDto.DSC, "sig4"))
+ .andExpect(c -> assertTrustListItem(c, certDscEuDeleted, "EU", CertificateTypeDto.DSC, null, true))
+ .andExpect(c -> assertTrustListItem(c, certCscaDe, "DE", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certCscaEu, "EU", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadDe, "DE", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadEu, "EU", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthEu, "EU", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certCscaDe2, "DE", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certCscaEu2, "EU", CertificateTypeDto.CSCA, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadDe2, "DE", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certUploadEu2, "EU", CertificateTypeDto.UPLOAD, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe2, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthEu2, "EU", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListLength(c, 17));
+ }
+
+ @Test
+ void testTrustListDownloadNoFilterIsSincePageable() throws Exception {
+ prepareTestCertsCreatedAtNowMinusOneHour();
+ String authCertHash = trustedPartyTestHelper.getHash(TrustedPartyEntity.CertificateType.AUTHENTICATION, countryCode);
+
+ mockMvc.perform(get("/trustList?page=-1&pagesize=10")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneHour)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 17));
+
+ mockMvc.perform(get("/trustList?page=0&pagesize=10")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneHour)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 10));
+
+ mockMvc.perform(get("/trustList?page=0&pagesize=100")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneMinute)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 8));
+
+ mockMvc.perform(get("/trustList?page=1&pagesize=5")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneMinute)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 3));
+
+ mockMvc.perform(get("/trustList?page=2&pagesize=10")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneMinute)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 0));
+ }
+
+ @Test
+ void testTrustListDownloadNoFilterByTypeAndCountryIsSincePageable() throws Exception {
+ prepareTestCertsCreatedAtNowMinusOneHour();
+ String authCertHash = trustedPartyTestHelper.getHash(TrustedPartyEntity.CertificateType.AUTHENTICATION, countryCode);
+
+ mockMvc.perform(get("/trustList/AUTHENTICATION")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneHour)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthEu, "EU", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe2, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthEu2, "EU", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListLength(c, 4));
+
+ mockMvc.perform(get("/trustList/AUTHENTICATION/DE")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListItem(c, certAuthDe2, "DE", CertificateTypeDto.AUTHENTICATION, null))
+ .andExpect(c -> assertTrustListLength(c, 2));
+
+ mockMvc.perform(get("/trustList/DSC?page=0&pagesize=10")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneMinute)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 2));
+
+ mockMvc.perform(get("/trustList/DSC/DE?page=0&pagesize=10")
+ .accept(MediaType.APPLICATION_JSON_VALUE)
+ .header(IF_MODIFIED_SINCE_HEADER, nowMinusOneMinute)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getThumbprint(), authCertHash)
+ .header(dgcConfigProperties.getCertAuth().getHeaderFields().getDistinguishedName(), authCertSubject)
+ )
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(c -> assertTrustListLength(c, 1));
+ }
+
@Test
void testTrustListDownloadNoFilter() throws Exception {
String authCertHash = trustedPartyTestHelper.getHash(TrustedPartyEntity.CertificateType.AUTHENTICATION, countryCode);
@@ -516,7 +690,31 @@ void testBadRequests(String url) throws Exception {
.andExpect(status().isBadRequest());
}
- private void assertTrustListItem(MvcResult result, X509Certificate certificate, String country, CertificateTypeDto certificateTypeDto, String signature) throws CertificateEncodingException, UnsupportedEncodingException, JsonProcessingException {
+ private void prepareTestCertsCreatedAtNowMinusOneHour() throws Exception {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ec");
+ certDscDe2 = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "DE", "DETest");
+ certDscEu2 = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "EU", "EUTest");
+ certDscEuDeleted = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "EU", "EUTestDeleted");
+ signerInformationTestHelper.createSignerInformationInDB("DE", "sig3", certDscDe2, nowMinusOneHour);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig4",certDscEu2, nowMinusOneHour);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig5_deleted",certDscEuDeleted, now.minusHours(2), nowMinusOneHour);
+
+ certUploadDe2 = trustedPartyTestHelper.getTestCert("test1", TrustedPartyEntity.CertificateType.UPLOAD, "DE", nowMinusOneHour);
+ certCscaDe2 = trustedPartyTestHelper.getTestCert("test2", TrustedPartyEntity.CertificateType.CSCA, "DE", nowMinusOneHour);
+ certAuthDe2 = trustedPartyTestHelper.getTestCert("test3", TrustedPartyEntity.CertificateType.AUTHENTICATION, "DE", nowMinusOneHour);
+ certUploadEu2 = trustedPartyTestHelper.getTestCert("test4", TrustedPartyEntity.CertificateType.UPLOAD, "EU", nowMinusOneHour);
+ certCscaEu2 = trustedPartyTestHelper.getTestCert("test5", TrustedPartyEntity.CertificateType.CSCA, "EU", nowMinusOneHour);
+ certAuthEu2 = trustedPartyTestHelper.getTestCert("test6", TrustedPartyEntity.CertificateType.AUTHENTICATION, "EU", nowMinusOneHour);
+ }
+
+ private void assertTrustListItem(MvcResult result, X509Certificate certificate, String country, CertificateTypeDto certificateTypeDto, String signature) throws UnsupportedEncodingException, CertificateEncodingException, JsonProcessingException {
+ assertTrustListItem(result, certificate, country, certificateTypeDto, signature, false);
+ }
+
+ private void assertTrustListItem(MvcResult result, X509Certificate certificate, String country, CertificateTypeDto certificateTypeDto, String signature, boolean deleted) throws CertificateEncodingException, UnsupportedEncodingException, JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
List trustList = objectMapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() {
@@ -535,8 +733,11 @@ private void assertTrustListItem(MvcResult result, X509Certificate certificate,
Assertions.assertEquals(country, trustListItem.getCountry());
Assertions.assertEquals(certificateTypeDto, trustListItem.getCertificateType());
Assertions.assertEquals(certificateUtils.getCertThumbprint(certificate), trustListItem.getThumbprint());
- Assertions.assertEquals(Base64.getEncoder().encodeToString(certificate.getEncoded()), trustListItem.getRawData());
-
+ if (deleted) {
+ Assertions.assertNull(trustListItem.getRawData());
+ } else {
+ Assertions.assertEquals(Base64.getEncoder().encodeToString(certificate.getEncoded()), trustListItem.getRawData());
+ }
if (signature != null) {
Assertions.assertEquals(signature, trustListItem.getSignature());
}
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationCleanUpServiceTest.java b/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationCleanUpServiceTest.java
new file mode 100644
index 00000000..592aebd2
--- /dev/null
+++ b/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationCleanUpServiceTest.java
@@ -0,0 +1,85 @@
+package eu.europa.ec.dgc.gateway.service;
+
+import eu.europa.ec.dgc.gateway.entity.SignerInformationEntity;
+import eu.europa.ec.dgc.gateway.repository.SignerInformationRepository;
+import eu.europa.ec.dgc.gateway.testdata.CertificateTestUtils;
+import eu.europa.ec.dgc.utils.CertificateUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.security.KeyPairGenerator;
+import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
+import java.util.Base64;
+import java.util.List;
+
+@SpringBootTest(properties = "dgc.signer-information.delete-threshold=14")
+@Slf4j
+class SignerInformationCleanUpServiceTest {
+
+ @Autowired
+ CertificateUtils certificateUtils;
+
+ @Autowired
+ SignerInformationRepository signerInformationRepository;
+
+ @Autowired
+ SignerInformationCleanUpService underTest;
+
+
+ @BeforeEach
+ public void setup() {
+ signerInformationRepository.deleteAll();
+ }
+
+
+ @Test
+ void testCleanup() throws Exception {
+
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ec");
+ X509Certificate x509Certificate1 = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "DE", "DETest1");
+ X509Certificate x509Certificate2 = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "DE", "DETest2");
+ X509Certificate x509Certificate3 = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "DE", "DETest3");
+
+ SignerInformationEntity deleted3DaysAgo = createSignerInformationInDB("DE", null,
+ certificateUtils.getCertThumbprint(x509Certificate2), Base64.getEncoder().encodeToString(x509Certificate1.getEncoded()),
+ ZonedDateTime.now().minusDays(30), ZonedDateTime.now().minusDays(3));
+
+ SignerInformationEntity deleted3WeeksAgo = createSignerInformationInDB("DE", null,
+ certificateUtils.getCertThumbprint(x509Certificate3), Base64.getEncoder().encodeToString(x509Certificate1.getEncoded()),
+ ZonedDateTime.now().minusDays(40), ZonedDateTime.now().minusDays(21));
+
+
+ SignerInformationEntity notDeleted = createSignerInformationInDB("DE", "sig3",
+ certificateUtils.getCertThumbprint(x509Certificate1), Base64.getEncoder().encodeToString(x509Certificate1.getEncoded()),
+ ZonedDateTime.now().minusDays(40), null);
+
+ underTest.cleanup();
+
+ Assertions.assertEquals(2, signerInformationRepository.count());
+ List remaining = signerInformationRepository.findAll();
+ Assertions.assertTrue(remaining.stream().anyMatch(it -> it.getId().equals(notDeleted.getId())));
+ Assertions.assertTrue(remaining.stream().anyMatch(it -> it.getId().equals(deleted3DaysAgo.getId())));
+ Assertions.assertFalse(remaining.stream().anyMatch(it -> it.getId().equals(deleted3WeeksAgo.getId())));
+ }
+
+
+
+ private SignerInformationEntity createSignerInformationInDB(String countryCode, String signature,
+ String thumbprint, String encoded, ZonedDateTime createdAt, ZonedDateTime deletedAt) throws Exception {
+ return signerInformationRepository.save(new SignerInformationEntity(
+ null,
+ createdAt,
+ deletedAt,
+ countryCode,
+ thumbprint,
+ encoded,
+ signature,
+ SignerInformationEntity.CertificateType.DSC
+ ));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationServiceTest.java b/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationServiceTest.java
index db0be2be..4378a286 100644
--- a/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationServiceTest.java
+++ b/src/test/java/eu/europa/ec/dgc/gateway/service/SignerInformationServiceTest.java
@@ -20,22 +20,26 @@
package eu.europa.ec.dgc.gateway.service;
-import eu.europa.ec.dgc.gateway.config.DgcConfigProperties;
import eu.europa.ec.dgc.gateway.entity.SignerInformationEntity;
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
import eu.europa.ec.dgc.gateway.repository.SignerInformationRepository;
import eu.europa.ec.dgc.gateway.testdata.CertificateTestUtils;
import eu.europa.ec.dgc.gateway.testdata.DgcTestKeyStore;
+import eu.europa.ec.dgc.gateway.testdata.SignerInformationTestHelper;
import eu.europa.ec.dgc.gateway.testdata.TrustedPartyTestHelper;
import eu.europa.ec.dgc.utils.CertificateUtils;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
import java.util.Base64;
+import java.util.List;
import java.util.Optional;
import org.bouncycastle.cert.X509CertificateHolder;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -43,9 +47,6 @@
@SpringBootTest
class SignerInformationServiceTest {
- @Autowired
- DgcConfigProperties dgcConfigProperties;
-
@Autowired
CertificateUtils certificateUtils;
@@ -58,12 +59,147 @@ class SignerInformationServiceTest {
@Autowired
SignerInformationRepository signerInformationRepository;
+ @Autowired
+ SignerInformationTestHelper signerInformationTestHelper;
+
@Autowired
SignerInformationService signerInformationService;
private static final String countryCode = "EU";
private static final String dummySignature = "randomStringAsSignatureWhichIsNotValidatedInServiceLevel";
+ private static final ZonedDateTime now = ZonedDateTime.now();
+ private static final ZonedDateTime nowMinusOneMinute = ZonedDateTime.now().minusMinutes(1);
+ private static final ZonedDateTime nowMinusOneHour = ZonedDateTime.now().minusHours(1);
+
+ @BeforeEach
+ void setUp() {
+ cleanupTestSignerInformation();
+ }
+
+ @AfterEach
+ void tearDown() {
+ cleanupTestSignerInformation();
+ }
+
+ @Test
+ void testSuccessfulGetSignerInformationIsSincePageable() throws Exception {
+ long signerInformationEntitiesInDb = signerInformationRepository.count();
+ prepareTestSignerInformation();
+
+ Assertions.assertEquals(signerInformationEntitiesInDb + 7, signerInformationRepository.count());
+
+ List signerInformationEntities =
+ signerInformationService.getSignerInformation(null, null, null);
+ Assertions.assertEquals(7, signerInformationEntities.size());
+ Assertions.assertTrue(signerInformationEntities.stream().anyMatch(it -> it.getDeletedAt() != null && it.getSignature() == null));
+
+ List signerInformationEntities2 = signerInformationService.getSignerInformation(
+ nowMinusOneMinute, null, null);
+ Assertions.assertEquals(3, signerInformationEntities2.size());
+
+ List signerInformationEntities3 = signerInformationService.getSignerInformation(
+ null, 0, 10);
+ Assertions.assertEquals(7, signerInformationEntities3.size());
+
+ List signerInformationEntities4 = signerInformationService.getSignerInformation(
+ null, 10, 10);
+ Assertions.assertEquals(0, signerInformationEntities4.size());
+
+ List signerInformationEntities5 = signerInformationService.getSignerInformation(
+ nowMinusOneMinute, 0, 10);
+ Assertions.assertEquals(3, signerInformationEntities5.size());
+
+ List signerInformationEntities6 = signerInformationService.getSignerInformation(
+ nowMinusOneMinute, 1, 2);
+ Assertions.assertEquals(1, signerInformationEntities6.size());
+
+ }
+
+ @Test
+ void testFailedGetSignerInformationIsSincePageable() throws Exception {
+ long signerInformationEntitiesInDb = signerInformationRepository.count();
+ prepareTestSignerInformation();
+ Assertions.assertEquals(signerInformationEntitiesInDb + 7, signerInformationRepository.count());
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
+ signerInformationService.getSignerInformation(null, -1, 2));
+ Assertions.assertEquals(signerInformationEntitiesInDb + 7, signerInformationRepository.count());
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
+ signerInformationService.getSignerInformation(null, 0, 0));
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
+ signerInformationService.getSignerInformation(null, -1, 0));
+
+ Assertions.assertEquals(signerInformationEntitiesInDb + 7, signerInformationRepository.count());
+
+ }
+
+ @Test
+ void testSuccessfulGetSignerInformationByTypeAndCountryIsSincePageable() throws Exception {
+ long signerInformationEntitiesInDb = signerInformationRepository.count();
+ prepareTestSignerInformation();
+
+ Assertions.assertEquals(signerInformationEntitiesInDb + 7, signerInformationRepository.count());
+
+ List signerInformationEntities =
+ signerInformationService.getSignerInformation(SignerInformationEntity.CertificateType.DSC,
+ null, null, null);
+ Assertions.assertEquals(7, signerInformationEntities.size());
+
+ List signerInformationEntities2 = signerInformationService.getSignerInformation(
+ SignerInformationEntity.CertificateType.DSC,
+ nowMinusOneMinute, null, null);
+ Assertions.assertEquals(3, signerInformationEntities2.size());
+
+ List signerInformationEntities3 = signerInformationService.getSignerInformation(
+ "DE", SignerInformationEntity.CertificateType.DSC,
+ null, 0, 10);
+ Assertions.assertEquals(2, signerInformationEntities3.size());
+
+ List signerInformationEntities4 = signerInformationService.getSignerInformation(
+ "DE", SignerInformationEntity.CertificateType.DSC,
+ nowMinusOneMinute, 0, 10);
+ Assertions.assertEquals(1, signerInformationEntities4.size());
+
+ List signerInformationEntities5 = signerInformationService.getSignerInformation(
+ "D", SignerInformationEntity.CertificateType.DSC,
+ nowMinusOneHour, 0, 10);
+ Assertions.assertEquals(0, signerInformationEntities5.size());
+ }
+
+ private void cleanupTestSignerInformation() {
+ signerInformationRepository.deleteAll();
+ }
+
+ private void prepareTestSignerInformation() throws Exception {
+
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ec");
+ signerInformationTestHelper.createSignerInformationInDB("DE", "sig1",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "DE", "DETest"), nowMinusOneHour);
+ signerInformationTestHelper.createSignerInformationInDB("DE", "sig2",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "DE", "DETest2"), now);
+ signerInformationTestHelper.createSignerInformationInDB("AT", "sig3",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "AT", "ATTest"), nowMinusOneHour);
+ signerInformationTestHelper.createSignerInformationInDB("AT", "sig4",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "AT", "ATTest2"), now);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig5",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "EU", "EUTest"), nowMinusOneHour);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig6",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "EU", "EUTest2"), now);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig7_deleted",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "EU", "EUTest3"), now.minusHours(2), nowMinusOneHour);
+ }
+
+
@Test
void testSuccessfulAddingNewSignerInformationAndDelete() throws Exception {
long signerInformationEntitiesInDb = signerInformationRepository.count();
@@ -100,11 +236,15 @@ void testSuccessfulAddingNewSignerInformationAndDelete() throws Exception {
countryCode
);
- Optional deletedSignerInformationEntity =
- signerInformationRepository.getFirstByThumbprint(certificateUtils.getCertThumbprint(payloadCertificate));
+ List entities =
+ signerInformationRepository.getByCertificateType(SignerInformationEntity.CertificateType.DSC);
- Assertions.assertTrue(deletedSignerInformationEntity.isEmpty());
- Assertions.assertEquals(signerInformationEntitiesInDb, signerInformationRepository.count());
+ Assertions.assertFalse(entities.isEmpty());
+ SignerInformationEntity deletedSignerInformationEntity = entities.get(0);
+ Assertions.assertEquals(createdSignerInformationEntity.get().getThumbprint(), deletedSignerInformationEntity.getThumbprint());
+ Assertions.assertNull(deletedSignerInformationEntity.getSignature());
+ Assertions.assertEquals(createdSignerInformationEntity.get().getRawData(), deletedSignerInformationEntity.getRawData());
+ Assertions.assertEquals(signerInformationEntitiesInDb + 1, signerInformationRepository.count());
}
@Test
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/service/TrustListServiceTest.java b/src/test/java/eu/europa/ec/dgc/gateway/service/TrustListServiceTest.java
index 1c09021c..efef5f1c 100644
--- a/src/test/java/eu/europa/ec/dgc/gateway/service/TrustListServiceTest.java
+++ b/src/test/java/eu/europa/ec/dgc/gateway/service/TrustListServiceTest.java
@@ -20,13 +20,13 @@
package eu.europa.ec.dgc.gateway.service;
-import eu.europa.ec.dgc.gateway.entity.SignerInformationEntity;
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
import eu.europa.ec.dgc.gateway.model.TrustList;
import eu.europa.ec.dgc.gateway.model.TrustListType;
import eu.europa.ec.dgc.gateway.repository.SignerInformationRepository;
import eu.europa.ec.dgc.gateway.repository.TrustedPartyRepository;
import eu.europa.ec.dgc.gateway.testdata.CertificateTestUtils;
+import eu.europa.ec.dgc.gateway.testdata.SignerInformationTestHelper;
import eu.europa.ec.dgc.gateway.testdata.TrustedPartyTestHelper;
import eu.europa.ec.dgc.utils.CertificateUtils;
import java.security.KeyPairGenerator;
@@ -54,6 +54,9 @@ class TrustListServiceTest {
@Autowired
TrustedPartyTestHelper trustedPartyTestHelper;
+ @Autowired
+ SignerInformationTestHelper signerInformationTestHelper;
+
@Autowired
TrustListService trustListService;
@@ -62,6 +65,10 @@ class TrustListServiceTest {
X509Certificate certUploadDe, certUploadEu, certCscaDe, certCscaEu, certAuthDe, certAuthEu, certDscDe, certDscEu;
+ private static final ZonedDateTime now = ZonedDateTime.now();
+ private static final ZonedDateTime nowMinusOneMinute = ZonedDateTime.now().minusMinutes(1);
+ private static final ZonedDateTime nowMinusOneHour = ZonedDateTime.now().minusHours(1);
+
@BeforeEach
void testData() throws Exception {
trustedPartyRepository.deleteAll();
@@ -78,25 +85,31 @@ void testData() throws Exception {
certDscDe = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "DE", "Test");
certDscEu = CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(), "EU", "Test");
- signerInformationRepository.save(new SignerInformationEntity(
- null,
- ZonedDateTime.now(),
- "DE",
- certificateUtils.getCertThumbprint(certDscDe),
- Base64.getEncoder().encodeToString(certDscDe.getEncoded()),
- "sig1",
- SignerInformationEntity.CertificateType.DSC
- ));
-
- signerInformationRepository.save(new SignerInformationEntity(
- null,
- ZonedDateTime.now(),
- "EU",
- certificateUtils.getCertThumbprint(certDscEu),
- Base64.getEncoder().encodeToString(certDscEu.getEncoded()),
- "sig2",
- SignerInformationEntity.CertificateType.DSC
- ));
+ signerInformationTestHelper.createSignerInformationInDB("DE", "sig1", certDscDe, now);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig2", certDscEu, now);
+ }
+
+ @Test
+ void testSuccessfulGetTrustedListIsSincePageable() throws Exception {
+ prepareTestCertsCreatedAtNowMinusOneHour();
+
+ List trustLists = trustListService.getTrustList(null, null, null);
+ Assertions.assertEquals(16, trustLists.size());
+
+ List trustLists2 = trustListService.getTrustList(nowMinusOneMinute,
+ null, null);
+ Assertions.assertEquals(8, trustLists2.size());
+
+ List trustLists3 = trustListService.getTrustList(TrustListType.DSC,
+ nowMinusOneMinute, null, null);
+ Assertions.assertEquals(2, trustLists3.size());
+
+ List trustLists4 = trustListService.getTrustList(TrustListType.DSC, null, 0, 10);
+ Assertions.assertEquals(4, trustLists4.size());
+
+ List trustLists5 = trustListService.getTrustList(TrustListType.UPLOAD, "DE",
+ nowMinusOneMinute, 0, 10);
+ Assertions.assertEquals(1, trustLists5.size());
}
@Test
@@ -169,6 +182,24 @@ void testTrustListFilterByTypeAndCountry() throws Exception {
assertTrustListItem(trustList, certAuthEu, "EU", TrustListType.AUTHENTICATION, null);
}
+ private void prepareTestCertsCreatedAtNowMinusOneHour() throws Exception {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ec");
+ signerInformationTestHelper.createSignerInformationInDB("DE", "sig3",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "DE", "DETest"), nowMinusOneHour);
+ signerInformationTestHelper.createSignerInformationInDB("EU", "sig4",
+ CertificateTestUtils.generateCertificate(keyPairGenerator.generateKeyPair(),
+ "EU", "EUTest"), nowMinusOneHour);
+
+ trustedPartyTestHelper.getTestCert("test1", TrustedPartyEntity.CertificateType.UPLOAD, "DE", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test2", TrustedPartyEntity.CertificateType.CSCA, "DE", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test3", TrustedPartyEntity.CertificateType.AUTHENTICATION, "DE", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test4", TrustedPartyEntity.CertificateType.UPLOAD, "EU", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test5", TrustedPartyEntity.CertificateType.CSCA, "EU", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test6", TrustedPartyEntity.CertificateType.AUTHENTICATION, "EU", nowMinusOneHour);
+ }
+
+
private void assertTrustListItem(List trustList, X509Certificate certificate, String country, TrustListType trustListType, String signature) throws CertificateEncodingException {
Optional trustListOptional = trustList
.stream()
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/service/TrustedPartyServiceTest.java b/src/test/java/eu/europa/ec/dgc/gateway/service/TrustedPartyServiceTest.java
index aa607f5a..c6a6522a 100644
--- a/src/test/java/eu/europa/ec/dgc/gateway/service/TrustedPartyServiceTest.java
+++ b/src/test/java/eu/europa/ec/dgc/gateway/service/TrustedPartyServiceTest.java
@@ -22,9 +22,10 @@
import eu.europa.ec.dgc.gateway.entity.TrustedPartyEntity;
import eu.europa.ec.dgc.gateway.repository.TrustedPartyRepository;
-import eu.europa.ec.dgc.gateway.testdata.DgcTestKeyStore;
import eu.europa.ec.dgc.gateway.testdata.TrustedPartyTestHelper;
import eu.europa.ec.dgc.signing.SignedCertificateMessageBuilder;
+import java.time.ZonedDateTime;
+import java.util.List;
import java.util.Optional;
import org.bouncycastle.cert.X509CertificateHolder;
import org.junit.jupiter.api.AfterEach;
@@ -45,17 +46,111 @@ class TrustedPartyServiceTest {
@Autowired
TrustedPartyTestHelper trustedPartyTestHelper;
- @Autowired
- DgcTestKeyStore dgcTestKeyStore;
-
private static final String countryCode = "EU";
+ private static final ZonedDateTime now = ZonedDateTime.now();
+ private static final ZonedDateTime nowMinusOneMinute = ZonedDateTime.now().minusMinutes(1);
+ private static final ZonedDateTime nowMinusOneHour = ZonedDateTime.now().minusHours(1);
+ private static final int TEST_CERTIFICATE_LIST_SIZE = 12;
+
@AfterEach
void cleanUp() {
// We have to delete all certs after each test because some tests are manipulating certs in DB.
trustedPartyRepository.deleteAll();
}
+ @Test
+ void testSuccessfulGetTrustedPartyListIsSincePageable() throws Exception {
+ cleanUp();
+ long trustedPartyEntitiesInDb = trustedPartyRepository.count();
+ prepareTestTrustedParty();
+ Assertions.assertEquals(trustedPartyEntitiesInDb + TEST_CERTIFICATE_LIST_SIZE, trustedPartyRepository.count());
+
+ List trustedPartyEntities =
+ trustedPartyService.getCertificates(null, null, null);
+ Assertions.assertEquals(TEST_CERTIFICATE_LIST_SIZE, trustedPartyEntities.size());
+
+ List trustedPartyEntities3 =
+ trustedPartyService.getCertificates( nowMinusOneMinute, null, null);
+ Assertions.assertEquals(TEST_CERTIFICATE_LIST_SIZE /2, trustedPartyEntities3.size());
+
+ List trustedPartyEntities4 =
+ trustedPartyService.getCertificates(null, 0, 10);
+ Assertions.assertEquals(10, trustedPartyEntities4.size());
+
+ List trustedPartyEntities5 =
+ trustedPartyService.getCertificates(null, 0, 100);
+ Assertions.assertEquals(TEST_CERTIFICATE_LIST_SIZE, trustedPartyEntities5.size());
+
+ List trustedPartyEntities6 =
+ trustedPartyService.getCertificates(null, 1, 10);
+ Assertions.assertEquals(2, trustedPartyEntities6.size());
+
+ List trustedPartyEntities7 =
+ trustedPartyService.getCertificates(null, 2, 10);
+ Assertions.assertEquals(0, trustedPartyEntities7.size());
+
+ List trustedPartyEntities8 =
+ trustedPartyService.getCertificates( nowMinusOneMinute, 0, 10);
+ Assertions.assertEquals(TEST_CERTIFICATE_LIST_SIZE /2, trustedPartyEntities8.size());
+
+ List trustedPartyEntities9 =
+ trustedPartyService.getCertificates( nowMinusOneMinute, 1, 10);
+ Assertions.assertEquals(0, trustedPartyEntities9.size());
+ }
+
+ @Test
+ void testSuccessfulGetTrustedPartyListByTypeAndCountryIsSincePageable() throws Exception {
+ cleanUp();
+ long trustedPartyEntitiesInDb = trustedPartyRepository.count();
+ prepareTestTrustedParty();
+ Assertions.assertEquals(trustedPartyEntitiesInDb + TEST_CERTIFICATE_LIST_SIZE,
+ trustedPartyRepository.count());
+
+ List trustedPartyEntities =
+ trustedPartyService.getCertificates(TrustedPartyEntity.CertificateType.UPLOAD,
+ null, null, null);
+ Assertions.assertEquals(4, trustedPartyEntities.size());
+
+ List trustedPartyEntities3 =
+ trustedPartyService.getCertificates(TrustedPartyEntity.CertificateType.CSCA,
+ nowMinusOneMinute, null, null);
+ Assertions.assertEquals(2, trustedPartyEntities3.size());
+
+ List trustedPartyEntities4 =
+ trustedPartyService.getCertificates(countryCode, TrustedPartyEntity.CertificateType.UPLOAD,
+ null, 0, 10);
+ Assertions.assertEquals(2, trustedPartyEntities4.size());
+
+ List trustedPartyEntities5 =
+ trustedPartyService.getCertificates(countryCode, TrustedPartyEntity.CertificateType.UPLOAD,
+ null, 1, 10);
+ Assertions.assertEquals(0, trustedPartyEntities5.size());
+
+ List trustedPartyEntities6 =
+ trustedPartyService.getCertificates(countryCode, TrustedPartyEntity.CertificateType.CSCA,
+ nowMinusOneMinute, 0, 10);
+ Assertions.assertEquals(1, trustedPartyEntities6.size());
+
+ List trustedPartyEntities7 =
+ trustedPartyService.getCertificates(countryCode, TrustedPartyEntity.CertificateType.CSCA,
+ nowMinusOneMinute, 1, 10);
+ Assertions.assertEquals(0, trustedPartyEntities7.size());
+ }
+
+ @Test
+ void testFailedGetTrustedPartyListIsSincePageable() {
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
+ trustedPartyService.getCertificates(countryCode, TrustedPartyEntity.CertificateType.CSCA,
+ null,-1,2));
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
+ trustedPartyService.getCertificates(null, 0, 0));
+
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
+ trustedPartyService.getCertificates(null, -1, 0));
+ }
+
@Test
void trustedPartyServiceShouldReturnCertificate() throws Exception {
String hash = trustedPartyTestHelper.getHash(TrustedPartyEntity.CertificateType.UPLOAD, countryCode);
@@ -159,4 +254,20 @@ void trustedPartyServiceShouldNotReturnCertificateIfSignatureIsFromUnknownTrustA
certOptional = trustedPartyService.getCertificate(trustedPartyEntity.getThumbprint(), countryCode, TrustedPartyEntity.CertificateType.CSCA);
Assertions.assertTrue(certOptional.isEmpty());
}
+
+ private void prepareTestTrustedParty() throws Exception {
+ trustedPartyTestHelper.getTestCert("test1", TrustedPartyEntity.CertificateType.UPLOAD, "DE", now);
+ trustedPartyTestHelper.getTestCert("test2", TrustedPartyEntity.CertificateType.CSCA, "DE", now);
+ trustedPartyTestHelper.getTestCert("test3", TrustedPartyEntity.CertificateType.AUTHENTICATION, "DE", now);
+ trustedPartyTestHelper.getTestCert("test4", TrustedPartyEntity.CertificateType.UPLOAD, "DE", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test5", TrustedPartyEntity.CertificateType.CSCA, "DE", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test6", TrustedPartyEntity.CertificateType.AUTHENTICATION, "DE", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test7", TrustedPartyEntity.CertificateType.UPLOAD, "EU", now);
+ trustedPartyTestHelper.getTestCert("test8", TrustedPartyEntity.CertificateType.CSCA, "EU", now);
+ trustedPartyTestHelper.getTestCert("test9", TrustedPartyEntity.CertificateType.AUTHENTICATION, "EU", now);
+ trustedPartyTestHelper.getTestCert("test10", TrustedPartyEntity.CertificateType.UPLOAD, "EU", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test11", TrustedPartyEntity.CertificateType.CSCA, "EU", nowMinusOneHour);
+ trustedPartyTestHelper.getTestCert("test12", TrustedPartyEntity.CertificateType.AUTHENTICATION, "EU", nowMinusOneHour);
+ }
+
}
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/testdata/SignerInformationTestHelper.java b/src/test/java/eu/europa/ec/dgc/gateway/testdata/SignerInformationTestHelper.java
new file mode 100644
index 00000000..eaf63074
--- /dev/null
+++ b/src/test/java/eu/europa/ec/dgc/gateway/testdata/SignerInformationTestHelper.java
@@ -0,0 +1,58 @@
+/*-
+ * ---license-start
+ * EU Digital Green Certificate Gateway Service / dgc-gateway
+ * ---
+ * Copyright (C) 2021 - 2022 T-Systems International GmbH and all other contributors
+ * ---
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ---license-end
+ */
+
+package eu.europa.ec.dgc.gateway.testdata;
+
+import eu.europa.ec.dgc.gateway.entity.SignerInformationEntity;
+import eu.europa.ec.dgc.gateway.repository.SignerInformationRepository;
+import eu.europa.ec.dgc.utils.CertificateUtils;
+import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
+import java.util.Base64;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class SignerInformationTestHelper {
+
+ private final SignerInformationRepository signerInformationRepository;
+
+ private final CertificateUtils certificateUtils;
+
+ public void createSignerInformationInDB(String countryCode, String signature,
+ X509Certificate certificate, ZonedDateTime createdAt) throws Exception {
+ createSignerInformationInDB(countryCode, signature, certificate, createdAt, null);
+ }
+ public void createSignerInformationInDB(String countryCode, String signature,
+ X509Certificate certificate, ZonedDateTime createdAt,
+ ZonedDateTime deletedAt) throws Exception {
+ signerInformationRepository.save(new SignerInformationEntity(
+ null,
+ createdAt,
+ deletedAt,
+ countryCode,
+ certificateUtils.getCertThumbprint(certificate),
+ Base64.getEncoder().encodeToString(certificate.getEncoded()),
+ deletedAt == null ? signature : null,
+ SignerInformationEntity.CertificateType.DSC
+ ));
+ }
+}
diff --git a/src/test/java/eu/europa/ec/dgc/gateway/testdata/TrustedPartyTestHelper.java b/src/test/java/eu/europa/ec/dgc/gateway/testdata/TrustedPartyTestHelper.java
index aacbded0..257ba19c 100644
--- a/src/test/java/eu/europa/ec/dgc/gateway/testdata/TrustedPartyTestHelper.java
+++ b/src/test/java/eu/europa/ec/dgc/gateway/testdata/TrustedPartyTestHelper.java
@@ -25,12 +25,11 @@
import eu.europa.ec.dgc.signing.SignedCertificateMessageBuilder;
import eu.europa.ec.dgc.signing.SignedStringMessageBuilder;
import eu.europa.ec.dgc.utils.CertificateUtils;
-
-import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
@@ -67,6 +66,11 @@ public class TrustedPartyTestHelper {
private final DgcTestKeyStore testKeyStore;
+ public X509Certificate getTestCert(String testCertId, TrustedPartyEntity.CertificateType type,
+ String countryCode,ZonedDateTime createdAt) throws Exception {
+ return createAndInsertCert(testCertId, type, countryCode,createdAt);
+ }
+
public String getHash(TrustedPartyEntity.CertificateType type, String countryCode) throws Exception {
prepareTestCert(type, countryCode);
return hashMap.get(type).get(countryCode);
@@ -109,40 +113,55 @@ private void prepareTestCert(TrustedPartyEntity.CertificateType type, String cou
if (trustedPartyRepository.getFirstByThumbprintAndCertificateType(
hashMap.get(type).get(countryCode), type
).isEmpty()) {
- insertTestCert(type, countryCode);
+ insertCert(type, countryCode, null, certificateMap.get(type).get(countryCode));
}
}
private void createAndInsertCert(TrustedPartyEntity.CertificateType type, String countryCode) throws Exception {
KeyPair keyPair = KeyPairGenerator.getInstance("ec").generateKeyPair();
X509Certificate authCertificate =
- CertificateTestUtils.generateCertificate(keyPair, countryCode, "DGC Test " + type.name() + " Cert");
- String certHash = certificateUtils.getCertThumbprint(authCertificate);
+ CertificateTestUtils.generateCertificate(keyPair, countryCode,
+ "DGC Test " + type.name() + " Cert");
certificateMap.get(type).put(countryCode, authCertificate);
- hashMap.get(type).put(countryCode, certHash);
+ hashMap.get(type).put(countryCode, certificateUtils.getCertThumbprint(authCertificate));
privateKeyMap.get(type).put(countryCode, keyPair.getPrivate());
- insertTestCert(type, countryCode);
+ insertCert(type, countryCode, null, authCertificate);
}
- private void insertTestCert(TrustedPartyEntity.CertificateType type, String countryCode) throws Exception {
- String certRawData = Base64.getEncoder().encodeToString(
- certificateMap.get(type).get(countryCode).getEncoded());
+ private X509Certificate createAndInsertCert(String testCertId, TrustedPartyEntity.CertificateType type,
+ String countryCode, ZonedDateTime createdAt) throws Exception {
+ KeyPair keyPair = KeyPairGenerator.getInstance("ec").generateKeyPair();
+ X509Certificate authCertificate =
+ CertificateTestUtils.generateCertificate(keyPair, countryCode,
+ "DGC Test " + type.name() + " Cert-" + testCertId);
+
+ return insertCert(type, countryCode, createdAt, authCertificate);
+ }
+
+ private X509Certificate insertCert(TrustedPartyEntity.CertificateType type, String countryCode,
+ ZonedDateTime createdAt, X509Certificate authCertificate) throws Exception {
+
+ String certRawData = Base64.getEncoder().encodeToString(authCertificate.getEncoded());
+ String certHash = certificateUtils.getCertThumbprint(authCertificate);
String signature = new SignedCertificateMessageBuilder()
- .withPayload(new X509CertificateHolder(certificateMap.get(type).get(countryCode).getEncoded()))
- .withSigningCertificate(new X509CertificateHolder(testKeyStore.getTrustAnchor().getEncoded()), testKeyStore.getTrustAnchorPrivateKey())
+ .withPayload(new X509CertificateHolder(authCertificate.getEncoded()))
+ .withSigningCertificate(new X509CertificateHolder(testKeyStore.getTrustAnchor().getEncoded()),
+ testKeyStore.getTrustAnchorPrivateKey())
.buildAsString(true);
TrustedPartyEntity trustedPartyEntity = new TrustedPartyEntity();
+ if(createdAt != null) trustedPartyEntity.setCreatedAt(createdAt);
trustedPartyEntity.setCertificateType(type);
trustedPartyEntity.setCountry(countryCode);
trustedPartyEntity.setSignature(signature);
trustedPartyEntity.setRawData(certRawData);
- trustedPartyEntity.setThumbprint(hashMap.get(type).get(countryCode));
+ trustedPartyEntity.setThumbprint(certHash);
trustedPartyRepository.save(trustedPartyEntity);
+ return authCertificate;
}
public String signString(final String hashdata) throws Exception {