1414import com .uid2 .shared .secure .AttestationFailure ;
1515import com .uid2 .shared .secure .AttestationResult ;
1616import com .uid2 .shared .secure .ICoreAttestationService ;
17+ import com .uid2 .shared .store .reader .RotatingS3KeyProvider ;
1718import io .vertx .core .*;
1819import io .vertx .core .buffer .Buffer ;
20+ import io .vertx .core .json .JsonArray ;
1921import io .vertx .core .json .JsonObject ;
2022import io .vertx .ext .web .client .HttpResponse ;
2123import io .vertx .ext .web .client .WebClient ;
2527import static org .junit .jupiter .api .Assertions .*;
2628
2729import org .junit .jupiter .api .BeforeEach ;
30+ import org .junit .jupiter .api .Tag ;
2831import org .junit .jupiter .api .Test ;
32+ import org .junit .jupiter .api .TestInfo ;
2933import org .junit .jupiter .api .extension .ExtendWith ;
3034import org .mockito .Mock ;
3135import org .mockito .MockitoAnnotations ;
3842import java .util .*;
3943import java .util .concurrent .Callable ;
4044
45+ import com .uid2 .shared .model .S3Key ;
46+ import java .util .Arrays ;
47+
4148import static org .mockito .Mockito .*;
4249
4350@ ExtendWith (VertxExtension .class )
@@ -56,23 +63,31 @@ public class TestCoreVerticle {
5663 private OperatorJWTTokenProvider operatorJWTTokenProvider ;
5764 @ Mock
5865 private JwtService jwtService ;
66+ @ Mock
67+ private RotatingS3KeyProvider s3KeyProvider ;
5968
6069 private AttestationService attestationService ;
6170
6271 private static final String attestationProtocol = "test-attestation-protocol" ;
72+ private static final String attestationProtocolPublic = "trusted" ;
6373
6474 @ BeforeEach
65- void deployVerticle (Vertx vertx , VertxTestContext testContext ) throws Throwable {
75+ void deployVerticle (TestInfo info , Vertx vertx , VertxTestContext testContext ) throws Throwable {
6676 JsonObject config = new JsonObject ();
6777 config .put (Const .Config .OptOutUrlProp , "test_optout_url" );
6878 config .put (Const .Config .CorePublicUrlProp , "test_core_url" );
6979 config .put (Const .Config .AwsKmsJwtSigningKeyIdProp , "test_aws_kms_keyId" );
70- config .put (Const .Config .EnforceJwtProp , true );
80+ if (info .getTags ().contains ("dontForceJwt" )) {
81+ config .put (Const .Config .EnforceJwtProp , false );
82+ } else {
83+ config .put (Const .Config .EnforceJwtProp , true );
84+ }
7185 ConfigStore .Global .load (config );
7286
7387 attestationService = new AttestationService ();
7488 MockitoAnnotations .initMocks (this );
75- CoreVerticle verticle = new CoreVerticle (cloudStorage , authProvider , attestationService , attestationTokenService , enclaveIdentifierProvider , operatorJWTTokenProvider , jwtService );
89+
90+ CoreVerticle verticle = new CoreVerticle (cloudStorage , authProvider , attestationService , attestationTokenService , enclaveIdentifierProvider , operatorJWTTokenProvider , jwtService , s3KeyProvider );
7691 vertx .deployVerticle (verticle , testContext .succeeding (id -> testContext .completeNow ()));
7792 }
7893
@@ -81,6 +96,10 @@ private String getUrlForEndpoint(String endpoint) {
8196 }
8297
8398 private void fakeAuth (Role ... roles ) {
99+ this .fakeAuth (attestationProtocol , roles );
100+ }
101+
102+ private void fakeAuth (String attestationProtocol , Role ... roles ) {
84103 OperatorKey operatorKey = new OperatorKey ("test-key-hash" , "test-key-salt" , "test-name" , "test-contact" , attestationProtocol , 0 , false , 88 , new HashSet <>(Arrays .asList (roles )), OperatorType .PRIVATE , "test-key-id" );
85104 when (authProvider .get (any ())).thenReturn (operatorKey );
86105 }
@@ -108,6 +127,11 @@ private void get(Vertx vertx, String endpoint, MultiMap form, Handler<AsyncResul
108127 client .getAbs (getUrlForEndpoint (endpoint )).putHeader ("content-type" , "multipart/form-data" ).sendForm (form , handler );
109128 }
110129
130+ private void get (Vertx vertx , String endpoint , Handler <AsyncResult <HttpResponse <Buffer >>> handler ) {
131+ WebClient client = WebClient .create (vertx );
132+ client .getAbs (getUrlForEndpoint (endpoint )).send (handler );
133+ }
134+
111135 private void addAttestationProvider (String protocol ) {
112136 attestationService .with (protocol , attestationProvider );
113137 }
@@ -450,4 +474,146 @@ void wrongMethodForEndpoint(Vertx vertx, VertxTestContext testContext) {
450474 testContext .completeNow ();
451475 });
452476 }
477+
478+ @ Test
479+ void wrongMethodForEndpointS3 (Vertx vertx , VertxTestContext testContext ) {
480+ post (vertx , "/s3encryption_keys/retrieve" , makeAttestationRequestJson (null , null ), ar -> {
481+ HttpResponse response = ar .result ();
482+ assertEquals (405 , response .statusCode ());
483+ assertEquals ("Method Not Allowed" , response .statusMessage ());
484+ testContext .completeNow ();
485+ });
486+ }
487+
488+ @ Tag ("dontForceJwt" )
489+ @ Test
490+ void s3encryptionKeyRetrieveSuccess (Vertx vertx , VertxTestContext testContext ) {
491+ fakeAuth (attestationProtocolPublic , Role .OPERATOR );
492+ addAttestationProvider (attestationProtocolPublic );
493+ onHandleAttestationRequest (() -> {
494+ byte [] resultPublicKey = null ;
495+ return Future .succeededFuture (new AttestationResult (resultPublicKey , "test" ));
496+ });
497+
498+ S3Key key = new S3Key (1 , 88 , 1687635529 , 1687808329 , "newSecret" );
499+
500+ List <S3Key > keys = Arrays .asList (key );
501+ when (s3KeyProvider .getKeys (88 )).thenReturn (keys );
502+
503+ get (vertx , "s3encryption_keys/retrieve" , ar -> {
504+ if (ar .succeeded ()) {
505+ HttpResponse <Buffer > response = ar .result ();
506+ assertEquals (200 , response .statusCode ());
507+
508+ JsonObject json = response .bodyAsJsonObject ();
509+ JsonArray s3KeysArray = json .getJsonArray ("s3Keys" );
510+
511+ assertNotNull (s3KeysArray );
512+ assertEquals (1 , s3KeysArray .size ());
513+
514+ JsonObject s3KeyJson = s3KeysArray .getJsonObject (0 );
515+ assertEquals (1 , s3KeyJson .getInteger ("id" ));
516+ assertEquals (88 , s3KeyJson .getInteger ("siteId" ));
517+ assertEquals (1687635529 , s3KeyJson .getLong ("activates" ));
518+ assertEquals (1687808329 , s3KeyJson .getLong ("created" ));
519+ assertEquals ("newSecret" , s3KeyJson .getString ("secret" ));
520+
521+ testContext .completeNow ();
522+ } else {
523+ testContext .failNow (ar .cause ());
524+ }
525+ });
526+ }
527+
528+
529+ @ Tag ("dontForceJwt" )
530+ @ Test
531+ void s3encryptionKeyRetrieveSuccessWithThreeKeys (Vertx vertx , VertxTestContext testContext ) {
532+ fakeAuth (attestationProtocolPublic , Role .OPERATOR );
533+ addAttestationProvider (attestationProtocolPublic );
534+ onHandleAttestationRequest (() -> {
535+ byte [] resultPublicKey = null ;
536+ return Future .succeededFuture (new AttestationResult (resultPublicKey , "test" ));
537+ });
538+
539+ // Create 3 S3Key objects
540+ S3Key key1 = new S3Key (1 , 88 , 1687635529 , 1687808329 , "secret1" );
541+ S3Key key2 = new S3Key (2 , 88 , 1687635530 , 1687808330 , "secret2" );
542+ S3Key key3 = new S3Key (3 , 88 , 1687635531 , 1687808331 , "secret3" );
543+
544+ List <S3Key > keys = Arrays .asList (key1 , key2 , key3 );
545+ when (s3KeyProvider .getKeys (88 )).thenReturn (keys );
546+
547+ get (vertx , "s3encryption_keys/retrieve" , ar -> {
548+ if (ar .succeeded ()) {
549+ HttpResponse <Buffer > response = ar .result ();
550+ assertEquals (200 , response .statusCode ());
551+
552+ JsonObject json = response .bodyAsJsonObject ();
553+ JsonArray s3KeysArray = json .getJsonArray ("s3Keys" );
554+
555+ assertNotNull (s3KeysArray );
556+ assertEquals (3 , s3KeysArray .size ());
557+
558+ for (int i = 0 ; i < 3 ; i ++) {
559+ JsonObject s3KeyJson = s3KeysArray .getJsonObject (i );
560+ assertEquals (i + 1 , s3KeyJson .getInteger ("id" ));
561+ assertEquals (88 , s3KeyJson .getInteger ("siteId" ));
562+ assertEquals (1687635529 + i , s3KeyJson .getLong ("activates" ));
563+ assertEquals (1687808329 + i , s3KeyJson .getLong ("created" ));
564+ assertEquals ("secret" + (i + 1 ), s3KeyJson .getString ("secret" ));
565+ }
566+
567+ testContext .completeNow ();
568+ } else {
569+ testContext .failNow (ar .cause ());
570+ }
571+ });
572+ }
573+
574+ @ Tag ("dontForceJwt" )
575+ @ Test
576+ void s3encryptionKeyRetrieveNoKeysOrError (Vertx vertx , VertxTestContext testContext ) {
577+ fakeAuth (attestationProtocolPublic , Role .OPERATOR );
578+ addAttestationProvider (attestationProtocolPublic );
579+ onHandleAttestationRequest (() -> {
580+ byte [] resultPublicKey = null ;
581+ return Future .succeededFuture (new AttestationResult (resultPublicKey , "test" ));
582+ });
583+
584+ // Test case 1: No keys found
585+ when (s3KeyProvider .getKeys (anyInt ())).thenReturn (Collections .emptyList ());
586+
587+ get (vertx , "s3encryption_keys/retrieve" , ar -> {
588+ if (ar .succeeded ()) {
589+ HttpResponse <Buffer > response = ar .result ();
590+ assertEquals (500 , response .statusCode ());
591+
592+ JsonObject json = response .bodyAsJsonObject ();
593+ assertEquals ("No S3 keys found" , json .getString ("status" ));
594+ assertTrue (json .getString ("message" ).contains ("No S3 keys found for siteId:" ));
595+
596+ // Test case 2: Exception thrown
597+ when (s3KeyProvider .getKeys (anyInt ())).thenThrow (new RuntimeException ("Test exception" ));
598+
599+ get (vertx , "s3encryption_keys/retrieve" , ar2 -> {
600+ if (ar2 .succeeded ()) {
601+ HttpResponse <Buffer > response2 = ar2 .result ();
602+ assertEquals (500 , response2 .statusCode ());
603+
604+ JsonObject json2 = response2 .bodyAsJsonObject ();
605+ System .out .println (json2 );
606+ assertEquals ("error" , json2 .getString ("status" ));
607+ assertEquals ("error generating attestation token" , json2 .getString ("message" ));
608+
609+ testContext .completeNow ();
610+ } else {
611+ testContext .failNow (ar2 .cause ());
612+ }
613+ });
614+ } else {
615+ testContext .failNow (ar .cause ());
616+ }
617+ });
618+ }
453619}
0 commit comments