@cipherstash/stack 0.4.0 → 0.6.0
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/CHANGELOG.md +19 -0
- package/README.md +9 -36
- package/dist/bin/stash.js +220 -184
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-OAPLZLR5.js → chunk-GXGEW6T4.js} +2 -76
- package/dist/chunk-GXGEW6T4.js.map +1 -0
- package/dist/{chunk-KOU2MHXJ.js → chunk-HCL75LXQ.js} +1 -1
- package/dist/chunk-HCL75LXQ.js.map +1 -0
- package/dist/chunk-LBMC4D6D.js +19 -0
- package/dist/chunk-LBMC4D6D.js.map +1 -0
- package/dist/chunk-Q5FTQLYG.js +68 -0
- package/dist/chunk-Q5FTQLYG.js.map +1 -0
- package/dist/{chunk-WUZGKTMG.js → chunk-TGUELLJS.js} +16 -19
- package/dist/chunk-TGUELLJS.js.map +1 -0
- package/dist/chunk-YLISU7FD.js +357 -0
- package/dist/chunk-YLISU7FD.js.map +1 -0
- package/dist/{client-CrGQnSlk.d.ts → client-CJueivkw.d.cts} +36 -3
- package/dist/{client-CUGXheRq.d.cts → client-hHEpZIZH.d.ts} +36 -3
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/drizzle/index.cjs.map +1 -1
- package/dist/drizzle/index.d.cts +14 -6
- package/dist/drizzle/index.d.ts +14 -6
- package/dist/drizzle/index.js +3 -3
- package/dist/drizzle/index.js.map +1 -1
- package/dist/dynamodb/index.cjs +68 -0
- package/dist/dynamodb/index.cjs.map +1 -1
- package/dist/dynamodb/index.d.cts +4 -4
- package/dist/dynamodb/index.d.ts +4 -4
- package/dist/dynamodb/index.js +9 -0
- package/dist/dynamodb/index.js.map +1 -1
- package/dist/encryption/index.cjs +2572 -0
- package/dist/encryption/index.cjs.map +1 -0
- package/dist/encryption/index.d.cts +7 -0
- package/dist/encryption/index.d.ts +7 -0
- package/dist/encryption/index.js +17 -0
- package/dist/encryption/index.js.map +1 -0
- package/dist/errors/index.cjs +44 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.cts +94 -0
- package/dist/errors/index.d.ts +94 -0
- package/dist/errors/index.js +9 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/identity/index.cjs +21 -13
- package/dist/identity/index.cjs.map +1 -1
- package/dist/identity/index.d.cts +78 -2
- package/dist/identity/index.d.ts +78 -2
- package/dist/identity/index.js +7 -3
- package/dist/identity/index.js.map +1 -1
- package/dist/index.cjs +379 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -19
- package/dist/index.d.ts +21 -19
- package/dist/index.js +14 -8
- package/dist/schema/index.d.cts +1 -2
- package/dist/schema/index.d.ts +1 -2
- package/dist/secrets/index.cjs +70 -39
- package/dist/secrets/index.cjs.map +1 -1
- package/dist/secrets/index.d.cts +4 -6
- package/dist/secrets/index.d.ts +4 -6
- package/dist/secrets/index.js +9 -318
- package/dist/secrets/index.js.map +1 -1
- package/dist/supabase/index.cjs +84 -1
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +4 -4
- package/dist/supabase/index.d.ts +4 -4
- package/dist/supabase/index.js +24 -1
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-public-Wj6tB_ux.d.ts → types-public-07ilcGY-.d.cts} +1 -9
- package/dist/{types-public-Wj6tB_ux.d.cts → types-public-07ilcGY-.d.ts} +1 -9
- package/dist/types-public.cjs.map +1 -1
- package/dist/types-public.d.cts +1 -2
- package/dist/types-public.d.ts +1 -2
- package/dist/types-public.js +1 -1
- package/package.json +29 -1
- package/dist/chunk-KOU2MHXJ.js.map +0 -1
- package/dist/chunk-OAPLZLR5.js.map +0 -1
- package/dist/chunk-WUZGKTMG.js.map +0 -1
- package/dist/index-9-Ya3fDK.d.cts +0 -169
- package/dist/index-9-Ya3fDK.d.ts +0 -169
package/dist/index.cjs
CHANGED
|
@@ -31,28 +31,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
Encryption: () => Encryption,
|
|
34
|
-
|
|
34
|
+
Secrets: () => Secrets,
|
|
35
35
|
encryptedColumn: () => encryptedColumn,
|
|
36
36
|
encryptedField: () => encryptedField,
|
|
37
37
|
encryptedTable: () => encryptedTable,
|
|
38
|
-
|
|
38
|
+
encryptedToPgComposite: () => encryptedToPgComposite,
|
|
39
|
+
isEncryptedPayload: () => isEncryptedPayload
|
|
39
40
|
});
|
|
40
41
|
module.exports = __toCommonJS(index_exports);
|
|
41
42
|
|
|
42
|
-
// src/errors/index.ts
|
|
43
|
-
var EncryptionErrorTypes = {
|
|
44
|
-
ClientInitError: "ClientInitError",
|
|
45
|
-
EncryptionError: "EncryptionError",
|
|
46
|
-
DecryptionError: "DecryptionError",
|
|
47
|
-
LockContextError: "LockContextError",
|
|
48
|
-
CtsTokenError: "CtsTokenError"
|
|
49
|
-
};
|
|
50
|
-
function getErrorMessage(error) {
|
|
51
|
-
if (error instanceof Error) return error.message;
|
|
52
|
-
if (typeof error === "string") return error;
|
|
53
|
-
return String(error);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
43
|
// src/schema/index.ts
|
|
57
44
|
var import_zod = require("zod");
|
|
58
45
|
var castAsEnum = import_zod.z.enum(["bigint", "boolean", "date", "number", "string", "json", "text"]).default("text");
|
|
@@ -380,6 +367,15 @@ function buildEncryptConfig(...protectTables) {
|
|
|
380
367
|
return config;
|
|
381
368
|
}
|
|
382
369
|
|
|
370
|
+
// src/errors/index.ts
|
|
371
|
+
var EncryptionErrorTypes = {
|
|
372
|
+
ClientInitError: "ClientInitError",
|
|
373
|
+
EncryptionError: "EncryptionError",
|
|
374
|
+
DecryptionError: "DecryptionError",
|
|
375
|
+
LockContextError: "LockContextError",
|
|
376
|
+
CtsTokenError: "CtsTokenError"
|
|
377
|
+
};
|
|
378
|
+
|
|
383
379
|
// src/utils/config/index.ts
|
|
384
380
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
385
381
|
var import_node_path = __toESM(require("path"), 1);
|
|
@@ -445,25 +441,33 @@ function loadWorkSpaceId(suppliedCrn) {
|
|
|
445
441
|
|
|
446
442
|
// src/utils/logger/index.ts
|
|
447
443
|
var import_evlog = require("evlog");
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
444
|
+
var validLevels = ["debug", "info", "error"];
|
|
445
|
+
function levelFromEnv() {
|
|
446
|
+
const env = process.env.STASH_STACK_LOG;
|
|
447
|
+
if (env && validLevels.includes(env)) return env;
|
|
448
|
+
return "error";
|
|
449
|
+
}
|
|
450
|
+
function samplingRatesForLevel(level) {
|
|
451
|
+
switch (level) {
|
|
452
|
+
case "debug":
|
|
453
|
+
return { debug: 100, info: 100, warn: 100, error: 100 };
|
|
454
|
+
case "info":
|
|
455
|
+
return { debug: 0, info: 100, warn: 100, error: 100 };
|
|
456
|
+
case "error":
|
|
457
|
+
default:
|
|
458
|
+
return { debug: 0, info: 0, warn: 0, error: 100 };
|
|
459
|
+
}
|
|
455
460
|
}
|
|
456
461
|
var initialized = false;
|
|
457
|
-
function initStackLogger(
|
|
462
|
+
function initStackLogger() {
|
|
458
463
|
if (initialized) return;
|
|
459
464
|
initialized = true;
|
|
460
|
-
const
|
|
465
|
+
const level = levelFromEnv();
|
|
466
|
+
const rates = samplingRatesForLevel(level);
|
|
461
467
|
(0, import_evlog.initLogger)({
|
|
462
468
|
env: { service: "@cipherstash/stack" },
|
|
463
|
-
enabled:
|
|
464
|
-
|
|
465
|
-
...rates && { sampling: { rates } },
|
|
466
|
-
...config?.drain && { drain: config.drain }
|
|
469
|
+
enabled: true,
|
|
470
|
+
sampling: { rates }
|
|
467
471
|
});
|
|
468
472
|
}
|
|
469
473
|
initStackLogger();
|
|
@@ -501,8 +505,14 @@ var logger = {
|
|
|
501
505
|
// src/encryption/index.ts
|
|
502
506
|
var import_result11 = require("@byteslice/result");
|
|
503
507
|
var import_protect_ffi9 = require("@cipherstash/protect-ffi");
|
|
508
|
+
var import_uuid = require("uuid");
|
|
504
509
|
|
|
505
510
|
// src/encryption/helpers/index.ts
|
|
511
|
+
function encryptedToPgComposite(obj) {
|
|
512
|
+
return {
|
|
513
|
+
data: obj
|
|
514
|
+
};
|
|
515
|
+
}
|
|
506
516
|
function encryptedToCompositeLiteral(obj) {
|
|
507
517
|
return `(${JSON.stringify(JSON.stringify(obj))})`;
|
|
508
518
|
}
|
|
@@ -2809,23 +2819,14 @@ var EncryptionClient = class {
|
|
|
2809
2819
|
};
|
|
2810
2820
|
}
|
|
2811
2821
|
};
|
|
2812
|
-
|
|
2813
|
-
// src/index.ts
|
|
2814
|
-
function isValidUuid(uuid) {
|
|
2815
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
2816
|
-
return uuidRegex.test(uuid);
|
|
2817
|
-
}
|
|
2818
2822
|
var Encryption = async (config) => {
|
|
2819
|
-
if (config.logging) {
|
|
2820
|
-
initStackLogger(config.logging);
|
|
2821
|
-
}
|
|
2822
2823
|
const { schemas, config: clientConfig } = config;
|
|
2823
2824
|
if (!schemas.length) {
|
|
2824
2825
|
throw new Error(
|
|
2825
2826
|
"[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
|
|
2826
2827
|
);
|
|
2827
2828
|
}
|
|
2828
|
-
if (clientConfig?.keyset && "id" in clientConfig.keyset && !
|
|
2829
|
+
if (clientConfig?.keyset && "id" in clientConfig.keyset && !(0, import_uuid.validate)(clientConfig.keyset.id)) {
|
|
2829
2830
|
throw new Error(
|
|
2830
2831
|
"[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
|
|
2831
2832
|
);
|
|
@@ -2841,13 +2842,350 @@ var Encryption = async (config) => {
|
|
|
2841
2842
|
}
|
|
2842
2843
|
return result.data;
|
|
2843
2844
|
};
|
|
2845
|
+
|
|
2846
|
+
// src/secrets/index.ts
|
|
2847
|
+
var Secrets = class {
|
|
2848
|
+
encryptionClient = null;
|
|
2849
|
+
config;
|
|
2850
|
+
apiBaseUrl = process.env.STASH_API_URL || "https://dashboard.cipherstash.com/api/secrets";
|
|
2851
|
+
secretsSchema = encryptedTable("secrets", {
|
|
2852
|
+
value: encryptedColumn("value")
|
|
2853
|
+
});
|
|
2854
|
+
constructor(config) {
|
|
2855
|
+
const workspaceCRN = config.workspaceCRN ?? process.env.CS_WORKSPACE_CRN;
|
|
2856
|
+
const clientId = config.clientId ?? process.env.CS_CLIENT_ID;
|
|
2857
|
+
const clientKey = config.clientKey ?? process.env.CS_CLIENT_KEY;
|
|
2858
|
+
const accessKey = config.accessKey ?? process.env.CS_CLIENT_ACCESS_KEY;
|
|
2859
|
+
if (!workspaceCRN || !clientId || !clientKey || !accessKey) {
|
|
2860
|
+
throw new Error(
|
|
2861
|
+
"Missing required configuration or environment variables."
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
this.config = {
|
|
2865
|
+
environment: config.environment,
|
|
2866
|
+
workspaceCRN,
|
|
2867
|
+
clientId,
|
|
2868
|
+
clientKey,
|
|
2869
|
+
accessKey
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
initPromise = null;
|
|
2873
|
+
/**
|
|
2874
|
+
* Initialize the Secrets client and underlying Encryption client
|
|
2875
|
+
*/
|
|
2876
|
+
async ensureInitialized() {
|
|
2877
|
+
if (!this.initPromise) {
|
|
2878
|
+
this.initPromise = this._doInit();
|
|
2879
|
+
}
|
|
2880
|
+
return this.initPromise;
|
|
2881
|
+
}
|
|
2882
|
+
async _doInit() {
|
|
2883
|
+
logger.debug("Initializing the Secrets client.");
|
|
2884
|
+
this.encryptionClient = await Encryption({
|
|
2885
|
+
schemas: [this.secretsSchema],
|
|
2886
|
+
config: {
|
|
2887
|
+
workspaceCrn: this.config.workspaceCRN,
|
|
2888
|
+
clientId: this.config.clientId,
|
|
2889
|
+
clientKey: this.config.clientKey,
|
|
2890
|
+
accessKey: this.config.accessKey,
|
|
2891
|
+
keyset: { name: this.config.environment }
|
|
2892
|
+
}
|
|
2893
|
+
});
|
|
2894
|
+
logger.debug("Successfully initialized the Secrets client.");
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
2897
|
+
* Get the authorization header for API requests
|
|
2898
|
+
*/
|
|
2899
|
+
getAuthHeader() {
|
|
2900
|
+
return `Bearer ${this.config.accessKey}`;
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Make an API request with error handling.
|
|
2904
|
+
*
|
|
2905
|
+
* For GET requests, `params` are appended as URL query parameters.
|
|
2906
|
+
* For POST requests, `body` is sent as JSON in the request body.
|
|
2907
|
+
*/
|
|
2908
|
+
async apiRequest(method, path2, options) {
|
|
2909
|
+
try {
|
|
2910
|
+
let url = `${this.apiBaseUrl}${path2}`;
|
|
2911
|
+
if (options?.params) {
|
|
2912
|
+
const searchParams = new URLSearchParams(options.params);
|
|
2913
|
+
url = `${url}?${searchParams.toString()}`;
|
|
2914
|
+
}
|
|
2915
|
+
logger.debug(`Secrets API request: ${method} ${path2}`);
|
|
2916
|
+
const headers = {
|
|
2917
|
+
"Content-Type": "application/json",
|
|
2918
|
+
Authorization: this.getAuthHeader()
|
|
2919
|
+
};
|
|
2920
|
+
const response = await fetch(url, {
|
|
2921
|
+
method,
|
|
2922
|
+
headers,
|
|
2923
|
+
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
2924
|
+
});
|
|
2925
|
+
if (!response.ok) {
|
|
2926
|
+
const errorText = await response.text();
|
|
2927
|
+
let errorMessage = `API request failed with status ${response.status}`;
|
|
2928
|
+
try {
|
|
2929
|
+
const errorJson = JSON.parse(errorText);
|
|
2930
|
+
errorMessage = errorJson.message || errorJson.error || errorMessage;
|
|
2931
|
+
} catch {
|
|
2932
|
+
errorMessage = errorText || errorMessage;
|
|
2933
|
+
}
|
|
2934
|
+
logger.error(`Secrets API error on ${method} ${path2}: ${errorMessage}`);
|
|
2935
|
+
return {
|
|
2936
|
+
failure: {
|
|
2937
|
+
type: "ApiError",
|
|
2938
|
+
message: errorMessage
|
|
2939
|
+
}
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
logger.debug(`Secrets API request successful: ${method} ${path2}`);
|
|
2943
|
+
const data = await response.json();
|
|
2944
|
+
return { data };
|
|
2945
|
+
} catch (error) {
|
|
2946
|
+
const message = error instanceof Error ? error.message : "Unknown network error occurred";
|
|
2947
|
+
logger.error(`Secrets network error on ${method} ${path2}: ${message}`);
|
|
2948
|
+
return {
|
|
2949
|
+
failure: {
|
|
2950
|
+
type: "NetworkError",
|
|
2951
|
+
message
|
|
2952
|
+
}
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
/**
|
|
2957
|
+
* Store an encrypted secret in the vault.
|
|
2958
|
+
* The value is encrypted locally before being sent to the API.
|
|
2959
|
+
*
|
|
2960
|
+
* API: POST /api/secrets/set
|
|
2961
|
+
*
|
|
2962
|
+
* @param name - The name of the secret
|
|
2963
|
+
* @param value - The plaintext value to encrypt and store
|
|
2964
|
+
* @returns A Result containing the API response or an error
|
|
2965
|
+
*/
|
|
2966
|
+
async set(name, value) {
|
|
2967
|
+
logger.debug("Setting secret");
|
|
2968
|
+
await this.ensureInitialized();
|
|
2969
|
+
if (!this.encryptionClient) {
|
|
2970
|
+
return {
|
|
2971
|
+
failure: {
|
|
2972
|
+
type: "ClientError",
|
|
2973
|
+
message: "Failed to initialize Encryption client"
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
const encryptResult = await this.encryptionClient.encrypt(value, {
|
|
2978
|
+
column: this.secretsSchema.value,
|
|
2979
|
+
table: this.secretsSchema
|
|
2980
|
+
});
|
|
2981
|
+
if (encryptResult.failure) {
|
|
2982
|
+
logger.error("Failed to encrypt secret");
|
|
2983
|
+
return {
|
|
2984
|
+
failure: {
|
|
2985
|
+
type: "EncryptionError",
|
|
2986
|
+
message: encryptResult.failure.message
|
|
2987
|
+
}
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
2991
|
+
return await this.apiRequest("POST", "/set", {
|
|
2992
|
+
body: {
|
|
2993
|
+
workspaceId,
|
|
2994
|
+
environment: this.config.environment,
|
|
2995
|
+
name,
|
|
2996
|
+
encryptedValue: encryptedToPgComposite(encryptResult.data)
|
|
2997
|
+
}
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Retrieve and decrypt a secret from the vault.
|
|
3002
|
+
* The secret is decrypted locally after retrieval.
|
|
3003
|
+
*
|
|
3004
|
+
* API: GET /api/secrets/get?workspaceId=...&environment=...&name=...
|
|
3005
|
+
*
|
|
3006
|
+
* @param name - The name of the secret to retrieve
|
|
3007
|
+
* @returns A Result containing the decrypted value or an error
|
|
3008
|
+
*/
|
|
3009
|
+
async get(name) {
|
|
3010
|
+
logger.debug("Getting secret");
|
|
3011
|
+
await this.ensureInitialized();
|
|
3012
|
+
if (!this.encryptionClient) {
|
|
3013
|
+
return {
|
|
3014
|
+
failure: {
|
|
3015
|
+
type: "ClientError",
|
|
3016
|
+
message: "Failed to initialize Encryption client"
|
|
3017
|
+
}
|
|
3018
|
+
};
|
|
3019
|
+
}
|
|
3020
|
+
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
3021
|
+
const apiResult = await this.apiRequest("GET", "/get", {
|
|
3022
|
+
params: {
|
|
3023
|
+
workspaceId,
|
|
3024
|
+
environment: this.config.environment,
|
|
3025
|
+
name
|
|
3026
|
+
}
|
|
3027
|
+
});
|
|
3028
|
+
if (apiResult.failure) {
|
|
3029
|
+
return apiResult;
|
|
3030
|
+
}
|
|
3031
|
+
const decryptResult = await this.encryptionClient.decrypt(
|
|
3032
|
+
apiResult.data.encryptedValue.data
|
|
3033
|
+
);
|
|
3034
|
+
if (decryptResult.failure) {
|
|
3035
|
+
logger.error("Failed to decrypt secret");
|
|
3036
|
+
return {
|
|
3037
|
+
failure: {
|
|
3038
|
+
type: "DecryptionError",
|
|
3039
|
+
message: decryptResult.failure.message
|
|
3040
|
+
}
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
if (typeof decryptResult.data !== "string") {
|
|
3044
|
+
logger.error("Decrypted secret value is not a string");
|
|
3045
|
+
return {
|
|
3046
|
+
failure: {
|
|
3047
|
+
type: "DecryptionError",
|
|
3048
|
+
message: "Decrypted value is not a string"
|
|
3049
|
+
}
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
return { data: decryptResult.data };
|
|
3053
|
+
}
|
|
3054
|
+
/**
|
|
3055
|
+
* Retrieve and decrypt many secrets from the vault.
|
|
3056
|
+
* The secrets are decrypted locally after retrieval.
|
|
3057
|
+
* This method only triggers a single network request to the ZeroKMS.
|
|
3058
|
+
*
|
|
3059
|
+
* API: GET /api/secrets/get-many?workspaceId=...&environment=...&names=name1,name2,...
|
|
3060
|
+
*
|
|
3061
|
+
* Constraints:
|
|
3062
|
+
* - Minimum 2 secret names required
|
|
3063
|
+
* - Maximum 100 secret names per request
|
|
3064
|
+
*
|
|
3065
|
+
* @param names - The names of the secrets to retrieve (min 2, max 100)
|
|
3066
|
+
* @returns A Result containing an object mapping secret names to their decrypted values
|
|
3067
|
+
*/
|
|
3068
|
+
async getMany(names) {
|
|
3069
|
+
logger.debug(`Getting ${names.length} secrets.`);
|
|
3070
|
+
await this.ensureInitialized();
|
|
3071
|
+
if (!this.encryptionClient) {
|
|
3072
|
+
return {
|
|
3073
|
+
failure: {
|
|
3074
|
+
type: "ClientError",
|
|
3075
|
+
message: "Failed to initialize Encryption client"
|
|
3076
|
+
}
|
|
3077
|
+
};
|
|
3078
|
+
}
|
|
3079
|
+
if (names.length < 2) {
|
|
3080
|
+
return {
|
|
3081
|
+
failure: {
|
|
3082
|
+
type: "ClientError",
|
|
3083
|
+
message: "At least 2 secret names are required for getMany"
|
|
3084
|
+
}
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
if (names.length > 100) {
|
|
3088
|
+
return {
|
|
3089
|
+
failure: {
|
|
3090
|
+
type: "ClientError",
|
|
3091
|
+
message: "Maximum 100 secret names per request"
|
|
3092
|
+
}
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
3096
|
+
const apiResult = await this.apiRequest(
|
|
3097
|
+
"GET",
|
|
3098
|
+
"/get-many",
|
|
3099
|
+
{
|
|
3100
|
+
params: {
|
|
3101
|
+
workspaceId,
|
|
3102
|
+
environment: this.config.environment,
|
|
3103
|
+
names: names.join(",")
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
);
|
|
3107
|
+
if (apiResult.failure) {
|
|
3108
|
+
return apiResult;
|
|
3109
|
+
}
|
|
3110
|
+
const dataToDecrypt = apiResult.data.map((item) => ({
|
|
3111
|
+
name: item.name,
|
|
3112
|
+
value: item.encryptedValue.data
|
|
3113
|
+
}));
|
|
3114
|
+
const decryptResult = await this.encryptionClient.bulkDecryptModels(dataToDecrypt);
|
|
3115
|
+
if (decryptResult.failure) {
|
|
3116
|
+
logger.error(
|
|
3117
|
+
`Failed to decrypt secrets: ${decryptResult.failure.message}`
|
|
3118
|
+
);
|
|
3119
|
+
return {
|
|
3120
|
+
failure: {
|
|
3121
|
+
type: "DecryptionError",
|
|
3122
|
+
message: decryptResult.failure.message
|
|
3123
|
+
}
|
|
3124
|
+
};
|
|
3125
|
+
}
|
|
3126
|
+
const decryptedSecrets = decryptResult.data;
|
|
3127
|
+
const secretsMap = {};
|
|
3128
|
+
for (const secret of decryptedSecrets) {
|
|
3129
|
+
if (secret.name && secret.value) {
|
|
3130
|
+
secretsMap[secret.name] = secret.value;
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
return { data: secretsMap };
|
|
3134
|
+
}
|
|
3135
|
+
/**
|
|
3136
|
+
* List all secrets in the environment.
|
|
3137
|
+
* Only names and metadata are returned; values remain encrypted.
|
|
3138
|
+
*
|
|
3139
|
+
* API: GET /api/secrets/list?workspaceId=...&environment=...
|
|
3140
|
+
*
|
|
3141
|
+
* @returns A Result containing the list of secrets or an error
|
|
3142
|
+
*/
|
|
3143
|
+
async list() {
|
|
3144
|
+
logger.debug("Listing secrets.");
|
|
3145
|
+
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
3146
|
+
const apiResult = await this.apiRequest(
|
|
3147
|
+
"GET",
|
|
3148
|
+
"/list",
|
|
3149
|
+
{
|
|
3150
|
+
params: {
|
|
3151
|
+
workspaceId,
|
|
3152
|
+
environment: this.config.environment
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
);
|
|
3156
|
+
if (apiResult.failure) {
|
|
3157
|
+
return apiResult;
|
|
3158
|
+
}
|
|
3159
|
+
return { data: apiResult.data.secrets };
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Delete a secret from the vault.
|
|
3163
|
+
*
|
|
3164
|
+
* API: POST /api/secrets/delete
|
|
3165
|
+
*
|
|
3166
|
+
* @param name - The name of the secret to delete
|
|
3167
|
+
* @returns A Result containing the API response or an error
|
|
3168
|
+
*/
|
|
3169
|
+
async delete(name) {
|
|
3170
|
+
logger.debug("Deleting secret");
|
|
3171
|
+
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
3172
|
+
return await this.apiRequest("POST", "/delete", {
|
|
3173
|
+
body: {
|
|
3174
|
+
workspaceId,
|
|
3175
|
+
environment: this.config.environment,
|
|
3176
|
+
name
|
|
3177
|
+
}
|
|
3178
|
+
});
|
|
3179
|
+
}
|
|
3180
|
+
};
|
|
2844
3181
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2845
3182
|
0 && (module.exports = {
|
|
2846
3183
|
Encryption,
|
|
2847
|
-
|
|
3184
|
+
Secrets,
|
|
2848
3185
|
encryptedColumn,
|
|
2849
3186
|
encryptedField,
|
|
2850
3187
|
encryptedTable,
|
|
2851
|
-
|
|
3188
|
+
encryptedToPgComposite,
|
|
3189
|
+
isEncryptedPayload
|
|
2852
3190
|
});
|
|
2853
3191
|
//# sourceMappingURL=index.cjs.map
|