4949import java .security .spec .X509EncodedKeySpec ;
5050import java .time .Instant ;
5151import java .util .*;
52+
5253import com .uid2 .shared .store .reader .RotatingS3KeyProvider ;
5354import 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