Skip to content

Commit 455735f

Browse files
authored
Merge pull request #161 from IABTechLab/tjm-UID2-4246-only-shutdown-on-401
Return AttestationFailure or RetryableFailures
2 parents ccceef0 + 0dbd2cd commit 455735f

File tree

5 files changed

+291
-218
lines changed

5 files changed

+291
-218
lines changed

pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.uid2</groupId>
88
<artifactId>uid2-core</artifactId>
9-
<version>2.20.0</version>
9+
<version>2.20.1-alpha-50-SNAPSHOT</version>
1010

1111
<properties>
1212
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -24,7 +24,7 @@
2424
<vertx.verticle>com.uid2.core.vertx.CoreVerticle</vertx.verticle>
2525
<launcher.class>io.vertx.core.Launcher</launcher.class>
2626

27-
<uid2-shared.version>7.19.0</uid2-shared.version>
27+
<uid2-shared.version>7.20.0</uid2-shared.version>
2828
<image.version>${project.version}</image.version>
2929
</properties>
3030

src/main/java/com/uid2/core/handler/AttestationFailureHandler.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package com.uid2.core.handler;
22

33
import com.uid2.core.Const;
4-
import com.uid2.core.vertx.AttestationFailureReason;
54
import com.uid2.shared.auth.IAuthorizable;
65
import com.uid2.shared.auth.OperatorKey;
76
import com.uid2.shared.middleware.AuthMiddleware;
7+
import com.uid2.shared.secure.AttestationFailure;
88
import io.vertx.core.Handler;
99
import io.vertx.core.json.JsonObject;
1010
import io.vertx.core.net.SocketAddress;
@@ -40,14 +40,14 @@ private void logAttestationFailure(RoutingContext context) {
4040
return;
4141
}
4242

43-
final AttestationFailureReason attestationFailureReason = context.get(Const.RoutingContextData.ATTESTATION_FAILURE_REASON_PROP);
43+
final AttestationFailure attestationFailure = context.get(Const.RoutingContextData.ATTESTATION_FAILURE_REASON_PROP);
4444
final String attestationFailureDataJson = getAttestationFailureDataJson(context);
4545

4646
final String originatingIpAddress = getOriginatingIpAddress(context);
4747

