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

Commit

Permalink
Release 1.0.8 (#613)
Browse files Browse the repository at this point in the history
* Introduce new version 1.0.8

* Disable UserDetailsServiceAutoConfiguration (#594)

* Cherry-Pick: Add random key padding (#609)

* Cherry-Pick: Minor code prettification (#612)

Co-authored-by: Johannes Eschrig <[email protected]>
Co-authored-by: Pit Humke <[email protected]>
  • Loading branch information
3 people authored Jun 22, 2020
1 parent 9429244 commit ccbfe41
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .mvn/maven.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-Drevision=1.0.7
-Drevision=1.0.8
-Dlicense.projectName=Corona-Warn-App
-Dlicense.inceptionYear=2020
-Dlicense.licenseName=apache_v2
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;

@SpringBootApplication
@SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class})
@EnableJpaRepositories(basePackages = "app.coronawarn.server.common.persistence")
@EntityScan(basePackages = "app.coronawarn.server.common.persistence")
@ComponentScan({"app.coronawarn.server.common.persistence",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,25 @@

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

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

@Component
@ConfigurationProperties(prefix = "services.submission")
@Validated
public class SubmissionServiceConfig {

// Exponential moving average of the last N real request durations (in ms), where
// N = fakeDelayMovingAverageSamples.
private Double initialFakeDelayMilliseconds;
private Double fakeDelayMovingAverageSamples;
private Integer retentionDays;
@Min(1)
@Max(100)
private Integer randomKeyPaddingMultiplier;
private Integer connectionPoolSize;
private Payload payload;
private Verification verification;
Expand Down Expand Up @@ -61,6 +68,14 @@ public void setRetentionDays(Integer retentionDays) {
this.retentionDays = retentionDays;
}

public Integer getRandomKeyPaddingMultiplier() {
return randomKeyPaddingMultiplier;
}

public void setRandomKeyPaddingMultiplier(Integer randomKeyPaddingMultiplier) {
this.randomKeyPaddingMultiplier = randomKeyPaddingMultiplier;
}

public Integer getConnectionPoolSize() {
return connectionPoolSize;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
import app.coronawarn.server.services.submission.validation.ValidSubmissionPayload;
import app.coronawarn.server.services.submission.verification.TanVerifier;
import io.micrometer.core.annotation.Timed;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import org.apache.commons.math3.distribution.PoissonDistribution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -65,6 +67,7 @@ public class SubmissionController {
private final TanVerifier tanVerifier;
private final Double fakeDelayMovingAverageSamples;
private final Integer retentionDays;
private final Integer randomKeyPaddingMultiplier;
private Double fakeDelay;

SubmissionController(DiagnosisKeyService diagnosisKeyService, TanVerifier tanVerifier,
Expand All @@ -75,6 +78,7 @@ public class SubmissionController {
fakeDelay = submissionServiceConfig.getInitialFakeDelayMilliseconds();
fakeDelayMovingAverageSamples = submissionServiceConfig.getFakeDelayMovingAverageSamples();
retentionDays = submissionServiceConfig.getRetentionDays();
randomKeyPaddingMultiplier = submissionServiceConfig.getRandomKeyPaddingMultiplier();
submissionControllerMonitor.initializeGauges(this);
}

Expand Down Expand Up @@ -166,7 +170,29 @@ public void persistDiagnosisKeysPayload(SubmissionPayload protoBufDiagnosisKeys)
}
}

diagnosisKeyService.saveDiagnosisKeys(diagnosisKeys);
diagnosisKeyService.saveDiagnosisKeys(padDiagnosisKeys(diagnosisKeys));
}

private List<DiagnosisKey> padDiagnosisKeys(List<DiagnosisKey> diagnosisKeys) {
List<DiagnosisKey> paddedDiagnosisKeys = new ArrayList<>();
diagnosisKeys.forEach(diagnosisKey -> {
paddedDiagnosisKeys.add(diagnosisKey);
IntStream.range(1, randomKeyPaddingMultiplier)
.mapToObj(index -> DiagnosisKey.builder()
.withKeyData(generateRandomKeyData())
.withRollingStartIntervalNumber(diagnosisKey.getRollingStartIntervalNumber())
.withTransmissionRiskLevel(diagnosisKey.getTransmissionRiskLevel())
.withRollingPeriod(diagnosisKey.getRollingPeriod())
.build())
.forEach(paddedDiagnosisKeys::add);
});
return paddedDiagnosisKeys;
}

private static byte[] generateRandomKeyData() {
byte[] randomKeyData = new byte[16];
new SecureRandom().nextBytes(randomKeyData);
return randomKeyData;
}

private void updateFakeDelay(long realRequestDuration) {
Expand Down
6 changes: 6 additions & 0 deletions services/submission/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ services:
# The number of samples for the calculation of the moving average for fake request delays.
fake-delay-moving-average-samples: 10
retention-days: 14
# The number of keys to save to the DB for every real submitted key.
# Example: If the 'random-key-padding-multiplier' is set to 10, and 5 keys are being submitted,
# then the 5 real submitted keys will be saved to the DB, plus an additional 45 keys with
# random 'key_data'. All properties, besides the 'key_data', of the additional keys will be
# identical to the real key.
random-key-padding-multiplier: ${RANDOM_KEY_PADDING_MULTIPLIER:1}
connection-pool-size: 200
payload:
max-number-of-keys: 14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,27 @@ void singleKeyWithOutdatedRollingStartIntervalNumberDoesNotGetSaved() {

@Test
void keysWithOutdatedRollingStartIntervalNumberDoNotGetSaved() {
Collection<TemporaryExposureKey> keys = buildPayloadWithMultipleKeys();
Collection<TemporaryExposureKey> submittedKeys = buildPayloadWithMultipleKeys();
TemporaryExposureKey outdatedKey = createOutdatedKey();
keys.add(outdatedKey);
submittedKeys.add(outdatedKey);
ArgumentCaptor<Collection<DiagnosisKey>> argument = ArgumentCaptor.forClass(Collection.class);

executor.executeRequest(keys, buildOkHeaders());
executor.executeRequest(submittedKeys, buildOkHeaders());

verify(diagnosisKeyService, atLeastOnce()).saveDiagnosisKeys(argument.capture());
keys.remove(outdatedKey);
assertElementsCorrespondToEachOther(keys, argument.getValue());
submittedKeys.remove(outdatedKey);
assertElementsCorrespondToEachOther(submittedKeys, argument.getValue());
}

@Test
void checkSaveOperationCallForValidParameters() {
Collection<TemporaryExposureKey> keys = buildPayloadWithMultipleKeys();
void checkSaveOperationCallAndFakeDelayUpdateForValidParameters() {
Collection<TemporaryExposureKey> submittedKeys = buildPayloadWithMultipleKeys();
ArgumentCaptor<Collection<DiagnosisKey>> argument = ArgumentCaptor.forClass(Collection.class);

executor.executeRequest(keys, buildOkHeaders());
executor.executeRequest(submittedKeys, buildOkHeaders());

verify(diagnosisKeyService, atLeastOnce()).saveDiagnosisKeys(argument.capture());
assertElementsCorrespondToEachOther(keys, argument.getValue());
assertElementsCorrespondToEachOther(submittedKeys, argument.getValue());
}

@ParameterizedTest
Expand Down Expand Up @@ -181,7 +181,7 @@ 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(elem -> Arguments.of(elem));
.map(Arguments::of);
}

@Test
Expand Down Expand Up @@ -237,18 +237,37 @@ private static Collection<TemporaryExposureKey> buildPayloadWithInvalidKey() {
buildTemporaryExposureKey(VALID_KEY_DATA_1, createRollingStartIntervalNumber(2), 999))
.collect(Collectors.toCollection(ArrayList::new));
}
private void assertElementsCorrespondToEachOther
(Collection<TemporaryExposureKey> submittedKeys, Collection<DiagnosisKey> keyEntities) {
Set<DiagnosisKey> expKeys = submittedKeys.stream()
.map(aSubmittedKey -> DiagnosisKey.builder().fromProtoBuf(aSubmittedKey).build())

private void assertElementsCorrespondToEachOther(Collection<TemporaryExposureKey> submittedTemporaryExposureKeys,
Collection<DiagnosisKey> savedDiagnosisKeys) {

Set<DiagnosisKey> submittedDiagnosisKeys = submittedTemporaryExposureKeys.stream()
.map(submittedDiagnosisKey -> DiagnosisKey.builder().fromProtoBuf(submittedDiagnosisKey).build())
.collect(Collectors.toSet());

assertThat(keyEntities.size())
.withFailMessage("Number of submitted keys and generated key entities don't match.")
.isEqualTo(expKeys.size());
keyEntities.forEach(anActKey -> assertThat(expKeys)
.withFailMessage("Key entity does not correspond to a submitted key.")
.contains(anActKey)
);
assertThat(savedDiagnosisKeys).hasSize(submittedDiagnosisKeys.size() * config.getRandomKeyPaddingMultiplier());
assertThat(savedDiagnosisKeys).containsAll(submittedDiagnosisKeys);

submittedDiagnosisKeys.forEach(submittedDiagnosisKey -> {
List<DiagnosisKey> savedKeysForSingleSubmittedKey = savedDiagnosisKeys.stream()
.filter(savedDiagnosisKey -> savedDiagnosisKey.getRollingPeriod() ==
submittedDiagnosisKey.getRollingPeriod())
.filter(savedDiagnosisKey -> savedDiagnosisKey.getTransmissionRiskLevel() ==
submittedDiagnosisKey.getTransmissionRiskLevel())
.filter(savedDiagnosisKey -> savedDiagnosisKey.getRollingStartIntervalNumber() ==
submittedDiagnosisKey.getRollingStartIntervalNumber())
.collect(Collectors.toList());

assertThat(savedKeysForSingleSubmittedKey).hasSize(config.getRandomKeyPaddingMultiplier());
assertThat(savedKeysForSingleSubmittedKey.stream().filter(savedKey ->
Arrays.equals(savedKey.getKeyData(), submittedDiagnosisKey.getKeyData()))).hasSize(1);
assertThat(savedKeysForSingleSubmittedKey).allMatch(
savedKey -> savedKey.getRollingPeriod() == submittedDiagnosisKey.getRollingPeriod());
assertThat(savedKeysForSingleSubmittedKey).allMatch(
savedKey -> savedKey.getRollingStartIntervalNumber() == submittedDiagnosisKey
.getRollingStartIntervalNumber());
assertThat(savedKeysForSingleSubmittedKey).allMatch(
savedKey -> savedKey.getTransmissionRiskLevel() == submittedDiagnosisKey.getTransmissionRiskLevel());
});
}
}
1 change: 1 addition & 0 deletions services/submission/src/test/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ services:
initial-fake-delay-milliseconds: 1
fake-delay-moving-average-samples: 1
retention-days: 14
random-key-padding-multiplier: 10
connection-pool-size: 200
payload:
max-number-of-keys: 14
Expand Down

0 comments on commit ccbfe41

Please sign in to comment.