@microsoft/vscode-azext-azureauth 5.1.1 → 6.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +9 -79
  3. package/dist/cjs/src/contracts/AzureAccount.js +7 -0
  4. package/dist/cjs/src/contracts/AzureSubscriptionProviderRequestOptions.js +48 -0
  5. package/dist/cjs/src/index.js +13 -10
  6. package/dist/cjs/src/providers/AzureDevOpsSubscriptionProvider.js +178 -0
  7. package/dist/cjs/src/providers/AzureSubscriptionProviderBase.js +393 -0
  8. package/dist/cjs/src/providers/VSCodeAzureSubscriptionProvider.js +269 -0
  9. package/dist/cjs/src/utils/Limiter.js +41 -0
  10. package/dist/cjs/src/{NotSignedInError.js → utils/NotSignedInError.js} +3 -2
  11. package/dist/cjs/src/utils/configuredAzureEnv.js +14 -16
  12. package/dist/cjs/src/utils/dedupeSubscriptions.js +27 -0
  13. package/dist/cjs/src/utils/getMetricsForTelemetry.js +47 -0
  14. package/dist/cjs/src/{getSessionFromVSCode.js → utils/getSessionFromVSCode.js} +5 -2
  15. package/dist/cjs/src/utils/getSignalForToken.js +29 -0
  16. package/dist/cjs/src/utils/map/CaselessMap.js +71 -0
  17. package/dist/cjs/src/utils/map/TwoKeyCaselessMap.js +194 -0
  18. package/dist/cjs/src/utils/screen.js +62 -0
  19. package/dist/cjs/src/{signInToTenant.js → utils/signInToTenant.js} +15 -13
  20. package/dist/cjs/src/utils/tryGetTokenExpiration.js +25 -0
  21. package/dist/esm/src/contracts/AzureAccount.d.ts +5 -0
  22. package/dist/esm/src/contracts/AzureAccount.js +6 -0
  23. package/dist/esm/src/{AzureAuthentication.d.ts → contracts/AzureAuthentication.d.ts} +1 -1
  24. package/dist/esm/src/{AzureSubscription.d.ts → contracts/AzureSubscription.d.ts} +4 -4
  25. package/dist/esm/src/contracts/AzureSubscriptionProvider.d.ts +112 -0
  26. package/dist/esm/src/contracts/AzureSubscriptionProviderRequestOptions.d.ts +103 -0
  27. package/dist/esm/src/contracts/AzureSubscriptionProviderRequestOptions.js +44 -0
  28. package/dist/esm/src/contracts/AzureTenant.d.ts +15 -0
  29. package/dist/esm/src/index.d.ts +13 -10
  30. package/dist/esm/src/index.js +13 -10
  31. package/dist/esm/src/providers/AzureDevOpsSubscriptionProvider.d.ts +68 -0
  32. package/dist/esm/src/providers/AzureDevOpsSubscriptionProvider.js +140 -0
  33. package/dist/esm/src/providers/AzureSubscriptionProviderBase.d.ts +74 -0
  34. package/dist/esm/src/providers/AzureSubscriptionProviderBase.js +356 -0
  35. package/dist/esm/src/providers/VSCodeAzureSubscriptionProvider.d.ts +70 -0
  36. package/dist/esm/src/providers/VSCodeAzureSubscriptionProvider.js +232 -0
  37. package/dist/esm/src/utils/Limiter.d.ts +9 -0
  38. package/dist/esm/src/utils/Limiter.js +37 -0
  39. package/dist/esm/src/{NotSignedInError.d.ts → utils/NotSignedInError.d.ts} +2 -2
  40. package/dist/esm/src/{NotSignedInError.js → utils/NotSignedInError.js} +3 -2
  41. package/dist/esm/src/utils/configuredAzureEnv.d.ts +7 -4
  42. package/dist/esm/src/utils/configuredAzureEnv.js +14 -16
  43. package/dist/esm/src/utils/dedupeSubscriptions.d.ts +14 -0
  44. package/dist/esm/src/utils/dedupeSubscriptions.js +24 -0
  45. package/dist/esm/src/utils/getMetricsForTelemetry.d.ts +32 -0
  46. package/dist/esm/src/utils/getMetricsForTelemetry.js +44 -0
  47. package/dist/esm/src/{getSessionFromVSCode.js → utils/getSessionFromVSCode.js} +5 -2
  48. package/dist/esm/src/utils/getSignalForToken.d.ts +7 -0
  49. package/dist/esm/src/utils/getSignalForToken.js +26 -0
  50. package/dist/esm/src/utils/map/CaselessMap.d.ts +28 -0
  51. package/dist/esm/src/utils/map/CaselessMap.js +67 -0
  52. package/dist/esm/src/utils/map/TwoKeyCaselessMap.d.ts +49 -0
  53. package/dist/esm/src/utils/map/TwoKeyCaselessMap.js +190 -0
  54. package/dist/esm/src/utils/screen.d.ts +9 -0
  55. package/dist/esm/src/utils/screen.js +59 -0
  56. package/dist/esm/src/utils/signInToTenant.d.ts +7 -0
  57. package/dist/esm/src/{signInToTenant.js → utils/signInToTenant.js} +16 -14
  58. package/dist/esm/src/utils/tryGetTokenExpiration.d.ts +2 -0
  59. package/dist/esm/src/utils/tryGetTokenExpiration.js +22 -0
  60. package/package.json +33 -23
  61. package/AzureFederatedCredentialsGuide.md +0 -174
  62. package/dist/cjs/src/AzureDevOpsSubscriptionProvider.js +0 -215
  63. package/dist/cjs/src/VSCodeAzureSubscriptionProvider.js +0 -395
  64. package/dist/cjs/src/utils/getUnauthenticatedTenants.js +0 -23
  65. package/dist/cjs/src/utils/isGetSubscriptionsFilter.js +0 -27
  66. package/dist/esm/src/AzureDevOpsSubscriptionProvider.d.ts +0 -68
  67. package/dist/esm/src/AzureDevOpsSubscriptionProvider.js +0 -210
  68. package/dist/esm/src/AzureSubscriptionProvider.d.ts +0 -82
  69. package/dist/esm/src/AzureTenant.d.ts +0 -5
  70. package/dist/esm/src/VSCodeAzureSubscriptionProvider.d.ts +0 -116
  71. package/dist/esm/src/VSCodeAzureSubscriptionProvider.js +0 -358
  72. package/dist/esm/src/signInToTenant.d.ts +0 -6
  73. package/dist/esm/src/utils/getUnauthenticatedTenants.d.ts +0 -9
  74. package/dist/esm/src/utils/getUnauthenticatedTenants.js +0 -20
  75. package/dist/esm/src/utils/isGetSubscriptionsFilter.d.ts +0 -14
  76. package/dist/esm/src/utils/isGetSubscriptionsFilter.js +0 -23
  77. /package/dist/cjs/src/{AzureAuthentication.js → contracts/AzureAuthentication.js} +0 -0
  78. /package/dist/cjs/src/{AzureSubscription.js → contracts/AzureSubscription.js} +0 -0
  79. /package/dist/cjs/src/{AzureSubscriptionProvider.js → contracts/AzureSubscriptionProvider.js} +0 -0
  80. /package/dist/cjs/src/{AzureTenant.js → contracts/AzureTenant.js} +0 -0
  81. /package/dist/esm/src/{AzureAuthentication.js → contracts/AzureAuthentication.js} +0 -0
  82. /package/dist/esm/src/{AzureSubscription.js → contracts/AzureSubscription.js} +0 -0
  83. /package/dist/esm/src/{AzureSubscriptionProvider.js → contracts/AzureSubscriptionProvider.js} +0 -0
  84. /package/dist/esm/src/{AzureTenant.js → contracts/AzureTenant.js} +0 -0
  85. /package/dist/esm/src/{getSessionFromVSCode.d.ts → utils/getSessionFromVSCode.d.ts} +0 -0
