4
4
package com .microsoft .aad .msal4j ;
5
5
6
6
import com .nimbusds .oauth2 .sdk .util .URLUtils ;
7
- import org .apache .http .HttpStatus ;
8
- import org .junit .jupiter .api .BeforeAll ;
9
- import org .junit .jupiter .api .BeforeEach ;
7
+ import org .junit .jupiter .api .Nested ;
10
8
import org .junit .jupiter .api .Test ;
11
9
import org .junit .jupiter .api .TestInstance ;
12
10
import org .junit .jupiter .api .extension .ExtendWith ;
13
11
import org .junit .jupiter .params .ParameterizedTest ;
14
12
import org .junit .jupiter .params .provider .MethodSource ;
13
+ import org .junit .jupiter .params .provider .ValueSource ;
15
14
import org .mockito .junit .jupiter .MockitoExtension ;
16
15
17
16
import java .net .SocketException ;
18
- import java .net .URISyntaxException ;
19
17
import java .nio .file .Path ;
20
18
import java .nio .file .Paths ;
21
- import java .time .Instant ;
22
- import java .time .temporal .ChronoUnit ;
23
- import java .util .Collections ;
24
19
import java .util .HashMap ;
25
20
import java .util .List ;
26
21
import java .util .Map ;
27
22
import java .util .concurrent .CompletableFuture ;
28
23
import java .util .concurrent .ExecutionException ;
29
24
25
+ import static com .microsoft .aad .msal4j .ManagedIdentitySourceType .*;
26
+ import static com .microsoft .aad .msal4j .MsalError .*;
27
+ import static com .microsoft .aad .msal4j .MsalErrorMessage .*;
28
+ import static java .util .Collections .*;
29
+ import static org .apache .http .HttpStatus .*;
30
30
import static org .junit .jupiter .api .Assertions .*;
31
31
import static org .mockito .Mockito .*;
32
32
@@ -77,8 +77,8 @@ private HttpRequest expectedRequest(ManagedIdentitySourceType source, String res
77
77
case APP_SERVICE : {
78
78
endpoint = appServiceEndpoint ;
79
79
80
- queryParameters .put ("api-version" , Collections . singletonList ("2019-08-01" ));
81
- queryParameters .put ("resource" , Collections . singletonList (resource ));
80
+ queryParameters .put ("api-version" , singletonList ("2019-08-01" ));
81
+ queryParameters .put ("resource" , singletonList (resource ));
82
82
83
83
headers .put ("X-IDENTITY-HEADER" , "secret" );
84
84
break ;
@@ -89,43 +89,43 @@ private HttpRequest expectedRequest(ManagedIdentitySourceType source, String res
89
89
headers .put ("ContentType" , "application/x-www-form-urlencoded" );
90
90
headers .put ("Metadata" , "true" );
91
91
92
- bodyParameters .put ("resource" , Collections . singletonList (resource ));
92
+ bodyParameters .put ("resource" , singletonList (resource ));
93
93
94
- queryParameters .put ("resource" , Collections . singletonList (resource ));
94
+ queryParameters .put ("resource" , singletonList (resource ));
95
95
return new HttpRequest (HttpMethod .GET , computeUri (endpoint , queryParameters ), headers , URLUtils .serializeParameters (bodyParameters ));
96
96
}
97
97
case IMDS : {
98
98
endpoint = IMDS_ENDPOINT ;
99
- queryParameters .put ("api-version" , Collections . singletonList ("2018-02-01" ));
100
- queryParameters .put ("resource" , Collections . singletonList (resource ));
99
+ queryParameters .put ("api-version" , singletonList ("2018-02-01" ));
100
+ queryParameters .put ("resource" , singletonList (resource ));
101
101
headers .put ("Metadata" , "true" );
102
102
break ;
103
103
}
104
104
case AZURE_ARC : {
105
105
endpoint = azureArcEndpoint ;
106
106
107
- queryParameters .put ("api-version" , Collections . singletonList ("2019-11-01" ));
108
- queryParameters .put ("resource" , Collections . singletonList (resource ));
107
+ queryParameters .put ("api-version" , singletonList ("2019-11-01" ));
108
+ queryParameters .put ("resource" , singletonList (resource ));
109
109
110
110
headers .put ("Metadata" , "true" );
111
111
break ;
112
112
}
113
113
case SERVICE_FABRIC :
114
114
endpoint = serviceFabricEndpoint ;
115
- queryParameters .put ("api-version" , Collections . singletonList ("2019-07-01-preview" ));
116
- queryParameters .put ("resource" , Collections . singletonList (resource ));
115
+ queryParameters .put ("api-version" , singletonList ("2019-07-01-preview" ));
116
+ queryParameters .put ("resource" , singletonList (resource ));
117
117
break ;
118
118
}
119
119
120
120
switch (id .getIdType ()) {
121
121
case CLIENT_ID :
122
- queryParameters .put ("client_id" , Collections . singletonList (id .getUserAssignedId ()));
122
+ queryParameters .put ("client_id" , singletonList (id .getUserAssignedId ()));
123
123
break ;
124
124
case RESOURCE_ID :
125
- queryParameters .put ("mi_res_id" , Collections . singletonList (id .getUserAssignedId ()));
125
+ queryParameters .put ("mi_res_id" , singletonList (id .getUserAssignedId ()));
126
126
break ;
127
127
case OBJECT_ID :
128
- queryParameters .put ("object_id" , Collections . singletonList (id .getUserAssignedId ()));
128
+ queryParameters .put ("object_id" , singletonList (id .getUserAssignedId ()));
129
129
break ;
130
130
}
131
131
@@ -511,43 +511,6 @@ void managedIdentity_RequestFailed_UnreachableNetwork(ManagedIdentitySourceType
511
511
verify (httpClientMock , times (1 )).send (any ());
512
512
}
513
513
514
- @ Test
515
- void azureArcManagedIdentity_MissingAuthHeader () throws Exception {
516
- IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper (ManagedIdentitySourceType .AZURE_ARC , azureArcEndpoint );
517
- ManagedIdentityApplication .setEnvironmentVariables (environmentVariables );
518
- DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
519
-
520
- HttpResponse response = new HttpResponse ();
521
- response .statusCode (HttpStatus .SC_UNAUTHORIZED );
522
-
523
- when (httpClientMock .send (any ())).thenReturn (response );
524
-
525
- miApp = ManagedIdentityApplication
526
- .builder (ManagedIdentityId .systemAssigned ())
527
- .httpClient (httpClientMock )
528
- .build ();
529
-
530
- // Clear caching to avoid cross test pollution.
531
- miApp .tokenCache ().accessTokens .clear ();
532
-
533
- try {
534
- miApp .acquireTokenForManagedIdentity (
535
- ManagedIdentityParameters .builder (resource )
536
- .build ()).get ();
537
- } catch (Exception exception ) {
538
- assert (exception .getCause () instanceof MsalServiceException );
539
-
540
- MsalServiceException miException = (MsalServiceException ) exception .getCause ();
541
- assertEquals (ManagedIdentitySourceType .AZURE_ARC .name (), miException .managedIdentitySource ());
542
- assertEquals (MsalError .MANAGED_IDENTITY_REQUEST_FAILED , miException .errorCode ());
543
- assertEquals (MsalErrorMessage .MANAGED_IDENTITY_NO_CHALLENGE_ERROR , miException .getMessage ());
544
- return ;
545
- }
546
-
547
- fail ("MsalServiceException is expected but not thrown." );
548
- verify (httpClientMock , times (1 )).send (any ());
549
- }
550
-
551
514
@ ParameterizedTest
552
515
@ MethodSource ("com.microsoft.aad.msal4j.ManagedIdentityTestDataProvider#createDataError" )
553
516
void managedIdentity_SharedCache (ManagedIdentitySourceType source , String endpoint ) throws Exception {
@@ -589,81 +552,85 @@ void managedIdentity_SharedCache(ManagedIdentitySourceType source, String endpoi
589
552
verify (httpClientMock , times (1 )).send (any ());
590
553
}
591
554
592
- @ Test
593
- void azureArcManagedIdentity_InvalidAuthHeader () throws Exception {
594
- IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper (ManagedIdentitySourceType .AZURE_ARC , azureArcEndpoint );
595
- ManagedIdentityApplication .setEnvironmentVariables (environmentVariables );
596
- DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
597
-
598
- HttpResponse response = new HttpResponse ();
599
- response .statusCode (HttpStatus .SC_UNAUTHORIZED );
600
- response .headers ().put ("WWW-Authenticate" , Collections .singletonList ("xyz" ));
555
+ @ Nested
556
+ class AzureArc {
601
557
602
- when (httpClientMock .send (any ())).thenReturn (response );
558
+ @ Test
559
+ void missingAuthHeader () throws Exception {
560
+ mockHttpResponse (emptyMap ());
603
561
604
- miApp = ManagedIdentityApplication
605
- .builder (ManagedIdentityId .systemAssigned ())
606
- .httpClient (httpClientMock )
607
- .build ();
608
-
609
- // Clear caching to avoid cross test pollution.
610
- miApp .tokenCache ().accessTokens .clear ();
562
+ assertMsalServiceException (MANAGED_IDENTITY_REQUEST_FAILED , MANAGED_IDENTITY_NO_CHALLENGE_ERROR );
563
+ }
611
564
612
- try {
613
- miApp .acquireTokenForManagedIdentity (
614
- ManagedIdentityParameters .builder (resource )
615
- .build ()).get ();
616
- } catch (Exception exception ) {
617
- assert (exception .getCause () instanceof MsalServiceException );
565
+ @ ParameterizedTest
566
+ @ ValueSource (strings = {"WWW-Authenticate" , "Www-Authenticate" })
567
+ void invalidAuthHeader (String authHeaderKey ) throws Exception {
568
+ mockHttpResponse (singletonMap (authHeaderKey , singletonList ("xyz" )));
618
569
619
- MsalServiceException miException = (MsalServiceException ) exception .getCause ();
620
- assertEquals (ManagedIdentitySourceType .AZURE_ARC .name (), miException .managedIdentitySource ());
621
- assertEquals (MsalError .MANAGED_IDENTITY_REQUEST_FAILED , miException .errorCode ());
622
- assertEquals (MsalErrorMessage .MANAGED_IDENTITY_INVALID_CHALLENGE , miException .getMessage ());
623
- return ;
570
+ assertMsalServiceException (MANAGED_IDENTITY_REQUEST_FAILED ,
571
+ MANAGED_IDENTITY_INVALID_CHALLENGE );
624
572
}
625
573
626
- fail ("MsalServiceException is expected but not thrown." );
627
- verify (httpClientMock , times (1 )).send (any ());
628
- }
574
+ @ ParameterizedTest
575
+ @ ValueSource (strings = {"WWW-Authenticate" , "Www-Authenticate" })
576
+ void validPathWithMissingFile (String authHeaderKey )
577
+ throws Exception {
578
+ Path validPathWithMissingFile = Paths .get (
579
+ System .getenv ("ProgramData" ) + "/AzureConnectedMachineAgent/Tokens/secret.key" );
629
580
630
- @ Test
631
- void azureArcManagedIdentityAuthheaderValidationTest () throws Exception {
632
- IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper (ManagedIdentitySourceType .AZURE_ARC , azureArcEndpoint );
633
- ManagedIdentityApplication .setEnvironmentVariables (environmentVariables );
634
- DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
581
+ mockHttpResponse (singletonMap (authHeaderKey , singletonList ("Basic realm=" + validPathWithMissingFile )));
635
582
636
- //Both a missing file and an invalid path structure should throw an exception
637
- Path validPathWithMissingFile = Paths . get ( System . getenv ( "ProgramData" )+ "/AzureConnectedMachineAgent/Tokens/secret.key" );
638
- Path invalidPathWithRealFile = Paths . get ( this . getClass (). getResource ( "/msi-azure-arc-secret.txt" ). toURI ());
583
+ assertMsalServiceException ( MANAGED_IDENTITY_FILE_READ_ERROR ,
584
+ MANAGED_IDENTITY_INVALID_FILEPATH );
585
+ }
639
586
640
- // Mock 401 response that returns WWW-Authenticate header
641
- HttpResponse response = new HttpResponse ();
642
- response .statusCode (HttpStatus .SC_UNAUTHORIZED );
643
- response .headers ().put ("WWW-Authenticate" , Collections .singletonList ("Basic realm=" + validPathWithMissingFile ));
587
+ @ ParameterizedTest
588
+ @ ValueSource (strings = {"WWW-Authenticate" , "Www-Authenticate" })
589
+ void invalidPathWithRealFile (String authHeaderKey )
590
+ throws Exception {
591
+ Path invalidPathWithRealFile = Paths .get (
592
+ this .getClass ().getResource ("/msi-azure-arc-secret.txt" ).toURI ());
644
593
645
- when ( httpClientMock . send ( expectedRequest ( ManagedIdentitySourceType . AZURE_ARC , resource ))). thenReturn ( response );
594
+ mockHttpResponse ( singletonMap ( authHeaderKey , singletonList ( "Basic realm=" + invalidPathWithRealFile )) );
646
595
647
- miApp = ManagedIdentityApplication
648
- .builder (ManagedIdentityId .systemAssigned ())
649
- .httpClient (httpClientMock )
650
- .build ();
596
+ assertMsalServiceException (MANAGED_IDENTITY_FILE_READ_ERROR ,
597
+ MANAGED_IDENTITY_INVALID_FILEPATH );
598
+ }
651
599
652
- // Clear caching to avoid cross test pollution.
653
- miApp .tokenCache ().accessTokens .clear ();
600
+ private void mockHttpResponse (Map <String , ? extends List <String >> responseHeaders ) throws Exception {
601
+ IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper (AZURE_ARC , azureArcEndpoint );
602
+ ManagedIdentityApplication .setEnvironmentVariables (environmentVariables );
603
+ DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
654
604
655
- CompletableFuture <IAuthenticationResult > future = miApp .acquireTokenForManagedIdentity (ManagedIdentityParameters .builder (resource ).build ());
605
+ HttpResponse response = new HttpResponse ();
606
+ response .statusCode (SC_UNAUTHORIZED );
607
+ response .headers ().putAll (responseHeaders );
656
608
657
- ExecutionException ex = assertThrows ( ExecutionException . class , future :: get );
658
- assertTrue ( ex . getCause () instanceof MsalServiceException );
659
- assertTrue ( ex . getMessage (). contains ( MsalErrorMessage . MANAGED_IDENTITY_INVALID_FILEPATH ) );
609
+ when ( httpClientMock . send (
610
+ expectedRequest ( AZURE_ARC , resource ))). thenReturn (
611
+ response );
660
612
661
- response .headers ().put ("WWW-Authenticate" , Collections .singletonList ("Basic realm=" + invalidPathWithRealFile ));
613
+ miApp = ManagedIdentityApplication
614
+ .builder (ManagedIdentityId .systemAssigned ())
615
+ .httpClient (httpClientMock )
616
+ .build ();
662
617
663
- future = miApp .acquireTokenForManagedIdentity (ManagedIdentityParameters .builder (resource ).build ());
618
+ // Clear caching to avoid cross test pollution.
619
+ miApp .tokenCache ().accessTokens .clear ();
620
+ }
664
621
665
- ex = assertThrows (ExecutionException .class , future ::get );
666
- assertTrue (ex .getCause () instanceof MsalServiceException );
667
- assertTrue (ex .getMessage ().contains (MsalErrorMessage .MANAGED_IDENTITY_INVALID_FILEPATH ));
622
+ private void assertMsalServiceException (String errorCode , String message ) throws Exception {
623
+ CompletableFuture <IAuthenticationResult > future =
624
+ miApp .acquireTokenForManagedIdentity (
625
+ ManagedIdentityParameters .builder (resource ).build ());
626
+
627
+ ExecutionException ex = assertThrows (ExecutionException .class , future ::get );
628
+ assertInstanceOf (MsalServiceException .class , ex .getCause ());
629
+ MsalServiceException msalException = (MsalServiceException ) ex .getCause ();
630
+ assertEquals (AZURE_ARC .name (),
631
+ msalException .managedIdentitySource ());
632
+ assertEquals (errorCode , msalException .errorCode ());
633
+ assertTrue (ex .getMessage ().contains (message ));
634
+ }
668
635
}
669
636
}
0 commit comments