@@ -302,6 +302,176 @@ public void multipleS3Credentials() {
302302 }
303303 }
304304
305+ @ Test
306+ public void nonExpiredTokenInProperties () {
307+ HttpRequest mockRequest = request ("/v1/credentials" ).withMethod (HttpMethod .GET .name ());
308+ String expiresAt = Long .toString (Instant .now ().plus (10 , ChronoUnit .HOURS ).toEpochMilli ());
309+ Credential credentialFromProperties =
310+ ImmutableCredential .builder ()
311+ .prefix ("s3" )
312+ .config (
313+ ImmutableMap .of (
314+ S3FileIOProperties .ACCESS_KEY_ID ,
315+ "randomAccessKeyFromProperties" ,
316+ S3FileIOProperties .SECRET_ACCESS_KEY ,
317+ "randomSecretAccessKeyFromProperties" ,
318+ S3FileIOProperties .SESSION_TOKEN ,
319+ "sessionTokenFromProperties" ,
320+ S3FileIOProperties .SESSION_TOKEN_EXPIRES_AT_MS ,
321+ expiresAt ))
322+ .build ();
323+
324+ Credential credential =
325+ ImmutableCredential .builder ()
326+ .prefix ("s3" )
327+ .config (
328+ ImmutableMap .of (
329+ S3FileIOProperties .ACCESS_KEY_ID ,
330+ "randomAccessKey" ,
331+ S3FileIOProperties .SECRET_ACCESS_KEY ,
332+ "randomSecretAccessKey" ,
333+ S3FileIOProperties .SESSION_TOKEN ,
334+ "sessionToken" ,
335+ S3FileIOProperties .SESSION_TOKEN_EXPIRES_AT_MS ,
336+ Long .toString (Instant .now ().plus (1 , ChronoUnit .HOURS ).toEpochMilli ())))
337+ .build ();
338+ LoadCredentialsResponse response =
339+ ImmutableLoadCredentialsResponse .builder ().addCredentials (credential ).build ();
340+
341+ HttpResponse mockResponse =
342+ response (LoadCredentialsResponseParser .toJson (response )).withStatusCode (200 );
343+ mockServer .when (mockRequest ).respond (mockResponse );
344+
345+ try (VendedCredentialsProvider provider =
346+ VendedCredentialsProvider .create (
347+ ImmutableMap .of (
348+ VendedCredentialsProvider .URI ,
349+ URI ,
350+ S3FileIOProperties .ACCESS_KEY_ID ,
351+ "randomAccessKeyFromProperties" ,
352+ S3FileIOProperties .SECRET_ACCESS_KEY ,
353+ "randomSecretAccessKeyFromProperties" ,
354+ S3FileIOProperties .SESSION_TOKEN ,
355+ "sessionTokenFromProperties" ,
356+ S3FileIOProperties .SESSION_TOKEN_EXPIRES_AT_MS ,
357+ expiresAt ))) {
358+ AwsCredentials awsCredentials = provider .resolveCredentials ();
359+
360+ verifyCredentials (awsCredentials , credentialFromProperties );
361+
362+ for (int i = 0 ; i < 5 ; i ++) {
363+ // resolving credentials multiple times should not hit the credentials endpoint again
364+ assertThat (provider .resolveCredentials ()).isSameAs (awsCredentials );
365+ }
366+ }
367+
368+ // token endpoint isn't hit, because the credentials are extracted from the properties
369+ mockServer .verify (mockRequest , VerificationTimes .never ());
370+ }
371+
372+ @ Test
373+ public void expiredTokenInProperties () {
374+ HttpRequest mockRequest = request ("/v1/credentials" ).withMethod (HttpMethod .GET .name ());
375+
376+ Credential credential =
377+ ImmutableCredential .builder ()
378+ .prefix ("s3" )
379+ .config (
380+ ImmutableMap .of (
381+ S3FileIOProperties .ACCESS_KEY_ID ,
382+ "randomAccessKey" ,
383+ S3FileIOProperties .SECRET_ACCESS_KEY ,
384+ "randomSecretAccessKey" ,
385+ S3FileIOProperties .SESSION_TOKEN ,
386+ "sessionToken" ,
387+ S3FileIOProperties .SESSION_TOKEN_EXPIRES_AT_MS ,
388+ Long .toString (Instant .now ().plus (1 , ChronoUnit .HOURS ).toEpochMilli ())))
389+ .build ();
390+ LoadCredentialsResponse response =
391+ ImmutableLoadCredentialsResponse .builder ().addCredentials (credential ).build ();
392+
393+ HttpResponse mockResponse =
394+ response (LoadCredentialsResponseParser .toJson (response )).withStatusCode (200 );
395+ mockServer .when (mockRequest ).respond (mockResponse );
396+
397+ try (VendedCredentialsProvider provider =
398+ VendedCredentialsProvider .create (
399+ ImmutableMap .of (
400+ VendedCredentialsProvider .URI ,
401+ URI ,
402+ S3FileIOProperties .ACCESS_KEY_ID ,
403+ "randomAccessKeyFromProperties" ,
404+ S3FileIOProperties .SECRET_ACCESS_KEY ,
405+ "randomSecretAccessKeyFromProperties" ,
406+ S3FileIOProperties .SESSION_TOKEN ,
407+ "sessionTokenFromProperties" ,
408+ S3FileIOProperties .SESSION_TOKEN_EXPIRES_AT_MS ,
409+ Long .toString (Instant .now ().minus (1 , ChronoUnit .HOURS ).toEpochMilli ())))) {
410+ AwsCredentials awsCredentials = provider .resolveCredentials ();
411+
412+ verifyCredentials (awsCredentials , credential );
413+
414+ for (int i = 0 ; i < 5 ; i ++) {
415+ // resolving credentials multiple times should not hit the credentials endpoint again
416+ assertThat (provider .resolveCredentials ()).isSameAs (awsCredentials );
417+ }
418+ }
419+
420+ // token endpoint is hit once due to the properties containing an expired token
421+ mockServer .verify (mockRequest , VerificationTimes .once ());
422+ }
423+
424+ @ Test
425+ public void invalidTokenInProperties () {
426+ HttpRequest mockRequest = request ("/v1/credentials" ).withMethod (HttpMethod .GET .name ());
427+
428+ Credential credential =
429+ ImmutableCredential .builder ()
430+ .prefix ("s3" )
431+ .config (
432+ ImmutableMap .of (
433+ S3FileIOProperties .ACCESS_KEY_ID ,
434+ "randomAccessKey" ,
435+ S3FileIOProperties .SECRET_ACCESS_KEY ,
436+ "randomSecretAccessKey" ,
437+ S3FileIOProperties .SESSION_TOKEN ,
438+ "sessionToken" ,
439+ S3FileIOProperties .SESSION_TOKEN_EXPIRES_AT_MS ,
440+ Long .toString (Instant .now ().plus (1 , ChronoUnit .HOURS ).toEpochMilli ())))
441+ .build ();
442+ LoadCredentialsResponse response =
443+ ImmutableLoadCredentialsResponse .builder ().addCredentials (credential ).build ();
444+
445+ HttpResponse mockResponse =
446+ response (LoadCredentialsResponseParser .toJson (response )).withStatusCode (200 );
447+ mockServer .when (mockRequest ).respond (mockResponse );
448+
449+ // token expiration is missing from the properties
450+ try (VendedCredentialsProvider provider =
451+ VendedCredentialsProvider .create (
452+ ImmutableMap .of (
453+ VendedCredentialsProvider .URI ,
454+ URI ,
455+ S3FileIOProperties .ACCESS_KEY_ID ,
456+ "randomAccessKeyFromProperties" ,
457+ S3FileIOProperties .SECRET_ACCESS_KEY ,
458+ "randomSecretAccessKeyFromProperties" ,
459+ S3FileIOProperties .SESSION_TOKEN ,
460+ "sessionTokenFromProperties" ))) {
461+ AwsCredentials awsCredentials = provider .resolveCredentials ();
462+
463+ verifyCredentials (awsCredentials , credential );
464+
465+ for (int i = 0 ; i < 5 ; i ++) {
466+ // resolving credentials multiple times should not hit the credentials endpoint again
467+ assertThat (provider .resolveCredentials ()).isSameAs (awsCredentials );
468+ }
469+ }
470+
471+ // token endpoint is hit once due to the properties not containing the token's expiration
472+ mockServer .verify (mockRequest , VerificationTimes .once ());
473+ }
474+
305475 private void verifyCredentials (AwsCredentials awsCredentials , Credential credential ) {
306476 assertThat (awsCredentials ).isInstanceOf (AwsSessionCredentials .class );
307477 AwsSessionCredentials creds = (AwsSessionCredentials ) awsCredentials ;
0 commit comments