Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
09b7250
Add changes for resources-api
MicroFish91 Nov 4, 2025
37147d3
Add changes to Azure Resources
MicroFish91 Nov 4, 2025
9920f41
Add todo
MicroFish91 Nov 4, 2025
611ab51
Some nits
MicroFish91 Nov 4, 2025
2f5d146
Misc changes
MicroFish91 Nov 6, 2025
bb212ab
Update error messages and readme
MicroFish91 Nov 6, 2025
a8d2e09
More updates to readme
MicroFish91 Nov 6, 2025
39e1b69
Update getAzureResourcesApi function signature
MicroFish91 Nov 6, 2025
18dce26
Void
MicroFish91 Nov 6, 2025
7d1dfdc
Clean up names some more
MicroFish91 Nov 6, 2025
f45cf0d
More updates to documentation
MicroFish91 Nov 6, 2025
3e80d80
Add logic for allowed extension ids
MicroFish91 Nov 6, 2025
183e4dc
Add important note
MicroFish91 Nov 6, 2025
79b7421
Use a set
MicroFish91 Nov 7, 2025
7dc9819
Simplify auth readme
MicroFish91 Nov 7, 2025
0b31112
WIP
MicroFish91 Nov 10, 2025
e1caffc
Revert package.json and package-lock.json
MicroFish91 Nov 10, 2025
1f5b406
Update api type def file
MicroFish91 Nov 10, 2025
b9af84e
Add azure tools publisher constant
MicroFish91 Nov 11, 2025
71f4f14
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 11, 2025
f188eca
Add auth tests and supporting logic
MicroFish91 Nov 11, 2025
e71785c
Update with better comments
MicroFish91 Nov 12, 2025
3f4cb3a
Revert launch change
MicroFish91 Nov 12, 2025
34d2f1a
Use extensionId var
MicroFish91 Nov 12, 2025
c34d952
Add note
MicroFish91 Nov 12, 2025
8079638
Update types, errors, and comments
MicroFish91 Nov 12, 2025
dbba10e
Update typings
MicroFish91 Nov 12, 2025
29e7976
Update comments
MicroFish91 Nov 12, 2025
5b0d57a
Merge with parent branch
MicroFish91 Nov 12, 2025
fa07ab1
Use an enum for error codes
MicroFish91 Nov 13, 2025
4e9e686
Update readme and comments
MicroFish91 Nov 13, 2025
4c49c09
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 13, 2025
0b1d03e
Update mock credential manager
MicroFish91 Nov 13, 2025
cb7b973
Update a comment
MicroFish91 Nov 13, 2025
570ecf4
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 13, 2025
03da414
Update enum formatting
MicroFish91 Nov 13, 2025
b446718
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 13, 2025
11d1ffa
Fix a typo
MicroFish91 Nov 13, 2025
0a7b447
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 13, 2025
4140cbf
Change comment casing
MicroFish91 Nov 13, 2025
3cf4fa3
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 13, 2025
69051c0
Remove part of a comment
MicroFish91 Nov 14, 2025
d178910
Update file structure, add capability for custom dependency injection
MicroFish91 Nov 19, 2025
a816d08
Remove a comment
MicroFish91 Nov 19, 2025
e433035
Merge with main + some new changes
MicroFish91 Nov 19, 2025
1718244
Fix formatting
MicroFish91 Nov 19, 2025
bb725ac
Add client related tests
MicroFish91 Nov 19, 2025
9ab914a
Fix some variable names
MicroFish91 Nov 19, 2025
06e2b99
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 19, 2025
d0eab17
Merge branch 'mwf/v4-tests' of https://github.com/microsoft/vscode-az…
MicroFish91 Nov 19, 2025
ef7ad23
Match to equal
MicroFish91 Nov 19, 2025
fb297bd
Merge branch 'mwf/v4-tests' of https://github.com/microsoft/vscode-az…
MicroFish91 Nov 19, 2025
0e438fa
semicolons
MicroFish91 Nov 19, 2025
97b1239
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 19, 2025
f22c0dc
Merge branch 'mwf/v4-tests' of https://github.com/microsoft/vscode-az…
MicroFish91 Nov 19, 2025
eda6ce6
Escape the symbol
MicroFish91 Nov 19, 2025
18db77c
Merge branch 'mwf/v4-tests' of https://github.com/microsoft/vscode-az…
MicroFish91 Nov 19, 2025
90fe885
Escape the symbol
MicroFish91 Nov 19, 2025
dbc30e6
Update a comment
MicroFish91 Nov 19, 2025
50026aa
Update another comment
MicroFish91 Nov 19, 2025
1c6db3b
Move client tools changes
MicroFish91 Nov 20, 2025
1f2bbf0
Add back in client tooling
MicroFish91 Nov 20, 2025
b5eb5f9
Merge branch 'mwf/v4-client-tools' of https://github.com/microsoft/vs…
MicroFish91 Nov 20, 2025
1b7eef5
Merge branch 'mwf/v4-tests' of https://github.com/microsoft/vscode-az…
MicroFish91 Nov 20, 2025
5a1ad77
Add back in some missing files that were moved
MicroFish91 Nov 20, 2025
b542c30
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 20, 2025
bf36371
Merge with main
MicroFish91 Nov 20, 2025
2580b09
Remove a var
MicroFish91 Nov 20, 2025
c9ce482
Semicolon
MicroFish91 Nov 20, 2025
54299f9
Preserve merge formatting
MicroFish91 Nov 20, 2025
16ba61a
Fix lint warning
MicroFish91 Nov 20, 2025
97bc6e8
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 20, 2025
81ce320
Merge with new eng package changes
MicroFish91 Nov 20, 2025
5c11b97
Inject more extension vars
MicroFish91 Nov 20, 2025
08b7d94
Revert unnecessary formats
MicroFish91 Nov 20, 2025
3817e17
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 20, 2025
ff9d912
Merge branch 'mwf/v4-client-tools' of https://github.com/microsoft/vs…
MicroFish91 Nov 20, 2025
6174219
Merge branch 'main' of https://github.com/microsoft/vscode-azureresou…
MicroFish91 Nov 21, 2025
f7f5026
Merge branch 'mwf/v4' of https://github.com/microsoft/vscode-azureres…
MicroFish91 Nov 21, 2025
1e9269d
Merge with main + add getUI
MicroFish91 Nov 21, 2025
8edafe9
Add type
MicroFish91 Nov 21, 2025
7807894
Merge with mwf/v4-tests
MicroFish91 Nov 21, 2025
62c9615
Remove extension bundle references
MicroFish91 Nov 21, 2025
5d0e4ad
Fix lint warning
MicroFish91 Nov 21, 2025
0d63c1c
Add an extra test
MicroFish91 Nov 21, 2025
20380f4
Merge branch 'mwf/v4-tests' of https://github.com/microsoft/vscode-az…
MicroFish91 Nov 21, 2025
475dfb0
Lint stuff
MicroFish91 Dec 4, 2025
3051f28
Merge with main
MicroFish91 Jan 27, 2026
398227e
Fix merge
MicroFish91 Jan 27, 2026
27c1f63
newline
MicroFish91 Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion api/src/auth/apiRequest/AzureResourcesApiRequestContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { AzureResourcesExtensionApi } from "../../extensionApi";
import { AzureResourcesExtensionApi, AzureResourcesExtensionAuthApi } from "../../extensionApi";
import { AzureExtensionApi } from "../../utils/apiUtils";
import { AzExtCredentialManager } from "../credentialManager/AzExtCredentialManager";
import { AzureResourcesApiRequestError } from "./apiRequestErrors";

