biz-a-cli 2.3.80-15270 → 2.3.80-15271
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/package.json +2 -1
- package/security/secretProvider.js +61 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "biz-a-cli",
|
|
3
|
-
"version": "2.3.80-
|
|
3
|
+
"version": "2.3.80-15271",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"message-broker/**/*",
|
|
18
18
|
"migrations/**/*",
|
|
19
19
|
"scheduler/**/*",
|
|
20
|
+
"security/**/*",
|
|
20
21
|
"worker/**/*",
|
|
21
22
|
"callbackController.js",
|
|
22
23
|
"mailController.js",
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Platform-level secret provider. Application-agnostic: resolves keys by NAME only —
|
|
2
|
+
// it knows nothing about "ledger", "supertail", or any app. The backing store is
|
|
3
|
+
// swappable (restricted-ACL file -> Windows DPAPI -> Vault/KMS) behind this same API
|
|
4
|
+
// without touching any application. Fails CLOSED: an unprovisioned name throws.
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
// Platform config knob (NOT an app secret): where the secrets store lives.
|
|
9
|
+
const STORE_PATH =
|
|
10
|
+
process.env.BIZA_SECRETS_FILE ||
|
|
11
|
+
path.join(process.cwd(), "config", "secrets.json");
|
|
12
|
+
|
|
13
|
+
let _cache = null;
|
|
14
|
+
|
|
15
|
+
function loadStore() {
|
|
16
|
+
if (_cache) return _cache;
|
|
17
|
+
try {
|
|
18
|
+
_cache = JSON.parse(fs.readFileSync(STORE_PATH, "utf8"));
|
|
19
|
+
} catch {
|
|
20
|
+
_cache = {}; // missing / corrupt store -> every resolve fails closed
|
|
21
|
+
}
|
|
22
|
+
return _cache;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Store shape (rotation-aware):
|
|
26
|
+
{
|
|
27
|
+
"supertail.ledger": { "currentKeyId": "st_ledger_v1",
|
|
28
|
+
"keys": { "st_ledger_v1": "<base64 key>" } }
|
|
29
|
+
}
|
|
30
|
+
Shorthand single-key form is also accepted (keyId = "default"):
|
|
31
|
+
{ "supertail.session": "<base64 key>" }
|
|
32
|
+
Key material is base64; decoded to bytes for HMAC. */
|
|
33
|
+
function resolve(name, keyId /* optional; used by verify to pin a past key */) {
|
|
34
|
+
const entry = loadStore()[name];
|
|
35
|
+
if (entry == null) {
|
|
36
|
+
throw new Error(`secret '${name}' is not provisioned (fail-closed)`);
|
|
37
|
+
}
|
|
38
|
+
if (typeof entry === "string") {
|
|
39
|
+
if (keyId && keyId !== "default") {
|
|
40
|
+
throw new Error(`secret '${name}' has no key '${keyId}'`);
|
|
41
|
+
}
|
|
42
|
+
return { keyId: "default", key: Buffer.from(entry, "base64") };
|
|
43
|
+
}
|
|
44
|
+
const id = keyId || entry.currentKeyId;
|
|
45
|
+
const b64 = entry.keys && entry.keys[id];
|
|
46
|
+
if (!b64) {
|
|
47
|
+
throw new Error(`secret '${name}' has no key '${id}'`);
|
|
48
|
+
}
|
|
49
|
+
return { keyId: id, key: Buffer.from(b64, "base64") };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const secretProvider = {
|
|
53
|
+
// sign with the current key for `name`
|
|
54
|
+
resolveForSign: (name) => resolve(name),
|
|
55
|
+
// verify against the key that produced a row (pinned by its stored keyId)
|
|
56
|
+
resolveForVerify: (name, keyId) => resolve(name, keyId),
|
|
57
|
+
// test hook — drop the cache so a re-provisioned store is re-read
|
|
58
|
+
_reset: () => {
|
|
59
|
+
_cache = null;
|
|
60
|
+
},
|
|
61
|
+
};
|