@@ -1,15 +1,15 @@
1
1
  import type { TokenCredential } from '@azure/core-auth';
2
2
  import type { Environment } from '@azure/ms-rest-azure-env';
3
- import type * as vscode from "vscode";
3
+ import type { AzureAccount } from './AzureAccount';
4
4
  import type { AzureAuthentication } from './AzureAuthentication';
5
5
  /**
6
6
  * A type representing an Azure subscription ID, not including the tenant ID.
7
7
  */
8
- export type SubscriptionId = string;
8
+ export type SubscriptionId = Readonly<string>;
9
9
  /**
10
10
  * A type representing an Azure tenant ID.
11
11
  */
12
- export type TenantId = string;
12
+ export type TenantId = Readonly<string>;
13
13
  /**
14
14
  * Represents an Azure subscription.
15
15
  */
@@ -45,5 +45,5 @@ export interface AzureSubscription {
45
45
  /**
46
46
  * The account associated with this subscription.
47
47
  */
48
- readonly account: vscode.AuthenticationSessionAccountInformation;
48
+ readonly account: AzureAccount;
49
49
  }
@@ -0,0 +1,112 @@
1
+ import type * as vscode from 'vscode';
2
+ import type { AzureAccount } from './AzureAccount';
3
+ import type { AzureSubscription } from './AzureSubscription';
4
+ import type { GetAccountsOptions, GetAvailableSubscriptionsOptions, GetSubscriptionsForTenantOptions, GetTenantsForAccountOptions, SignInOptions } from './AzureSubscriptionProviderRequestOptions';
5
+ import type { AzureTenant } from './AzureTenant';
6
+ /**
7
+ * An interface for obtaining Azure subscription information
8
+ */
9
+ export interface AzureSubscriptionProvider {
10
+ /**
11
+ * Fires when the list of available subscriptions may have changed, and a refresh is suggested.
12
+ * The callback will be given a {@link RefreshSuggestedEvent} with more information.
13
+ * @note This will be fired at most every 5 seconds, to avoid flooding. It is also suppressed
14
+ * during operations this provider is performing itself, such as during sign-in.
15
+ */
16
+ onRefreshSuggested: vscode.Event<RefreshSuggestedEvent>;
17
+ /**
18
+ * Signs in to Azure, if not already signed in. This will suppress {@link onRefreshSuggested} events until the sign-in is complete.
19
+ *
20
+ * @param tenant (Optional) If provided, signs in to the specified tenant and account.
21
+ * @param options (Optional) Additional options for signing in.
22
+ *
23
+ * @returns True if sign-in was successful, false otherwise.
24
+ */
25
+ signIn(tenant?: TenantIdAndAccount, options?: SignInOptions): Promise<boolean>;
26
+ /**
27
+ * The easier API. Across all accounts and all tenants*, returns the list of {@link AzureSubscription}s the user can access.
28
+ * No additional automatic sign-in is performed; unauthenticated accounts or tenants will simply be skipped.
29
+ *
30
+ * If you aren't interested in managing multiple accounts or tenant sign ins, this is the only method you need to call.
31
+ *
32
+ * The subscriptions will be deduplicated according to the strategy in {@link dedupeSubscriptions}. If you want a different
33
+ * strategy, you can use request all and deduplicate according to your needs.
34
+ *
35
+ * *The number of tenants processed will be limited to `options.maximumTenants` (default 10),
36
+ * to avoid excessive requests.
37
+ *
38
+ * @param options (Optional) Additional options for getting the subscriptions.
39
+ *
40
+ * @throws A {@link NotSignedInError} if the user is not signed in to any accounts. It will *not* throw if
41
+ * at least one account is signed in, even if no subscriptions are found.
42
+ * @throws A {@link vscode.CancellationError} if the operation is cancelled via the provided cancellation token.
43
+ */
44
+ getAvailableSubscriptions(options?: GetAvailableSubscriptionsOptions): Promise<AzureSubscription[]>;
45
+ /**
46
+ * Returns a list of all accounts. It is up to the caller to get tenants and subscriptions if needed, and the caller
47
+ * is also responsible for limiting the amount of subsequent requests made.
48
+ *
49
+ * @param options (Optional) Additional options for getting the accounts.
50
+ *
51
+ * @throws A {@link NotSignedInError} if the user is not signed in to any accounts.
52
+ * @throws A {@link vscode.CancellationError} if the operation is cancelled via the provided cancellation token.
53
+ */
54
+ getAccounts(options?: GetAccountsOptions): Promise<AzureAccount[]>;
55
+ /**
56
+ * Returns a list of all unauthenticated tenants for a given account.
57
+ *
58
+ * @param account The account to get unauthenticated tenants for.
59
+ * @param options (Optional) Additional options for getting the tenants.
60
+ *
61
+ * @throws A {@link NotSignedInError} if the user is not signed in to the specified account.
62
+ * @throws A {@link vscode.CancellationError} if the operation is cancelled via the provided cancellation token.
63
+ */
64
+ getUnauthenticatedTenantsForAccount(account: AzureAccount, options?: Omit<GetTenantsForAccountOptions, 'filter'>): Promise<AzureTenant[]>;
65
+ /**
66
+ * Returns a list of tenants for a given account. It is up to the caller to get subscriptions if needed, and the caller
67
+ * is also responsible for limiting the amount of subsequent requests made.
68
+ *
69
+ * @param account The account to get tenants for.
70
+ * @param options (Optional) Additional options for getting the tenants.
71
+ *
72
+ * @throws A {@link NotSignedInError} if the user is not signed in to the specified account.
73
+ * @throws A {@link vscode.CancellationError} if the operation is cancelled via the provided cancellation token.
74
+ */
75
+ getTenantsForAccount(account: AzureAccount, options?: GetTenantsForAccountOptions): Promise<AzureTenant[]>;
76
+ /**
77
+ * Returns a list of {@link AzureSubscription}s for a given tenant and account. The caller is responsible for
78
+ * limiting the amount of subsequent requests made.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const accounts = await subscriptionProvider.getAccounts();
83
+ * for (const account of accounts) {
84
+ * const tenants = await subscriptionProvider.getTenantsForAccount(account);
85
+ * for (const tenant of tenants) {
86
+ * const subscriptions = await subscriptionProvider.getSubscriptionsForTenant(tenant);
87
+ * // do something with subscriptions
88
+ * }
89
+ * }
90
+ * ```
91
+ *
92
+ * @param tenant The tenant (and account) to get subscriptions for.
93
+ * @param options (Optional) Additional options for getting the subscriptions.
94
+ *
95
+ * @throws A {@link NotSignedInError} if the user is not signed in to the specified account *and* tenant.
96
+ * @throws A {@link vscode.CancellationError} if the operation is cancelled via the provided cancellation token.
97
+ */
98
+ getSubscriptionsForTenant(tenant: TenantIdAndAccount, options?: GetSubscriptionsForTenantOptions): Promise<AzureSubscription[]>;
99
+ }
100
+ /**
101
+ * A type representing just the tenant ID and account information of an Azure tenant.
102
+ */
103
+ export type TenantIdAndAccount = Required<Pick<AzureTenant, 'tenantId' | 'account'>>;
104
+ /**
105
+ * Information included when a refresh is suggested.
106
+ */
107
+ export interface RefreshSuggestedEvent {
108
+ /**
109
+ * The reason a refresh was suggested.
110
+ */
111
+ reason: 'sessionChange' | 'subscriptionFilterChange';
112
+ }
@@ -0,0 +1,103 @@
1
+ import type * as vscode from 'vscode';
2
+ /**
3
+ * Options for signing in to a tenant.
4
+ */
5
+ export type SignInOptions = {
6
+ /**
7
+ * (Optional, default false) Whether to force the account picker to reappear.
8
+ * Equivalent to setting {@link vscode.AuthenticationGetSessionOptions.clearSessionPreference} to true.
9
+ */
10
+ clearSessionPreference?: boolean;
11
+ /**
12
+ * (Optional, default true) If true, the user will be prompted to sign in if needed.
13
+ * If false, the {@link AzureSubscriptionProvider.signIn} method will return false if
14
+ * interactive sign-in is required.
15
+ */
16
+ promptIfNeeded?: boolean;
17
+ };
18
+ /**
19
+ * Default options for signing in to a tenant
20
+ */
21
+ export declare const DefaultSignInOptions: {
22
+ readonly clearSessionPreference: false;
23
+ readonly promptIfNeeded: true;
24
+ };
25
+ /**
26
+ * Options for getting items from the subscription provider
27
+ * @note As needed, remember to update the {@link getCoalescenceKey} function when modifying this type.
28
+ */
29
+ export type BaseOptions = {
30
+ /**
31
+ * (Optional, default true) If true, only items explicitly selected by the user will be returned.
32
+ */
33
+ filter?: boolean;
34
+ /**
35
+ * (Optional, default false) Whether to bypass any cached data and refresh from the source.
36
+ *
37
+ * @note In the reference implementation, `VSCodeAzureSubscriptionProvider`, it is NOT necessary to use
38
+ * `noCache: true` in the following cases:
39
+ * - Subscription filters have changed (caching is done before filtering)
40
+ * - A new sign-in has occurred (a partial cache refill will occur automatically)
41
+ *
42
+ * It is only necessary to use `noCache: true` if you expect that the subscriptions/tenants that an
43
+ * account has access to have changed--e.g. a subscription is created or removed, or RBAC changes.
44
+ *
45
+ * @note When `noCache: true` is used, it applies *only to that function call*. The entire cache will
46
+ * not be cleared--only the data needed for that call will be refreshed.
47
+ */
48
+ noCache?: boolean;
49
+ /**
50
+ * (Optional) A cancellation token to cancel the operation.
51
+ */
52
+ token?: vscode.CancellationToken;
53
+ };
54
+ /**
55
+ * Options when requesting accounts
56
+ */
57
+ export type GetAccountsOptions = BaseOptions;
58
+ /**
59
+ * Options when requesting tenants for an account
60
+ */
61
+ export type GetTenantsForAccountOptions = BaseOptions;
62
+ /**
63
+ * Options when requesting subscriptions for a tenant+account
64
+ */
65
+ export type GetSubscriptionsForTenantOptions = BaseOptions & {
66
+ /**
67
+ * (Optional, default true) Whether to deduplicate the subscriptions returned, according to the
68
+ * strategy in {@link dedupeSubscriptions}.
69
+ */
70
+ dedupe?: boolean;
71
+ };
72
+ /**
73
+ * Options when requesting available subscriptions across all accounts and tenants.
74
+ */
75
+ export type GetAvailableSubscriptionsOptions = GetAccountsOptions & GetTenantsForAccountOptions & GetSubscriptionsForTenantOptions & {
76
+ /**
77
+ * (Optional, default 10) The maximum number of tenants for which to get subscriptions. This is
78
+ * necessary because each account+tenant requires a token request plus a subscription list request.
79
+ * No subscription list maximum is applied; once a tenant is reached, all its subscriptions are retrieved.
80
+ */
81
+ maximumTenants?: number;
82
+ };
83
+ /**
84
+ * The default options when getting available subscriptions.
85
+ * @note This same value also is passed as the default to all the get* methods, since it
86
+ * is a superset of all of the available options.
87
+ */
88
+ export declare const DefaultOptions: {
89
+ readonly filter: true;
90
+ readonly noCache: false;
91
+ readonly token: undefined;
92
+ readonly dedupe: true;
93
+ readonly maximumTenants: 10;
94
+ };
95
+ /**
96
+ * Gets a promise coalescence key for the given {@link GetAvailableSubscriptionsOptions}.
97
+ * @param options The options to get the key for
98
+ * @returns A string key for coalescing promises, or undefined if coalescing is not applicable
99
+ * @internal This should not be used by external code. This is placed here so it can be adjacent
100
+ * to the {@link GetAvailableSubscriptionsOptions} type, but should be used only by internal
101
+ * implementations
102
+ */
103
+ export declare function getCoalescenceKey(options: GetAvailableSubscriptionsOptions): string | undefined;
@@ -0,0 +1,44 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ /**
6
+ * Default options for signing in to a tenant
7
+ */
8
+ export const DefaultSignInOptions = {
9
+ clearSessionPreference: false,
10
+ promptIfNeeded: true,
11
+ };
12
+ /**
13
+ * The default options when getting available subscriptions.
14
+ * @note This same value also is passed as the default to all the get* methods, since it
15
+ * is a superset of all of the available options.
16
+ */
17
+ export const DefaultOptions = {
18
+ filter: true,
19
+ noCache: false,
20
+ token: undefined,
21
+ dedupe: true,
22
+ maximumTenants: 10,
23
+ };
24
+ /**
25
+ * Gets a promise coalescence key for the given {@link GetAvailableSubscriptionsOptions}.
26
+ * @param options The options to get the key for
27
+ * @returns A string key for coalescing promises, or undefined if coalescing is not applicable
28
+ * @internal This should not be used by external code. This is placed here so it can be adjacent
29
+ * to the {@link GetAvailableSubscriptionsOptions} type, but should be used only by internal
30
+ * implementations
31
+ */
32
+ export function getCoalescenceKey(options) {
33
+ // Never coalesce if there is a cancellation token--no way to do it safely
34
+ if (options.token) {
35
+ return undefined;
36
+ }
37
+ return Object
38
+ .keys(options)
39
+ .filter(k => k !== 'token') // ignore token
40
+ .sort()
41
+ .map(k => `${k}:${options[k] ?? DefaultOptions[k]}`)
42
+ .join(',');
43
+ }
44
+ //# sourceMappingURL=AzureSubscriptionProviderRequestOptions.js.map
@@ -0,0 +1,15 @@
1
+ import type { TenantIdDescription } from "@azure/arm-resources-subscriptions";
2
+ import type { AzureAccount } from "./AzureAccount";
3
+ /**
4
+ * An Azure tenant associated with a specific account
5
+ */
6
+ export interface AzureTenant extends TenantIdDescription {
7
+ /**
8
+ * The account associated with this tenant
9
+ */
10
+ readonly account: AzureAccount;
11
+ /**
12
+ * @inheritdoc
13
+ */
14
+ readonly tenantId: string;
15
+ }
@@ -1,11 +1,14 @@
1
- export * from './AzureAuthentication';
2
- export * from './AzureDevOpsSubscriptionProvider';
3
- export * from './AzureSubscription';
4
- export * from './AzureSubscriptionProvider';
5
- export * from './AzureTenant';
6
- export * from './getSessionFromVSCode';
7
- export * from './NotSignedInError';
8
- export * from './signInToTenant';
1
+ export * from './contracts/AzureAccount';
2
+ export * from './contracts/AzureAuthentication';
3
+ export * from './contracts/AzureSubscription';
4
+ export * from './contracts/AzureSubscriptionProvider';
5
+ export type * from './contracts/AzureSubscriptionProviderRequestOptions';
6
+ export * from './contracts/AzureTenant';
7
+ export * from './providers/AzureSubscriptionProviderBase';
8
+ export * from './providers/VSCodeAzureSubscriptionProvider';
9
9
  export * from './utils/configuredAzureEnv';
