Skip to content

Commit

Permalink
auth: Add changes to be compatible with the new tenant view (#1789)
Browse files Browse the repository at this point in the history
* Add changes for tenant view

* change

* pass in account instead of session

* use getSessionFromVSCode

* changes

* make account required

* get build to pass

* add requested changes

* requested change

* change documentation
  • Loading branch information
motm32 committed Sep 19, 2024
1 parent 89f4c59 commit 097963c
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 42 deletions.
12 changes: 6 additions & 6 deletions auth/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions auth/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@microsoft/vscode-azext-azureauth",
"author": "Microsoft Corporation",
"version": "2.5.0",
"version": "2.6.0",
"description": "Azure authentication helpers for Visual Studio Code",
"tags": [
"azure",
Expand Down Expand Up @@ -41,7 +41,7 @@
"@types/node-fetch": "2.6.7",
"@types/semver": "^7.3.9",
"@types/uuid": "^9.0.1",
"@types/vscode": "1.76.0",
"@types/vscode": "1.93.0",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@vscode/test-electron": "^2.3.8",
"eslint": "^8.34.0",
Expand Down
4 changes: 4 additions & 0 deletions auth/src/AzureDevOpsSubscriptionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ export class AzureDevOpsSubscriptionProvider implements AzureSubscriptionProvide
subscriptionId: subscription.subscriptionId!,
/* eslint-enable @typescript-eslint/no-non-null-assertion */
tenantId,
account: {
id: "test-account-id",
label: "test-account",
},
});
}

Expand Down
8 changes: 7 additions & 1 deletion auth/src/AzureSubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import type { TokenCredential } from '@azure/core-auth';
import type { Environment } from '@azure/ms-rest-azure-env';
import type { AzureAuthentication } from './AzureAuthentication';
import * as vscode from "vscode";
import { AzureAuthentication } from './AzureAuthentication';

/**
* A type representing an Azure subscription ID, not including the tenant ID.
Expand Down Expand Up @@ -55,4 +56,9 @@ export interface AzureSubscription {
* The credential for authentication to this subscription. Compatible with Azure track 2 SDKs.
*/
readonly credential: TokenCredential;

/**
* The account associated with this subscription.
*/
readonly account: vscode.AuthenticationSessionAccountInformation;
}
6 changes: 4 additions & 2 deletions auth/src/AzureSubscriptionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import type { TenantIdDescription } from '@azure/arm-resources-subscriptions';
import type * as vscode from 'vscode';
import type { AzureSubscription } from './AzureSubscription';
import type { TenantIdDescription } from '@azure/arm-resources-subscriptions';

/**
* An interface for obtaining Azure subscription information
Expand All @@ -15,9 +15,11 @@ export interface AzureSubscriptionProvider {
* Gets a list of tenants available to the user.
* Use {@link isSignedIn} to check if the user is signed in to a particular tenant.
*
* @param account - Optionally pass in a specific account to get tenants for.
*
* @returns A list of tenants.
*/
getTenants(): Promise<TenantIdDescription[]>;
getTenants(account?: vscode.AuthenticationSessionAccountInformation): Promise<TenantIdDescription[]>;