4848
LOG.warn("Attestation failed. StatusCode={} Reason={} Data={} OperatorKeyHash={} OperatorKeyName={} SiteId={} Protocol={} OperatorType={} OriginatingIpAddress={}",
4949
context.response().getStatusCode(),
50-
attestationFailureReason,
50+
attestationFailure,
5151
attestationFailureDataJson,
5252
operatorKey.getKeyHash(),
5353
operatorKey.getName(),

src/main/java/com/uid2/core/vertx/AttestationFailureReason.java

-29
This file was deleted.

src/main/java/com/uid2/core/vertx/CoreVerticle.java

+46-23
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.security.spec.X509EncodedKeySpec;
5050
import java.time.Instant;
5151
import java.util.*;
52+
5253
import com.uid2.shared.store.reader.RotatingS3KeyProvider;
5354
import com.uid2.shared.model.S3Key;
5455

@@ -78,7 +79,6 @@ public class CoreVerticle extends AbstractVerticle {
7879
private final ISaltMetadataProvider saltMetadataProvider;
7980
private final IPartnerMetadataProvider partnerMetadataProvider;
8081
private final OperatorJWTTokenProvider operatorJWTTokenProvider;
81-
private final JwtService jwtService;
8282
private final RotatingS3KeyProvider s3KeyProvider;
8383

8484
public CoreVerticle(ICloudStorage cloudStorage,
@@ -96,7 +96,6 @@ public CoreVerticle(ICloudStorage cloudStorage,
9696

9797
this.attestationService = attestationService;
9898
this.attestationTokenService = attestationTokenService;
99-
this.jwtService = jwtService;
10099
this.enclaveIdentifierProvider = enclaveIdentifierProvider;
101100
this.enclaveIdentifierProvider.addListener(this.attestationService);
102101
this.s3KeyProvider = s3KeyProvider;
@@ -108,7 +107,7 @@ public CoreVerticle(ICloudStorage cloudStorage,
108107
enforceJwt = false;
109108
}
110109

111-
this.attestationMiddleware = new AttestationMiddleware(this.attestationTokenService, this.jwtService, jwtAudience, jwtIssuer, enforceJwt);
110+
this.attestationMiddleware = new AttestationMiddleware(this.attestationTokenService, jwtService, jwtAudience, jwtIssuer, enforceJwt);
112111

113112
this.auth = new AuthMiddleware(authProvider);
114113

@@ -225,15 +224,15 @@ private void handleAttestAsync(RoutingContext rc) {
225224
try {
226225
json = rc.body().asJsonObject();
227226
} catch (DecodeException e) {
228-
setAttestationFailureReason(rc, AttestationFailureReason.REQUEST_BODY_IS_NOT_VALID_JSON);
227+
setAttestationFailureReason(rc, AttestationFailure.BAD_PAYLOAD, Collections.singletonMap("cause", AttestationFailure.BAD_PAYLOAD.explain()));
229228
Error("request body is not a valid json", 400, rc, null);
230229
return;
231230
}
232231

233232
String request = json == null ? null : json.getString("attestation_request");
234233

235234
if (request == null || request.isEmpty()) {
236-
setAttestationFailureReason(rc, AttestationFailureReason.NO_ATTESTATION_REQUEST_ATTACHED);
235+
setAttestationFailureReason(rc, AttestationFailure.BAD_PAYLOAD, Collections.singletonMap("cause", AttestationFailure.BAD_PAYLOAD.explain()));
237236
Error("no attestation_request attached", 400, rc, null);
238237
return;
239238
}
@@ -243,22 +242,44 @@ private void handleAttestAsync(RoutingContext rc) {
243242
try {
244243
attestationService.attest(protocol, request, clientPublicKey, ar -> {
245244
if (!ar.succeeded()) {
246-
setAttestationFailureReason(rc, AttestationFailureReason.ATTESTATION_FAILURE, Collections.singletonMap("cause", ar.cause().getMessage()));
245+
if (ar.cause() instanceof AttestationClientException ace && ace.IsClientError()) {
246+
setAttestationFailureReason(rc, ace.getAttestationFailure(), Collections.singletonMap("reason", ace.getAttestationFailure().explain()));
247+
logger.warn("attestation failure: ", ace);
248+
Error("attestation failure", 400, rc, ace.getAttestationFailure().explain());
249+
return;
250+
}
251+
252+
// 500 is only for unknown errors in the attestation processing
253+
setAttestationFailureReason(rc, AttestationFailure.INTERNAL_ERROR, Collections.singletonMap("cause", ar.cause().getMessage()));
247254
logger.warn("attestation failure: ", ar.cause());
248255
Error("attestation failure", 500, rc, null);
249256
return;
250257
}
251258

252259
final AttestationResult attestationResult = ar.result();
253260
if (!attestationResult.isSuccess()) {
254-
setAttestationFailureReason(rc, AttestationFailureReason.ATTESTATION_FAILURE, Collections.singletonMap("reason", attestationResult.getReason()));
255-
Error(attestationResult.getReason(), 401, rc, null);
256-
return;
261+
AttestationFailure failure = attestationResult.getFailure();
262+
switch (failure) {
263+
case AttestationFailure.BAD_FORMAT:
264+
case AttestationFailure.INVALID_PROTOCOL:
265+
case AttestationFailure.BAD_CERTIFICATE:
266+
case AttestationFailure.BAD_PAYLOAD:
267+
case AttestationFailure.UNKNOWN_ATTESTATION_URL:
268+
case AttestationFailure.FORBIDDEN_ENCLAVE:
269+
setAttestationFailureReason(rc, failure, Collections.singletonMap("reason", attestationResult.getReason()));
270+
Error(attestationResult.getReason(), 403, rc, failure.explain());
271+
return;
272+
case AttestationFailure.UNKNOWN:
273+
case AttestationFailure.INTERNAL_ERROR:
274+
setAttestationFailureReason(rc, failure, Collections.singletonMap("reason", attestationResult.getReason()));
275+
Error(attestationResult.getReason(), 500, rc, failure.explain());
276+
return;
277+
}
257278
}
258279

259280
if (json.containsKey("operator_type") && !operator.getOperatorType().name().equalsIgnoreCase(json.getString("operator_type"))) {
260-
setAttestationFailureReason(rc, AttestationFailureReason.ATTESTATION_FAILURE);
261-
Error("attestation failure; invalid operator type", 400, rc, null);
281+
setAttestationFailureReason(rc, AttestationFailure.INVALID_TYPE, Collections.singletonMap("reason", AttestationFailure.INVALID_TYPE.explain()));
282+
Error("attestation failure; invalid operator type", 403, rc, null);
262283
return;
263284
}
264285

@@ -294,16 +315,16 @@ private void handleAttestAsync(RoutingContext rc) {
294315
}
295316
}
296317
} catch (Exception e) {
297-
Error("attestation failure", 500, rc, null);
318+
Error("attestation failure", 500, rc, AttestationFailure.INTERNAL_ERROR.explain());
298319
return;
299320
}
300321

301322
logger.info("attestation successful for SiteId: {}, Operator name: {}, protocol: {}", operator.getSiteId(), operator.getName(), protocol);
302323
Success(rc, responseObj);
303324
});
304325
} catch (AttestationService.NotFound e) {
305-
setAttestationFailureReason(rc, AttestationFailureReason.INVALID_PROTOCOL);
306-
Error("protocol not found", 500, rc, null);
326+
setAttestationFailureReason(rc, AttestationFailure.INVALID_PROTOCOL, Collections.singletonMap("cause", AttestationFailure.INVALID_PROTOCOL.explain()));
327+
Error("protocol not found", 403, rc, null);
307328
}
308329
}
309330

@@ -316,7 +337,7 @@ private static String encodeAttestationToken(RoutingContext rc, AttestationResul
316337
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
317338
return Base64.getEncoder().encodeToString(cipher.doFinal(encodedAttestationToken.getBytes(StandardCharsets.UTF_8)));
318339
} catch (Exception e) {
319-
setAttestationFailureReason(rc, AttestationFailureReason.RESPONSE_ENCRYPTION_EXCEPTION, Collections.singletonMap("exception", e.getMessage()));
340+
setAttestationFailureReason(rc, AttestationFailure.RESPONSE_ENCRYPTION_ERROR, Collections.singletonMap("exception", e.getMessage()));
320341
logger.warn("attestation failure: exception while encrypting response", e);
321342
throw e;
322343
}
@@ -333,10 +354,9 @@ private Map.Entry<String, String> getJWTTokens(RoutingContext rc, IAuthorizable
333354
String optOutJwtToken = this.operatorJWTTokenProvider.getOptOutJWTToken(operator.getKeyHash(), operator.getName(), operator.getRoles(), operator.getSiteId(), enclaveId, operator.getProtocol(), clientVersion, expiresAt);
334355
String coreJwtToken = this.operatorJWTTokenProvider.getCoreJWTToken(operator.getKeyHash(), operator.getName(), operator.getRoles(), operator.getSiteId(), enclaveId, operator.getProtocol(), clientVersion, expiresAt);
335356

336-
Map.Entry<String, String> tokens = new AbstractMap.SimpleEntry<>(optOutJwtToken, coreJwtToken);
337-
return tokens;
357+
return new AbstractMap.SimpleEntry<>(optOutJwtToken, coreJwtToken);
338358
} catch (JWTTokenProvider.JwtSigningException e) {
339-
setAttestationFailureReason(rc, AttestationFailureReason.INTERNAL_ERROR, Collections.singletonMap("exception", e.getMessage()));
359+
setAttestationFailureReason(rc, AttestationFailure.INTERNAL_ERROR, Collections.singletonMap("exception", e.getMessage()));
340360
logger.error("OptOut JWT token generation failed", e);
341361
throw e;
342362
}
@@ -346,11 +366,11 @@ private Map.Entry<String, String> getJWTTokens(RoutingContext rc, IAuthorizable
346366
return null;
347367
}
348368

349-
private static void setAttestationFailureReason(RoutingContext context, AttestationFailureReason reason) {
369+
private static void setAttestationFailureReason(RoutingContext context, AttestationFailure reason) {
350370
setAttestationFailureReason(context, reason, null);
351371
}
352372

353-
private static void setAttestationFailureReason(RoutingContext context, AttestationFailureReason reason, Map<String, Object> data) {
373+
private static void setAttestationFailureReason(RoutingContext context, AttestationFailure reason, Map<String, Object> data) {
354374
context.put(com.uid2.core.Const.RoutingContextData.ATTESTATION_FAILURE_REASON_PROP, reason);
355375
context.put(com.uid2.core.Const.RoutingContextData.ATTESTATION_FAILURE_DATA_PROP, data);
356376
}
@@ -523,14 +543,13 @@ JsonObject make(String name, String failReason) {
523543
}
524544

525545
Object enclavesObj = main.getValue("enclaves");
526-
if (!(enclavesObj instanceof JsonArray)) {
546+
if (!(enclavesObj instanceof JsonArray enclaves)) {
527547
logger.info("enclave register has been called without .enclaves key");
528548
Error("error", 400, rc, ".enclaves needs to be an array");
529549
return;
530550
}
531551

532552
JsonArray res = new JsonArray();
533-
JsonArray enclaves = (JsonArray) enclavesObj;
534553
for (int i = 0; i < enclaves.size(); i++) {
535554
Result result = new Result();
536555
JsonObject item = enclaves.getJsonObject(i);
@@ -573,7 +592,11 @@ private static String getClientVersionFromHeader(RoutingContext rc, IAuthorizabl
573592
String clientVersion = "unknown client version";
574593
if (rc.request().headers().contains(Const.Http.AppVersionHeader)) {
575594
var client = VertxUtils.parseClientAppVersion(rc.request().headers().get(Const.Http.AppVersionHeader));
576-
clientVersion = profile.getContact() + "|" + client.getKey() + "|" + client.getValue();
595+
if (client != null) {
596+
clientVersion = profile.getContact() + "|" + client.getKey() + "|" + client.getValue();
597+
} else {
598+
clientVersion = profile.getContact() + "|null client key";
599+
}
577600
}
578601
return clientVersion;
579602
}

0 commit comments

Comments
 (0)