10
- export * from './utils/getUnauthenticatedTenants';
11
- export * from './VSCodeAzureSubscriptionProvider';
10
+ export * from './utils/dedupeSubscriptions';
11
+ export * from './utils/getMetricsForTelemetry';
12
+ export * from './utils/getSessionFromVSCode';
13
+ export * from './utils/NotSignedInError';
14
+ export * from './utils/signInToTenant';
@@ -2,15 +2,18 @@
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- export * from './AzureAuthentication';
6
- export * from './AzureDevOpsSubscriptionProvider';
7
- export * from './AzureSubscription';
8
- export * from './AzureSubscriptionProvider';
9
- export * from './AzureTenant';
10
- export * from './getSessionFromVSCode';
11
- export * from './NotSignedInError';
12
- export * from './signInToTenant';
5
+ export * from './contracts/AzureAccount';
6
+ export * from './contracts/AzureAuthentication';
7
+ export * from './contracts/AzureSubscription';
8
+ export * from './contracts/AzureSubscriptionProvider';
9
+ export * from './contracts/AzureTenant';
10
+ // The `AzureDevOpsSubscriptionProvider` is intentionally not exported, it must be imported from `'@microsoft/vscode-azext-azureauth/azdo'`
11
+ export * from './providers/AzureSubscriptionProviderBase';
12
+ export * from './providers/VSCodeAzureSubscriptionProvider';
13
13
  export * from './utils/configuredAzureEnv';
