From 83ba6d2f8f066905a63e3301ce7dc15d1a5f382a Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:03:23 -0500 Subject: [PATCH 1/6] azure: Change the typings of the created clients --- azure/package-lock.json | 45 ++++++++++++------- azure/package.json | 4 +- azure/src/clients.ts | 34 +++++++++----- azure/src/tree/RoleDefinitionsItem.ts | 7 ++- azure/src/wizard/RoleAssignmentExecuteStep.ts | 13 +++++- azure/src/wizard/StorageAccountNameStep.ts | 5 +-- 6 files changed, 73 insertions(+), 35 deletions(-) diff --git a/azure/package-lock.json b/azure/package-lock.json index 05770ec620..0adeb4d48f 100644 --- a/azure/package-lock.json +++ b/azure/package-lock.json @@ -12,10 +12,10 @@ "@azure/arm-authorization": "^9.0.0", "@azure/arm-authorization-profile-2020-09-01-hybrid": "^2.1.0", "@azure/arm-msi": "^2.2.0", - "@azure/arm-resources": "^5.0.0", + "@azure/arm-resources": "^7.0.0", "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.1.0", "@azure/arm-resources-subscriptions": "^2.1.0", - "@azure/arm-storage": "^18.6.0", + "@azure/arm-storage": "^19.1.0", "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.1.0", "@azure/core-client": "^1.10.1", "@azure/core-rest-pipeline": "^1.22.2", @@ -99,20 +99,21 @@ } }, "node_modules/@azure/arm-resources": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.2.0.tgz", - "integrity": "sha512-wQyuhL8WQsLkW/KMdik8bLJIJCz3Z6mg/+AKm0KedgK73SKhicSqYP+ed3t+43tLlRFltcrmGKMcHLQ+Jhv/6A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-7.0.0.tgz", + "integrity": "sha512-ezC1YLuPp1bh0GQFALcBvBxAB+9H5O0ynS40jp1t6hTlYe2t61cSplM3M4+4+nt9FCFZOjQSgAwj4KWYb8gruA==", + "license": "MIT", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.7.0", - "@azure/core-lro": "^2.5.0", - "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.8.0", - "tslib": "^2.2.0" + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-lro": "^2.5.4", + "@azure/core-paging": "^1.6.2", + "@azure/core-rest-pipeline": "^1.19.0", + "tslib": "^2.8.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" } }, "node_modules/@azure/arm-resources-profile-2020-09-01-hybrid": { @@ -148,10 +149,22 @@ "node": ">=14.0.0" } }, + "node_modules/@azure/arm-resources/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@azure/arm-storage": { - "version": "18.6.0", - "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-18.6.0.tgz", - "integrity": "sha512-dyN50fxts2xClCLIQY8qoDepYx2ql/eW5cVOy8XP+5zt9wIr1cgN2Mmv9/so2HDg6M/zOz8LhrvY+bS2blbhDQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@azure/arm-storage/-/arm-storage-19.1.0.tgz", + "integrity": "sha512-eGwTw2lHVgAXNMOFN2Y6wWmZ700/Payubig4fSf0Yaz9nn3UzNqNor57wEtCxf4VxuhoXcD8k2bisjddu4jNGQ==", "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.1.2", diff --git a/azure/package.json b/azure/package.json index bad7a0db3f..a889f7730b 100644 --- a/azure/package.json +++ b/azure/package.json @@ -39,10 +39,10 @@ "@azure/arm-authorization": "^9.0.0", "@azure/arm-authorization-profile-2020-09-01-hybrid": "^2.1.0", "@azure/arm-msi": "^2.2.0", - "@azure/arm-resources": "^5.0.0", + "@azure/arm-resources": "^7.0.0", "@azure/arm-resources-profile-2020-09-01-hybrid": "^2.1.0", "@azure/arm-resources-subscriptions": "^2.1.0", - "@azure/arm-storage": "^18.6.0", + "@azure/arm-storage": "^19.1.0", "@azure/arm-storage-profile-2020-09-01-hybrid": "^2.1.0", "@azure/core-client": "^1.10.1", "@azure/core-rest-pipeline": "^1.22.2", diff --git a/azure/src/clients.ts b/azure/src/clients.ts index e5e3d36911..0dc10bc5f5 100644 --- a/azure/src/clients.ts +++ b/azure/src/clients.ts @@ -3,45 +3,55 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import type { AuthorizationManagementClient } from '@azure/arm-authorization'; +import type { AuthorizationManagementClient as AMC } from '@azure/arm-authorization'; +import type { AuthorizationManagementClient as PAMC } from '@azure/arm-authorization-profile-2020-09-01-hybrid'; import type { ManagedServiceIdentityClient } from '@azure/arm-msi'; -import type { ResourceManagementClient } from '@azure/arm-resources'; +import type { ResourceManagementClient as RMC } from '@azure/arm-resources'; +import type { ResourceManagementClient as PRMC } from '@azure/arm-resources-profile-2020-09-01-hybrid'; import type { SubscriptionClient } from '@azure/arm-resources-subscriptions'; -import type { StorageManagementClient } from '@azure/arm-storage'; -import type { AzExtClientType } from '../index'; +import type { StorageManagementClient as SMC } from '@azure/arm-storage'; +import type { StorageManagementClient as PSMC } from '@azure/arm-storage-profile-2020-09-01-hybrid'; import { createAzureClient, createAzureSubscriptionClient, InternalAzExtClientContext, parseClientContext } from './createAzureClient'; +export type CommonAuthorizationManagementClient = AMC | PAMC; +export type CommonResourcesClient = RMC | PRMC; +export type CommonStorageManagementClient = SMC | PSMC; + // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript -export async function createStorageClient(context: InternalAzExtClientContext): Promise { +export async function createStorageClient(context: InternalAzExtClientContext): Promise { if (parseClientContext(context).isCustomCloud) { - return createAzureClient(context, (await import('@azure/arm-storage-profile-2020-09-01-hybrid')).StorageManagementClient); + return createAzureClient(context, (await import('@azure/arm-storage-profile-2020-09-01-hybrid')).StorageManagementClient); } else { - return createAzureClient(context, (await import('@azure/arm-storage')).StorageManagementClient as unknown as AzExtClientType); + return createAzureClient(context, (await import('@azure/arm-storage')).StorageManagementClient); } } -export async function createResourcesClient(context: InternalAzExtClientContext): Promise { +export async function createResourcesClient(context: InternalAzExtClientContext): Promise { if (parseClientContext(context).isCustomCloud) { - return createAzureClient(context, (await import('@azure/arm-resources-profile-2020-09-01-hybrid')).ResourceManagementClient); + return createAzureClient(context, (await import('@azure/arm-resources-profile-2020-09-01-hybrid')).ResourceManagementClient); } else { return createAzureClient(context, (await import('@azure/arm-resources')).ResourceManagementClient); } } export async function createManagedServiceIdentityClient(context: InternalAzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-msi')).ManagedServiceIdentityClient as unknown as AzExtClientType); + return createAzureClient(context, (await import('@azure/arm-msi')).ManagedServiceIdentityClient); } -export async function createAuthorizationManagementClient(context: InternalAzExtClientContext): Promise { +export async function createAuthorizationManagementClient(context: InternalAzExtClientContext): Promise { if (parseClientContext(context).isCustomCloud) { - return createAzureClient(context, (await import('@azure/arm-authorization-profile-2020-09-01-hybrid')).AuthorizationManagementClient); + return createAzureClient(context, (await import('@azure/arm-authorization-profile-2020-09-01-hybrid')).AuthorizationManagementClient); } else { return createAzureClient(context, (await import('@azure/arm-authorization')).AuthorizationManagementClient); } } +export function isProfileAuthorizationManagementClient(client: CommonAuthorizationManagementClient): client is PAMC { + return !('listForSubscription' in client.roleAssignments); +} + export async function createSubscriptionsClient(context: InternalAzExtClientContext): Promise { return createAzureSubscriptionClient(context, (await import('@azure/arm-resources-subscriptions')).SubscriptionClient); } diff --git a/azure/src/tree/RoleDefinitionsItem.ts b/azure/src/tree/RoleDefinitionsItem.ts index 199cde3868..259576b001 100644 --- a/azure/src/tree/RoleDefinitionsItem.ts +++ b/azure/src/tree/RoleDefinitionsItem.ts @@ -9,7 +9,7 @@ import { AzExtParentTreeItem, AzExtTreeItem, createGenericElement, createSubscri import { AzExtResourceType, AzureSubscription, getAzExtResourceType } from "@microsoft/vscode-azureresources-api"; import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from "vscode"; import * as types from '../../index'; -import { createAuthorizationManagementClient, createSubscriptionsClient } from "../clients"; +import { createAuthorizationManagementClient, createSubscriptionsClient, isProfileAuthorizationManagementClient } from "../clients"; import { createPortalUri } from "../utils/createPortalUri"; import { parseAzureResourceGroupId, parseAzureResourceId } from "../utils/parseAzureResourceId"; import { uiUtils } from "../utils/uiUtils"; @@ -18,6 +18,11 @@ import { getAzureIconPath } from "./IconPath"; export async function createRoleDefinitionsItems(context: IActionContext, subscription: AzureSubscription | ISubscriptionContext, msi: Identity, parentResourceId: string): Promise { const subContext = isAzureSubscription(subscription) ? createSubscriptionContext(subscription) : subscription; const authClient = await createAuthorizationManagementClient([context, subContext]); + + if (isProfileAuthorizationManagementClient(authClient)) { + throw new Error('TODO: no can do boss'); + } + const roleAssignment = await uiUtils.listAllIterator(authClient.roleAssignments.listForSubscription()); // filter the role assignments to only show the ones that are assigned to the msi const roleAssignments = roleAssignment.filter((ra) => ra.principalId === msi.principalId); diff --git a/azure/src/wizard/RoleAssignmentExecuteStep.ts b/azure/src/wizard/RoleAssignmentExecuteStep.ts index 3fef3ec99b..e4c3fef99b 100644 --- a/azure/src/wizard/RoleAssignmentExecuteStep.ts +++ b/azure/src/wizard/RoleAssignmentExecuteStep.ts @@ -81,7 +81,18 @@ class SingleRoleAssignmentExecuteStep { + private async validateStorageAccountName(client: CommonStorageManagementClient, name: string): Promise { name = name.trim(); if (!name || name.length < storageAccountNamingRules.minLength || name.length > storageAccountNamingRules.maxLength) { return vscode.l10n.t('The name must be between {0} and {1} characters.', storageAccountNamingRules.minLength, storageAccountNamingRules.maxLength); From e9838e8e5b53f9d31092fa52873cc78c3969dca4 Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:05:59 -0500 Subject: [PATCH 2/6] Fix CJS build --- azure/src/clients.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/azure/src/clients.ts b/azure/src/clients.ts index 0dc10bc5f5..b293717451 100644 --- a/azure/src/clients.ts +++ b/azure/src/clients.ts @@ -11,6 +11,7 @@ import type { ResourceManagementClient as PRMC } from '@azure/arm-resources-prof import type { SubscriptionClient } from '@azure/arm-resources-subscriptions'; import type { StorageManagementClient as SMC } from '@azure/arm-storage'; import type { StorageManagementClient as PSMC } from '@azure/arm-storage-profile-2020-09-01-hybrid'; +import type { AzExtClientType } from '../index'; import { createAzureClient, createAzureSubscriptionClient, InternalAzExtClientContext, parseClientContext } from './createAzureClient'; export type CommonAuthorizationManagementClient = AMC | PAMC; @@ -24,7 +25,7 @@ export async function createStorageClient(context: InternalAzExtClientContext): if (parseClientContext(context).isCustomCloud) { return createAzureClient(context, (await import('@azure/arm-storage-profile-2020-09-01-hybrid')).StorageManagementClient); } else { - return createAzureClient(context, (await import('@azure/arm-storage')).StorageManagementClient); + return createAzureClient(context, (await import('@azure/arm-storage')).StorageManagementClient as unknown as AzExtClientType); } } @@ -37,7 +38,7 @@ export async function createResourcesClient(context: InternalAzExtClientContext) } export async function createManagedServiceIdentityClient(context: InternalAzExtClientContext): Promise { - return createAzureClient(context, (await import('@azure/arm-msi')).ManagedServiceIdentityClient); + return createAzureClient(context, (await import('@azure/arm-msi')).ManagedServiceIdentityClient as unknown as AzExtClientType); } export async function createAuthorizationManagementClient(context: InternalAzExtClientContext): Promise { From df2195fbc428ea81021937a8cafb5344909486f3 Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:06:08 -0500 Subject: [PATCH 3/6] Bump major version --- azure/package-lock.json | 4 ++-- azure/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azure/package-lock.json b/azure/package-lock.json index 0adeb4d48f..2b9336d885 100644 --- a/azure/package-lock.json +++ b/azure/package-lock.json @@ -1,12 +1,12 @@ { "name": "@microsoft/vscode-azext-azureutils", - "version": "4.0.1", + "version": "5.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@microsoft/vscode-azext-azureutils", - "version": "4.0.1", + "version": "5.0.0", "license": "MIT", "dependencies": { "@azure/arm-authorization": "^9.0.0", diff --git a/azure/package.json b/azure/package.json index a889f7730b..8c7ad07f69 100644 --- a/azure/package.json +++ b/azure/package.json @@ -1,7 +1,7 @@ { "name": "@microsoft/vscode-azext-azureutils", "author": "Microsoft Corporation", - "version": "4.0.1", + "version": "5.0.0", "description": "Common Azure utils for developing Azure extensions for VS Code", "tags": [ "azure", From 1d560771b8180ea159f2ee70072e8d7991fbc96f Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:09:00 -0500 Subject: [PATCH 4/6] Less changes --- azure/src/clients.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/azure/src/clients.ts b/azure/src/clients.ts index b293717451..3f601070b9 100644 --- a/azure/src/clients.ts +++ b/azure/src/clients.ts @@ -3,20 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import type { AuthorizationManagementClient as AMC } from '@azure/arm-authorization'; +import type { AuthorizationManagementClient } from '@azure/arm-authorization'; import type { AuthorizationManagementClient as PAMC } from '@azure/arm-authorization-profile-2020-09-01-hybrid'; import type { ManagedServiceIdentityClient } from '@azure/arm-msi'; -import type { ResourceManagementClient as RMC } from '@azure/arm-resources'; +import type { ResourceManagementClient } from '@azure/arm-resources'; import type { ResourceManagementClient as PRMC } from '@azure/arm-resources-profile-2020-09-01-hybrid'; import type { SubscriptionClient } from '@azure/arm-resources-subscriptions'; -import type { StorageManagementClient as SMC } from '@azure/arm-storage'; +import type { StorageManagementClient } from '@azure/arm-storage'; import type { StorageManagementClient as PSMC } from '@azure/arm-storage-profile-2020-09-01-hybrid'; import type { AzExtClientType } from '../index'; import { createAzureClient, createAzureSubscriptionClient, InternalAzExtClientContext, parseClientContext } from './createAzureClient'; -export type CommonAuthorizationManagementClient = AMC | PAMC; -export type CommonResourcesClient = RMC | PRMC; -export type CommonStorageManagementClient = SMC | PSMC; +export type CommonAuthorizationManagementClient = AuthorizationManagementClient | PAMC; +export type CommonResourcesClient = ResourceManagementClient | PRMC; +export type CommonStorageManagementClient = StorageManagementClient | PSMC; // Lazy-load @azure packages to improve startup performance. // NOTE: The client is the only import that matters, the rest of the types disappear when compiled to JavaScript @@ -25,7 +25,7 @@ export async function createStorageClient(context: InternalAzExtClientContext): if (parseClientContext(context).isCustomCloud) { return createAzureClient(context, (await import('@azure/arm-storage-profile-2020-09-01-hybrid')).StorageManagementClient); } else { - return createAzureClient(context, (await import('@azure/arm-storage')).StorageManagementClient as unknown as AzExtClientType); + return createAzureClient(context, (await import('@azure/arm-storage')).StorageManagementClient as unknown as AzExtClientType); } } From 80087c5b37baf577a357f44637a367fba1e4e807 Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:13:47 -0500 Subject: [PATCH 5/6] Fix build --- azure/src/clients.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure/src/clients.ts b/azure/src/clients.ts index 3f601070b9..bea4fdafe7 100644 --- a/azure/src/clients.ts +++ b/azure/src/clients.ts @@ -33,7 +33,7 @@ export async function createResourcesClient(context: InternalAzExtClientContext) if (parseClientContext(context).isCustomCloud) { return createAzureClient(context, (await import('@azure/arm-resources-profile-2020-09-01-hybrid')).ResourceManagementClient); } else { - return createAzureClient(context, (await import('@azure/arm-resources')).ResourceManagementClient); + return createAzureClient(context, (await import('@azure/arm-resources')).ResourceManagementClient as unknown as AzExtClientType); } } From fd19440a7006cdfd26b9dd98c0d32af04f111ddc Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:18:00 -0500 Subject: [PATCH 6/6] Update index --- azure/index.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure/index.d.ts b/azure/index.d.ts index 522ee85893..6fbf92711f 100644 --- a/azure/index.d.ts +++ b/azure/index.d.ts @@ -5,12 +5,12 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { AuthorizationManagementClient, type RoleDefinition } from '@azure/arm-authorization'; -import { Identity, ManagedServiceIdentityClient } from '@azure/arm-msi'; +import type { AuthorizationManagementClient, RoleDefinition } from '@azure/arm-authorization'; +import type { Identity, ManagedServiceIdentityClient } from '@azure/arm-msi'; import type { ExtendedLocation, ResourceGroup } from '@azure/arm-resources'; import type { Location } from '@azure/arm-resources-subscriptions'; import type { StorageAccount } from '@azure/arm-storage'; -import { type StorageManagementClient } from '@azure/arm-storage'; +import type { StorageManagementClient } from '@azure/arm-storage'; import type { ServiceClient, ServiceClientOptions } from '@azure/core-client'; import type { PagedAsyncIterableIterator } from '@azure/core-paging'; import type { PipelineRequestOptions, PipelineResponse } from '@azure/core-rest-pipeline';