From 51a0101f27256d03e1c82f8c9c29a26cc7b6b730 Mon Sep 17 00:00:00 2001 From: avdunn Date: Mon, 19 Aug 2024 16:24:43 -0700 Subject: [PATCH] Add object ID option for Managed Identity --- .../msal4j/AbstractManagedIdentitySource.java | 5 ++++- .../AppServiceManagedIdentitySource.java | 13 +++-------- .../com/microsoft/aad/msal4j/Constants.java | 1 + .../aad/msal4j/IMDSManagedIdentitySource.java | 17 ++++---------- .../aad/msal4j/ManagedIdentityClient.java | 14 +++--------- .../aad/msal4j/ManagedIdentityId.java | 17 ++++++++++++++ .../aad/msal4j/ManagedIdentityIdType.java | 3 ++- .../aad/msal4j/ManagedIdentityRequest.java | 22 +++++++++++++++++++ .../ServiceFabricManagedIdentitySource.java | 14 +++--------- .../ManagedIdentityTestDataProvider.java | 9 +++++++- .../aad/msal4j/ManagedIdentityTests.java | 3 +++ 11 files changed, 70 insertions(+), 48 deletions(-) diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractManagedIdentitySource.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractManagedIdentitySource.java index 2ae83f91..8df12efb 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractManagedIdentitySource.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractManagedIdentitySource.java @@ -15,13 +15,14 @@ //base class for all sources that support managed identity abstract class AbstractManagedIdentitySource { - protected static final String TIMEOUT_ERROR = "[Managed Identity] Authentication unavailable. The request to the managed identity endpoint timed out."; private static final Logger LOG = LoggerFactory.getLogger(AbstractManagedIdentitySource.class); private static final String MANAGED_IDENTITY_NO_RESPONSE_RECEIVED = "[Managed Identity] Authentication unavailable. No response received from the managed identity endpoint."; protected final ManagedIdentityRequest managedIdentityRequest; protected final ServiceBundle serviceBundle; ManagedIdentitySourceType managedIdentitySourceType; + ManagedIdentityIdType idType; + String userAssignedId; @Getter @Setter @@ -40,6 +41,8 @@ public AbstractManagedIdentitySource(MsalRequest msalRequest, ServiceBundle serv this.managedIdentityRequest = (ManagedIdentityRequest) msalRequest; this.managedIdentitySourceType = sourceType; this.serviceBundle = serviceBundle; + this.idType = ((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getIdType(); + this.userAssignedId = ((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getUserAssignedId(); } public ManagedIdentityResponse getManagedIdentityResponse( diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AppServiceManagedIdentitySource.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AppServiceManagedIdentitySource.java index 2b26b109..bb0f3112 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AppServiceManagedIdentitySource.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AppServiceManagedIdentitySource.java @@ -34,16 +34,9 @@ public void createManagedIdentityRequest(String resource) { managedIdentityRequest.queryParameters.put("api-version", Collections.singletonList(APP_SERVICE_MSI_API_VERSION)); managedIdentityRequest.queryParameters.put("resource", Collections.singletonList(resource)); - if (!StringHelper.isNullOrBlank(getManagedIdentityUserAssignedClientId())) - { - LOG.info("[Managed Identity] Adding user assigned client id to the request."); - managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_CLIENT_ID, Collections.singletonList(getManagedIdentityUserAssignedClientId())); - } - - if (!StringHelper.isNullOrBlank(getManagedIdentityUserAssignedResourceId())) - { - LOG.info("[Managed Identity] Adding user assigned resource id to the request."); - managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_RESOURCE_ID, Collections.singletonList(getManagedIdentityUserAssignedResourceId())); + if (this.idType != null && !StringHelper.isNullOrBlank(this.userAssignedId)) { + LOG.info("[Managed Identity] Adding user assigned ID to the request for App Service Managed Identity."); + managedIdentityRequest.addUserAssignedIdToQuery(this.idType, this.userAssignedId); } } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/Constants.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/Constants.java index aec0e880..07e99345 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/Constants.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/Constants.java @@ -13,6 +13,7 @@ final class Constants { public static final String MANAGED_IDENTITY_CLIENT_ID = "client_id"; public static final String MANAGED_IDENTITY_RESOURCE_ID = "mi_res_id"; + public static final String MANAGED_IDENTITY_OBJECT_ID = "object_id"; public static final String MANAGED_IDENTITY_DEFAULT_TENTANT = "managed_identity"; public static final String IDENTITY_ENDPOINT = "IDENTITY_ENDPOINT"; diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IMDSManagedIdentitySource.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IMDSManagedIdentitySource.java index 0dc2d2b1..c1973ee1 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IMDSManagedIdentitySource.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IMDSManagedIdentitySource.java @@ -34,8 +34,8 @@ class IMDSManagedIdentitySource extends AbstractManagedIdentitySource{ public IMDSManagedIdentitySource(MsalRequest msalRequest, ServiceBundle serviceBundle) { super(msalRequest, serviceBundle, ManagedIdentitySourceType.IMDS); - ManagedIdentityParameters parameters = (ManagedIdentityParameters) msalRequest.requestContext().apiParameters(); IEnvironmentVariables environmentVariables = getEnvironmentVariables(); + if (!StringHelper.isNullOrBlank(environmentVariables.getEnvironmentVariable(Constants.AZURE_POD_IDENTITY_AUTHORITY_HOST))){ LOG.info(String.format("[Managed Identity] Environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST for IMDS returned endpoint: %s", environmentVariables.getEnvironmentVariable(Constants.AZURE_POD_IDENTITY_AUTHORITY_HOST))); try { @@ -77,18 +77,9 @@ public void createManagedIdentityRequest(String resource) { managedIdentityRequest.queryParameters.put("api-version", Collections.singletonList(IMDS_API_VERSION)); managedIdentityRequest.queryParameters.put("resource", Collections.singletonList(resource)); - String clientId = getManagedIdentityUserAssignedClientId(); - String resourceId = getManagedIdentityUserAssignedResourceId(); - if (!StringHelper.isNullOrBlank(clientId)) - { - LOG.info("[Managed Identity] Adding user assigned client id to the request."); - managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_CLIENT_ID, Collections.singletonList(clientId)); - } - - if (!StringHelper.isNullOrBlank(resourceId)) - { - LOG.info("[Managed Identity] Adding user assigned resource id to the request."); - managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_RESOURCE_ID, Collections.singletonList(resourceId)); + if (this.idType != null && !StringHelper.isNullOrBlank(this.userAssignedId)) { + LOG.info("[Managed Identity] Adding user assigned ID to the request for IMDS Managed Identity."); + managedIdentityRequest.addUserAssignedIdToQuery(this.idType, this.userAssignedId); } } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityClient.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityClient.java index 334abec8..fbcd8386 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityClient.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityClient.java @@ -3,8 +3,6 @@ package com.microsoft.aad.msal4j; -import lombok.AccessLevel; -import lombok.Getter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,8 +29,9 @@ static ManagedIdentitySourceType getManagedIdentitySource() { !StringHelper.isNullOrBlank(environmentVariables.getEnvironmentVariable(Constants.IDENTITY_HEADER))) { if (!StringHelper.isNullOrBlank(environmentVariables.getEnvironmentVariable(Constants.IDENTITY_SERVER_THUMBPRINT))) { managedIdentitySourceType = ManagedIdentitySourceType.SERVICE_FABRIC; - } else - managedIdentitySourceType = ManagedIdentitySourceType.APP_SERVICE; + } else { + managedIdentitySourceType = ManagedIdentitySourceType.APP_SERVICE; + } } else if (!StringHelper.isNullOrBlank(environmentVariables.getEnvironmentVariable(Constants.MSI_ENDPOINT))) { managedIdentitySourceType = ManagedIdentitySourceType.CLOUD_SHELL; } else if (!StringHelper.isNullOrBlank(environmentVariables.getEnvironmentVariable(Constants.IDENTITY_ENDPOINT)) && @@ -54,12 +53,6 @@ static ManagedIdentitySourceType getManagedIdentitySource() { ManagedIdentityIdType identityIdType = managedIdentityApplication.getManagedIdentityId().getIdType(); if (!identityIdType.equals(ManagedIdentityIdType.SYSTEM_ASSIGNED)) { managedIdentitySource.setUserAssignedManagedIdentity(true); - String userAssignedId = managedIdentityApplication.getManagedIdentityId().getUserAssignedId(); - if (identityIdType.equals(ManagedIdentityIdType.CLIENT_ID)) { - managedIdentitySource.setManagedIdentityUserAssignedClientId(userAssignedId); - } else if (identityIdType.equals(ManagedIdentityIdType.RESOURCE_ID)) { - managedIdentitySource.setManagedIdentityUserAssignedResourceId(userAssignedId); - } } } @@ -70,7 +63,6 @@ ManagedIdentityResponse getManagedIdentityResponse(ManagedIdentityParameters par // This method tries to create managed identity source for different sources, if none is created then defaults to IMDS. private static AbstractManagedIdentitySource createManagedIdentitySource(MsalRequest msalRequest, ServiceBundle serviceBundle) { - AbstractManagedIdentitySource managedIdentitySource; if (managedIdentitySourceType == null || managedIdentitySourceType == ManagedIdentitySourceType.NONE) { managedIdentitySourceType = getManagedIdentitySource(); diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityId.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityId.java index 20c28728..5f2f18b3 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityId.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityId.java @@ -61,4 +61,21 @@ public static ManagedIdentityId userAssignedResourceId(String resourceId) return new ManagedIdentityId(ManagedIdentityIdType.RESOURCE_ID, resourceId); } + + /** + * Create an instance of ManagedIdentityId for a user assigned managed identity from an object id. + * + * @param objectId Object ID of the user assigned managed identity assigned to azure resource. + * @return Instance of ManagedIdentityId + * @exception NullPointerException Indicates the resourceId param is null or blank + */ + public static ManagedIdentityId userAssignedObjectId(String objectId) + { + if (StringHelper.isNullOrBlank(objectId)) + { + throw new NullPointerException(objectId); + } + + return new ManagedIdentityId(ManagedIdentityIdType.OBJECT_ID, objectId); + } } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityIdType.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityIdType.java index 8f7fbe44..6040f999 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityIdType.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityIdType.java @@ -7,5 +7,6 @@ enum ManagedIdentityIdType { SYSTEM_ASSIGNED, CLIENT_ID, - RESOURCE_ID + RESOURCE_ID, + OBJECT_ID } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityRequest.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityRequest.java index bf77b65c..2076c37b 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityRequest.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ManagedIdentityRequest.java @@ -4,16 +4,21 @@ package com.microsoft.aad.msal4j; import com.nimbusds.oauth2.sdk.util.URLUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.util.Collections; import java.util.List; import java.util.Map; class ManagedIdentityRequest extends MsalRequest { + private static final Logger LOG = LoggerFactory.getLogger(ManagedIdentityRequest.class); + URI baseEndpoint; HttpMethod method; @@ -53,4 +58,21 @@ private String appendQueryParametersToBaseEndpoint() { return baseEndpoint.toString() + "?" + queryString; } + + void addUserAssignedIdToQuery(ManagedIdentityIdType idType, String userAssignedId) { + switch (idType) { + case CLIENT_ID: + LOG.info("[Managed Identity] Adding user assigned client id to the request."); + queryParameters.put(Constants.MANAGED_IDENTITY_CLIENT_ID, Collections.singletonList(userAssignedId)); + break; + case RESOURCE_ID: + LOG.info("[Managed Identity] Adding user assigned resource id to the request."); + queryParameters.put(Constants.MANAGED_IDENTITY_RESOURCE_ID, Collections.singletonList(userAssignedId)); + break; + case OBJECT_ID: + LOG.info("[Managed Identity] Adding user assigned object id to the request."); + queryParameters.put(Constants.MANAGED_IDENTITY_OBJECT_ID, Collections.singletonList(userAssignedId)); + break; + } + } } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ServiceFabricManagedIdentitySource.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ServiceFabricManagedIdentitySource.java index 804eb486..6c20cf9c 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ServiceFabricManagedIdentitySource.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ServiceFabricManagedIdentitySource.java @@ -20,8 +20,6 @@ class ServiceFabricManagedIdentitySource extends AbstractManagedIdentitySource { private final URI msiEndpoint; private final String identityHeader; - private final ManagedIdentityIdType idType; - private final String userAssignedId; //Service Fabric requires a special check for an environment variable containing a certificate thumbprint used for validating requests. //No other flow need this and an app developer may not be aware of it, so it was decided that for the Service Fabric flow we will simply override @@ -41,12 +39,9 @@ public void createManagedIdentityRequest(String resource) { managedIdentityRequest.queryParameters.put("resource", Collections.singletonList(resource)); managedIdentityRequest.queryParameters.put("api-version", Collections.singletonList(SERVICE_FABRIC_MSI_API_VERSION)); - if (idType == ManagedIdentityIdType.CLIENT_ID) { - LOG.info("[Managed Identity] Adding user assigned client id to the request for Service Fabric Managed Identity."); - managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_CLIENT_ID, Collections.singletonList(userAssignedId)); - } else if (idType == ManagedIdentityIdType.RESOURCE_ID) { - LOG.info("[Managed Identity] Adding user assigned resource id to the request for Service Fabric Managed Identity."); - managedIdentityRequest.queryParameters.put(Constants.MANAGED_IDENTITY_RESOURCE_ID, Collections.singletonList(userAssignedId)); + if (this.idType != null && !StringHelper.isNullOrBlank(this.userAssignedId)) { + LOG.info("[Managed Identity] Adding user assigned ID to the request for Service Fabric Managed Identity."); + managedIdentityRequest.addUserAssignedIdToQuery(this.idType, this.userAssignedId); } } @@ -55,9 +50,6 @@ private ServiceFabricManagedIdentitySource(MsalRequest msalRequest, ServiceBundl super(msalRequest, serviceBundle, ManagedIdentitySourceType.SERVICE_FABRIC); this.msiEndpoint = msiEndpoint; this.identityHeader = identityHeader; - - this.idType = ((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getIdType(); - this.userAssignedId = ((ManagedIdentityApplication) msalRequest.application()).getManagedIdentityId().getUserAssignedId(); } @Override diff --git a/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTestDataProvider.java b/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTestDataProvider.java index 5132bc83..d5aedabf 100644 --- a/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTestDataProvider.java +++ b/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTestDataProvider.java @@ -10,6 +10,7 @@ class ManagedIdentityTestDataProvider { private static final String CLIENT_ID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"; private static final String RESOURCE_ID = "/subscriptions/ffa4aaa2-4444-4444-5555-e3ccedd3d046/resourcegroups/UAMI_group/providers/Microsoft.ManagedIdentityClient/userAssignedIdentities/UAMI"; + private static final String OBJECT_ID = "593b2662-5af7-4a90-a9cb-5a9de615b82f"; public static Stream createData() { return Stream.of( @@ -43,14 +44,20 @@ public static Stream createDataUserAssigned() { ManagedIdentityId.userAssignedClientId(CLIENT_ID)), Arguments.of(ManagedIdentitySourceType.APP_SERVICE, ManagedIdentityTests.appServiceEndpoint, ManagedIdentityId.userAssignedResourceId(RESOURCE_ID)), + Arguments.of(ManagedIdentitySourceType.APP_SERVICE, ManagedIdentityTests.appServiceEndpoint, + ManagedIdentityId.userAssignedObjectId(OBJECT_ID)), Arguments.of(ManagedIdentitySourceType.IMDS, null, ManagedIdentityId.userAssignedClientId(CLIENT_ID)), Arguments.of(ManagedIdentitySourceType.IMDS, null, ManagedIdentityId.userAssignedResourceId(RESOURCE_ID)), + Arguments.of(ManagedIdentitySourceType.IMDS, null, + ManagedIdentityId.userAssignedObjectId(OBJECT_ID)), Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint, ManagedIdentityId.userAssignedResourceId(CLIENT_ID)), Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint, - ManagedIdentityId.userAssignedResourceId(RESOURCE_ID))); + ManagedIdentityId.userAssignedResourceId(RESOURCE_ID)), + Arguments.of(ManagedIdentitySourceType.SERVICE_FABRIC, ManagedIdentityTests.serviceFabricEndpoint, + ManagedIdentityId.userAssignedObjectId(OBJECT_ID))); } public static Stream createDataUserAssignedNotSupported() { diff --git a/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java b/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java index 08fc7b61..3b99085f 100644 --- a/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java +++ b/msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java @@ -124,6 +124,9 @@ private HttpRequest expectedRequest(ManagedIdentitySourceType source, String res case RESOURCE_ID: queryParameters.put("mi_res_id", Collections.singletonList(id.getUserAssignedId())); break; + case OBJECT_ID: + queryParameters.put("object_id", Collections.singletonList(id.getUserAssignedId())); + break; } return new HttpRequest(HttpMethod.GET, computeUri(endpoint, queryParameters), headers);