14
- export * from './utils/getUnauthenticatedTenants';
15
- export * from './VSCodeAzureSubscriptionProvider';
14
+ export * from './utils/dedupeSubscriptions';
15
+ export * from './utils/getMetricsForTelemetry';
16
+ export * from './utils/getSessionFromVSCode';
17
+ export * from './utils/NotSignedInError';
18
+ export * from './utils/signInToTenant';
16
19
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,68 @@
1
+ import type { SubscriptionClient } from '@azure/arm-resources-subscriptions';
2
+ import type { TokenCredential } from '@azure/core-auth';
3
+ import type * as vscode from 'vscode';
4
+ import type { AzureAccount } from '../contracts/AzureAccount';
5
+ import type { AzureAuthentication } from '../contracts/AzureAuthentication';
6
+ import type { TenantIdAndAccount } from '../contracts/AzureSubscriptionProvider';
7
+ import type { AzureTenant } from '../contracts/AzureTenant';
8
+ import { AzureSubscriptionProviderBase } from './AzureSubscriptionProviderBase';
9
+ export interface AzureDevOpsSubscriptionProviderInitializer {
10
+ /**
11
+ * The resource ID of the Azure DevOps federated service connection,
12
+ * which can be found on the `resourceId` field of the URL at the address bar
13
+ * when viewing the service connection in the Azure DevOps portal
14
+ */
15
+ serviceConnectionId: string;
16
+ /**
17
+ * The `Tenant ID` field of the service connection properties
18
+ */
19
+ tenantId: string;
20
+ /**
21
+ * The `Service Principal Id` field of the service connection properties
22
+ */
23
+ clientId: string;
24
+ }
25
+ export declare function createAzureDevOpsSubscriptionProviderFactory(initializer: AzureDevOpsSubscriptionProviderInitializer): () => Promise<AzureDevOpsSubscriptionProvider>;
26
+ /**
27
+ * AzureSubscriptionProvider implemented to authenticate via federated DevOps service connection, using workflow identity federation
28
+ * To learn how to configure your DevOps environment to use this provider, refer to the README.md
29
+ * NOTE: This provider is only available when running in an Azure DevOps pipeline
30
+ * Reference: https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation
31
+ */
32
+ export declare class AzureDevOpsSubscriptionProvider extends AzureSubscriptionProviderBase {
33
+ private _tokenCredential;
34
+ private _serviceConnectionId;
35
+ private _tenantId;
36
+ private _clientId;
37
+ constructor({ serviceConnectionId, tenantId, clientId }: AzureDevOpsSubscriptionProviderInitializer, logger?: vscode.LogOutputChannel);
38
+ /**
39
+ * For {@link AzureSubscriptionProviderBase}, this event will never fire
40
+ */
41
+ onRefreshSuggested: () => {
42
+ dispose: () => void;
43
+ };
44
+ /**
45
+ * For {@link AzureSubscriptionProviderBase}, this returns a single account with a fixed ID and label
46
+ */
47
+ getAccounts(): Promise<AzureAccount[]>;
48
+ /**
49
+ * For {@link AzureSubscriptionProviderBase}, this returns an empty array
50
+ */
51
+ getUnauthenticatedTenantsForAccount(): Promise<AzureTenant[]>;
52
+ /**
53
+ * For {@link AzureSubscriptionProviderBase}, this returns a single tenant associated with the service principal
54
+ */
55
+ getTenantsForAccount(account: AzureAccount): Promise<AzureTenant[]>;
56
+ /**
57
+ * @inheritdoc
58
+ */
59
+ signIn(): Promise<boolean>;
60
+ /**
61
+ * @inheritdoc
62
+ */
63
+ protected getSubscriptionClient(tenant: TenantIdAndAccount): Promise<{
64
+ client: SubscriptionClient;
65
+ credential: TokenCredential;
66
+ authentication: AzureAuthentication;
67
+ }>;
68
+ }
@@ -0,0 +1,140 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import * as azureEnv from '@azure/ms-rest-azure-env'; // This package is so small that it's not worth lazy loading
6
+ import * as crypto from 'crypto';
7
+ import { isAuthenticationWwwAuthenticateRequest } from '../utils/isAuthenticationWwwAuthenticateRequest';
8
+ import { NotSignedInError } from '../utils/NotSignedInError';
9
+ import { AzureSubscriptionProviderBase } from './AzureSubscriptionProviderBase';
10
+ let azureDevOpsSubscriptionProvider;
11
+ export function createAzureDevOpsSubscriptionProviderFactory(initializer) {
12
+ return () => {
13
+ azureDevOpsSubscriptionProvider ??= new AzureDevOpsSubscriptionProvider(initializer);
14
+ return Promise.resolve(azureDevOpsSubscriptionProvider);
15
+ };
16
+ }
17
+ let armSubs;
18
+ let azIdentity;
19
+ /**
20
+ * AzureSubscriptionProvider implemented to authenticate via federated DevOps service connection, using workflow identity federation
21
+ * To learn how to configure your DevOps environment to use this provider, refer to the README.md
22
+ * NOTE: This provider is only available when running in an Azure DevOps pipeline
23
+ * Reference: https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation
24
+ */
25
+ export class AzureDevOpsSubscriptionProvider extends AzureSubscriptionProviderBase {
26
+ _tokenCredential;
27
+ _serviceConnectionId;
28
+ _tenantId;
29
+ _clientId;
30
+ constructor({ serviceConnectionId, tenantId, clientId }, logger) {
31
+ super(logger);
32
+ if (!serviceConnectionId || !tenantId || !clientId) {
33
+ throw new Error(`Missing initializer values to identify Azure DevOps federated service connection\n
34
+ Values provided:\n
35
+ serviceConnectionId: ${serviceConnectionId ? "✅" : "❌"}\n
36
+ tenantId: ${tenantId ? "✅" : "❌"}\n
37
+ clientId: ${clientId ? "✅" : "❌"}\n
38
+ `);
39
+ }
40
+ this._serviceConnectionId = serviceConnectionId;
41
+ this._tenantId = tenantId;
42
+ this._clientId = clientId;
43
+ }
44
+ /**
45
+ * For {@link AzureSubscriptionProviderBase}, this event will never fire
46
+ */
47
+ onRefreshSuggested = () => { return { dispose: () => { } }; };
48
+ /**
49
+ * For {@link AzureSubscriptionProviderBase}, this returns a single account with a fixed ID and label
50
+ */
51
+ getAccounts() {
52
+ return Promise.resolve([
53
+ {
54
+ id: 'test-account-id',
55
+ label: 'test-account',
56
+ }
57
+ ]);
58
+ }
59
+ /**
60
+ * For {@link AzureSubscriptionProviderBase}, this returns an empty array
61
+ */
62
+ getUnauthenticatedTenantsForAccount() {
63
+ // For DevOps federated service connection, there is only one tenant associated with the service principal, and we will be authenticated
64
+ return Promise.resolve([]);
65
+ }
66
+ /**
67
+ * For {@link AzureSubscriptionProviderBase}, this returns a single tenant associated with the service principal
68
+ */
69
+ getTenantsForAccount(account) {
70
+ return Promise.resolve([{
71
+ tenantId: this._tenantId,
72
+ account: account,
73
+ }]);
74
+ }
75
+ /**
76
+ * @inheritdoc
77
+ */
78
+ async signIn() {
79
+ this._tokenCredential ??= await getTokenCredential(this._serviceConnectionId, this._tenantId, this._clientId);
80
+ return !!this._tokenCredential;
81
+ }
82
+ /**
83
+ * @inheritdoc
84
+ */
85
+ async getSubscriptionClient(tenant) {
86
+ if (!this._tokenCredential) {
87
+ throw new NotSignedInError();
88
+ }
89
+ const getSessionWithScopes = async (scopes) => {
90
+ if (isAuthenticationWwwAuthenticateRequest(scopes)) {
91
+ throw new Error('Getting session with challenge is not supported in AzureDevOpsSubscriptionProvider.');
92
+ }
93
+ const token = await this._tokenCredential?.getToken(scopes);
94
+ if (!token) {
95
+ throw new NotSignedInError();
96
+ }
97
+ return {
98
+ accessToken: token.token,
99
+ id: crypto.randomUUID(),
100
+ account: tenant.account,
101
+ scopes: scopes,
102
+ };
103
+ };
104
+ armSubs ??= await import('@azure/arm-resources-subscriptions');
105
+ return {
106
+ client: new armSubs.SubscriptionClient(this._tokenCredential),
107
+ credential: this._tokenCredential,
108
+ authentication: {
109
+ getSession: () => {
110
+ return getSessionWithScopes([azureEnv.Environment.AzureCloud.managementEndpointUrl + '/.default']);
111
+ },
112
+ getSessionWithScopes: getSessionWithScopes,
113
+ }
114
+ };
115
+ }
116
+ }
117
+ /**
118
+ * @param serviceConnectionId The resource ID of the Azure DevOps federated service connection,
119
+ * which can be found on the `resourceId` field of the URL at the address bar when viewing the service connection in the Azure DevOps portal
120
+ * @param tenantId The `Tenant ID` field of the service connection properties
121
+ * @param clientId The `Service Principal Id` field of the service connection properties
122
+ */
123
+ async function getTokenCredential(serviceConnectionId, tenantId, clientId) {
124
+ if (!process.env.AGENT_BUILDDIRECTORY) {
125
+ // Assume that AGENT_BUILDDIRECTORY is set if running in an Azure DevOps pipeline.
126
+ // So when not running in an Azure DevOps pipeline, throw an error since we cannot use the DevOps federated service connection credential.
127
+ throw new Error('Cannot create DevOps federated service connection credential outside of an Azure DevOps pipeline.');
128
+ }
129
+ else if (!process.env.SYSTEM_ACCESSTOKEN) {
130
+ throw new Error('Cannot create DevOps federated service connection credential because the SYSTEM_ACCESSTOKEN environment variable is not set.');
131
+ }
132
+ else {
133
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
134
+ // @ts-ignore @azure/identity contains a bug where this type mismatches between CJS and ESM, we must ignore it. We also can't do @ts-expect-error because the error only happens when building CJS.
135
+ azIdentity ??= await import('@azure/identity');
136
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-type-assertion
137
+ return new azIdentity.AzurePipelinesCredential(tenantId, clientId, serviceConnectionId, process.env.SYSTEM_ACCESSTOKEN);
138
+ }
139
+ }
140
+ //# sourceMappingURL=AzureDevOpsSubscriptionProvider.js.map
@@ -0,0 +1,74 @@
1
+ import type { SubscriptionClient } from '@azure/arm-resources-subscriptions';
2
+ import type { TokenCredential } from '@azure/core-auth';
3
+ import * as vscode from 'vscode';
4
+ import type { AzureAccount } from '../contracts/AzureAccount';
5
+ import type { AzureAuthentication } from '../contracts/AzureAuthentication';
6
+ import type { AzureSubscription } from '../contracts/AzureSubscription';
7
+ import type { AzureSubscriptionProvider, RefreshSuggestedEvent, TenantIdAndAccount } from '../contracts/AzureSubscriptionProvider';
8
+ import { type GetAccountsOptions, type GetAvailableSubscriptionsOptions, type GetSubscriptionsForTenantOptions, type GetTenantsForAccountOptions, type SignInOptions } from '../contracts/AzureSubscriptionProviderRequestOptions';
9
+ import type { AzureTenant } from '../contracts/AzureTenant';
10
+ /**
11
+ * Base class for Azure subscription providers that use VS Code authentication.
12
+ * Handles actual communication with Azure via the Azure SDK, as well as
13
+ * controlling the firing of `onRefreshSuggested` events.
14
+ */
15
+ export declare abstract class AzureSubscriptionProviderBase implements AzureSubscriptionProvider, vscode.Disposable {
16
+ private readonly logger?;
17
+ private sessionChangeListener;
18
+ private readonly refreshSuggestedEmitter;
19
+ private lastRefreshSuggestedTime;
20
+ private suppressRefreshSuggestedEvents;
21
+ /**
22
+ * Constructs a new {@link AzureSubscriptionProviderBase}.
23
+ * @param logger (Optional) A logger to record information to
24
+ */
25
+ constructor(logger?: vscode.LogOutputChannel | undefined);
26
+ dispose(): void;
27
+ /**
28
+ * @inheritdoc
29
+ */
30
+ onRefreshSuggested(callback: (evtArgs: RefreshSuggestedEvent) => unknown, thisArg?: unknown, disposables?: vscode.Disposable[]): vscode.Disposable;
31
+ protected fireRefreshSuggestedIfNeeded(evtArgs: RefreshSuggestedEvent): boolean;
32
+ /**
33
+ * @inheritdoc
34
+ */
35
+ signIn(tenant?: Partial<TenantIdAndAccount>, options?: SignInOptions): Promise<boolean>;
36
+ /**
37
+ * @inheritdoc
38
+ */
39
+ getAvailableSubscriptions(options?: GetAvailableSubscriptionsOptions): Promise<AzureSubscription[]>;
40
+ /**
41
+ * @inheritdoc
42
+ */
43
+ getAccounts(options?: GetAccountsOptions): Promise<AzureAccount[]>;
44
+ /**
45
+ * @inheritdoc
46
+ */
47
+ getUnauthenticatedTenantsForAccount(account: AzureAccount, options?: Omit<GetTenantsForAccountOptions, 'filter'>): Promise<AzureTenant[]>;
48
+ /**
49
+ * @inheritdoc
50
+ */
51
+ getTenantsForAccount(account: AzureAccount, options?: GetTenantsForAccountOptions): Promise<AzureTenant[]>;
52
+ /**
53
+ * @inheritdoc
54
+ */
55
+ getSubscriptionsForTenant(tenant: TenantIdAndAccount, options?: GetSubscriptionsForTenantOptions): Promise<AzureSubscription[]>;
56
+ /**
57
+ * Gets a {@link SubscriptionClient} plus extras for the given account+tenant.
58
+ * @param tenant (Optional) The account+tenant to get a subscription client for. If not specified, the default account and home tenant
59
+ * will be used.
60
+ * @returns A {@link SubscriptionClient}, {@link TokenCredential}, and {@link AzureAuthentication} for the given account+tenant.
61
+ */
62
+ protected getSubscriptionClient(tenant: Partial<TenantIdAndAccount>): Promise<{
63
+ client: SubscriptionClient;
64
+ credential: TokenCredential;
65
+ authentication: AzureAuthentication;
66
+ }>;
67
+ protected log(message: string): void;
68
+ protected logForAccount(account: AzureAccount, message: string): void;
69
+ protected logForTenant(tenant: TenantIdAndAccount, message: string): void;
70
+ protected throwIfCancelled(token: vscode.CancellationToken | undefined): void;
71
+ private timeout;
72
+ private silenceRefreshEvents;
73
+ private remapLogRethrow;
74
+ }