7
7
import io .vertx .core .Vertx ;
8
8
import io .vertx .core .json .Json ;
9
9
import io .vertx .core .json .JsonObject ;
10
+ import lombok .Getter ;
10
11
import org .slf4j .Logger ;
11
12
import org .slf4j .LoggerFactory ;
12
13
import software .amazon .awssdk .utils .Pair ;
@@ -34,7 +35,7 @@ public class AttestationResponseHandler {
34
35
private final AtomicReference <String > attestationToken ;
35
36
private final AtomicReference <String > optOutJwt ;
36
37
private final AtomicReference <String > coreJwt ;
37
- private final Handler <Pair <Integer , String >> responseWatcher ;
38
+ private final Handler <Pair <AttestationResponseCode , String >> responseWatcher ;
38
39
private final String attestationEndpoint ;
39
40
private final byte [] encodedAttestationEndpoint ;
40
41
private final IClock clock ;
@@ -46,6 +47,7 @@ public class AttestationResponseHandler {
46
47
private Instant attestationTokenExpiresAt = Instant .MAX ;
47
48
private final Lock lock ;
48
49
private final AttestationTokenDecryptor attestationTokenDecryptor ;
50
+ @ Getter
49
51
private final String appVersionHeader ;
50
52
private final int attestCheckMilliseconds ;
51
53
private final AtomicReference <String > optOutUrl ;
@@ -56,17 +58,18 @@ public AttestationResponseHandler(Vertx vertx,
56
58
String operatorType ,
57
59
ApplicationVersion appVersion ,
58
60
IAttestationProvider attestationProvider ,
59
- Handler <Pair <Integer , String >> responseWatcher ,
61
+ Handler <Pair <AttestationResponseCode , String >> responseWatcher ,
60
62
Proxy proxy ) {
61
63
this (vertx , attestationEndpoint , clientApiToken , operatorType , appVersion , attestationProvider , responseWatcher , proxy , new InstantClock (), null , null , 60000 );
62
64
}
65
+
63
66
public AttestationResponseHandler (Vertx vertx ,
64
67
String attestationEndpoint ,
65
68
String clientApiToken ,
66
69
String operatorType ,
67
70
ApplicationVersion appVersion ,
68
71
IAttestationProvider attestationProvider ,
69
- Handler <Pair <Integer , String >> responseWatcher ,
72
+ Handler <Pair <AttestationResponseCode , String >> responseWatcher ,
70
73
Proxy proxy ,
71
74
IClock clock ,
72
75
URLConnectionHttpClient httpClient ,
@@ -131,11 +134,7 @@ private void attestationExpirationCheck(long timerId) {
131
134
}
132
135
133
136
attest ();
134
- } catch (AttestationResponseHandlerException e ) {
135
- notifyResponseWatcher (401 , e .getMessage ());
136
- LOGGER .info ("Re-attest failed: " , e );
137
- } catch (IOException e ){
138
- notifyResponseWatcher (500 , e .getMessage ());
137
+ } catch (AttestationResponseHandlerException | IOException e ) {
139
138
LOGGER .info ("Re-attest failed: " , e );
140
139
} finally {
141
140
this .isAttesting .set (false );
@@ -180,30 +179,32 @@ public void attest() throws IOException, AttestationResponseHandlerException {
180
179
181
180
int statusCode = response .statusCode ();
182
181
String responseBody = response .body ();
183
- notifyResponseWatcher (statusCode , responseBody );
184
182
185
- if (statusCode < 200 || statusCode >= 300 ) {
186
- LOGGER .warn ("attestation failed with UID2 Core returning statusCode={}" , statusCode );
187
- throw new AttestationResponseHandlerException (statusCode , "unexpected status code from uid core service" );
183
+ AttestationResponseCode responseCode = this .getAttestationResponseCodeFromHttpStatus (statusCode );
184
+
185
+ notifyResponseWatcher (responseCode , responseBody );
186
+
187
+ if (responseCode != AttestationResponseCode .Success ) {
188
+ throw new AttestationResponseHandlerException (responseCode , "Non-success response from Core on attest" );
188
189
}
189
190
190
191
JsonObject responseJson = (JsonObject ) Json .decodeValue (responseBody );
191
192
if (isFailed (responseJson )) {
192
- throw new AttestationResponseHandlerException (statusCode , "response did not return a successful status" );
193
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response did not return a successful status" );
193
194
}
194
195
195
196
JsonObject innerBody = responseJson .getJsonObject ("body" );
196
197
if (innerBody == null ) {
197
- throw new AttestationResponseHandlerException (statusCode , "response did not contain a body object" );
198
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response did not contain a body object" );
198
199
}
199
200
200
201
String atoken = getAttestationToken (innerBody );
201
202
if (atoken == null ) {
202
- throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.attestation_token" );
203
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response json does not contain body.attestation_token" );
203
204
}
204
205
String expiresAt = getAttestationTokenExpiresAt (innerBody );
205
206
if (expiresAt == null ) {
206
- throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.expiresAt" );
207
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response json does not contain body.expiresAt" );
207
208
}
208
209
209
210
atoken = new String (attestationTokenDecryptor .decrypt (Base64 .getDecoder ().decode (atoken ), keyPair .getPrivate ()), StandardCharsets .UTF_8 );
@@ -215,8 +216,8 @@ public void attest() throws IOException, AttestationResponseHandlerException {
215
216
setOptoutURLFromResponse (innerBody );
216
217
217
218
scheduleAttestationExpirationCheck ();
218
- } catch (IOException ioe ) {
219
- throw ioe ;
219
+ } catch (AttestationResponseHandlerException | IOException e ) {
220
+ throw e ;
220
221
} catch (Exception e ) {
221
222
throw new AttestationResponseHandlerException (e );
222
223
}
@@ -242,10 +243,6 @@ public String getOptOutUrl() {
242
243
return this .optOutUrl .get ();
243
244
}
244
245
245
- public String getAppVersionHeader () {
246
- return this .appVersionHeader ;
247
- }
248
-
249
246
private void setAttestationTokenExpiresAt (String expiresAt ) {
250
247
this .attestationTokenExpiresAt = Instant .parse (expiresAt );
251
248
}
@@ -299,11 +296,15 @@ private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
299
296
return gen .generateKeyPair ();
300
297
}
301
298
302
- private void notifyResponseWatcher (int statusCode , String responseBody ) {
299
+ private void notifyResponseWatcher (AttestationResponseCode responseCode , String responseBody ) {
300
+ if (responseCode != AttestationResponseCode .Success ) {
301
+ LOGGER .warn ("Received a non-success response code on Attestation: ResponseCode: {}, Message: {}" , responseCode , responseBody );
302
+ }
303
+
303
304
this .lock .lock ();
304
305
try {
305
306
if (this .responseWatcher != null )
306
- this .responseWatcher .handle (Pair .of (statusCode , responseBody ));
307
+ this .responseWatcher .handle (Pair .of (responseCode , responseBody ));
307
308
} finally {
308
309
lock .unlock ();
309
310
}
@@ -318,4 +319,16 @@ private byte[] encodeStringUnicodeAttestationEndpoint(String data) {
318
319
ByteBuffer buffer = StandardCharsets .UTF_8 .encode (data );
319
320
return Arrays .copyOf (buffer .array (), buffer .limit ());
320
321
}
322
+
323
+ private AttestationResponseCode getAttestationResponseCodeFromHttpStatus (int httpStatus ) {
324
+ if (httpStatus == 401 || httpStatus == 403 ) {
325
+ return AttestationResponseCode .AttestationFailure ;
326
+ }
327
+
328
+ if (httpStatus == 200 ) {
329
+ return AttestationResponseCode .Success ;
330
+ }
331
+
332
+ return AttestationResponseCode .RetryableFailure ;
333
+ }
321
334
}
0 commit comments