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

Commit 7298166

Browse files
authored
Merge pull request #30 from corona-warn-app/feat/signing-api-header
Add Location-Id and Transaction-Id Header for UBirch API
2 parents 4c19e6e + 0fe933d commit 7298166

File tree

6 files changed

+56
-22
lines changed

6 files changed

+56
-22
lines changed

src/main/java/app/coronawarn/dcc/client/SigningApiClient.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.http.MediaType;
2525
import org.springframework.web.bind.annotation.PostMapping;
2626
import org.springframework.web.bind.annotation.RequestBody;
27+
import org.springframework.web.bind.annotation.RequestHeader;
2728

2829
/**
2930
* This class represents the Verification Server Feign client.
@@ -44,5 +45,8 @@ public interface SigningApiClient {
4445
consumes = MediaType.TEXT_PLAIN_VALUE,
4546
produces = MediaType.APPLICATION_CBOR_VALUE
4647
)
47-
byte[] sign(@RequestBody String hash);
48+
byte[] sign(
49+
@RequestBody String hash,
50+
@RequestHeader("X-Location-Id") String labIdHash,
51+
@RequestHeader("X-Transaction-Id") String dcciHash);
4852
}

src/main/java/app/coronawarn/dcc/client/SigningApiClientConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public Client signingApiClient() {
7474

7575
List<BasicHeader> headers = new ArrayList<>();
7676

77-
if (config.getSigningApiServer().getApiKey() != null) {
77+
if (!config.getSigningApiServer().getApiKey().isEmpty()) {
7878
headers.add(
7979
new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + config.getSigningApiServer().getApiKey()));
8080
}

src/main/java/app/coronawarn/dcc/service/DccService.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public class DccService {
4242

4343
private final SigningApiClient signingApiClient;
4444

45+
private final HashingService hashingService;
46+
4547
/**
4648
* Creates signed data for a DCCRegistration.
4749
* This Endpoints queries the SigningAPI and signs the hash assigned to this Registration.
@@ -58,7 +60,10 @@ public DccRegistration sign(DccRegistration registration) throws DccGenerateExce
5860
byte[] hashBytes = Hex.decode(registration.getDccHash());
5961
String hashBase64 = Base64.getEncoder().encodeToString(hashBytes);
6062

61-
coseBytes = callSigningApiWithRetry(hashBase64);
63+
coseBytes = callSigningApiWithRetry(
64+
hashBase64,
65+
hashingService.hash(registration.getLabId()),
66+
hashingService.hash(registration.getDcci()));
6267
} catch (FeignException e) {
6368
log.error("Failed to sign DCC. Http Status Code: {}, Message: {}", e.status(), e.getMessage());
6469

@@ -81,12 +86,12 @@ public DccRegistration sign(DccRegistration registration) throws DccGenerateExce
8186
return registration;
8287
}
8388

84-
private byte[] callSigningApiWithRetry(String hashBase64) {
89+
private byte[] callSigningApiWithRetry(String hashBase64, String hashedLabId, String hashedDcci) {
8590
try {
86-
return signingApiClient.sign(hashBase64);
91+
return signingApiClient.sign(hashBase64, hashedLabId, hashedDcci);
8792
} catch (FeignException e) {
8893
log.info("First try of calling Signing API failed. Status Code: {}, Message: {}", e.status(), e.getMessage());
89-
return signingApiClient.sign(hashBase64);
94+
return signingApiClient.sign(hashBase64, hashedLabId, hashedDcci);
9095
}
9196
}
9297

src/main/resources/application-cloud.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ cwa:
4343
key-store-password: ${CWA_DCC_SIGNINGAPISERVER_KEYSTOREPASSWORD}
4444
trust-store-password: ${CWA_DCC_SIGNINGAPISERVER_TRUSTSTOREPASSWORD}
4545
trust-store-path: ${CWA_DCC_SIGNINGAPISERVER_TRUSTSTOREPATH}
46-
api-key: ${CWA_DCC_SIGNINGAPISERVER_APIKEY}
46+
api-key: ${CWA_DCC_SIGNINGAPISERVER_APIKEY:}
4747
verify-hostnames: true
48-
connection-close-workaround: ${CWA_DCC_SIGNINGAPISERVER_CONNECTIONCLOSEWORKAROUND}
48+
connection-close-workaround: ${CWA_DCC_SIGNINGAPISERVER_CONNECTIONCLOSEWORKAROUND:false}
4949
request:
5050
sizelimit: 10000
5151
entities:

src/test/java/app/coronawarn/dcc/controller/InternalDccControllerTest.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import static app.coronawarn.dcc.utils.TestValues.registrationTokenValue;
3535
import static app.coronawarn.dcc.utils.TestValues.testId;
3636
import static org.hamcrest.Matchers.equalTo;
37+
import static org.mockito.ArgumentMatchers.anyString;
3738
import static org.mockito.ArgumentMatchers.eq;
3839
import static org.mockito.Mockito.doThrow;
3940
import static org.mockito.Mockito.never;
@@ -52,6 +53,7 @@
5253
import app.coronawarn.dcc.repository.DccRegistrationRepository;
5354
import app.coronawarn.dcc.repository.LabIdClaimRepository;
5455
import app.coronawarn.dcc.service.DccRegistrationService;
56+
import app.coronawarn.dcc.service.HashingService;
5557
import app.coronawarn.dcc.service.LabIdClaimService;
5658
import app.coronawarn.dcc.utils.TestUtils;
5759
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -89,6 +91,9 @@ public class InternalDccControllerTest {
8991
@Autowired
9092
DccRegistrationService dccRegistrationService;
9193

94+
@Autowired
95+
HashingService hashingService;
96+
9297
@MockBean
9398
VerificationServerClient verificationServerClientMock;
9499

@@ -103,7 +108,7 @@ void setup() {
103108
when(verificationServerClientMock.result(eq(registrationToken)))
104109
.thenReturn(new InternalTestResult(6, labId, testId, 0));
105110

106-
when(signingApiClientMock.sign(eq(dccHashBase64)))
111+
when(signingApiClientMock.sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString()))
107112
.thenReturn(partialDcc);
108113
}
109114

@@ -123,7 +128,7 @@ void testUploadDcc() throws Exception {
123128
.andExpect(status().isOk())
124129
.andExpect(jsonPath("$.partialDcc").value(equalTo(partialDccBase64)));
125130

126-
verify(signingApiClientMock).sign(eq(dccHashBase64));
131+
verify(signingApiClientMock).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
127132

128133
Optional<DccRegistration> dccRegistration = dccRegistrationRepository.findByRegistrationToken(registrationTokenValue);
129134

@@ -147,7 +152,7 @@ void testUploadDccFailedUnknownTestId() throws Exception {
147152
)
148153
.andExpect(status().isNotFound());
149154

150-
verify(signingApiClientMock, never()).sign(eq(dccHashBase64));
155+
verify(signingApiClientMock, never()).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
151156
}
152157

153158
@Test
@@ -166,7 +171,7 @@ void testUploadDccFailedLabIdNotAssignedToPartner() throws Exception {
166171
)
167172
.andExpect(status().isForbidden());
168173

169-
verify(signingApiClientMock, never()).sign(eq(dccHashBase64));
174+
verify(signingApiClientMock, never()).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
170175
}
171176

172177
@Test
@@ -186,7 +191,7 @@ void testUploadDccFailedAlreadyExists() throws Exception {
186191
)
187192
.andExpect(status().isConflict());
188193

189-
verify(signingApiClientMock, never()).sign(eq(dccHashBase64));
194+
verify(signingApiClientMock, never()).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
190195
}
191196

192197
@Test
@@ -202,7 +207,7 @@ void testUploadDccFailedInvalidDCC() throws Exception {
202207
)
203208
.andExpect(status().isBadRequest());
204209

205-
verify(signingApiClientMock, never()).sign(eq(dccHashBase64));
210+
verify(signingApiClientMock, never()).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
206211
}
207212

208213
@Test
@@ -218,7 +223,7 @@ void testUploadDccFailedInvalidDek() throws Exception {
218223
)
219224
.andExpect(status().isBadRequest());
220225

221-
verify(signingApiClientMock, never()).sign(eq(dccHashBase64));
226+
verify(signingApiClientMock, never()).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
222227
}
223228

224229
@Test
@@ -228,7 +233,7 @@ void testUploadDccFailedBadResponseFromSignignAPI4xx() throws Exception {
228233
DccUploadRequest dccUploadRequest = new DccUploadRequest(dccHash, encryptedDccBase64, encryptedDekBase64);
229234

230235
doThrow(new FeignException.BadRequest("", dummyRequest, null))
231-
.when(signingApiClientMock).sign(eq(dccHashBase64));
236+
.when(signingApiClientMock).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
232237

233238
mockMvc.perform(post("/version/v1/test/" + testId + "/dcc")
234239
.contentType(MediaType.APPLICATION_JSON_VALUE)
@@ -254,7 +259,7 @@ void testUploadDccFailedBadResponseFromSignignAPI5xx() throws Exception {
254259
DccUploadRequest dccUploadRequest = new DccUploadRequest(dccHash, encryptedDccBase64, encryptedDekBase64);
255260

256261
doThrow(new FeignException.InternalServerError("", dummyRequest, null))
257-
.when(signingApiClientMock).sign(eq(dccHashBase64));
262+
.when(signingApiClientMock).sign(eq(dccHashBase64), eq(hashingService.hash(labId)), anyString());
258263

259264
mockMvc.perform(post("/version/v1/test/" + testId + "/dcc")
260265
.contentType(MediaType.APPLICATION_JSON_VALUE)

src/test/java/app/coronawarn/dcc/service/DccServiceTest.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import static app.coronawarn.dcc.utils.TestValues.registrationToken;
3131
import static app.coronawarn.dcc.utils.TestValues.registrationTokenValue;
3232
import static app.coronawarn.dcc.utils.TestValues.testId;
33+
import static org.mockito.ArgumentMatchers.anyString;
3334
import static org.mockito.ArgumentMatchers.eq;
3435
import static org.mockito.Mockito.doThrow;
3536
import static org.mockito.Mockito.when;
@@ -65,6 +66,9 @@ public class DccServiceTest {
6566
@Autowired
6667
DccRegistrationRepository dccRegistrationRepository;
6768

69+
@Autowired
70+
HashingService hashingService;
71+
6872
@MockBean
6973
VerificationServerClient verificationServerClientMock;
7074

@@ -80,7 +84,11 @@ void setup() {
8084
void testSigning() throws NoSuchAlgorithmException, DccRegistrationService.DccRegistrationException {
8185

8286
when(verificationServerClientMock.result(eq(registrationToken))).thenReturn(new InternalTestResult(6, labId, testId, 0));
83-
when(signingApiClient.sign(eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))))).thenReturn(partialDcc);
87+
when(signingApiClient.sign(
88+
eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))),
89+
eq(hashingService.hash(labId)),
90+
anyString()
91+
)).thenReturn(partialDcc);
8492

8593
PublicKey publicKey = TestUtils.generateKeyPair().getPublic();
8694
DccRegistration registration = dccRegistrationService.createDccRegistration(registrationTokenValue, publicKey);
@@ -105,7 +113,10 @@ void testSigningFailedBySigningApi4xx() throws NoSuchAlgorithmException, DccRegi
105113
when(verificationServerClientMock.result(eq(registrationToken))).thenReturn(new InternalTestResult(6, labId, testId, 0));
106114

107115
doThrow(new FeignException.BadRequest("", dummyRequest, null))
108-
.when(signingApiClient).sign(eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))));
116+
.when(signingApiClient).sign(
117+
eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))),
118+
eq(hashingService.hash(labId)),
119+
anyString());
109120

110121
PublicKey publicKey = TestUtils.generateKeyPair().getPublic();
111122
DccRegistration registration = dccRegistrationService.createDccRegistration(registrationTokenValue, publicKey);
@@ -131,7 +142,10 @@ void testSigningFailedBySigningApi5xx() throws NoSuchAlgorithmException, DccRegi
131142
when(verificationServerClientMock.result(eq(registrationToken))).thenReturn(new InternalTestResult(6, labId, testId, 0));
132143

133144
doThrow(new FeignException.InternalServerError("", dummyRequest, null))
134-
.when(signingApiClient).sign(eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))));
145+
.when(signingApiClient).sign(
146+
eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))),
147+
eq(hashingService.hash((labId))),
148+
anyString());
135149

136150
PublicKey publicKey = TestUtils.generateKeyPair().getPublic();
137151
DccRegistration registration = dccRegistrationService.createDccRegistration(registrationTokenValue, publicKey);
@@ -158,7 +172,10 @@ void testSigningRetry() throws NoSuchAlgorithmException, DccRegistrationService.
158172

159173
doThrow(new FeignException.InternalServerError("", dummyRequest, null))
160174
.doReturn(partialDcc)
161-
.when(signingApiClient).sign(eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))));
175+
.when(signingApiClient).sign(
176+
eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))),
177+
eq(hashingService.hash(labId)),
178+
anyString());
162179

163180
PublicKey publicKey = TestUtils.generateKeyPair().getPublic();
164181
DccRegistration registration = dccRegistrationService.createDccRegistration(registrationTokenValue, publicKey);
@@ -185,7 +202,10 @@ void testSigningFailedOnFirstRequestButSuccessOnSecond() throws NoSuchAlgorithmE
185202
doThrow(new FeignException.InternalServerError("", dummyRequest, null))
186203
.doThrow(new FeignException.InternalServerError("", dummyRequest, null))
187204
.doReturn(partialDcc)
188-
.when(signingApiClient).sign(eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))));
205+
.when(signingApiClient).sign(
206+
eq(Base64.getEncoder().encodeToString(Hex.decode(dccHash))),
207+
eq(hashingService.hash(labId)),
208+
anyString());
189209

190210
PublicKey publicKey = TestUtils.generateKeyPair().getPublic();
191211
DccRegistration registration = dccRegistrationService.createDccRegistration(registrationTokenValue, publicKey);

0 commit comments

Comments
 (0)