Skip to content
This repository has been archived by the owner on May 16, 2023. It is now read-only.

Feature/merge master into federation #829

Merged
merged 36 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f3d3114
Revert "Usage of postgres in test environment for database consistenc…
fredrb Jul 29, 2020
ab81402
Mitigate CVE-2020-13935 (#690)
Jul 30, 2020
36c062b
Revert to test postgresql docker image using test-containers. (#694)
Aug 6, 2020
db83e31
Test cases and debug support.for submission (#698)
EugenM-SAP Aug 12, 2020
12b310a
Update maven.config with current version 1.4.0-SNAPSHOT (#697)
EvgeniiSkrebtcov Aug 12, 2020
9d93f17
-fix invalid test and name refactoring (#703)
ioangut Aug 13, 2020
4b188b9
Add app-features as external configuration (#704)
Aug 13, 2020
47f61e0
use same version for spring-boot-starter-parent accross all component…
hilmarf Aug 14, 2020
8c2fea2
Fix/700 retention policy (#711)
fredrb Aug 18, 2020
87eb979
Submission Service - updated documentation (#713)
emmetsap Aug 24, 2020
db18b68
Submission Service - Enhance TEK's (#712)
ioangut Aug 25, 2020
5e81409
Feature/enrich app config (#726)
KevponSAP Aug 25, 2020
a4d90dd
Fix Sonar issues (#754)
Sep 10, 2020
aa0c624
Bugfix/submission tek rolling period (#752)
ioangut Sep 11, 2020
3ef4ecf
Feature/update risk score master (#758)
ioangut Sep 11, 2020
8c7f6eb
Update exposure-config.yaml (#765)
ioangut Sep 14, 2020
f3d6684
Update attenuation-duration.yaml (#775) (#776)
Sep 15, 2020
af621f5
prepare release 1.5.0 (#793)
hilmarf Sep 18, 2020
db7be7f
Fix sping web guava (#808)
hilmarf Sep 23, 2020
f7dc00c
Update CODEOWNERS file (#817)
michael-burwig Sep 24, 2020
8aad1e1
Admin/update codeowners (#818)
mibrasap Sep 25, 2020
9cfd6d3
Add hot fix for submission payload validation (#822) (#825)
ioangut Sep 30, 2020
e239a30
Merge remote-tracking branch 'origin/master' into feature/federation
ioangut Sep 30, 2020
afc7672
Merge branch 'feature/federation' of https://github.com/corona-warn-a…
ioangut Sep 30, 2020
15331d9
fix branch after merge conflicts
ioangut Sep 30, 2020
c001649
Adjustments after code review
ioangut Sep 30, 2020
aadfe09
removed unused getExpiryDateTime method
ioangut Sep 30, 2020
51296cd
Merge branch 'feature/federation' into feature/merge-master-into-fede…
hilmarf Sep 30, 2020
35ca15d
removed unused import code smell
ioangut Oct 1, 2020
a4fb4b3
Adjust submission payload validation checks in Master(#832) f (#834)
ioangut Oct 1, 2020
4e56f76
Merge remote-tracking branch 'origin/master' into feature/merge-maste…
ioangut Oct 1, 2020
2492186
Removed unused duplicated methods
ioangut Oct 1, 2020
c3cb6a6
Merge branch 'feature/federation' into feature/merge-master-into-fede…
ioangut Oct 1, 2020
5f4a834
Merge branch 'feature/federation' into feature/merge-master-into-fede…
hilmarf Oct 1, 2020
31f1c60
Merge branch 'feature/federation' into feature/merge-master-into-fede…
fredrb Oct 1, 2020
9a854cc
Merge branch 'feature/federation' into feature/merge-master-into-fede…
hilmarf Oct 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ private static Optional<LocalDateTime> getEarliestDistributableTimestamp(
return distributableDiagnosisKeys.keySet().stream().min(LocalDateTime::compareTo);
}

/**
* Calculates the earliest point in time at which the specified {@link DiagnosisKey} can be distributed, while
* respecting the expiry policy and the submission timestamp. Before keys are allowed to be distributed, they must be
* expired for a configured amount of time.
*
* @return {@link LocalDateTime} at which the specified {@link DiagnosisKey} can be distributed.
*/
private LocalDateTime getDistributionDateTimeByExpiryPolicy(DiagnosisKey diagnosisKey) {
return sharingPoliciesChecker.getEarliestTimeForSharingKey(diagnosisKey,
ExpirationPolicy.of(expiryPolicyMinutes, ChronoUnit.MINUTES));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
package app.coronawarn.server.services.submission.validation;

import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingInt;
import static java.util.stream.Collectors.toList;

import app.coronawarn.server.common.protocols.external.exposurenotification.TemporaryExposureKey;
Expand All @@ -33,7 +31,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
Expand Down Expand Up @@ -98,7 +95,6 @@ public boolean isValid(SubmissionPayload submissionPayload, ConstraintValidatorC

if (keysHaveFlexibleRollingPeriod(exposureKeys)) {
return checkStartIntervalNumberIsAtMidNight(exposureKeys, validatorContext)
&& checkKeysCumulateEqualOrLessThanMaxRollingPeriodPerDay(exposureKeys, validatorContext)
&& checkOriginCountryIsValid(submissionPayload, validatorContext)
&& checkVisitedCountriesAreValid(submissionPayload, validatorContext)
&& checkRequiredFieldsNotMissing(exposureKeys, validatorContext)
Expand All @@ -107,7 +103,6 @@ && checkTransmissionRiskLevelIsAcceptable(exposureKeys, validatorContext)
} else {
return checkStartIntervalNumberIsAtMidNight(exposureKeys, validatorContext)
&& checkKeyCollectionSize(exposureKeys, validatorContext)
&& checkUniqueStartIntervalNumbers(exposureKeys, validatorContext)
&& checkOriginCountryIsValid(submissionPayload, validatorContext)
&& checkVisitedCountriesAreValid(submissionPayload, validatorContext)
&& checkRequiredFieldsNotMissing(exposureKeys, validatorContext)
Expand All @@ -130,38 +125,6 @@ private boolean checkKeyCollectionSize(List<TemporaryExposureKey> exposureKeys,
return true;
}

private boolean checkUniqueStartIntervalNumbers(List<TemporaryExposureKey> exposureKeys,
ConstraintValidatorContext validatorContext) {
Integer[] startIntervalNumbers = exposureKeys.stream()
.mapToInt(TemporaryExposureKey::getRollingStartIntervalNumber).boxed().toArray(Integer[]::new);
long distinctSize = Arrays.stream(startIntervalNumbers)
.distinct()
.count();

if (distinctSize < exposureKeys.size()) {
addViolation(validatorContext, String.format(
"Duplicate StartIntervalNumber found. StartIntervalNumbers: %s", startIntervalNumbers));
return false;
}
return true;
}

private boolean checkKeysCumulateEqualOrLessThanMaxRollingPeriodPerDay(List<TemporaryExposureKey> exposureKeys,
ConstraintValidatorContext validatorContext) {

boolean isValidRollingPeriod = exposureKeys.stream()
.collect(groupingBy(TemporaryExposureKey::getRollingStartIntervalNumber,
summingInt(TemporaryExposureKey::getRollingPeriod)))
.values().stream()
.anyMatch(sum -> sum <= maxRollingPeriod);

if (!isValidRollingPeriod) {
addViolation(validatorContext, "The sum of the rolling periods exceeds 144 per day");
return false;
}
return true;
}

private boolean keysHaveFlexibleRollingPeriod(List<TemporaryExposureKey> exposureKeys) {
return exposureKeys.stream()
.anyMatch(temporaryExposureKey -> temporaryExposureKey.getRollingPeriod() < maxRollingPeriod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class PayloadValidationTest {

@BeforeEach
public void setUpMocks() {
when(this.tanVerifier.verifyTan(anyString())).thenReturn(true);
when(tanVerifier.verifyTan(anyString())).thenReturn(true);
}

@Autowired
Expand Down Expand Up @@ -145,7 +145,7 @@ void check400ResponseStatusForMissingTrlAndDsos() {
}

@Test
void check400ResponseStatusForKeysWithFixedRollingPeriodAndDuplicateStartIntervals() {
void check200ResponseStatusForKeysWithFixedRollingPeriodAndDuplicateStartIntervals() {
int rollingStartIntervalNumber = createRollingStartIntervalNumber(2);
var keysWithDuplicateStartIntervalNumber = Lists.list(
buildTemporaryExposureKey(VALID_KEY_DATA_1, rollingStartIntervalNumber, 1,
Expand All @@ -154,7 +154,7 @@ void check400ResponseStatusForKeysWithFixedRollingPeriodAndDuplicateStartInterva

ResponseEntity<Void> actResponse = executor.executePost(keysWithDuplicateStartIntervalNumber);

assertThat(actResponse.getStatusCode()).isEqualTo(BAD_REQUEST);
assertThat(actResponse.getStatusCode()).isEqualTo(OK);
}

@Test
Expand Down Expand Up @@ -228,22 +228,6 @@ private Collection<TemporaryExposureKey> buildPayloadWithMoreThan14KeysAndFlexib
return flexibleRollingPeriodKeys;
}

@Test
void check400ResponseStatusWhenTwoKeysCumulateMoreThanMaxRollingPeriodInSameDay() {
ResponseEntity<Void> actResponse = executor.executePost(buildPayloadWithKeysThatCumulateMoreThanMaxRollingPeriodPerDay());
assertThat(actResponse.getStatusCode()).isEqualTo(BAD_REQUEST);
}

private Collection<TemporaryExposureKey> buildPayloadWithKeysThatCumulateMoreThanMaxRollingPeriodPerDay() {
ArrayList<TemporaryExposureKey> temporaryExposureKeys = new ArrayList<>();
temporaryExposureKeys.add(buildTemporaryExposureKeyWithFlexibleRollingPeriod(VALID_KEY_DATA_1,
createRollingStartIntervalNumber(2), 3, 100));
temporaryExposureKeys.add(buildTemporaryExposureKeyWithFlexibleRollingPeriod(VALID_KEY_DATA_1,
createRollingStartIntervalNumber(2), 3, 144));

return temporaryExposureKeys;
}

@Test
void check200ResponseStatusWithTwoKeysOneFlexibleAndOneDefaultOnDifferentDays() {
ResponseEntity<Void> actResponse = executor.executePost(buildPayloadWithTwoKeysOneFlexibleAndOneDefaultOnDifferentDays());
Expand All @@ -263,13 +247,6 @@ private Collection<TemporaryExposureKey> buildPayloadWithTwoKeysOneFlexibleAndOn
return flexibleRollingPeriodKeys;
}

@Test
void check200ResponseStatusWhenKeysCumulateToMaxRollingPeriodInSameDay() {
ResponseEntity<Void> actResponse = executor.executePost(buildPayloadWithTwoKeysWithFlexibleRollingPeriod());

assertThat(actResponse.getStatusCode()).isEqualTo(OK);
}

private Collection<TemporaryExposureKey> buildPayloadWithTwoKeysWithFlexibleRollingPeriod() {
ArrayList<TemporaryExposureKey> flexibleRollingPeriodKeys = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@

package app.coronawarn.server.services.submission.controller;

import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.VALID_KEY_DATA_1;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.VALID_KEY_DATA_2;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayload;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildMultipleKeys;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildMultipleKeysWithoutDSOS;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildMultipleKeysWithoutDSOSAndTRL;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildMultipleKeysWithoutTRL;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayload;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithInvalidKey;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithInvalidOriginCountry;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithOneKey;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithPadding;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithTooLargePadding;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithVisitedCountries;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithTooLargePadding;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.createRollingStartIntervalNumber;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildPayloadWithInvalidOriginCountry;
import static app.coronawarn.server.services.submission.controller.SubmissionPayloadMockData.buildTemporaryExposureKey;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
Expand All @@ -51,6 +52,7 @@

import app.coronawarn.server.common.persistence.domain.DiagnosisKey;
import app.coronawarn.server.common.persistence.service.DiagnosisKeyService;
import app.coronawarn.server.common.protocols.external.exposurenotification.ReportType;
import app.coronawarn.server.common.protocols.external.exposurenotification.TemporaryExposureKey;
import app.coronawarn.server.common.protocols.internal.SubmissionPayload;
import app.coronawarn.server.services.submission.config.SubmissionServiceConfig;
Expand Down Expand Up @@ -106,21 +108,6 @@ class SubmissionControllerTest {
@Autowired
private SubmissionServiceConfig config;

private static Stream<Arguments> createIncompleteHeaders() {
return Stream.of(
Arguments.of(HttpHeaderBuilder.builder().build()),
Arguments.of(HttpHeaderBuilder.builder().contentTypeProtoBuf().build()),
Arguments.of(HttpHeaderBuilder.builder().contentTypeProtoBuf().withoutCwaFake().build()),
Arguments.of(HttpHeaderBuilder.builder().contentTypeProtoBuf().cwaAuth().build()));
}

private static Stream<Arguments> createDeniedHttpMethods() {
return Arrays.stream(HttpMethod.values())
.filter(method -> method != HttpMethod.POST)
.filter(method -> method != HttpMethod.PATCH) /* not supported by Rest Template */
.map(Arguments::of);
}

@BeforeEach
public void setUpMocks() {
when(tanVerifier.verifyTan(anyString())).thenReturn(true);
Expand Down Expand Up @@ -232,8 +219,8 @@ void checkDSOSIsPersistedForKeysWithTRLOnly() {
}

/**
* The test verifies that even if the payload does not provide keys with TRL, the information
* is still derived from the DSOS field and correctly persisted.
* The test verifies that even if the payload does not provide keys with TRL, the information is still derived from
* the DSOS field and correctly persisted.
*
* <li>DSOS - days since onset of symptoms
* <li>TRL - transmission risk level
Expand Down Expand Up @@ -459,4 +446,26 @@ private DiagnosisKey findDiagnosisKeyMatch(TemporaryExposureKey temporaryExposur
diagnosisKey -> temporaryExposureKey.getKeyData().equals(ByteString.copyFrom(diagnosisKey.getKeyData())))
.findFirst().orElseThrow();
}

public static SubmissionPayload buildPayloadWithInvalidKey() {
TemporaryExposureKey invalidKey =
buildTemporaryExposureKey(VALID_KEY_DATA_1, createRollingStartIntervalNumber(2), 999,
ReportType.CONFIRMED_CLINICAL_DIAGNOSIS, 1);
return buildPayload(invalidKey);
}

private static Stream<Arguments> createIncompleteHeaders() {
return Stream.of(
Arguments.of(HttpHeaderBuilder.builder().build()),
Arguments.of(HttpHeaderBuilder.builder().contentTypeProtoBuf().build()),
Arguments.of(HttpHeaderBuilder.builder().contentTypeProtoBuf().withoutCwaFake().build()),
Arguments.of(HttpHeaderBuilder.builder().contentTypeProtoBuf().cwaAuth().build()));
}

private static Stream<Arguments> createDeniedHttpMethods() {
return Arrays.stream(HttpMethod.values())
.filter(method -> method != HttpMethod.POST)
.filter(method -> method != HttpMethod.PATCH) /* not supported by Rest Template */
.map(Arguments::of);
}
}