Skip to content

Adding FMI source to MI app #5299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open

Adding FMI source to MI app #5299

wants to merge 15 commits into from

Conversation

trwalke
Copy link
Member

@trwalke trwalke commented May 21, 2025

This PR is adding WithServiceFabricFmi() which will be used to enable MI applications to detect the FMI service fabric endpoints.
This API is only intended to be used by MISE for the FMI credential.
Fixes # https://identitydivision.visualstudio.com/Engineering/_workitems/edit/3245126/

Changes proposed in this request
Please see proposal here: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5309/files

Testing

Performance impact

Documentation

  • All relevant documentation is updated.

string identityEndpoint = EnvironmentVariables.IdentityEndpoint;

requestContext.Logger.Info(() => "[Managed Identity] Service fabric managed identity is available.");

if (!Uri.TryCreate(identityEndpoint, UriKind.Absolute, out Uri endpointUri))
if (requestContext.ServiceBundle.Config.IsFmiServiceFabric)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was considering letting MSAL autodetect the correct env variable, but I am not sure if it is a good idea. Both env variables may be set (IDENTITY_ENDPOINT and APP_IDENTITY_ENDPOINT), so I don't want to introduce bugs. Adding an api for this that will only be used from MISE will make this more robust.

Copy link
Member

@bgavrilMS bgavrilMS May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's take a step back and think how we'd go about doing this in MSAL if we were to productize getting the FMI credential.

The FMI credential is just a token with a specific audience. And it can use different endpoints.

Can we use the existing MSI APIs, and have different logic based on the audience? i.e. if app developer requests token for api://AzureFMITokenExchange (or the GUID format) - then add your custom logic?

Also, let's add the "experimental features" to this?

Copy link
Member Author

@trwalke trwalke May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bgavrilMS I understand what you are saying, but since this scenario isnt intended to use a resource and is simply acquiring the token from MITS, all of the additional application logic for resources/scopes/caching is not needed. I would also would be concerned if someone wanted to use MI to exchange an FMI credential for an access token using api://AzureFMITokenExchange, but instead they just get another FMI Credential. so, maybe instead of using the fmi token exchange resource, we can create some string like "FmiMitsAcquisition" or something so that no one will trigger this logic in MSAL by accident? But if you feel like no one will ever use api://AzureFMITokenExchange with a MI app, this this will work.

Copy link
Member

@bgavrilMS bgavrilMS May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with an experimental API mi.AcquireFmiCredential(). Not sure I see a scenario where api://AzureFMITokenExchange can be mis-used either.

@rayluo - thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trwalke - can you put toghter a small design doc for this and let's discuss with the team?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bgavrilMS Added here
#5309

@trwalke trwalke mentioned this pull request May 30, 2025
1 task
@trwalke trwalke changed the title PROTOTYPE: Adding WithServiceFabricFmi() PROTOTYPE: Adding FMI source to MI app Jun 6, 2025
Adding experimental feature requirement.
@trwalke trwalke changed the title PROTOTYPE: Adding FMI source to MI app Adding FMI source to MI app Jun 11, 2025
@trwalke trwalke marked this pull request as ready for review June 11, 2025 07:24
@trwalke trwalke requested a review from a team as a code owner June 11, 2025 07:24
request.QueryParameters["api-version"] = ServiceFabricMsiApiVersion;
request.QueryParameters["resource"] = resource;

switch (_requestContext.ServiceBundle.Config.ManagedIdentityId.IdType)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldnt there be a default case? We could log the unexpected, that could give us additional information when troubleshooting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically yes, but this ID is a required parameter for the managed identity application. So it will always be set to something unless there is a catastrophic failure.

Copy link
Member

@bgavrilMS bgavrilMS Jul 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still a good practice to throw an exception @trwalke on default. It will protect against a case where a new enum parameter is added.

internal static Lazy<HttpClient> _httpClientLazy;

public static AbstractManagedIdentity Create(RequestContext requestContext)
public static AbstractManagedIdentity Create(RequestContext requestContext, bool isFmiServiceFabric = false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is right. The source detection should not interfere with isFmi flag. The MSI source should be expected to be cached (statically, in memory) by MSAL.

In other words, each MSI request can either go to the normal endpoint or to the fmi endpoint.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think this is the case. The source detection is effectively turned off if IsFmi is enabled and only the FMI source will be used.
See ManagedIdentityClient

This parameter specifically is to change this source to only do FMI.

Also, when you say cached (statically, in memory), can more that one of these source objects be cached? meaning, can there be one for regular SF and one for FMI?

}

[TestMethod]
public async Task ValidateThatFmiCredentialCanBeAcquiredFromMits()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need a test where you ask for a FMI credential, then for an FMI token (and repeat).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didnt add this because this code is only responsible for acquiring the credential. The full E2E is already tested in MISE. Are we sure we also want to add the full e2e test here?

Copy link
Member

@bgavrilMS bgavrilMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source detection should not depend on isFmi


if (resource.Equals("api://AzureFMITokenExchange/.default", StringComparison.OrdinalIgnoreCase))
{
Parameters.isFmiCredentialRequest = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an extra param here? Can't ManagedIdentity classes deal with this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can do that

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it is better to keep this here because there the check is needed for the experimental features to be enabled.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with dropping the experimental feature flag if it leads to better design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants