diff --git a/packages/cli/package.json b/packages/cli/package.json
index 7772bbfc91..90eebaed21 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -81,6 +81,8 @@
"ts-essentials": "^7.0.3"
},
"dependencies": {
+ "@azure/identity": "^4.3.0",
+ "@azure/keyvault-secrets": "^4.8.0",
"@n8n/client-oauth2": "workspace:*",
"@n8n/config": "workspace:*",
"@n8n/localtunnel": "2.1.0",
diff --git a/packages/cli/src/ExternalSecrets/ExternalSecretsProviders.ee.ts b/packages/cli/src/ExternalSecrets/ExternalSecretsProviders.ee.ts
index f7367064a3..33228673c3 100644
--- a/packages/cli/src/ExternalSecrets/ExternalSecretsProviders.ee.ts
+++ b/packages/cli/src/ExternalSecrets/ExternalSecretsProviders.ee.ts
@@ -3,6 +3,7 @@ import { Service } from 'typedi';
import { InfisicalProvider } from './providers/infisical';
import { VaultProvider } from './providers/vault';
import { AwsSecretsManager } from './providers/aws-secrets/aws-secrets-manager';
+import { AzureKeyVault } from './providers/azure-key-vault/azure-key-vault';
@Service()
export class ExternalSecretsProviders {
@@ -10,6 +11,7 @@ export class ExternalSecretsProviders {
awsSecretsManager: AwsSecretsManager,
infisical: InfisicalProvider,
vault: VaultProvider,
+ azureKeyVault: AzureKeyVault,
};
getProvider(name: string): { new (): SecretsProvider } | null {
diff --git a/packages/cli/src/ExternalSecrets/constants.ts b/packages/cli/src/ExternalSecrets/constants.ts
index d62dd1e459..e3ea016262 100644
--- a/packages/cli/src/ExternalSecrets/constants.ts
+++ b/packages/cli/src/ExternalSecrets/constants.ts
@@ -1,5 +1,16 @@
+import type { INodeProperties } from 'n8n-workflow';
+
export const EXTERNAL_SECRETS_DB_KEY = 'feature.externalSecrets';
export const EXTERNAL_SECRETS_INITIAL_BACKOFF = 10 * 1000;
export const EXTERNAL_SECRETS_MAX_BACKOFF = 5 * 60 * 1000;
export const EXTERNAL_SECRETS_NAME_REGEX = /^[a-zA-Z0-9\-\_\/]+$/;
+
+export const DOCS_HELP_NOTICE: INodeProperties = {
+ displayName:
+ 'Need help filling out these fields? Open docs',
+ name: 'notice',
+ type: 'notice',
+ default: '',
+ noDataExpression: true,
+};
diff --git a/packages/cli/src/ExternalSecrets/providers/__tests__/azure-key-vault.test.ts b/packages/cli/src/ExternalSecrets/providers/__tests__/azure-key-vault.test.ts
new file mode 100644
index 0000000000..329bfca2ac
--- /dev/null
+++ b/packages/cli/src/ExternalSecrets/providers/__tests__/azure-key-vault.test.ts
@@ -0,0 +1,70 @@
+import { SecretClient } from '@azure/keyvault-secrets';
+import type { KeyVaultSecret } from '@azure/keyvault-secrets';
+import { AzureKeyVault } from '../azure-key-vault/azure-key-vault';
+import { mock } from 'jest-mock-extended';
+import type { AzureKeyVaultContext } from '../azure-key-vault/types';
+
+jest.mock('@azure/identity');
+jest.mock('@azure/keyvault-secrets');
+
+describe('AzureKeyVault', () => {
+ const azureKeyVault = new AzureKeyVault();
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should update cached secrets', async () => {
+ /**
+ * Arrange
+ */
+ await azureKeyVault.init(
+ mock({
+ settings: {
+ vaultName: 'my-vault',
+ tenantId: 'my-tenant-id',
+ clientId: 'my-client-id',
+ clientSecret: 'my-client-secret',
+ },
+ }),
+ );
+
+ const listSpy = jest
+ .spyOn(SecretClient.prototype, 'listPropertiesOfSecrets')
+ // @ts-expect-error Partial mock
+ .mockImplementation(() => ({
+ async *[Symbol.asyncIterator]() {
+ yield { name: 'secret1' };
+ yield { name: 'secret2' };
+ yield { name: 'secret3' }; // no value
+ yield { name: '#@&' }; // invalid name
+ },
+ }));
+
+ const getSpy = jest
+ .spyOn(SecretClient.prototype, 'getSecret')
+ .mockImplementation(async (name: string) => {
+ return mock({ value: { secret1: 'value1', secret2: 'value2' }[name] });
+ });
+
+ /**
+ * Act
+ */
+ await azureKeyVault.connect();
+ await azureKeyVault.update();
+
+ /**
+ * Assert
+ */
+ expect(listSpy).toHaveBeenCalled();
+ expect(getSpy).toHaveBeenCalledWith('secret1');
+ expect(getSpy).toHaveBeenCalledWith('secret2');
+ expect(getSpy).toHaveBeenCalledWith('secret3');
+ expect(getSpy).not.toHaveBeenCalledWith('#@&');
+
+ expect(azureKeyVault.getSecret('secret1')).toBe('value1');
+ expect(azureKeyVault.getSecret('secret2')).toBe('value2');
+ expect(azureKeyVault.getSecret('secret3')).toBeUndefined(); // no value
+ expect(azureKeyVault.getSecret('#@&')).toBeUndefined(); // invalid name
+ });
+});
diff --git a/packages/cli/src/ExternalSecrets/providers/aws-secrets/aws-secrets-manager.ts b/packages/cli/src/ExternalSecrets/providers/aws-secrets/aws-secrets-manager.ts
index 986b2fcadc..b7b5f52d7b 100644
--- a/packages/cli/src/ExternalSecrets/providers/aws-secrets/aws-secrets-manager.ts
+++ b/packages/cli/src/ExternalSecrets/providers/aws-secrets/aws-secrets-manager.ts
@@ -1,6 +1,6 @@
import { AwsSecretsClient } from './aws-secrets-client';
import { UnknownAuthTypeError } from '@/errors/unknown-auth-type.error';
-import { EXTERNAL_SECRETS_NAME_REGEX } from '@/ExternalSecrets/constants';
+import { DOCS_HELP_NOTICE, EXTERNAL_SECRETS_NAME_REGEX } from '@/ExternalSecrets/constants';
import type { SecretsProvider, SecretsProviderState } from '@/Interfaces';
import type { INodeProperties } from 'n8n-workflow';
import type { AwsSecretsManagerContext } from './types';
@@ -13,14 +13,7 @@ export class AwsSecretsManager implements SecretsProvider {
state: SecretsProviderState = 'initializing';
properties: INodeProperties[] = [
- {
- displayName:
- 'Need help filling out these fields? Open docs',
- name: 'notice',
- type: 'notice',
- default: '',
- noDataExpression: true,
- },
+ DOCS_HELP_NOTICE,
{
displayName: 'Region',
name: 'region',
diff --git a/packages/cli/src/ExternalSecrets/providers/azure-key-vault/azure-key-vault.ts b/packages/cli/src/ExternalSecrets/providers/azure-key-vault/azure-key-vault.ts
new file mode 100644
index 0000000000..c51e54e799
--- /dev/null
+++ b/packages/cli/src/ExternalSecrets/providers/azure-key-vault/azure-key-vault.ts
@@ -0,0 +1,131 @@
+import { ClientSecretCredential } from '@azure/identity';
+import { SecretClient } from '@azure/keyvault-secrets';
+import type { SecretsProvider, SecretsProviderState } from '@/Interfaces';
+import type { INodeProperties } from 'n8n-workflow';
+import type { AzureKeyVaultContext } from './types';
+import { DOCS_HELP_NOTICE, EXTERNAL_SECRETS_NAME_REGEX } from '@/ExternalSecrets/constants';
+
+export class AzureKeyVault implements SecretsProvider {
+ name = 'azureKeyVault';
+
+ displayName = 'Azure Key Vault';
+
+ state: SecretsProviderState = 'initializing';
+
+ properties: INodeProperties[] = [
+ DOCS_HELP_NOTICE,
+ {
+ displayName: 'Vault Name',
+ hint: 'The name of your existing Azure Key Vault.',
+ name: 'vaultName',
+ type: 'string',
+ default: '',
+ required: true,
+ placeholder: 'e.g. my-vault',
+ noDataExpression: true,
+ },
+ {
+ displayName: 'Tenant ID',
+ name: 'tenantId',
+ hint: 'In Azure, this can be called "Directory (Tenant) ID".',
+ type: 'string',
+ default: '',
+ required: true,
+ placeholder: 'e.g. 7dec9324-7074-72b7-a3ca-a9bb3012f466',
+ noDataExpression: true,
+ },
+ {
+ displayName: 'Client ID',
+ name: 'clientId',
+ hint: 'In Azure, this can be called "Application (Client) ID".',
+ type: 'string',
+ default: '',
+ required: true,
+ placeholder: 'e.g. 7753d8c2-e41f-22ed-3dd7-c9e96463622c',
+ typeOptions: { password: true },
+ noDataExpression: true,
+ },
+ {
+ displayName: 'Client Secret',
+ name: 'clientSecret',
+ hint: 'The client secret value of your registered application.',
+ type: 'string',
+ default: '',
+ required: true,
+ typeOptions: { password: true },
+ noDataExpression: true,
+ },
+ ];
+
+ private cachedSecrets: Record = {};
+
+ private client: SecretClient;
+
+ private settings: AzureKeyVaultContext['settings'];
+
+ async init(context: AzureKeyVaultContext) {
+ this.settings = context.settings;
+ }
+
+ async connect() {
+ const { vaultName, tenantId, clientId, clientSecret } = this.settings;
+
+ try {
+ const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
+ this.client = new SecretClient(`https://${vaultName}.vault.azure.net/`, credential);
+ this.state = 'connected';
+ } catch (error) {
+ this.state = 'error';
+ }
+ }
+
+ async test(): Promise<[boolean] | [boolean, string]> {
+ if (!this.client) return [false, 'Failed to connect to Azure Key Vault'];
+
+ try {
+ await this.client.listPropertiesOfSecrets().next();
+ return [true];
+ } catch (error: unknown) {
+ return [false, error instanceof Error ? error.message : 'unknown error'];
+ }
+ }
+
+ async disconnect() {
+ // unused
+ }
+
+ async update() {
+ const secretNames: string[] = [];
+
+ for await (const secret of this.client.listPropertiesOfSecrets()) {
+ secretNames.push(secret.name);
+ }
+
+ const promises = secretNames
+ .filter((name) => EXTERNAL_SECRETS_NAME_REGEX.test(name))
+ .map(async (name) => {
+ const { value } = await this.client.getSecret(name);
+ return { name, value };
+ });
+
+ const secrets = await Promise.all(promises);
+
+ this.cachedSecrets = secrets.reduce>((acc, cur) => {
+ if (cur.value === undefined) return acc;
+ acc[cur.name] = cur.value;
+ return acc;
+ }, {});
+ }
+
+ getSecret(name: string) {
+ return this.cachedSecrets[name];
+ }
+
+ hasSecret(name: string) {
+ return name in this.cachedSecrets;
+ }
+
+ getSecretNames() {
+ return Object.keys(this.cachedSecrets);
+ }
+}
diff --git a/packages/cli/src/ExternalSecrets/providers/azure-key-vault/types.ts b/packages/cli/src/ExternalSecrets/providers/azure-key-vault/types.ts
new file mode 100644
index 0000000000..cd229a2589
--- /dev/null
+++ b/packages/cli/src/ExternalSecrets/providers/azure-key-vault/types.ts
@@ -0,0 +1,8 @@
+import type { SecretsProviderSettings } from '@/Interfaces';
+
+export type AzureKeyVaultContext = SecretsProviderSettings<{
+ vaultName: string;
+ tenantId: string;
+ clientId: string;
+ clientSecret: string;
+}>;
diff --git a/packages/cli/src/ExternalSecrets/providers/infisical.ts b/packages/cli/src/ExternalSecrets/providers/infisical.ts
index 0d700486a7..d9a2f93cda 100644
--- a/packages/cli/src/ExternalSecrets/providers/infisical.ts
+++ b/packages/cli/src/ExternalSecrets/providers/infisical.ts
@@ -3,7 +3,7 @@ import InfisicalClient from 'infisical-node';
import { populateClientWorkspaceConfigsHelper } from 'infisical-node/lib/helpers/key';
import { getServiceTokenData } from 'infisical-node/lib/api/serviceTokenData';
import { ApplicationError, type IDataObject, type INodeProperties } from 'n8n-workflow';
-import { EXTERNAL_SECRETS_NAME_REGEX } from '../constants';
+import { DOCS_HELP_NOTICE, EXTERNAL_SECRETS_NAME_REGEX } from '../constants';
export interface InfisicalSettings {
token: string;
@@ -24,13 +24,7 @@ interface InfisicalServiceToken {
export class InfisicalProvider implements SecretsProvider {
properties: INodeProperties[] = [
- {
- displayName:
- 'Need help filling out these fields? Open docs',
- name: 'notice',
- type: 'notice',
- default: '',
- },
+ DOCS_HELP_NOTICE,
{
displayName: 'Service Token',
name: 'token',
diff --git a/packages/cli/src/ExternalSecrets/providers/vault.ts b/packages/cli/src/ExternalSecrets/providers/vault.ts
index 43c6ae9f74..6735d26d6d 100644
--- a/packages/cli/src/ExternalSecrets/providers/vault.ts
+++ b/packages/cli/src/ExternalSecrets/providers/vault.ts
@@ -4,7 +4,7 @@ import type { IDataObject, INodeProperties } from 'n8n-workflow';
import type { AxiosInstance, AxiosResponse } from 'axios';
import axios from 'axios';
import { Logger } from '@/Logger';
-import { EXTERNAL_SECRETS_NAME_REGEX } from '../constants';
+import { DOCS_HELP_NOTICE, EXTERNAL_SECRETS_NAME_REGEX } from '../constants';
import { preferGet } from '../externalSecretsHelper.ee';
import { Container } from 'typedi';
@@ -85,13 +85,7 @@ interface VaultSecretList {
export class VaultProvider extends SecretsProvider {
properties: INodeProperties[] = [
- {
- displayName:
- 'Need help filling out these fields? Open docs',
- name: 'notice',
- type: 'notice',
- default: '',
- },
+ DOCS_HELP_NOTICE,
{
displayName: 'Vault URL',
name: 'url',
diff --git a/packages/editor-ui/src/assets/images/azure-key-vault.svg b/packages/editor-ui/src/assets/images/azure-key-vault.svg
new file mode 100644
index 0000000000..68a9c17c4e
--- /dev/null
+++ b/packages/editor-ui/src/assets/images/azure-key-vault.svg
@@ -0,0 +1,23 @@
+
diff --git a/packages/editor-ui/src/components/ExternalSecretsProviderImage.ee.vue b/packages/editor-ui/src/components/ExternalSecretsProviderImage.ee.vue
index 0d6b308d83..dc40fed88c 100644
--- a/packages/editor-ui/src/components/ExternalSecretsProviderImage.ee.vue
+++ b/packages/editor-ui/src/components/ExternalSecretsProviderImage.ee.vue
@@ -6,6 +6,7 @@ import infisical from '../assets/images/infisical.webp';
import doppler from '../assets/images/doppler.webp';
import vault from '../assets/images/hashicorp.webp';
import awsSecretsManager from '../assets/images/aws-secrets-manager.svg';
+import azureKeyVault from '../assets/images/azure-key-vault.svg';
const props = defineProps<{
provider: ExternalSecretsProvider;
@@ -18,6 +19,7 @@ const image = computed(
infisical,
vault,
awsSecretsManager,
+ azureKeyVault,
})[props.provider.name],
);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 15800ee6d3..8cfa83da0c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -538,6 +538,12 @@ importers:
packages/cli:
dependencies:
+ '@azure/identity':
+ specifier: ^4.3.0
+ version: 4.3.0
+ '@azure/keyvault-secrets':
+ specifier: ^4.8.0
+ version: 4.8.0
'@n8n/client-oauth2':
specifier: workspace:*
version: link:../@n8n/client-oauth2
@@ -1978,14 +1984,18 @@ packages:
resolution: {integrity: sha512-3X9wzaaGgRaBCwhLQZDtFp5uLIXCPrGbwJNWPPugvL4xbIGgScv77YzzxToKGLAKvG9amDoofMoP+9hsH1vs1w==}
engines: {node: '>=18.0.0'}
- '@azure/core-client@1.6.1':
- resolution: {integrity: sha512-mZ1MSKhZBYoV8GAWceA+PEJFWV2VpdNSpxxcj1wjIAOi00ykRuIQChT99xlQGZWLY3/NApWhSImlFwsmCEs4vA==}
- engines: {node: '>=12.0.0'}
+ '@azure/core-client@1.9.2':
+ resolution: {integrity: sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==}
+ engines: {node: '>=18.0.0'}
'@azure/core-http-compat@1.3.0':
resolution: {integrity: sha512-ZN9avruqbQ5TxopzG3ih3KRy52n8OAbitX3fnZT5go4hzu0J+KVPSzkL+Wt3hpJpdG8WIfg1sBD1tWkgUdEpBA==}
engines: {node: '>=12.0.0'}
+ '@azure/core-http-compat@2.1.2':
+ resolution: {integrity: sha512-5MnV1yqzZwgNLLjlizsU3QqOeQChkIXw781Fwh1xdAqJR5AA32IUaq6xv1BICJvfbHoa+JYcaij2HFkhLbNTJQ==}
+ engines: {node: '>=18.0.0'}
+
'@azure/core-http@2.3.2':
resolution: {integrity: sha512-Z4dfbglV9kNZO177CNx4bo5ekFuYwwsvjLiKdZI4r84bYGv3irrbQz7JC3/rUfFH2l4T/W6OFleJaa2X0IaQqw==}
engines: {node: '>=14.0.0'}
@@ -2018,10 +2028,18 @@ packages:
resolution: {integrity: sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA==}
engines: {node: '>=14.0.0'}
+ '@azure/identity@4.3.0':
+ resolution: {integrity: sha512-LHZ58/RsIpIWa4hrrE2YuJ/vzG1Jv9f774RfTTAVDZDriubvJ0/S5u4pnw4akJDlS0TiJb6VMphmVUFsWmgodQ==}
+ engines: {node: '>=18.0.0'}
+
'@azure/keyvault-keys@4.6.0':
resolution: {integrity: sha512-0112LegxeR03L8J4k+q6HwBVvrpd9y+oInG0FG3NaHXN7YUubVBon/eb5jFI6edGrvNigpxSR0XIsprFXdkzCQ==}
engines: {node: '>=12.0.0'}
+ '@azure/keyvault-secrets@4.8.0':
+ resolution: {integrity: sha512-RGfpFk6XUXHfWuTAiokOe8t6ej5C4ijf4HVyJUmTfN6VjDBVPvTtoiOi/C5072/ENHScYZFhiYOgIjLgYjfJ/A==}
+ engines: {node: '>=18.0.0'}
+
'@azure/logger@1.0.3':
resolution: {integrity: sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g==}
engines: {node: '>=12.0.0'}
@@ -2030,10 +2048,22 @@ packages:
resolution: {integrity: sha512-mnmi8dCXVNZI+AGRq0jKQ3YiodlIC4W9npr6FCB9WN6NQT+6rq+cIlxgUb//BjLyzKsnYo+i4LROGeMyU+6v1A==}
engines: {node: '>=0.8.0'}
+ '@azure/msal-browser@3.19.0':
+ resolution: {integrity: sha512-3unHlh3qWtXbqks/TLq3qGWzxfmwRfk9tXSGvVCcHHnCH5QKtcg/JiDIeP/1B2qFlqnSgtYY0JPLy9EIVoZ7Ag==}
+ engines: {node: '>=0.8.0'}
+
+ '@azure/msal-common@14.13.0':
+ resolution: {integrity: sha512-b4M/tqRzJ4jGU91BiwCsLTqChveUEyFK3qY2wGfZ0zBswIBZjAxopx5CYt5wzZFKuN15HqRDYXQbztttuIC3nA==}
+ engines: {node: '>=0.8.0'}
+
'@azure/msal-common@14.7.1':
resolution: {integrity: sha512-v96btzjM7KrAu4NSEdOkhQSTGOuNUIIsUdB8wlyB9cdgl5KqEKnTonHUZ8+khvZ6Ap542FCErbnTyDWl8lZ2rA==}
engines: {node: '>=0.8.0'}
+ '@azure/msal-node@2.11.0':
+ resolution: {integrity: sha512-yNRCp4Do4CGSBe1WXq4DWhfa/vYZCUgGrweYLC5my/6eDnYMt0fYGPHuTMw0iRslQGXF3CecGAxXp7ab57V4zg==}
+ engines: {node: '>=16'}
+
'@azure/msal-node@2.6.4':
resolution: {integrity: sha512-nNvEPx009/80UATCToF+29NZYocn01uKrB91xtFr7bSqkqO1PuQGXRyYwryWRztUrYZ1YsSbw9A+LmwOhpVvcg==}
engines: {node: '>=16'}
@@ -14146,9 +14176,9 @@ snapshots:
'@azure/core-util': 1.7.0
tslib: 2.6.2
- '@azure/core-client@1.6.1':
+ '@azure/core-client@1.9.2':
dependencies:
- '@azure/abort-controller': 1.1.0
+ '@azure/abort-controller': 2.0.0
'@azure/core-auth': 1.6.0
'@azure/core-rest-pipeline': 1.9.2
'@azure/core-tracing': 1.0.1
@@ -14161,7 +14191,15 @@ snapshots:
'@azure/core-http-compat@1.3.0':
dependencies:
'@azure/abort-controller': 1.1.0
- '@azure/core-client': 1.6.1
+ '@azure/core-client': 1.9.2
+ '@azure/core-rest-pipeline': 1.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@azure/core-http-compat@2.1.2':
+ dependencies:
+ '@azure/abort-controller': 2.0.0
+ '@azure/core-client': 1.9.2
'@azure/core-rest-pipeline': 1.9.2
transitivePeerDependencies:
- supports-color
@@ -14229,7 +14267,7 @@ snapshots:
dependencies:
'@azure/abort-controller': 1.1.0
'@azure/core-auth': 1.6.0
- '@azure/core-client': 1.6.1
+ '@azure/core-client': 1.9.2
'@azure/core-rest-pipeline': 1.9.2
'@azure/core-tracing': 1.0.1
'@azure/core-util': 1.7.0
@@ -14244,11 +14282,30 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@azure/identity@4.3.0':
+ dependencies:
+ '@azure/abort-controller': 1.1.0
+ '@azure/core-auth': 1.6.0
+ '@azure/core-client': 1.9.2
+ '@azure/core-rest-pipeline': 1.9.2
+ '@azure/core-tracing': 1.0.1
+ '@azure/core-util': 1.7.0
+ '@azure/logger': 1.0.3
+ '@azure/msal-browser': 3.19.0
+ '@azure/msal-node': 2.11.0
+ events: 3.3.0
+ jws: 4.0.0
+ open: 8.4.0
+ stoppable: 1.1.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
'@azure/keyvault-keys@4.6.0':
dependencies:
'@azure/abort-controller': 1.1.0
'@azure/core-auth': 1.6.0
- '@azure/core-client': 1.6.1
+ '@azure/core-client': 1.9.2
'@azure/core-http-compat': 1.3.0
'@azure/core-lro': 2.4.0
'@azure/core-paging': 1.3.0
@@ -14260,6 +14317,22 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@azure/keyvault-secrets@4.8.0':
+ dependencies:
+ '@azure/abort-controller': 1.1.0
+ '@azure/core-auth': 1.6.0
+ '@azure/core-client': 1.9.2
+ '@azure/core-http-compat': 2.1.2
+ '@azure/core-lro': 2.4.0
+ '@azure/core-paging': 1.3.0
+ '@azure/core-rest-pipeline': 1.9.2
+ '@azure/core-tracing': 1.0.1
+ '@azure/core-util': 1.7.0
+ '@azure/logger': 1.0.3
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
'@azure/logger@1.0.3':
dependencies:
tslib: 2.6.2
@@ -14268,8 +14341,20 @@ snapshots:
dependencies:
'@azure/msal-common': 14.7.1
+ '@azure/msal-browser@3.19.0':
+ dependencies:
+ '@azure/msal-common': 14.13.0
+
+ '@azure/msal-common@14.13.0': {}
+
'@azure/msal-common@14.7.1': {}
+ '@azure/msal-node@2.11.0':
+ dependencies:
+ '@azure/msal-common': 14.13.0
+ jsonwebtoken: 9.0.2
+ uuid: 8.3.2
+
'@azure/msal-node@2.6.4':
dependencies:
'@azure/msal-common': 14.7.1
@@ -14320,7 +14405,7 @@ snapshots:
'@babel/traverse': 7.24.0
'@babel/types': 7.24.0
convert-source-map: 2.0.0
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 7.6.0
@@ -14441,7 +14526,7 @@ snapshots:
'@babel/core': 7.24.6
'@babel/helper-compilation-targets': 7.24.6
'@babel/helper-plugin-utils': 7.24.6
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
lodash.debounce: 4.0.8
resolve: 1.22.8
transitivePeerDependencies:
@@ -14452,7 +14537,7 @@ snapshots:
'@babel/core': 7.24.6
'@babel/helper-compilation-targets': 7.24.6
'@babel/helper-plugin-utils': 7.24.6
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
lodash.debounce: 4.0.8
resolve: 1.22.8
transitivePeerDependencies:
@@ -15336,7 +15421,7 @@ snapshots:
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.24.0
'@babel/types': 7.24.0
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -15351,7 +15436,7 @@ snapshots:
'@babel/helper-split-export-declaration': 7.24.6
'@babel/parser': 7.24.6
'@babel/types': 7.24.6
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -18923,7 +19008,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 6.7.5
'@typescript-eslint/visitor-keys': 6.7.5
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.0
@@ -19344,7 +19429,7 @@ snapshots:
agent-base@7.1.0:
dependencies:
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
transitivePeerDependencies:
- supports-color
@@ -20790,7 +20875,7 @@ snapshots:
detect-port@1.5.1:
dependencies:
address: 1.2.2
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
transitivePeerDependencies:
- supports-color
@@ -21168,7 +21253,7 @@ snapshots:
esbuild-register@3.5.0(esbuild@0.20.2):
dependencies:
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
esbuild: 0.20.2
transitivePeerDependencies:
- supports-color
@@ -22405,7 +22490,7 @@ snapshots:
dependencies:
'@tootallnate/once': 1.1.2
agent-base: 6.0.2
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
transitivePeerDependencies:
- supports-color
optional: true
@@ -22414,7 +22499,7 @@ snapshots:
dependencies:
'@tootallnate/once': 2.0.0
agent-base: 6.0.2
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
transitivePeerDependencies:
- supports-color
@@ -22823,7 +22908,7 @@ snapshots:
istanbul-lib-source-maps@4.0.1:
dependencies:
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
istanbul-lib-coverage: 3.2.2
source-map: 0.6.1
transitivePeerDependencies:
@@ -26241,7 +26326,7 @@ snapshots:
socks-proxy-agent@6.2.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.5(supports-color@8.1.1)
socks: 2.7.1
transitivePeerDependencies:
- supports-color