@culturefy/shared 1.0.76 → 1.0.77
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.
- package/build/cjs/middlewares/withPermissionsMw.js +73 -0
- package/build/cjs/middlewares/withPermissionsMw.js.map +1 -0
- package/build/cjs/service/tokenMapping.service.js +3 -3
- package/build/cjs/service/tokenMapping.service.js.map +1 -1
- package/build/cjs/service/user.service.js +2 -2
- package/build/cjs/service/user.service.js.map +1 -1
- package/build/cjs/utils/cache.js +4 -1
- package/build/cjs/utils/cache.js.map +1 -1
- package/build/cjs/utils/secrets.js +89 -19
- package/build/cjs/utils/secrets.js.map +1 -1
- package/build/esm/middlewares/withPermissionsMw.js +68 -0
- package/build/esm/middlewares/withPermissionsMw.js.map +1 -0
- package/build/esm/service/tokenMapping.service.js +1 -1
- package/build/esm/service/tokenMapping.service.js.map +1 -1
- package/build/esm/service/user.service.js +1 -1
- package/build/esm/service/user.service.js.map +1 -1
- package/build/esm/utils/cache.js +5 -2
- package/build/esm/utils/cache.js.map +1 -1
- package/build/esm/utils/secrets.js +88 -19
- package/build/esm/utils/secrets.js.map +1 -1
- package/build/src/schema/location.model.d.ts +1 -1
- package/build/src/service/tokenMapping.service.d.ts +1 -1
- package/build/src/service/tokenMapping.service.js +9 -9
- package/build/src/service/tokenMapping.service.js.map +1 -1
- package/build/src/service/user.service.d.ts +1 -1
- package/build/src/service/user.service.js +2 -2
- package/build/src/service/user.service.js.map +1 -1
- package/build/src/types/location.d.ts +1 -1
- package/build/src/utils/cache.js +5 -1
- package/build/src/utils/cache.js.map +1 -1
- package/build/src/utils/secrets.d.ts +12 -4
- package/build/src/utils/secrets.js +91 -18
- package/build/src/utils/secrets.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerSecretsRedis = registerSecretsRedis;
|
|
3
4
|
exports.getAzureVaultSecretByKey = getAzureVaultSecretByKey;
|
|
4
5
|
exports.getInterservicesCommunicationKey = getInterservicesCommunicationKey;
|
|
5
6
|
const tslib_1 = require("tslib");
|
|
@@ -7,36 +8,108 @@ const identity_1 = require("@azure/identity");
|
|
|
7
8
|
const keyvault_secrets_1 = require("@azure/keyvault-secrets");
|
|
8
9
|
const enums_1 = require("../enums");
|
|
9
10
|
const mapper_1 = require("./mapper");
|
|
11
|
+
// L1: in-memory cache — permanent for the lifetime of the Function host instance
|
|
12
|
+
const secretCache = new Map();
|
|
13
|
+
// Deduplicate concurrent in-flight fetches for the same key
|
|
14
|
+
const secretInflight = new Map();
|
|
15
|
+
// Singleton SecretClient per vault URL
|
|
16
|
+
const secretClients = new Map();
|
|
17
|
+
// L2: Redis cache — injected by cache.ts after Redis connects (avoids circular import)
|
|
18
|
+
const SECRET_REDIS_TTL = 60; // seconds
|
|
19
|
+
const SECRET_REDIS_NS = "kv-secret";
|
|
20
|
+
let _redis = null;
|
|
21
|
+
// These secrets are needed to bootstrap the Redis connection itself —
|
|
22
|
+
// they must never be looked up via Redis to prevent infinite recursion.
|
|
23
|
+
const BOOTSTRAP_KEYS = new Set([
|
|
24
|
+
enums_1.AzureSecretKeysEnum.REDIS_HOST,
|
|
25
|
+
enums_1.AzureSecretKeysEnum.REDIS_KEY,
|
|
26
|
+
enums_1.AzureSecretKeysEnum.REDIS_PORT,
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* Called by cache.ts after the Redis client successfully connects.
|
|
30
|
+
* Enables L2 Redis caching for Key Vault secrets without a circular import.
|
|
31
|
+
*/
|
|
32
|
+
function registerSecretsRedis(client) {
|
|
33
|
+
_redis = client;
|
|
34
|
+
}
|
|
35
|
+
function getSecretClient(vaultName) {
|
|
36
|
+
const vaultUrl = `https://${vaultName}.vault.azure.net`;
|
|
37
|
+
if (!secretClients.has(vaultUrl)) {
|
|
38
|
+
secretClients.set(vaultUrl, new keyvault_secrets_1.SecretClient(vaultUrl, new identity_1.DefaultAzureCredential()));
|
|
39
|
+
}
|
|
40
|
+
return secretClients.get(vaultUrl);
|
|
41
|
+
}
|
|
10
42
|
/**
|
|
11
43
|
* Fetches a secret value from Azure Key Vault by key.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
44
|
+
*
|
|
45
|
+
* Lookup order (fastest to slowest):
|
|
46
|
+
* L1 in-memory → L2 Redis (60s TTL) → Azure Key Vault
|
|
47
|
+
*
|
|
48
|
+
* Bootstrap secrets (REDIS_HOST/KEY/PORT) skip Redis to avoid circular calls.
|
|
49
|
+
*/
|
|
16
50
|
function getAzureVaultSecretByKey(context, vaultName, key) {
|
|
17
51
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
18
52
|
var _a;
|
|
19
|
-
// Build the list of valid enum values once
|
|
20
53
|
const validKeys = (0, mapper_1.enumMapper)(enums_1.AzureSecretKeysEnum);
|
|
21
|
-
// Validate
|
|
22
54
|
if (!validKeys.includes(key)) {
|
|
23
55
|
const msg = `Invalid secret key requested: ${key}`;
|
|
24
56
|
context.error(msg);
|
|
25
57
|
throw new Error(msg);
|
|
26
58
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
const cacheKey = `${vaultName}:${key}`;
|
|
60
|
+
// L1 — in-memory
|
|
61
|
+
const l1 = secretCache.get(cacheKey);
|
|
62
|
+
if (l1 !== undefined)
|
|
63
|
+
return l1;
|
|
64
|
+
// L2 — Redis (skipped for bootstrap keys)
|
|
65
|
+
const useRedis = _redis !== null && !BOOTSTRAP_KEYS.has(key);
|
|
66
|
+
if (useRedis) {
|
|
67
|
+
try {
|
|
68
|
+
const l2 = yield _redis.get(`${SECRET_REDIS_NS}:${cacheKey}`);
|
|
69
|
+
if (l2 !== null) {
|
|
70
|
+
secretCache.set(cacheKey, l2);
|
|
71
|
+
return l2;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
(_a = context.warn) === null || _a === void 0 ? void 0 : _a.call(context, `Redis L2 secret cache read failed for "${key}", falling through to Key Vault`, err);
|
|
76
|
+
}
|
|
39
77
|
}
|
|
78
|
+
// Deduplicate concurrent fetches for the same key
|
|
79
|
+
const inflight = secretInflight.get(cacheKey);
|
|
80
|
+
if (inflight)
|
|
81
|
+
return inflight;
|
|
82
|
+
const fetchPromise = (() => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
var _a, _b;
|
|
84
|
+
const client = getSecretClient(vaultName);
|
|
85
|
+
try {
|
|
86
|
+
const secret = yield client.getSecret(key);
|
|
87
|
+
const value = (_a = secret.value) !== null && _a !== void 0 ? _a : "";
|
|
88
|
+
// Populate L1
|
|
89
|
+
secretCache.set(cacheKey, value);
|
|
90
|
+
// Populate L2 — re-check _redis at write time in case Redis connected
|
|
91
|
+
// during the Key Vault round-trip (cold-start race)
|
|
92
|
+
const redisForWrite = !BOOTSTRAP_KEYS.has(key) ? _redis : null;
|
|
93
|
+
if (redisForWrite) {
|
|
94
|
+
try {
|
|
95
|
+
yield redisForWrite.set(`${SECRET_REDIS_NS}:${cacheKey}`, value, "EX", SECRET_REDIS_TTL);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
(_b = context.warn) === null || _b === void 0 ? void 0 : _b.call(context, `Redis L2 secret cache write failed for "${key}"`, err);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
context.error(`Error fetching secret "${key}" from vault "${vaultName}"`, err);
|
|
105
|
+
throw new Error(`Failed to fetch secret "${key}": ${err.message}`);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
secretInflight.delete(cacheKey);
|
|
109
|
+
}
|
|
110
|
+
}))();
|
|
111
|
+
secretInflight.set(cacheKey, fetchPromise);
|
|
112
|
+
return fetchPromise;
|
|
40
113
|
});
|
|
41
114
|
}
|
|
42
115
|
function getInterservicesCommunicationKey(context) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/utils/secrets.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/utils/secrets.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED