Skip to content

Commit

Permalink
[Identity] Re-enabling the Service Fabric MSI (#17579)
Browse files Browse the repository at this point in the history
* [Identity] Re-enabling the Service Fabric MSI

* Update managedIdentityCredential.spec.ts

* CHANGELOG entry

* Update fabricMsi.ts

* Update fabricMsi.ts
  • Loading branch information
sadasant authored Oct 22, 2021
1 parent a00a662 commit 04c45d1
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 26 deletions.
2 changes: 2 additions & 0 deletions sdk/identity/identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Features Added

- The `ManagedIdentityCredential` now supports the Service Fabric environment.

### Breaking Changes

### Bugs Fixed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import https from "https";
import { createHttpHeaders, PipelineRequestOptions } from "@azure/core-rest-pipeline";
import { AccessToken, GetTokenOptions } from "@azure/core-auth";
import { MSI, MSIConfiguration } from "./models";
Expand Down Expand Up @@ -87,7 +88,7 @@ export const fabricMsi: MSI = {
configuration: MSIConfiguration,
getTokenOptions: GetTokenOptions = {}
): Promise<AccessToken | null> {
const { identityClient, scopes, clientId } = configuration;
const { scopes, identityClient, clientId } = configuration;

logger.info(
[
Expand All @@ -103,7 +104,12 @@ export const fabricMsi: MSI = {
identityClient,
prepareRequestOptions(scopes, clientId),
expiresInParser,
getTokenOptions
getTokenOptions,
new https.Agent({
// This is necessary because Service Fabric provides a self-signed certificate.
// The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
rejectUnauthorized: false
})
);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { imdsMsi } from "./imdsMsi";
import { MSI } from "./models";
import { arcMsi } from "./arcMsi";
import { tokenExchangeMsi } from "./tokenExchangeMsi";
import { fabricMsi } from "./fabricMsi";

const logger = credentialLogger("ManagedIdentityCredential");

Expand Down Expand Up @@ -74,9 +75,7 @@ export class ManagedIdentityCredential implements TokenCredential {
return this.cachedMSI;
}

// "fabricMsi" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,
// which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];
const MSIs = [fabricMsi, appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];

for (const msi of MSIs) {
if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { AccessToken, GetTokenOptions } from "@azure/core-auth";
import { PipelineRequestOptions, createPipelineRequest } from "@azure/core-rest-pipeline";
import { Agent } from "http";
import { IdentityClient } from "../../client/identityClient";
import { DefaultScopeSuffix } from "./constants";
import { MSIExpiresInParser } from "./models";
Expand Down Expand Up @@ -38,14 +39,19 @@ export async function msiGenericGetToken(
identityClient: IdentityClient,
requestOptions: PipelineRequestOptions,
expiresInParser: MSIExpiresInParser | undefined,
getTokenOptions: GetTokenOptions = {}
getTokenOptions: GetTokenOptions = {},
agent?: Agent
): Promise<AccessToken | null> {
const request = createPipelineRequest({
abortSignal: getTokenOptions.abortSignal,
...requestOptions,
allowInsecureConnection: true
});

if (agent) {
request.agent = agent;
}

const tokenResponse = await identityClient.sendTokenRequest(request, expiresInParser);
return (tokenResponse && tokenResponse.accessToken) || null;
}
28 changes: 13 additions & 15 deletions sdk/identity/identity/test/httpRequests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,23 +172,21 @@ export async function prepareIdentityTests({
const totalOptions: http.RequestOptions[] = [];

try {
sandbox.replace(
providerObject,
"request",
(options: string | URL | http.RequestOptions, resolve: any) => {
totalOptions.push(options as http.RequestOptions);
const fakeRequest = (options: string | URL | http.RequestOptions, resolve: any) => {
totalOptions.push(options as http.RequestOptions);

const { response, error } = responses.shift()!;
if (error) {
throw error;
} else {
resolve(responseToIncomingMessage(response!));
}
const request = createRequest();
spies.push(sandbox.spy(request, "end"));
return request;
const { response, error } = responses.shift()!;
if (error) {
throw error;
} else {
resolve(responseToIncomingMessage(response!));
}
);
const request = createRequest();
spies.push(sandbox.spy(request, "end"));
return request;
};
sandbox.replace(providerObject, "request", fakeRequest);
sandbox.replace(providerObject.Agent.prototype as any, "request", fakeRequest);
} catch (e) {
console.debug(
"Failed to replace the request. This might be expected if you're running multiple sendCredentialRequests() calls."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,10 +447,7 @@ describe("ManagedIdentityCredential", function() {
}
});

// "fabricMsi" isn't part of the ManagedIdentityCredential MSIs yet
// because our HTTPs pipeline doesn't allow skipping the SSL verification step,
// which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
it.skip("sends an authorization request correctly in an Azure Fabric environment", async () => {
it("sends an authorization request correctly in an Azure Fabric environment", async () => {
// Trigger App Service behavior by setting environment variables
process.env.IDENTITY_ENDPOINT = "https://endpoint";
process.env.IDENTITY_HEADER = "secret";
Expand All @@ -463,7 +460,7 @@ describe("ManagedIdentityCredential", function() {
credential: new ManagedIdentityCredential("client"),
secureResponses: [
createResponse(200, {
token: "token",
access_token: "token",
expires_on: 1
})
]
Expand Down

0 comments on commit 04c45d1

Please sign in to comment.