Skip to content

Commit 651bfdf

Browse files
authored
Service Fabric MSI (#729)
* Support for service fabric, most tests working * TODOs and sonarlint recommendations * Address PR comments
1 parent b15f3ff commit 651bfdf

File tree

6 files changed

+128
-24
lines changed

6 files changed

+128
-24
lines changed

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AppServiceManagedIdentitySource.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ class AppServiceManagedIdentitySource extends AbstractManagedIdentitySource{
1919
private static final String APP_SERVICE_MSI_API_VERSION = "2019-08-01";
2020
private static final String SECRET_HEADER_NAME = "X-IDENTITY-HEADER";
2121

22-
private final URI MSI_ENDPOINT;
23-
private final String SECRET;
22+
private final URI msiEndpoint;
23+
private final String identityHeader;
2424

2525
@Override
2626
public void createManagedIdentityRequest(String resource) {
27-
managedIdentityRequest.baseEndpoint = MSI_ENDPOINT;
27+
managedIdentityRequest.baseEndpoint = msiEndpoint;
2828
managedIdentityRequest.method = HttpMethod.GET;
2929

3030
managedIdentityRequest.headers = new HashMap<>();
31-
managedIdentityRequest.headers.put(SECRET_HEADER_NAME, SECRET);
31+
managedIdentityRequest.headers.put(SECRET_HEADER_NAME, identityHeader);
3232

3333
managedIdentityRequest.queryParameters = new HashMap<>();
3434
managedIdentityRequest.queryParameters.put("api-version", Collections.singletonList(APP_SERVICE_MSI_API_VERSION));
@@ -50,8 +50,8 @@ public void createManagedIdentityRequest(String resource) {
5050
private AppServiceManagedIdentitySource(MsalRequest msalRequest, ServiceBundle serviceBundle, URI msiEndpoint, String secret)
5151
{
5252
super(msalRequest, serviceBundle, ManagedIdentitySourceType.APP_SERVICE);
53-
this.MSI_ENDPOINT = msiEndpoint;
54-
this.SECRET = secret;
53+
this.msiEndpoint = msiEndpoint;
54+
this.identityHeader = secret;
5555
}
5656

5757
static AbstractManagedIdentitySource create(MsalRequest msalRequest, ServiceBundle serviceBundle) {

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/CloudShellManagedIdentitySource.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ class CloudShellManagedIdentitySource extends AbstractManagedIdentitySource{
1515

1616
private static final Logger LOG = LoggerFactory.getLogger(CloudShellManagedIdentitySource.class);
1717

18-
private final URI MSI_ENDPOINT;
18+
private final URI msiEndpoint;
1919

2020
@Override
2121
public void createManagedIdentityRequest(String resource) {
22-
managedIdentityRequest.baseEndpoint = MSI_ENDPOINT;
22+
managedIdentityRequest.baseEndpoint = msiEndpoint;
2323
managedIdentityRequest.method = HttpMethod.POST;
2424

2525
managedIdentityRequest.headers = new HashMap<>();
@@ -33,7 +33,7 @@ public void createManagedIdentityRequest(String resource) {
3333
private CloudShellManagedIdentitySource(MsalRequest msalRequest, ServiceBundle serviceBundle, URI msiEndpoint)
3434
{
3535
super(msalRequest, serviceBundle, ManagedIdentitySourceType.CLOUD_SHELL);
36-
this.MSI_ENDPOINT = msiEndpoint;
36+
this.msiEndpoint = msiEndpoint;
3737

3838
ManagedIdentityIdType idType =
3939
((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getIdType();
@@ -57,28 +57,23 @@ static AbstractManagedIdentitySource create(MsalRequest msalRequest, ServiceBund
5757
return null;
5858
}
5959

60-
URI validatedUri = validateAndGetUri(msiEndpoint);
61-
return validatedUri == null ? null
62-
: new CloudShellManagedIdentitySource(msalRequest, serviceBundle, validatedUri);
60+
return new CloudShellManagedIdentitySource(msalRequest, serviceBundle, validateAndGetUri(msiEndpoint));
6361
}
6462

6563
private static URI validateAndGetUri(String msiEndpoint)
6664
{
67-
URI endpointUri = null;
68-
6965
try
7066
{
71-
endpointUri = new URI(msiEndpoint);
67+
URI endpointUri = new URI(msiEndpoint);
68+
LOG.info("[Managed Identity] Environment variables validation passed for cloud shell managed identity. Endpoint URI: " + endpointUri + ". Creating cloud shell managed identity.");
69+
return endpointUri;
7270
}
7371
catch (URISyntaxException ex)
7472
{
7573
throw new MsalManagedIdentityException(MsalError.INVALID_MANAGED_IDENTITY_ENDPOINT, String.format(
7674
MsalErrorMessage.MANAGED_IDENTITY_ENDPOINT_INVALID_URI_ERROR, "MSI_ENDPOINT", msiEndpoint, "Cloud Shell"),
7775
ManagedIdentitySourceType.CLOUD_SHELL);
7876
}
79-
80-
LOG.info("[Managed Identity] Environment variables validation passed for cloud shell managed identity. Endpoint URI: " + endpointUri + ". Creating cloud shell managed identity.");
81-
return endpointUri;
8277
}
8378

8479
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityClient.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ ManagedIdentityResponse getManagedIdentityResponse(ManagedIdentityParameters par
3434
private static AbstractManagedIdentitySource createManagedIdentitySource(MsalRequest msalRequest,
3535
ServiceBundle serviceBundle) {
3636
AbstractManagedIdentitySource managedIdentitySource;
37-
if ((managedIdentitySource = AppServiceManagedIdentitySource.create(msalRequest, serviceBundle)) != null) {
37+
if ((managedIdentitySource = ServiceFabricManagedIdentitySource.create(msalRequest, serviceBundle)) != null) {
38+
return managedIdentitySource;
39+
} else if ((managedIdentitySource = AppServiceManagedIdentitySource.create(msalRequest, serviceBundle)) != null) {
3840
return managedIdentitySource;
3941
} else if ((managedIdentitySource = CloudShellManagedIdentitySource.create(msalRequest, serviceBundle)) != null) {
4042
return managedIdentitySource;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.aad.msal4j;
5+
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import java.net.URI;
10+
import java.net.URISyntaxException;
11+
import java.util.Collections;
12+
import java.util.HashMap;
13+
14+
class ServiceFabricManagedIdentitySource extends AbstractManagedIdentitySource {
15+
16+
private static final Logger LOG = LoggerFactory.getLogger(ServiceFabricManagedIdentitySource.class);
17+
18+
private static final String SERVICE_FABRIC_MSI_API_VERSION = "2019-07-01-preview";
19+
20+
private final URI msiEndpoint;
21+
private final String identityHeader;
22+
private final ManagedIdentityIdType idType;
23+
private final String userAssignedId;
24+
25+
@Override
26+
public void createManagedIdentityRequest(String resource) {
27+
managedIdentityRequest.baseEndpoint = msiEndpoint;
28+
managedIdentityRequest.method = HttpMethod.GET;
29+
30+
managedIdentityRequest.headers = new HashMap<>();
31+
managedIdentityRequest.headers.put("secret", identityHeader);
32+
33+
managedIdentityRequest.queryParameters = new HashMap<>();
34+
managedIdentityRequest.queryParameters.put("resource", Collections.singletonList(resource));
35+
managedIdentityRequest.queryParameters.put("api-version", Collections.singletonList(SERVICE_FABRIC_MSI_API_VERSION));
36+
37+
if (idType == ManagedIdentityIdType.CLIENT_ID) {
38+
LOG.info("[Managed Identity] Adding user assigned client id to the request for Service Fabric Managed Identity.");
39+
managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_CLIENT_ID, Collections.singletonList(userAssignedId));
40+
} else if (idType == ManagedIdentityIdType.RESOURCE_ID) {
41+
LOG.info("[Managed Identity] Adding user assigned resource id to the request for Service Fabric Managed Identity.");
42+
managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_RESOURCE_ID, Collections.singletonList(userAssignedId));
43+
}
44+
}
45+
46+
private ServiceFabricManagedIdentitySource(MsalRequest msalRequest, ServiceBundle serviceBundle, URI msiEndpoint, String identityHeader)
47+
{
48+
super(msalRequest, serviceBundle, ManagedIdentitySourceType.SERVICE_FABRIC);
49+
this.msiEndpoint = msiEndpoint;
50+
this.identityHeader = identityHeader;
51+
52+
this.idType = ((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getIdType();
53+
this.userAssignedId = ((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getUserAssignedId();
54+
}
55+
56+
static AbstractManagedIdentitySource create(MsalRequest msalRequest, ServiceBundle serviceBundle) {
57+
58+
IEnvironmentVariables environmentVariables = getEnvironmentVariables((ManagedIdentityParameters) msalRequest.requestContext().apiParameters());
59+
String msiEndpoint = environmentVariables.getEnvironmentVariable(Constants.MSI_ENDPOINT);
60+
String identityHeader = environmentVariables.getEnvironmentVariable(Constants.IDENTITY_ENDPOINT);
61+
String identityServerThumbprint = environmentVariables.getEnvironmentVariable(Constants.IDENTITY_SERVER_THUMBPRINT);
62+
63+
64+
if (StringHelper.isNullOrBlank(msiEndpoint) || StringHelper.isNullOrBlank(identityHeader) || StringHelper.isNullOrBlank(identityServerThumbprint))
65+
{
66+
LOG.info("[Managed Identity] Service fabric managed identity is unavailable.");
67+
return null;
68+
}
69+
70+
return new ServiceFabricManagedIdentitySource(msalRequest, serviceBundle, validateAndGetUri(msiEndpoint), identityHeader);
71+
}
72+
73+
private static URI validateAndGetUri(String msiEndpoint)
74+
{
75+
try
76+
{
77+
URI endpointUri = new URI(msiEndpoint);
78+
LOG.info("[Managed Identity] Environment variables validation passed for Service Fabric Managed Identity. Endpoint URI: " + endpointUri);
79+
return endpointUri;
80+
}
81+
catch (URISyntaxException ex)
82+
{
83+
throw new MsalManagedIdentityException(MsalError.INVALID_MANAGED_IDENTITY_ENDPOINT, String.format(
84+
MsalErrorMessage.MANAGED_IDENTITY_ENDPOINT_INVALID_URI_ERROR, "MSI_ENDPOINT", msiEndpoint, "Service Fabric"),
85+
ManagedIdentitySourceType.SERVICE_FABRIC);
86+
}
87+
}
88+
89+
}

msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTestDataProvider.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ public static Stream<Arguments> createData() {
3030
Arguments.of(ManagedIdentitySourceType.IMDS, ManagedIdentityTests.IMDS_ENDPOINT,
3131
ManagedIdentityTests.resourceDefaultSuffix),
3232
Arguments.of(ManagedIdentitySourceType.IMDS, null,
33-
ManagedIdentityTests.resource));
33+
ManagedIdentityTests.resource),
34+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint,
35+
ManagedIdentityTests.resource),
36+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint,
37+
ManagedIdentityTests.resourceDefaultSuffix));
3438
}
3539

3640
public static Stream<Arguments> createDataUserAssigned() {
@@ -42,6 +46,10 @@ public static Stream<Arguments> createDataUserAssigned() {
4246
Arguments.of(ManagedIdentitySourceType.IMDS, null,
4347
ManagedIdentityId.userAssignedClientId(CLIENT_ID)),
4448
Arguments.of(ManagedIdentitySourceType.IMDS, null,
49+
ManagedIdentityId.userAssignedResourceId(RESOURCE_ID)),
50+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint,
51+
ManagedIdentityId.userAssignedResourceId(CLIENT_ID)),
52+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint,
4553
ManagedIdentityId.userAssignedResourceId(RESOURCE_ID)));
4654
}
4755

@@ -74,6 +82,10 @@ public static Stream<Arguments> createDataWrongScope() {
7482
Arguments.of(ManagedIdentitySourceType.IMDS, ManagedIdentityTests.IMDS_ENDPOINT,
7583
"user.read"),
7684
Arguments.of(ManagedIdentitySourceType.IMDS, ManagedIdentityTests.IMDS_ENDPOINT,
85+
"https://management.core.windows.net//user_impersonation"),
86+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint,
87+
"user.read"),
88+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint,
7789
"https://management.core.windows.net//user_impersonation"));
7890
}
7991

@@ -82,6 +94,7 @@ public static Stream<Arguments> createDataError() {
8294
Arguments.of(ManagedIdentitySourceType.AZURE_ARC, ManagedIdentityTests.azureArcEndpoint),
8395
Arguments.of(ManagedIdentitySourceType.APP_SERVICE, ManagedIdentityTests.appServiceEndpoint),
8496
Arguments.of(ManagedIdentitySourceType.CLOUD_SHELL, ManagedIdentityTests.cloudShellEndpoint),
85-
Arguments.of(ManagedIdentitySourceType.IMDS, ManagedIdentityTests.IMDS_ENDPOINT));
97+
Arguments.of(ManagedIdentitySourceType.IMDS, ManagedIdentityTests.IMDS_ENDPOINT),
98+
Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint));
8699
}
87100
}

msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ private HttpRequest expectedRequest(ManagedIdentitySourceType source, String res
9797
headers.put("Metadata", "true");
9898
break;
9999
}
100+
case SERVICE_FABRIC:
101+
endpoint = serviceFabricEndpoint;
102+
queryParameters.put("api-version", Collections.singletonList("2019-07-01-preview"));
103+
queryParameters.put("resource", Collections.singletonList(resource));
104+
break;
100105
}
101106

102107
switch (id.getIdType()) {
@@ -412,7 +417,7 @@ void azureArcManagedIdentity_MissingAuthHeader() throws Exception {
412417

413418
// Clear caching to avoid cross test pollution.
414419
miApp.tokenCache().accessTokens.clear();
415-
420+
416421
try {
417422
miApp.acquireTokenForManagedIdentity(
418423
ManagedIdentityParameters.builder(resource)
@@ -447,12 +452,12 @@ void managedIdentity_SharedCache(ManagedIdentitySourceType source, String endpoi
447452

448453
// Clear caching to avoid cross test pollution.
449454
miApp.tokenCache().accessTokens.clear();
450-
455+
451456
ManagedIdentityApplication miApp2 = ManagedIdentityApplication
452457
.builder(ManagedIdentityId.systemAssigned())
453458
.httpClient(httpClientMock)
454459
.build();
455-
460+
456461
IAuthenticationResult resultMiApp1 = miApp.acquireTokenForManagedIdentity(
457462
ManagedIdentityParameters.builder(resource)
458463
.environmentVariables(environmentVariables)

0 commit comments

Comments
 (0)