/**
* Gets a list of Azure subscriptions available to the user.
Expand Down
72 changes: 42 additions & 30 deletions auth/src/VSCodeAzureSubscriptionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import type { SubscriptionClient, TenantIdDescription } from '@azure/arm-resources-subscriptions'; // Keep this as `import type` to avoid actually loading the package before necessary
import type { TokenCredential } from '@azure/core-auth'; // Keep this as `import type` to avoid actually loading the package (at all, this one is dev-only)
import * as vscode from 'vscode';
import type { AzureAuthentication } from './AzureAuthentication';
import type { AzureSubscription, SubscriptionId, TenantId } from './AzureSubscription';
import type { AzureSubscriptionProvider } from './AzureSubscriptionProvider';
import { NotSignedInError } from './NotSignedInError';
import { AzureAuthentication } from './AzureAuthentication';
import { AzureSubscription, SubscriptionId, TenantId } from './AzureSubscription';
import { AzureSubscriptionProvider } from './AzureSubscriptionProvider';
import { getSessionFromVSCode } from './getSessionFromVSCode';
import { NotSignedInError } from './NotSignedInError';
import { getConfiguredAuthProviderId, getConfiguredAzureEnv } from './utils/configuredAzureEnv';

const EventDebounce = 5 * 1000; // 5 seconds
Expand Down Expand Up @@ -56,15 +56,19 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
* Gets a list of tenants available to the user.
* Use {@link isSignedIn} to check if the user is signed in to a particular tenant.
*
* @param account (Optional) A specific account to get tenants for. If not provided, all accounts will be used.
*
* @returns A list of tenants.
*/
public async getTenants(): Promise<TenantIdDescription[]> {
const { client } = await this.getSubscriptionClient();

public async getTenants(account?: vscode.AuthenticationSessionAccountInformation): Promise<TenantIdDescription[]> {
const results: TenantIdDescription[] = [];

for await (const tenant of client.tenants.list()) {
results.push(tenant);
for await (account of account ? [account] : await vscode.authentication.getAccounts(getConfiguredAuthProviderId())) {
const { client } = await this.getSubscriptionClient(account, undefined, undefined);

for await (const tenant of client.tenants.list()) {
results.push(tenant);
}
}

return results;
Expand All @@ -91,23 +95,26 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
try {
this.suppressSignInEvents = true;

// Get the list of tenants
for (const tenant of await this.getTenants()) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const tenantId = tenant.tenantId!;

// If filtering is enabled, and the current tenant is not in that list, then skip it
if (shouldFilterTenants && !tenantIds.includes(tenantId)) {
continue;
}

// If the user is not signed in to this tenant, then skip it
if (!(await this.isSignedIn(tenantId))) {
continue;
// Get the list of tenants from each account
const accounts = await vscode.authentication.getAccounts(getConfiguredAuthProviderId());
for (const account of accounts) {
for (const tenant of await this.getTenants(account)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const tenantId = tenant.tenantId!;

// If filtering is enabled, and the current tenant is not in that list, then skip it
if (shouldFilterTenants && !tenantIds.includes(tenantId)) {
continue;
}

// If the user is not signed in to this tenant, then skip it
if (!(await this.isSignedIn(tenantId))) {
continue;
}

// For each tenant, get the list of subscriptions
results.push(...await this.getSubscriptionsForTenant(tenantId, account));
}

// For each tenant, get the list of subscriptions
results.push(...await this.getSubscriptionsForTenant(tenantId));
}
} finally {
this.suppressSignInEvents = false;
Expand Down Expand Up @@ -204,11 +211,12 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
* Gets the subscriptions for a given tenant.
*
* @param tenantId The tenant ID to get subscriptions for.
* @param account The account to get the subscriptions for.
*
* @returns The list of subscriptions for the tenant.
*/
private async getSubscriptionsForTenant(tenantId: string): Promise<AzureSubscription[]> {
const { client, credential, authentication } = await this.getSubscriptionClient(tenantId);
private async getSubscriptionsForTenant(tenantId: string, account: vscode.AuthenticationSessionAccountInformation): Promise<AzureSubscription[]> {
const { client, credential, authentication } = await this.getSubscriptionClient(account, tenantId, undefined);
const environment = getConfiguredAzureEnv();

const subscriptions: AzureSubscription[] = [];
Expand All @@ -224,6 +232,7 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
subscriptionId: subscription.subscriptionId!,
/* eslint-enable @typescript-eslint/no-non-null-assertion */
tenantId: tenantId,
account: account
});
}

Expand All @@ -234,12 +243,15 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
* Gets a fully-configured subscription client for a given tenant ID
*
* @param tenantId (Optional) The tenant ID to get a client for
* @param account The account that you would like to get the session for
*
* @returns A client, the credential used by the client, and the authentication function
*/
private async getSubscriptionClient(tenantId?: string, scopes?: string[]): Promise<{ client: SubscriptionClient, credential: TokenCredential, authentication: AzureAuthentication }> {
private async getSubscriptionClient(account: vscode.AuthenticationSessionAccountInformation, tenantId?: string, scopes?: string[]): Promise<{ client: SubscriptionClient, credential: TokenCredential, authentication: AzureAuthentication }> {
const armSubs = await import('@azure/arm-resources-subscriptions');
const session = await getSessionFromVSCode(scopes, tenantId, { createIfNone: false, silent: true });

const session = await getSessionFromVSCode(scopes, tenantId, { createIfNone: false, silent: true, account });

if (!session) {
throw new NotSignedInError();
}
Expand All @@ -262,7 +274,7 @@ export class VSCodeAzureSubscriptionProvider extends vscode.Disposable implement
authentication: {
getSession: () => session,
getSessionWithScopes: (scopes) => {
return getSessionFromVSCode(scopes, tenantId, { createIfNone: false, silent: true })
return getSessionFromVSCode(scopes, tenantId, { createIfNone: false, silent: true, account });
},
}
};
Expand Down
2 changes: 1 addition & 1 deletion auth/src/getSessionFromVSCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { getConfiguredAuthProviderId, getConfiguredAzureEnv } from "./utils/configuredAzureEnv";
import * as vscode from "vscode";
import { getConfiguredAuthProviderId, getConfiguredAzureEnv } from "./utils/configuredAzureEnv";

function ensureEndingSlash(value: string): string {
return value.endsWith('/') ? value : `${value}/`;
Expand Down

0 comments on commit 097963c

Please sign in to comment.