export interface AzureResourcesApiRequestContext {
Expand All @@ -30,3 +31,19 @@ export interface AzureResourcesApiRequestContext {
*/
onApiRequestError?: (error: AzureResourcesApiRequestError) => void | Promise<void>;
}

// NOTE: Dependency injection options for tests; skip publically exporting this in the index
export interface CustomRequestDependenciesContext extends AzureResourcesApiRequestContext {
/**
* An optional credential manager used for issuing and verifying the client extensions credentials. If none are supplied, a simple UUID credential manager is used.
* @test Use this to more easily mock and inspect the behavior of the underlying credential manager.
*/
credentialManager?: AzExtCredentialManager;

/**
* An optional API provider to be used in lieu of the VS Code extension provider `vscode.extension.getExtension()`.
* This should _NOT_ be used in production environments.
* @test Use this to more easily mock and inject custom host extension API exports.
*/
hostApiProvider?: { getApi(): AzureResourcesExtensionAuthApi };
}
8 changes: 4 additions & 4 deletions api/src/auth/apiRequest/apiRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { AzureResourcesExtensionAuthApi } from "../../extensionApi";
import { apiUtils, AzureExtensionApi } from "../../utils/apiUtils";
import { AzExtCredentialManager } from "../credentialManager/AzExtCredentialManager";
import { AzExtUUIDCredentialManager } from "../credentialManager/AzExtUUIDCredentialManager";
import { AzureResourcesApiRequestContext } from "./AzureResourcesApiRequestContext";
import { AzureResourcesApiRequestContext, CustomRequestDependenciesContext } from "./AzureResourcesApiRequestContext";
import { AzureResourcesApiRequestErrorCode } from "./apiRequestErrors";

const azureResourcesAuthApiVersion: string = '^4.0.0';
Expand Down Expand Up @@ -38,7 +38,7 @@ export function prepareAzureResourcesApiRequest<T extends AzureExtensionApi>(con
throw new Error('You must specify at least one Azure Resources API version.');
}

const clientCredentialManager: AzExtCredentialManager = new AzExtUUIDCredentialManager();
const clientCredentialManager: AzExtCredentialManager = (context as CustomRequestDependenciesContext).credentialManager ?? new AzExtUUIDCredentialManager();

if (!clientExtensionApi.receiveAzureResourcesApiSession) {
clientExtensionApi.receiveAzureResourcesApiSession = createReceiveAzureResourcesApiSession(context, clientCredentialManager);
Expand All @@ -62,7 +62,7 @@ async function requestAzureResourcesSession(context: AzureResourcesApiRequestCon
}

try {
const resourcesAuthApi = await getExtensionApi<AzureResourcesExtensionAuthApi>(azureResourcesExtId, azureResourcesAuthApiVersion);
const resourcesAuthApi = (context as CustomRequestDependenciesContext).hostApiProvider?.getApi() ?? await getExtensionApi<AzureResourcesExtensionAuthApi>(azureResourcesExtId, azureResourcesAuthApiVersion);
await resourcesAuthApi.createAzureResourcesApiSession(context.clientExtensionId, clientApiVersion, clientCredential);
} catch (err) {
if (err instanceof Error) {
Expand Down Expand Up @@ -92,7 +92,7 @@ function createReceiveAzureResourcesApiSession(context: AzureResourcesApiRequest
}

try {
const resourcesAuthApi = await getExtensionApi<AzureResourcesExtensionAuthApi>(azureResourcesExtId, azureResourcesAuthApiVersion);
const resourcesAuthApi = (context as CustomRequestDependenciesContext).hostApiProvider?.getApi() ?? await getExtensionApi<AzureResourcesExtensionAuthApi>(azureResourcesExtId, azureResourcesAuthApiVersion);
const resourcesApis = await resourcesAuthApi.getAzureResourcesApis(context.clientExtensionId, azureResourcesCredential, context.azureResourcesApiVersions);
void context.onDidReceiveAzureResourcesApis(resourcesApis);
} catch (err) {
Expand Down
2 changes: 1 addition & 1 deletion api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

export * from './auth/apiRequest/apiRequest';
export * from './auth/apiRequest/apiRequestErrors';
export * from './auth/apiRequest/AzureResourcesApiRequestContext';
export { AzureResourcesApiRequestContext } from './auth/apiRequest/AzureResourcesApiRequestContext';
export * from './AzExtResourceType';
export * from './extensionApi';
export * from './getAzExtResourceType';
Expand Down
2 changes: 1 addition & 1 deletion src/testApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface TestApi {
* Get the output channel
*/
getOutputChannel(): IAzExtLogOutputChannel;

/**
* Get the focused group
*/
Expand Down
92 changes: 92 additions & 0 deletions test/api/auth/v4.client.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as assert from "assert";
import { AzureExtensionApi, AzureResourcesApiRequestContext, AzureResourcesApiRequestError, AzureResourcesApiRequestErrorCode, AzureResourcesExtensionApi, prepareAzureResourcesApiRequest } from "../../../api/src";
import { CustomRequestDependenciesContext } from "../../../api/src/auth/apiRequest/AzureResourcesApiRequestContext";
import { AzExtUUIDCredentialManager } from "../../../api/src/auth/credentialManager/AzExtUUIDCredentialManager";
import { createMockAuthApi } from "./mockAuthApi";

const clientExtensionId: string = 'ms-azuretools.vscode-azurecontainerapps';

suite('Azure Resources API client-side request tests', async () => {
test('prepareAzureResourcesApiRequest should successfully enable the handshake & return available APIs if on the allow list', async () => {
let receivedResourcesApis: (AzureExtensionApi | AzureResourcesExtensionApi | undefined)[] = [];

await new Promise<void>((resolve) => {
const timeout = setTimeout(resolve, 5000);

const requestContext: AzureResourcesApiRequestContext = {
clientExtensionId,
azureResourcesApiVersions: ['0.0.1', '^2.0.0'],
onDidReceiveAzureResourcesApis: (azureResourcesApis: (AzureExtensionApi | AzureResourcesExtensionApi | undefined)[]) => {
clearTimeout(timeout);
receivedResourcesApis = azureResourcesApis;
resolve();
},
onApiRequestError: () => {
clearTimeout(timeout);
resolve();
},
};

const coreClientExtensionApi: AzureExtensionApi = {
apiVersion: '1.0.0',
};

// Inject an external manager so the two preparation calls that follow will point to the same one
(requestContext as CustomRequestDependenciesContext).credentialManager = new AzExtUUIDCredentialManager();

// For testing, it is necessary to wire up both the client and host api provider to represent the parties on each side of the handshake.
// The prepare call needs to happen twice in order to set this scenario up - once to generate the client API for the host to point to,
// and then once more to pass that client to the host API for the final handshake method to point to.
//
// NOTE: This is not normally necessary since VS Code's API normally manages extension exports; however, this is not something we can rely on
// during tests because we need to be able to point to our own mocked APIs (which requires us to swap out the native VS Code extension provider).

const { clientApi } = prepareAzureResourcesApiRequest(requestContext, coreClientExtensionApi);
const hostApi = createMockAuthApi({ clientApiProvider: { getApi: () => clientApi } });
(requestContext as CustomRequestDependenciesContext).hostApiProvider = { getApi: () => hostApi };

const { requestResourcesApis } = prepareAzureResourcesApiRequest(requestContext, clientApi);
requestResourcesApis();
});

assert.equal(receivedResourcesApis[0]?.apiVersion, '0.0.1');
assert.match(receivedResourcesApis[1]?.apiVersion ?? '', /^2\./);
});

test('prepareAzureResourcesApiRequest should return an error if not on the allow list', async () => {
let receivedError: AzureResourcesApiRequestError | undefined;

await new Promise<void>((resolve) => {
const timeout = setTimeout(resolve, 5000);

const requestContext: AzureResourcesApiRequestContext = {
clientExtensionId: 'extension1',
azureResourcesApiVersions: ['0.0.1', '^2.0.0'],
onDidReceiveAzureResourcesApis: () => {
clearTimeout(timeout);
resolve();
},
onApiRequestError: (error: AzureResourcesApiRequestError) => {
clearTimeout(timeout);
receivedError = error;
resolve();
}
};

const coreClientExtensionApi: AzureExtensionApi = {
apiVersion: '1.0.0',
};

// We don't need to wire up the custom test api providers as we expect the initial call to fail before the host ever tries to reach back out to the client
const { requestResourcesApis } = prepareAzureResourcesApiRequest(requestContext, coreClientExtensionApi);
requestResourcesApis();
});

assert.equal(receivedError?.code, AzureResourcesApiRequestErrorCode.HostCreateSessionFailed);
});
});