diff --git a/common-npm-packages/azure-arm-rest/Tests/azure-arm-app-service-tests.ts b/common-npm-packages/azure-arm-rest/Tests/azure-arm-app-service-tests.ts index ae2dd248..71ac2305 100644 --- a/common-npm-packages/azure-arm-rest/Tests/azure-arm-app-service-tests.ts +++ b/common-npm-packages/azure-arm-rest/Tests/azure-arm-app-service-tests.ts @@ -4,6 +4,8 @@ import { AzureEndpoint } from '../azureModels'; import * as querystring from 'querystring'; import tl = require('azure-pipelines-task-lib/task'); var endpoint = getMockEndpoint(); +var msi2018endpoint = getMockEndpoint("ManagedServiceIdentity"); +var msi2019endpoint = getMockEndpoint("ManagedServiceIdentity", null, true); mockAzureAppServiceTests(); @@ -114,8 +116,8 @@ class AzureAppServiceTests { }); } - public static async get() { - var appSerivce: AzureAppService = new AzureAppService(endpoint, "MOCK_RESOURCE_GROUP_NAME", "MOCK_APP_SERVICE_NAME"); + public static async get(testEndpoint: AzureEndpoint) { + var appSerivce: AzureAppService = new AzureAppService(testEndpoint, "MOCK_RESOURCE_GROUP_NAME", "MOCK_APP_SERVICE_NAME"); try { var value = await appSerivce.get(); console.log('MOCK_APP_SERVICE_NAME ID: ' + value.id); @@ -125,7 +127,7 @@ class AzureAppServiceTests { tl.setResult(tl.TaskResult.Failed, 'AzureAppServiceTests.get() should have passed but failed'); } - var appSerivceSlot: AzureAppService = new AzureAppService(endpoint, "MOCK_RESOURCE_GROUP_NAME", "MOCK_APP_SERVICE_NAME", "MOCK_SLOT_NAME"); + var appSerivceSlot: AzureAppService = new AzureAppService(testEndpoint, "MOCK_RESOURCE_GROUP_NAME", "MOCK_APP_SERVICE_NAME", "MOCK_SLOT_NAME"); try { await appSerivceSlot.get(); tl.setResult(tl.TaskResult.Failed, 'AzureAppServiceTests.get() should have failed but passed'); @@ -368,7 +370,7 @@ async function RUNTESTS() { await AzureAppServiceTests.swap(); await AzureAppServiceTests.swapSlotWithPreview(); await AzureAppServiceTests.cancelSwapSlotWithPreview(); - await AzureAppServiceTests.get(); + await AzureAppServiceTests.get(endpoint); await AzureAppServiceTests.getPublishingProfileWithSecrets(); await AzureAppServiceTests.getPublishingCredentials(); await AzureAppServiceTests.getApplicationSettings(); @@ -378,6 +380,10 @@ async function RUNTESTS() { await AzureAppServiceTests.patchConfiguration(); await AzureAppServiceTests.getMetadata(); await AzureAppServiceTests.updateMetadata(); + + // Test MSI behaviors + await AzureAppServiceTests.get(msi2018endpoint); + await AzureAppServiceTests.get(msi2019endpoint); } -RUNTESTS(); \ No newline at end of file +RUNTESTS(); diff --git a/common-npm-packages/azure-arm-rest/Tests/mock_utils.ts b/common-npm-packages/azure-arm-rest/Tests/mock_utils.ts index 81111e70..eb8825c9 100644 --- a/common-npm-packages/azure-arm-rest/Tests/mock_utils.ts +++ b/common-npm-packages/azure-arm-rest/Tests/mock_utils.ts @@ -4,7 +4,7 @@ import * as querystring from "querystring"; import { ApplicationTokenCredentials } from '../azure-arm-common'; export var nock = require('nock'); -export function getMockEndpoint(scheme?: string, msiClientId?: string) { +export function getMockEndpoint(scheme?: string, msiClientId?: string, mockMsi2019: boolean = false) { process.env["AZURE_HTTP_USER_AGENT"] = "TEST_AGENT"; var endpoint: AzureEndpoint = { @@ -37,13 +37,22 @@ export function getMockEndpoint(scheme?: string, msiClientId?: string) { access_token: "DUMMY_ACCESS_TOKEN" }).persist(); - let apiVersion = "2018-02-01"; + const tokenEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token"; + const reqheaders = { + "Metadata": true + }; + + if (mockMsi2019) { + const identityHeader = "00000000-0000-0000-0000-000000000000"; + process.env["IDENTITY_ENDPOINT"] = tokenEndpoint; + process.env["IDENTITY_HEADER"] = identityHeader; + reqheaders["X-Identity-Header"] = identityHeader; + } + let apiVersion = mockMsi2019 ? "2019-08-01" : "2018-02-01"; let msiClientIdUrl = msiClientId ? "&client_id=" + msiClientId : ""; - var msiUrl = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=" + apiVersion + "&resource=https://management.azure.com/" + msiClientIdUrl; + var msiUrl = tokenEndpoint + "?api-version=" + apiVersion + "&resource=https://management.azure.com/" + msiClientIdUrl; nock(msiUrl, { - reqheaders: { - "Metadata": true - } + reqheaders: reqheaders }) .get("/oauth2/token?resource=https://management.azure.com/") .reply(200, { @@ -718,4 +727,4 @@ export function mockAzureARMResourcesTests() { properties: {} }] }).persist(); -} \ No newline at end of file +} diff --git a/common-npm-packages/azure-arm-rest/azure-arm-common.ts b/common-npm-packages/azure-arm-rest/azure-arm-common.ts index c78816ca..b9eada5f 100644 --- a/common-npm-packages/azure-arm-rest/azure-arm-common.ts +++ b/common-npm-packages/azure-arm-rest/azure-arm-common.ts @@ -366,11 +366,16 @@ export class ApplicationTokenCredentials { // same for MSAL let webRequest = new webClient.WebRequest(); webRequest.method = "GET"; - let apiVersion = "2018-02-01"; - webRequest.uri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=" + apiVersion + "&resource=" + resourceId; + const useMsi2019 = process.env.IDENTITY_ENDPOINT && process.env.IDENTITY_HEADER; + const apiVersion = useMsi2019 ? "2019-08-01" : "2018-02-01"; + const tokenEndpoint = useMsi2019 ? process.env.IDENTITY_ENDPOINT : "http://169.254.169.254/metadata/identity/oauth2/token"; + webRequest.uri = `${tokenEndpoint}?api-version=${apiVersion}&resource=${resourceId}`; webRequest.headers = { "Metadata": true - }; + }; + if (useMsi2019) { + webRequest.headers["X-Identity-Header"] = process.env.IDENTITY_HEADER; + } webClient.sendRequest(webRequest).then( (response: webClient.WebResponse) => { @@ -703,4 +708,4 @@ function getJWT(url: string, clientId: string, tenantId: string, pemFilePath: st var token = jwt.sign(jwtObject, pemFileContent, { algorithm: 'RS256', header: additionalHeaders }); return token; -} \ No newline at end of file +}