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,16 +134,7 @@ private void attestationExpirationCheck(long timerId) {
131
134
}
132
135
133
136
attest ();
134
- } catch (AttestationResponseHandlerException e ) {
135
- if (e .isAttestationFailure ()) {
136
- notifyResponseWatcher (401 , e .getMessage ());
137
- LOGGER .info ("Re-attest failed with attestation failure: " , e );
138
- } else {
139
- notifyResponseWatcher (e .getStatusCode (), e .getMessage ());
140
- LOGGER .info ("Re-attest failed with retryable failure: " , e );
141
- }
142
- } catch (IOException e ){
143
- notifyResponseWatcher (500 , e .getMessage ());
137
+ } catch (AttestationResponseHandlerException | IOException e ) {
144
138
LOGGER .info ("Re-attest failed: " , e );
145
139
} finally {
146
140
this .isAttesting .set (false );
@@ -185,35 +179,32 @@ public void attest() throws IOException, AttestationResponseHandlerException {
185
179
186
180
int statusCode = response .statusCode ();
187
181
String responseBody = response .body ();
188
- notifyResponseWatcher (statusCode , responseBody );
189
182
190
- if (statusCode == 401 || statusCode == 403 ) {
191
- LOGGER .warn ("attestation failed with UID2 Core returning statusCode={}" , statusCode );
192
- throw new AttestationResponseHandlerException (statusCode , "Attestation Failure response from Core" );
193
- }
183
+ AttestationResponseCode responseCode = this .getAttestationResponseCodeFromHttpStatus (statusCode );
184
+
185
+ notifyResponseWatcher (responseCode , responseBody );
194
186
195
- if (statusCode < 200 || statusCode >= 300 ) {
196
- LOGGER .warn ("attestation failed with UID2 Core returning statusCode={}" , statusCode );
197
- throw new AttestationResponseHandlerException (statusCode , "unexpected status code from uid core service" );
187
+ if (responseCode != AttestationResponseCode .Success ) {
188
+ throw new AttestationResponseHandlerException (responseCode , "Non-success response from Core on attest" );
198
189
}
199
190
200
191
JsonObject responseJson = (JsonObject ) Json .decodeValue (responseBody );
201
192
if (isFailed (responseJson )) {
202
- throw new AttestationResponseHandlerException (statusCode , "response did not return a successful status" );
193
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response did not return a successful status" );
203
194
}
204
195
205
196
JsonObject innerBody = responseJson .getJsonObject ("body" );
206
197
if (innerBody == null ) {
207
- throw new AttestationResponseHandlerException (statusCode , "response did not contain a body object" );
198
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response did not contain a body object" );
208
199
}
209
200
210
201
String atoken = getAttestationToken (innerBody );
211
202
if (atoken == null ) {
212
- 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" );
213
204
}
214
205
String expiresAt = getAttestationTokenExpiresAt (innerBody );
215
206
if (expiresAt == null ) {
216
- throw new AttestationResponseHandlerException (statusCode , "response json does not contain body.expiresAt" );
207
+ throw new AttestationResponseHandlerException (AttestationResponseCode . RetryableFailure , "response json does not contain body.expiresAt" );
217
208
}
218
209
219
210
atoken = new String (attestationTokenDecryptor .decrypt (Base64 .getDecoder ().decode (atoken ), keyPair .getPrivate ()), StandardCharsets .UTF_8 );
@@ -225,8 +216,8 @@ public void attest() throws IOException, AttestationResponseHandlerException {
225
216
setOptoutURLFromResponse (innerBody );
226
217
227
218
scheduleAttestationExpirationCheck ();
228
- } catch (IOException ioe ) {
229
- throw ioe ;
219
+ } catch (AttestationResponseHandlerException | IOException e ) {
220
+ throw e ;
230
221
} catch (Exception e ) {
231
222
throw new AttestationResponseHandlerException (e );
232
223
}
@@ -252,10 +243,6 @@ public String getOptOutUrl() {
252
243
return this .optOutUrl .get ();
253
244
}
254
245
255
- public String getAppVersionHeader () {
256
- return this .appVersionHeader ;
257
- }
258
-
259
246
private void setAttestationTokenExpiresAt (String expiresAt ) {
260
247
this .attestationTokenExpiresAt = Instant .parse (expiresAt );
261
248
}
@@ -309,11 +296,15 @@ private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
309
296
return gen .generateKeyPair ();
310
297
}
311
298
312
- 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
+
313
304
this .lock .lock ();
314
305
try {
315
306
if (this .responseWatcher != null )
316
- this .responseWatcher .handle (Pair .of (statusCode , responseBody ));
307
+ this .responseWatcher .handle (Pair .of (responseCode , responseBody ));
317
308
} finally {
318
309
lock .unlock ();
319
310
}
@@ -328,4 +319,16 @@ private byte[] encodeStringUnicodeAttestationEndpoint(String data) {
328
319
ByteBuffer buffer = StandardCharsets .UTF_8 .encode (data );
329
320
return Arrays .copyOf (buffer .array (), buffer .limit ());
330
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
+ }
331
334
}
0 commit comments