-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathkeyvault.test.ts
More file actions
142 lines (127 loc) · 6.13 KB
/
keyvault.test.ts
File metadata and controls
142 lines (127 loc) · 6.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as chai from "chai";
import * as chaiAsPromised from "chai-as-promised";
chai.use(chaiAsPromised);
const expect = chai.expect;
import { load } from "./exportedApi.js";
import { MAX_TIME_OUT, sinon, createMockedConnectionString, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, mockSecretClientGetSecret, restoreMocks, createMockedKeyVaultReference } from "./utils/testHelper.js";
import { KeyVaultSecret, SecretClient } from "@azure/keyvault-secrets";
const mockedData = [
// key, secretUri, value
["TestKey", "https://fake-vault-name.vault.azure.net/secrets/fakeSecretName", "SecretValue"],
["TestKeyFixedVersion", "https://fake-vault-name.vault.azure.net/secrets/fakeSecretName/741a0fc52610449baffd6e1c55b9d459", "OldSecretValue"],
["TestKey2", "https://fake-vault-name2.vault.azure.net/secrets/fakeSecretName2", "SecretValue2"]
];
function mockAppConfigurationClient() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const kvs = mockedData.map(([key, vaultUri, _value]) => createMockedKeyVaultReference(key, vaultUri));
mockAppConfigurationClientListConfigurationSettings([kvs]);
}
function mockNewlyCreatedKeyVaultSecretClients() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
mockSecretClientGetSecret(mockedData.map(([_key, secretUri, value]) => [secretUri, value]));
}
describe("key vault reference", function () {
this.timeout(MAX_TIME_OUT);
beforeEach(() => {
mockAppConfigurationClient();
mockNewlyCreatedKeyVaultSecretClients();
});
afterEach(() => {
restoreMocks();
});
it("require key vault options to resolve reference", async () => {
try {
await load(createMockedConnectionString());
} catch (error) {
expect(error.message).eq("Failed to load.");
expect(error.cause.message).eq("Failed to process the Key Vault reference because Key Vault options are not configured.");
return;
}
// we should never reach here, load should throw an error
throw new Error("Expected load to throw.");
});
it("should resolve key vault reference with credential", async () => {
const settings = await load(createMockedConnectionString(), {
keyVaultOptions: {
credential: createMockedTokenCredential()
}
});
expect(settings).not.undefined;
expect(settings.get("TestKey")).eq("SecretValue");
expect(settings.get("TestKeyFixedVersion")).eq("OldSecretValue");
});
it("should resolve key vault reference with secret resolver", async () => {
const settings = await load(createMockedConnectionString(), {
keyVaultOptions: {
secretResolver: (kvrUrl) => {
return "SecretResolver::" + kvrUrl.toString();
}
}
});
expect(settings).not.undefined;
expect(settings.get("TestKey")).eq("SecretResolver::https://fake-vault-name.vault.azure.net/secrets/fakeSecretName");
});
it("should resolve key vault reference with corresponding secret clients", async () => {
sinon.restore();
mockAppConfigurationClient();
// mock specific behavior per secret client
const client1 = new SecretClient("https://fake-vault-name.vault.azure.net", createMockedTokenCredential());
sinon.stub(client1, "getSecret").returns(Promise.resolve({value: "SecretValueViaClient1" } as KeyVaultSecret));
const client2 = new SecretClient("https://fake-vault-name2.vault.azure.net", createMockedTokenCredential());
sinon.stub(client2, "getSecret").returns(Promise.resolve({value: "SecretValueViaClient2" } as KeyVaultSecret));
const settings = await load(createMockedConnectionString(), {
keyVaultOptions: {
secretClients: [
client1,
client2,
]
}
});
expect(settings).not.undefined;
expect(settings.get("TestKey")).eq("SecretValueViaClient1");
expect(settings.get("TestKey2")).eq("SecretValueViaClient2");
});
it("should throw error when secret clients not provided for all key vault references", async () => {
try {
await load(createMockedConnectionString(), {
keyVaultOptions: {
secretClients: [
new SecretClient("https://fake-vault-name.vault.azure.net", createMockedTokenCredential()),
]
}
});
} catch (error) {
expect(error.message).eq("Failed to load.");
expect(error.cause.message).eq("Failed to process the key vault reference. No key vault secret client, credential or secret resolver callback is available to resolve the secret.");
return;
}
// we should never reach here, load should throw an error
throw new Error("Expected load to throw.");
});
it("should fallback to use default credential when corresponding secret client not provided", async () => {
const settings = await load(createMockedConnectionString(), {
keyVaultOptions: {
secretClients: [
new SecretClient("https://fake-vault-name.vault.azure.net", createMockedTokenCredential()),
],
credential: createMockedTokenCredential()
}
});
expect(settings).not.undefined;
expect(settings.get("TestKey")).eq("SecretValue");
expect(settings.get("TestKey2")).eq("SecretValue2");
});
it("should resolve key vault reference in parallel", async () => {
const settings = await load(createMockedConnectionString(), {
keyVaultOptions: {
credential: createMockedTokenCredential(),
parallelSecretResolutionEnabled: true
}
});
expect(settings).not.undefined;
expect(settings.get("TestKey")).eq("SecretValue");
expect(settings.get("TestKeyFixedVersion")).eq("OldSecretValue");
});
});