1+ // Copyright (c) Microsoft Corporation.
2+ // Licensed under the MIT license.
3+
4+ const chai = require ( "chai" ) ;
5+ const chaiAsPromised = require ( "chai-as-promised" ) ;
6+ chai . use ( chaiAsPromised ) ;
7+ const expect = chai . expect ;
8+ const { load } = require ( "../dist/index" ) ;
9+ const { sinon,
10+ createMockedConnectionString,
11+ createMockedTokenCredential,
12+ mockAppConfigurationClientListConfigurationSettings, mockSecretClientGetSecret, restoreMocks, createMockedKeyVaultReference } = require ( "./utils/testHelper" ) ;
13+ const { SecretClient } = require ( "@azure/keyvault-secrets" ) ;
14+
15+ const mockedData = [
16+ // key, secretUri, value
17+ [ "TestKey" , "https://fake-vault-name.vault.azure.net/secrets/fakeSecretName" , "SecretValue" ] ,
18+ [ "TestKeyFixedVersion" , "https://fake-vault-name.vault.azure.net/secrets/fakeSecretName/741a0fc52610449baffd6e1c55b9d459" , "OldSecretValue" ] ,
19+ [ "TestKey2" , "https://fake-vault-name2.vault.azure.net/secrets/fakeSecretName2" , "SecretValue2" ]
20+ ] ;
21+
22+ function mockAppConfigurationClient ( ) {
23+ const kvs = mockedData . map ( ( [ key , vaultUri , _value ] ) => createMockedKeyVaultReference ( key , vaultUri ) ) ;
24+ mockAppConfigurationClientListConfigurationSettings ( kvs ) ;
25+ }
26+
27+ function mockNewlyCreatedKeyVaultSecretClients ( ) {
28+ mockSecretClientGetSecret ( mockedData . map ( ( [ _key , secretUri , value ] ) => [ secretUri , value ] ) ) ;
29+ }
30+ describe ( "key vault reference" , function ( ) {
31+ beforeEach ( ( ) => {
32+ mockAppConfigurationClient ( ) ;
33+ mockNewlyCreatedKeyVaultSecretClients ( ) ;
34+ } ) ;
35+
36+ afterEach ( ( ) => {
37+ restoreMocks ( ) ;
38+ } ) ;
39+
40+ it ( "require key vault options to resolve reference" , async ( ) => {
41+ expect ( load ( createMockedConnectionString ( ) ) ) . eventually . rejected ;
42+ } ) ;
43+
44+ it ( "should resolve key vault reference with credential" , async ( ) => {
45+ const settings = await load ( createMockedConnectionString ( ) , {
46+ keyVaultOptions : {
47+ credential : createMockedTokenCredential ( )
48+ }
49+ } ) ;
50+ expect ( settings ) . not . undefined ;
51+ expect ( settings . get ( "TestKey" ) ) . eq ( "SecretValue" ) ;
52+ expect ( settings . get ( "TestKeyFixedVersion" ) ) . eq ( "OldSecretValue" ) ;
53+ } ) ;
54+
55+ it ( "should resolve key vault reference with secret resolver" , async ( ) => {
56+ const settings = await load ( createMockedConnectionString ( ) , {
57+ keyVaultOptions : {
58+ secretResolver : ( kvrUrl ) => {
59+ return "SecretResolver::" + kvrUrl . toString ( ) ;
60+ }
61+ }
62+ } ) ;
63+ expect ( settings ) . not . undefined ;
64+ expect ( settings . get ( "TestKey" ) ) . eq ( "SecretResolver::https://fake-vault-name.vault.azure.net/secrets/fakeSecretName" ) ;
65+ } ) ;
66+
67+ it ( "should resolve key vault reference with corresponding secret clients" , async ( ) => {
68+ sinon . restore ( ) ;
69+ mockAppConfigurationClient ( ) ;
70+
71+ // mock specific behavior per secret client
72+ const client1 = new SecretClient ( "https://fake-vault-name.vault.azure.net" , createMockedTokenCredential ( ) ) ;
73+ sinon . stub ( client1 , "getSecret" ) . returns ( { value : "SecretValueViaClient1" } ) ;
74+ const client2 = new SecretClient ( "https://fake-vault-name2.vault.azure.net" , createMockedTokenCredential ( ) ) ;
75+ sinon . stub ( client2 , "getSecret" ) . returns ( { value : "SecretValueViaClient2" } ) ;
76+ const settings = await load ( createMockedConnectionString ( ) , {
77+ keyVaultOptions : {
78+ secretClients : [
79+ client1 ,
80+ client2 ,
81+ ]
82+ }
83+ } ) ;
84+ expect ( settings ) . not . undefined ;
85+ expect ( settings . get ( "TestKey" ) ) . eq ( "SecretValueViaClient1" ) ;
86+ expect ( settings . get ( "TestKey2" ) ) . eq ( "SecretValueViaClient2" ) ;
87+ } ) ;
88+
89+ it ( "should throw error when secret clients not provided for all key vault references" , async ( ) => {
90+ const loadKeyVaultPromise = load ( createMockedConnectionString ( ) , {
91+ keyVaultOptions : {
92+ secretClients : [
93+ new SecretClient ( "https://fake-vault-name.vault.azure.net" , createMockedTokenCredential ( ) ) ,
94+ ]
95+ }
96+ } ) ;
97+ expect ( loadKeyVaultPromise ) . eventually . rejected ;
98+ } ) ;
99+
100+ it ( "should fallback to use default credential when corresponding secret client not provided" , async ( ) => {
101+ const settings = await load ( createMockedConnectionString ( ) , {
102+ keyVaultOptions : {
103+ secretClients : [
104+ new SecretClient ( "https://fake-vault-name.vault.azure.net" , createMockedTokenCredential ( ) ) ,
105+ ] ,
106+ credential : createMockedTokenCredential ( )
107+ }
108+ } ) ;
109+ expect ( settings ) . not . undefined ;
110+ expect ( settings . get ( "TestKey" ) ) . eq ( "SecretValue" ) ;
111+ expect ( settings . get ( "TestKey2" ) ) . eq ( "SecretValue2" ) ;
112+ } ) ;
113+ } )
0 commit comments