@cipherstash/stack 0.3.0 → 0.5.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 +10 -37
- package/dist/bin/stash.js +261 -320
- package/dist/bin/stash.js.map +1 -1
- package/dist/{chunk-SUYMGQBY.js → chunk-4RNBI3UH.js} +1 -7
- package/dist/chunk-4RNBI3UH.js.map +1 -0
- package/dist/{chunk-OAPLZLR5.js → chunk-GXGEW6T4.js} +2 -76
- package/dist/chunk-GXGEW6T4.js.map +1 -0
- package/dist/{chunk-JLI27P46.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-MW6D52V2.js → chunk-TGUELLJS.js} +58 -150
- package/dist/chunk-TGUELLJS.js.map +1 -0
- package/dist/{chunk-TBAIVO6T.js → chunk-Y35W4WFN.js} +6 -6
- package/dist/chunk-Y35W4WFN.js.map +1 -0
- package/dist/chunk-YLISU7FD.js +357 -0
- package/dist/chunk-YLISU7FD.js.map +1 -0
- package/dist/{client-Bf0Xw2xo.d.cts → client-BFrHTgC6.d.ts} +50 -18
- package/dist/{client-Kfp8OsPB.d.ts → client-BVQvgvdY.d.cts} +50 -18
- package/dist/client.cjs +5 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -4
- package/dist/client.d.ts +4 -4
- package/dist/client.js +1 -1
- package/dist/drizzle/index.cjs +5 -5
- 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 +4 -4
- 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 +425 -182
- 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 +15 -9
- package/dist/schema/index.cjs +5 -5
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1 -2
- package/dist/schema/index.d.ts +1 -2
- package/dist/schema/index.js +1 -1
- package/dist/secrets/index.cjs +116 -180
- 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 +86 -3
- 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 +26 -3
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-public-0CzBV45X.d.cts → types-public-dKxDzTIL.d.cts} +47 -34
- package/dist/{types-public-0CzBV45X.d.ts → types-public-dKxDzTIL.d.ts} +47 -34
- 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 +30 -2
- package/dist/chunk-JLI27P46.js.map +0 -1
- package/dist/chunk-MW6D52V2.js.map +0 -1
- package/dist/chunk-OAPLZLR5.js.map +0 -1
- package/dist/chunk-SUYMGQBY.js.map +0 -1
- package/dist/chunk-TBAIVO6T.js.map +0 -1
- package/dist/index-9-Ya3fDK.d.cts +0 -169
- package/dist/index-9-Ya3fDK.d.ts +0 -169
package/dist/secrets/index.cjs
CHANGED
|
@@ -41,15 +41,9 @@ function encryptedToPgComposite(obj) {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
function encryptedToCompositeLiteral(obj) {
|
|
44
|
-
if (obj === null) {
|
|
45
|
-
throw new Error("encryptedToCompositeLiteral: obj cannot be null");
|
|
46
|
-
}
|
|
47
44
|
return `(${JSON.stringify(JSON.stringify(obj))})`;
|
|
48
45
|
}
|
|
49
46
|
function encryptedToEscapedCompositeLiteral(obj) {
|
|
50
|
-
if (obj === null) {
|
|
51
|
-
throw new Error("encryptedToEscapedCompositeLiteral: obj cannot be null");
|
|
52
|
-
}
|
|
53
47
|
return JSON.stringify(encryptedToCompositeLiteral(obj));
|
|
54
48
|
}
|
|
55
49
|
function formatEncryptedResult(encrypted, returnType) {
|
|
@@ -78,18 +72,9 @@ function isEncryptedPayload(value) {
|
|
|
78
72
|
return true;
|
|
79
73
|
}
|
|
80
74
|
|
|
81
|
-
// src/errors/index.ts
|
|
82
|
-
var EncryptionErrorTypes = {
|
|
83
|
-
ClientInitError: "ClientInitError",
|
|
84
|
-
EncryptionError: "EncryptionError",
|
|
85
|
-
DecryptionError: "DecryptionError",
|
|
86
|
-
LockContextError: "LockContextError",
|
|
87
|
-
CtsTokenError: "CtsTokenError"
|
|
88
|
-
};
|
|
89
|
-
|
|
90
75
|
// src/schema/index.ts
|
|
91
76
|
var import_zod = require("zod");
|
|
92
|
-
var castAsEnum = import_zod.z.enum(["bigint", "boolean", "date", "number", "string", "json"]).default("
|
|
77
|
+
var castAsEnum = import_zod.z.enum(["bigint", "boolean", "date", "number", "string", "json", "text"]).default("text");
|
|
93
78
|
var tokenFilterSchema = import_zod.z.object({
|
|
94
79
|
kind: import_zod.z.literal("downcase")
|
|
95
80
|
});
|
|
@@ -137,7 +122,7 @@ var EncryptedField = class {
|
|
|
137
122
|
castAsValue;
|
|
138
123
|
constructor(valueName) {
|
|
139
124
|
this.valueName = valueName;
|
|
140
|
-
this.castAsValue = "
|
|
125
|
+
this.castAsValue = "text";
|
|
141
126
|
}
|
|
142
127
|
/**
|
|
143
128
|
* Set or override the plaintext data type for this field.
|
|
@@ -146,7 +131,7 @@ var EncryptedField = class {
|
|
|
146
131
|
* a different type so the encryption layer knows how to encode the plaintext
|
|
147
132
|
* before encrypting.
|
|
148
133
|
*
|
|
149
|
-
* @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'bigint'`, or `'json'`.
|
|
134
|
+
* @param castAs - The plaintext data type: `'string'`, `'number'`, `'boolean'`, `'date'`, `'text'`, `'bigint'`, or `'json'`.
|
|
150
135
|
* @returns This `EncryptedField` instance for method chaining.
|
|
151
136
|
*
|
|
152
137
|
* @example
|
|
@@ -162,7 +147,7 @@ var EncryptedField = class {
|
|
|
162
147
|
}
|
|
163
148
|
build() {
|
|
164
149
|
return {
|
|
165
|
-
cast_as: this.castAsValue,
|
|
150
|
+
cast_as: this.castAsValue === "string" ? "text" : this.castAsValue,
|
|
166
151
|
indexes: {}
|
|
167
152
|
};
|
|
168
153
|
}
|
|
@@ -316,7 +301,7 @@ var EncryptedColumn = class {
|
|
|
316
301
|
}
|
|
317
302
|
build() {
|
|
318
303
|
return {
|
|
319
|
-
cast_as: this.castAsValue,
|
|
304
|
+
cast_as: this.castAsValue === "string" ? "text" : this.castAsValue,
|
|
320
305
|
indexes: this.indexesValue
|
|
321
306
|
};
|
|
322
307
|
}
|
|
@@ -411,6 +396,15 @@ function buildEncryptConfig(...protectTables) {
|
|
|
411
396
|
return config;
|
|
412
397
|
}
|
|
413
398
|
|
|
399
|
+
// src/errors/index.ts
|
|
400
|
+
var EncryptionErrorTypes = {
|
|
401
|
+
ClientInitError: "ClientInitError",
|
|
402
|
+
EncryptionError: "EncryptionError",
|
|
403
|
+
DecryptionError: "DecryptionError",
|
|
404
|
+
LockContextError: "LockContextError",
|
|
405
|
+
CtsTokenError: "CtsTokenError"
|
|
406
|
+
};
|
|
407
|
+
|
|
414
408
|
// src/utils/config/index.ts
|
|
415
409
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
416
410
|
var import_node_path = __toESM(require("path"), 1);
|
|
@@ -476,25 +470,33 @@ function loadWorkSpaceId(suppliedCrn) {
|
|
|
476
470
|
|
|
477
471
|
// src/utils/logger/index.ts
|
|
478
472
|
var import_evlog = require("evlog");
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
473
|
+
var validLevels = ["debug", "info", "error"];
|
|
474
|
+
function levelFromEnv() {
|
|
475
|
+
const env = process.env.STASH_STACK_LOG;
|
|
476
|
+
if (env && validLevels.includes(env)) return env;
|
|
477
|
+
return "error";
|
|
478
|
+
}
|
|
479
|
+
function samplingRatesForLevel(level) {
|
|
480
|
+
switch (level) {
|
|
481
|
+
case "debug":
|
|
482
|
+
return { debug: 100, info: 100, warn: 100, error: 100 };
|
|
483
|
+
case "info":
|
|
484
|
+
return { debug: 0, info: 100, warn: 100, error: 100 };
|
|
485
|
+
case "error":
|
|
486
|
+
default:
|
|
487
|
+
return { debug: 0, info: 0, warn: 0, error: 100 };
|
|
488
|
+
}
|
|
486
489
|
}
|
|
487
490
|
var initialized = false;
|
|
488
|
-
function initStackLogger(
|
|
491
|
+
function initStackLogger() {
|
|
489
492
|
if (initialized) return;
|
|
490
493
|
initialized = true;
|
|
491
|
-
const
|
|
494
|
+
const level = levelFromEnv();
|
|
495
|
+
const rates = samplingRatesForLevel(level);
|
|
492
496
|
(0, import_evlog.initLogger)({
|
|
493
497
|
env: { service: "@cipherstash/stack" },
|
|
494
|
-
enabled:
|
|
495
|
-
|
|
496
|
-
...rates && { sampling: { rates } },
|
|
497
|
-
...config?.drain && { drain: config.drain }
|
|
498
|
+
enabled: true,
|
|
499
|
+
sampling: { rates }
|
|
498
500
|
});
|
|
499
501
|
}
|
|
500
502
|
initStackLogger();
|
|
@@ -532,6 +534,7 @@ var logger = {
|
|
|
532
534
|
// src/encryption/index.ts
|
|
533
535
|
var import_result11 = require("@byteslice/result");
|
|
534
536
|
var import_protect_ffi9 = require("@cipherstash/protect-ffi");
|
|
537
|
+
var import_uuid = require("uuid");
|
|
535
538
|
|
|
536
539
|
// src/encryption/helpers/type-guards.ts
|
|
537
540
|
function isScalarQueryTermArray(value) {
|
|
@@ -687,18 +690,6 @@ var EncryptionOperation = class {
|
|
|
687
690
|
};
|
|
688
691
|
|
|
689
692
|
// src/encryption/operations/batch-encrypt-query.ts
|
|
690
|
-
function filterNullTerms(terms) {
|
|
691
|
-
const nullIndices = /* @__PURE__ */ new Set();
|
|
692
|
-
const nonNullTerms = [];
|
|
693
|
-
terms.forEach((term, index) => {
|
|
694
|
-
if (term.value === null || term.value === void 0) {
|
|
695
|
-
nullIndices.add(index);
|
|
696
|
-
} else {
|
|
697
|
-
nonNullTerms.push({ term, originalIndex: index });
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
return { nullIndices, nonNullTerms };
|
|
701
|
-
}
|
|
702
693
|
function buildQueryPayload(term, lockContext) {
|
|
703
694
|
assertValidNumericValue(term.value);
|
|
704
695
|
const { indexType, queryOp } = resolveIndexType(
|
|
@@ -719,13 +710,10 @@ function buildQueryPayload(term, lockContext) {
|
|
|
719
710
|
}
|
|
720
711
|
return payload;
|
|
721
712
|
}
|
|
722
|
-
function assembleResults(
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
results[originalIndex] = formatEncryptedResult(encrypted, term.returnType);
|
|
727
|
-
});
|
|
728
|
-
return results;
|
|
713
|
+
function assembleResults(terms, encryptedValues) {
|
|
714
|
+
return terms.map(
|
|
715
|
+
(term, i) => formatEncryptedResult(encryptedValues[i], term.returnType)
|
|
716
|
+
);
|
|
729
717
|
}
|
|
730
718
|
var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
731
719
|
constructor(client, terms) {
|
|
@@ -752,23 +740,18 @@ var BatchEncryptQueryOperation = class extends EncryptionOperation {
|
|
|
752
740
|
log.emit();
|
|
753
741
|
return { data: [] };
|
|
754
742
|
}
|
|
755
|
-
const { nullIndices, nonNullTerms } = filterNullTerms(this.terms);
|
|
756
|
-
if (nonNullTerms.length === 0) {
|
|
757
|
-
log.emit();
|
|
758
|
-
return { data: this.terms.map(() => null) };
|
|
759
|
-
}
|
|
760
743
|
const result = await (0, import_result.withResult)(
|
|
761
744
|
async () => {
|
|
762
745
|
if (!this.client) throw noClientError();
|
|
763
746
|
const { metadata } = this.getAuditData();
|
|
764
|
-
const queries =
|
|
765
|
-
(
|
|
747
|
+
const queries = this.terms.map(
|
|
748
|
+
(term) => buildQueryPayload(term)
|
|
766
749
|
);
|
|
767
750
|
const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
|
|
768
751
|
queries,
|
|
769
752
|
unverifiedContext: metadata
|
|
770
753
|
});
|
|
771
|
-
return assembleResults(this.terms
|
|
754
|
+
return assembleResults(this.terms, encrypted);
|
|
772
755
|
},
|
|
773
756
|
(error) => {
|
|
774
757
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -802,11 +785,6 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
802
785
|
log.emit();
|
|
803
786
|
return { data: [] };
|
|
804
787
|
}
|
|
805
|
-
const { nullIndices, nonNullTerms } = filterNullTerms(this.terms);
|
|
806
|
-
if (nonNullTerms.length === 0) {
|
|
807
|
-
log.emit();
|
|
808
|
-
return { data: this.terms.map(() => null) };
|
|
809
|
-
}
|
|
810
788
|
const lockContextResult = await this.lockContext.getLockContext();
|
|
811
789
|
if (lockContextResult.failure) {
|
|
812
790
|
log.emit();
|
|
@@ -817,15 +795,15 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
817
795
|
async () => {
|
|
818
796
|
if (!this.client) throw noClientError();
|
|
819
797
|
const { metadata } = this.getAuditData();
|
|
820
|
-
const queries =
|
|
821
|
-
(
|
|
798
|
+
const queries = this.terms.map(
|
|
799
|
+
(term) => buildQueryPayload(term, context)
|
|
822
800
|
);
|
|
823
801
|
const encrypted = await (0, import_protect_ffi2.encryptQueryBulk)(this.client, {
|
|
824
802
|
queries,
|
|
825
803
|
serviceToken: ctsToken,
|
|
826
804
|
unverifiedContext: metadata
|
|
827
805
|
});
|
|
828
|
-
return assembleResults(this.terms
|
|
806
|
+
return assembleResults(this.terms, encrypted);
|
|
829
807
|
},
|
|
830
808
|
(error) => {
|
|
831
809
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -845,42 +823,25 @@ var BatchEncryptQueryOperationWithLockContext = class extends EncryptionOperatio
|
|
|
845
823
|
var import_result2 = require("@byteslice/result");
|
|
846
824
|
var import_protect_ffi3 = require("@cipherstash/protect-ffi");
|
|
847
825
|
var createDecryptPayloads = (encryptedPayloads, lockContext) => {
|
|
848
|
-
return encryptedPayloads.map((
|
|
826
|
+
return encryptedPayloads.map(({ id, data }) => ({
|
|
849
827
|
id,
|
|
850
828
|
ciphertext: data,
|
|
851
|
-
originalIndex,
|
|
852
829
|
...lockContext && { lockContext }
|
|
853
830
|
}));
|
|
854
831
|
};
|
|
855
|
-
var createNullResult = (encryptedPayloads) => {
|
|
856
|
-
return encryptedPayloads.map(({ id }) => ({
|
|
857
|
-
id,
|
|
858
|
-
data: null
|
|
859
|
-
}));
|
|
860
|
-
};
|
|
861
832
|
var mapDecryptedDataToResult = (encryptedPayloads, decryptedData) => {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
const decryptResult = decryptedData[decryptedIndex];
|
|
869
|
-
if ("error" in decryptResult) {
|
|
870
|
-
result[i] = {
|
|
871
|
-
id: encryptedPayloads[i].id,
|
|
872
|
-
error: decryptResult.error
|
|
873
|
-
};
|
|
874
|
-
} else {
|
|
875
|
-
result[i] = {
|
|
876
|
-
id: encryptedPayloads[i].id,
|
|
877
|
-
data: decryptResult.data
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
|
-
decryptedIndex++;
|
|
833
|
+
return decryptedData.map((decryptResult, i) => {
|
|
834
|
+
if ("error" in decryptResult) {
|
|
835
|
+
return {
|
|
836
|
+
id: encryptedPayloads[i].id,
|
|
837
|
+
error: decryptResult.error
|
|
838
|
+
};
|
|
881
839
|
}
|
|
882
|
-
|
|
883
|
-
|
|
840
|
+
return {
|
|
841
|
+
id: encryptedPayloads[i].id,
|
|
842
|
+
data: decryptResult.data
|
|
843
|
+
};
|
|
844
|
+
});
|
|
884
845
|
};
|
|
885
846
|
var BulkDecryptOperation = class extends EncryptionOperation {
|
|
886
847
|
client;
|
|
@@ -905,13 +866,10 @@ var BulkDecryptOperation = class extends EncryptionOperation {
|
|
|
905
866
|
if (!this.client) throw noClientError();
|
|
906
867
|
if (!this.encryptedPayloads || this.encryptedPayloads.length === 0)
|
|
907
868
|
return [];
|
|
908
|
-
const
|
|
909
|
-
if (nonNullPayloads.length === 0) {
|
|
910
|
-
return createNullResult(this.encryptedPayloads);
|
|
911
|
-
}
|
|
869
|
+
const payloads = createDecryptPayloads(this.encryptedPayloads);
|
|
912
870
|
const { metadata } = this.getAuditData();
|
|
913
871
|
const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(this.client, {
|
|
914
|
-
ciphertexts:
|
|
872
|
+
ciphertexts: payloads,
|
|
915
873
|
unverifiedContext: metadata
|
|
916
874
|
});
|
|
917
875
|
return mapDecryptedDataToResult(this.encryptedPayloads, decryptedData);
|
|
@@ -963,16 +921,13 @@ var BulkDecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
963
921
|
if (context.failure) {
|
|
964
922
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
965
923
|
}
|
|
966
|
-
const
|
|
924
|
+
const payloads = createDecryptPayloads(
|
|
967
925
|
encryptedPayloads,
|
|
968
926
|
context.data.context
|
|
969
927
|
);
|
|
970
|
-
if (nonNullPayloads.length === 0) {
|
|
971
|
-
return createNullResult(encryptedPayloads);
|
|
972
|
-
}
|
|
973
928
|
const { metadata } = this.getAuditData();
|
|
974
929
|
const decryptedData = await (0, import_protect_ffi3.decryptBulkFallible)(client, {
|
|
975
|
-
ciphertexts:
|
|
930
|
+
ciphertexts: payloads,
|
|
976
931
|
serviceToken: context.data.ctsToken,
|
|
977
932
|
unverifiedContext: metadata
|
|
978
933
|
});
|
|
@@ -1611,34 +1566,14 @@ var BulkDecryptModelsOperationWithLockContext = class extends EncryptionOperatio
|
|
|
1611
1566
|
var import_result4 = require("@byteslice/result");
|
|
1612
1567
|
var import_protect_ffi5 = require("@cipherstash/protect-ffi");
|
|
1613
1568
|
var createEncryptPayloads = (plaintexts, column, table, lockContext) => {
|
|
1614
|
-
return plaintexts.map((
|
|
1569
|
+
return plaintexts.map(({ id, plaintext }) => ({
|
|
1615
1570
|
id,
|
|
1616
1571
|
plaintext,
|
|
1617
1572
|
column: column.getName(),
|
|
1618
1573
|
table: table.tableName,
|
|
1619
|
-
originalIndex,
|
|
1620
1574
|
...lockContext && { lockContext }
|
|
1621
1575
|
}));
|
|
1622
1576
|
};
|
|
1623
|
-
var createNullResult2 = (plaintexts) => {
|
|
1624
|
-
return plaintexts.map(({ id }) => ({ id, data: null }));
|
|
1625
|
-
};
|
|
1626
|
-
var mapEncryptedDataToResult = (plaintexts, encryptedData) => {
|
|
1627
|
-
const result = new Array(plaintexts.length);
|
|
1628
|
-
let encryptedIndex = 0;
|
|
1629
|
-
for (let i = 0; i < plaintexts.length; i++) {
|
|
1630
|
-
if (plaintexts[i].plaintext === null) {
|
|
1631
|
-
result[i] = { id: plaintexts[i].id, data: null };
|
|
1632
|
-
} else {
|
|
1633
|
-
result[i] = {
|
|
1634
|
-
id: plaintexts[i].id,
|
|
1635
|
-
data: encryptedData[encryptedIndex]
|
|
1636
|
-
};
|
|
1637
|
-
encryptedIndex++;
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
|
-
return result;
|
|
1641
|
-
};
|
|
1642
1577
|
var BulkEncryptOperation = class extends EncryptionOperation {
|
|
1643
1578
|
client;
|
|
1644
1579
|
plaintexts;
|
|
@@ -1671,20 +1606,20 @@ var BulkEncryptOperation = class extends EncryptionOperation {
|
|
|
1671
1606
|
if (!this.plaintexts || this.plaintexts.length === 0) {
|
|
1672
1607
|
return [];
|
|
1673
1608
|
}
|
|
1674
|
-
const
|
|
1609
|
+
const payloads = createEncryptPayloads(
|
|
1675
1610
|
this.plaintexts,
|
|
1676
1611
|
this.column,
|
|
1677
1612
|
this.table
|
|
1678
1613
|
);
|
|
1679
|
-
if (nonNullPayloads.length === 0) {
|
|
1680
|
-
return createNullResult2(this.plaintexts);
|
|
1681
|
-
}
|
|
1682
1614
|
const { metadata } = this.getAuditData();
|
|
1683
1615
|
const encryptedData = await (0, import_protect_ffi5.encryptBulk)(this.client, {
|
|
1684
|
-
plaintexts:
|
|
1616
|
+
plaintexts: payloads,
|
|
1685
1617
|
unverifiedContext: metadata
|
|
1686
1618
|
});
|
|
1687
|
-
return
|
|
1619
|
+
return encryptedData.map((data, i) => ({
|
|
1620
|
+
id: this.plaintexts[i].id,
|
|
1621
|
+
data
|
|
1622
|
+
}));
|
|
1688
1623
|
},
|
|
1689
1624
|
(error) => {
|
|
1690
1625
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1741,22 +1676,22 @@ var BulkEncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1741
1676
|
if (context.failure) {
|
|
1742
1677
|
throw new Error(`[encryption]: ${context.failure.message}`);
|
|
1743
1678
|
}
|
|
1744
|
-
const
|
|
1679
|
+
const payloads = createEncryptPayloads(
|
|
1745
1680
|
plaintexts,
|
|
1746
1681
|
column,
|
|
1747
1682
|
table,
|
|
1748
1683
|
context.data.context
|
|
1749
1684
|
);
|
|
1750
|
-
if (nonNullPayloads.length === 0) {
|
|
1751
|
-
return createNullResult2(plaintexts);
|
|
1752
|
-
}
|
|
1753
1685
|
const { metadata } = this.getAuditData();
|
|
1754
1686
|
const encryptedData = await (0, import_protect_ffi5.encryptBulk)(client, {
|
|
1755
|
-
plaintexts:
|
|
1687
|
+
plaintexts: payloads,
|
|
1756
1688
|
serviceToken: context.data.ctsToken,
|
|
1757
1689
|
unverifiedContext: metadata
|
|
1758
1690
|
});
|
|
1759
|
-
return
|
|
1691
|
+
return encryptedData.map((data, i) => ({
|
|
1692
|
+
id: plaintexts[i].id,
|
|
1693
|
+
data
|
|
1694
|
+
}));
|
|
1760
1695
|
},
|
|
1761
1696
|
(error) => {
|
|
1762
1697
|
log.set({ errorCode: getErrorCode(error) ?? "unknown" });
|
|
@@ -1906,9 +1841,6 @@ var DecryptOperation = class extends EncryptionOperation {
|
|
|
1906
1841
|
if (!this.client) {
|
|
1907
1842
|
throw noClientError();
|
|
1908
1843
|
}
|
|
1909
|
-
if (this.encryptedData === null) {
|
|
1910
|
-
return null;
|
|
1911
|
-
}
|
|
1912
1844
|
const { metadata } = this.getAuditData();
|
|
1913
1845
|
return await (0, import_protect_ffi6.decrypt)(this.client, {
|
|
1914
1846
|
ciphertext: this.encryptedData,
|
|
@@ -1959,9 +1891,6 @@ var DecryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
1959
1891
|
if (!client) {
|
|
1960
1892
|
throw noClientError();
|
|
1961
1893
|
}
|
|
1962
|
-
if (encryptedData === null) {
|
|
1963
|
-
return null;
|
|
1964
|
-
}
|
|
1965
1894
|
const { metadata } = this.getAuditData();
|
|
1966
1895
|
const context = await this.lockContext.getLockContext();
|
|
1967
1896
|
if (context.failure) {
|
|
@@ -2115,9 +2044,6 @@ var EncryptOperation = class extends EncryptionOperation {
|
|
|
2115
2044
|
if (!this.client) {
|
|
2116
2045
|
throw noClientError();
|
|
2117
2046
|
}
|
|
2118
|
-
if (this.plaintext === null) {
|
|
2119
|
-
return null;
|
|
2120
|
-
}
|
|
2121
2047
|
if (typeof this.plaintext === "number" && Number.isNaN(this.plaintext)) {
|
|
2122
2048
|
throw new Error("[encryption]: Cannot encrypt NaN value");
|
|
2123
2049
|
}
|
|
@@ -2179,9 +2105,6 @@ var EncryptOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2179
2105
|
if (!client) {
|
|
2180
2106
|
throw noClientError();
|
|
2181
2107
|
}
|
|
2182
|
-
if (plaintext === null) {
|
|
2183
|
-
return null;
|
|
2184
|
-
}
|
|
2185
2108
|
const { metadata } = this.getAuditData();
|
|
2186
2109
|
const context = await this.lockContext.getLockContext();
|
|
2187
2110
|
if (context.failure) {
|
|
@@ -2345,10 +2268,6 @@ var EncryptQueryOperation = class extends EncryptionOperation {
|
|
|
2345
2268
|
queryType: this.opts.queryType,
|
|
2346
2269
|
lockContext: false
|
|
2347
2270
|
});
|
|
2348
|
-
if (this.plaintext === null || this.plaintext === void 0) {
|
|
2349
|
-
log.emit();
|
|
2350
|
-
return { data: null };
|
|
2351
|
-
}
|
|
2352
2271
|
const validationError = validateNumericValue(this.plaintext);
|
|
2353
2272
|
if (validationError?.failure) {
|
|
2354
2273
|
log.emit();
|
|
@@ -2412,10 +2331,6 @@ var EncryptQueryOperationWithLockContext = class extends EncryptionOperation {
|
|
|
2412
2331
|
queryType: this.opts.queryType,
|
|
2413
2332
|
lockContext: true
|
|
2414
2333
|
});
|
|
2415
|
-
if (this.plaintext === null || this.plaintext === void 0) {
|
|
2416
|
-
log.emit();
|
|
2417
|
-
return { data: null };
|
|
2418
|
-
}
|
|
2419
2334
|
const validationError = validateNumericValue(this.plaintext);
|
|
2420
2335
|
if (validationError?.failure) {
|
|
2421
2336
|
log.emit();
|
|
@@ -2520,7 +2435,7 @@ var EncryptionClient = class {
|
|
|
2520
2435
|
/**
|
|
2521
2436
|
* Encrypt a value - returns a promise which resolves to an encrypted value.
|
|
2522
2437
|
*
|
|
2523
|
-
* @param plaintext - The plaintext value to be encrypted.
|
|
2438
|
+
* @param plaintext - The plaintext value to be encrypted.
|
|
2524
2439
|
* @param opts - Options specifying the column (or nested field) and table for encryption. See {@link EncryptOptions}.
|
|
2525
2440
|
* @returns An EncryptOperation that can be awaited or chained with additional methods.
|
|
2526
2441
|
*
|
|
@@ -2821,7 +2736,7 @@ var EncryptionClient = class {
|
|
|
2821
2736
|
*
|
|
2822
2737
|
* Each value is encrypted with its own unique key via a single call to ZeroKMS.
|
|
2823
2738
|
* Values can include optional `id` fields for correlating results back to
|
|
2824
|
-
* your application data.
|
|
2739
|
+
* your application data.
|
|
2825
2740
|
*
|
|
2826
2741
|
* @param plaintexts - An array of objects with `plaintext` (and optional `id`) fields.
|
|
2827
2742
|
* @param opts - Options specifying the target column (or nested {@link encryptedField}) and table. See {@link EncryptOptions}.
|
|
@@ -2842,7 +2757,6 @@ var EncryptionClient = class {
|
|
|
2842
2757
|
* [
|
|
2843
2758
|
* { id: "u1", plaintext: "alice@example.com" },
|
|
2844
2759
|
* { id: "u2", plaintext: "bob@example.com" },
|
|
2845
|
-
* { id: "u3", plaintext: null },
|
|
2846
2760
|
* ],
|
|
2847
2761
|
* { column: users.email, table: users },
|
|
2848
2762
|
* )
|
|
@@ -2896,23 +2810,14 @@ var EncryptionClient = class {
|
|
|
2896
2810
|
};
|
|
2897
2811
|
}
|
|
2898
2812
|
};
|
|
2899
|
-
|
|
2900
|
-
// src/index.ts
|
|
2901
|
-
function isValidUuid(uuid) {
|
|
2902
|
-
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;
|
|
2903
|
-
return uuidRegex.test(uuid);
|
|
2904
|
-
}
|
|
2905
2813
|
var Encryption = async (config) => {
|
|
2906
|
-
if (config.logging) {
|
|
2907
|
-
initStackLogger(config.logging);
|
|
2908
|
-
}
|
|
2909
2814
|
const { schemas, config: clientConfig } = config;
|
|
2910
2815
|
if (!schemas.length) {
|
|
2911
2816
|
throw new Error(
|
|
2912
2817
|
"[encryption]: At least one encryptedTable must be provided to initialize the encryption client"
|
|
2913
2818
|
);
|
|
2914
2819
|
}
|
|
2915
|
-
if (clientConfig?.keyset && "id" in clientConfig.keyset && !
|
|
2820
|
+
if (clientConfig?.keyset && "id" in clientConfig.keyset && !(0, import_uuid.validate)(clientConfig.keyset.id)) {
|
|
2916
2821
|
throw new Error(
|
|
2917
2822
|
"[encryption]: Invalid UUID provided for keyset id. Must be a valid UUID."
|
|
2918
2823
|
);
|
|
@@ -2938,7 +2843,22 @@ var Secrets = class {
|
|
|
2938
2843
|
value: encryptedColumn("value")
|
|
2939
2844
|
});
|
|
2940
2845
|
constructor(config) {
|
|
2941
|
-
|
|
2846
|
+
const workspaceCRN = config.workspaceCRN ?? process.env.CS_WORKSPACE_CRN;
|
|
2847
|
+
const clientId = config.clientId ?? process.env.CS_CLIENT_ID;
|
|
2848
|
+
const clientKey = config.clientKey ?? process.env.CS_CLIENT_KEY;
|
|
2849
|
+
const accessKey = config.accessKey ?? process.env.CS_CLIENT_ACCESS_KEY;
|
|
2850
|
+
if (!workspaceCRN || !clientId || !clientKey || !accessKey) {
|
|
2851
|
+
throw new Error(
|
|
2852
|
+
"Missing required configuration or environment variables."
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
this.config = {
|
|
2856
|
+
environment: config.environment,
|
|
2857
|
+
workspaceCRN,
|
|
2858
|
+
clientId,
|
|
2859
|
+
clientKey,
|
|
2860
|
+
accessKey
|
|
2861
|
+
};
|
|
2942
2862
|
}
|
|
2943
2863
|
initPromise = null;
|
|
2944
2864
|
/**
|
|
@@ -2951,24 +2871,24 @@ var Secrets = class {
|
|
|
2951
2871
|
return this.initPromise;
|
|
2952
2872
|
}
|
|
2953
2873
|
async _doInit() {
|
|
2874
|
+
logger.debug("Initializing the Secrets client.");
|
|
2954
2875
|
this.encryptionClient = await Encryption({
|
|
2955
2876
|
schemas: [this.secretsSchema],
|
|
2956
2877
|
config: {
|
|
2957
2878
|
workspaceCrn: this.config.workspaceCRN,
|
|
2958
2879
|
clientId: this.config.clientId,
|
|
2959
2880
|
clientKey: this.config.clientKey,
|
|
2960
|
-
accessKey: this.config.
|
|
2961
|
-
keyset: {
|
|
2962
|
-
name: this.config.environment
|
|
2963
|
-
}
|
|
2881
|
+
accessKey: this.config.accessKey,
|
|
2882
|
+
keyset: { name: this.config.environment }
|
|
2964
2883
|
}
|
|
2965
2884
|
});
|
|
2885
|
+
logger.debug("Successfully initialized the Secrets client.");
|
|
2966
2886
|
}
|
|
2967
2887
|
/**
|
|
2968
2888
|
* Get the authorization header for API requests
|
|
2969
2889
|
*/
|
|
2970
2890
|
getAuthHeader() {
|
|
2971
|
-
return `Bearer ${this.config.
|
|
2891
|
+
return `Bearer ${this.config.accessKey}`;
|
|
2972
2892
|
}
|
|
2973
2893
|
/**
|
|
2974
2894
|
* Make an API request with error handling.
|
|
@@ -2983,6 +2903,7 @@ var Secrets = class {
|
|
|
2983
2903
|
const searchParams = new URLSearchParams(options.params);
|
|
2984
2904
|
url = `${url}?${searchParams.toString()}`;
|
|
2985
2905
|
}
|
|
2906
|
+
logger.debug(`Secrets API request: ${method} ${path2}`);
|
|
2986
2907
|
const headers = {
|
|
2987
2908
|
"Content-Type": "application/json",
|
|
2988
2909
|
Authorization: this.getAuthHeader()
|
|
@@ -3001,6 +2922,7 @@ var Secrets = class {
|
|
|
3001
2922
|
} catch {
|
|
3002
2923
|
errorMessage = errorText || errorMessage;
|
|
3003
2924
|
}
|
|
2925
|
+
logger.error(`Secrets API error on ${method} ${path2}: ${errorMessage}`);
|
|
3004
2926
|
return {
|
|
3005
2927
|
failure: {
|
|
3006
2928
|
type: "ApiError",
|
|
@@ -3008,13 +2930,16 @@ var Secrets = class {
|
|
|
3008
2930
|
}
|
|
3009
2931
|
};
|
|
3010
2932
|
}
|
|
2933
|
+
logger.debug(`Secrets API request successful: ${method} ${path2}`);
|
|
3011
2934
|
const data = await response.json();
|
|
3012
2935
|
return { data };
|
|
3013
2936
|
} catch (error) {
|
|
2937
|
+
const message = error instanceof Error ? error.message : "Unknown network error occurred";
|
|
2938
|
+
logger.error(`Secrets network error on ${method} ${path2}: ${message}`);
|
|
3014
2939
|
return {
|
|
3015
2940
|
failure: {
|
|
3016
2941
|
type: "NetworkError",
|
|
3017
|
-
message
|
|
2942
|
+
message
|
|
3018
2943
|
}
|
|
3019
2944
|
};
|
|
3020
2945
|
}
|
|
@@ -3030,6 +2955,7 @@ var Secrets = class {
|
|
|
3030
2955
|
* @returns A Result containing the API response or an error
|
|
3031
2956
|
*/
|
|
3032
2957
|
async set(name, value) {
|
|
2958
|
+
logger.debug("Setting secret");
|
|
3033
2959
|
await this.ensureInitialized();
|
|
3034
2960
|
if (!this.encryptionClient) {
|
|
3035
2961
|
return {
|
|
@@ -3044,6 +2970,7 @@ var Secrets = class {
|
|
|
3044
2970
|
table: this.secretsSchema
|
|
3045
2971
|
});
|
|
3046
2972
|
if (encryptResult.failure) {
|
|
2973
|
+
logger.error("Failed to encrypt secret");
|
|
3047
2974
|
return {
|
|
3048
2975
|
failure: {
|
|
3049
2976
|
type: "EncryptionError",
|
|
@@ -3071,6 +2998,7 @@ var Secrets = class {
|
|
|
3071
2998
|
* @returns A Result containing the decrypted value or an error
|
|
3072
2999
|
*/
|
|
3073
3000
|
async get(name) {
|
|
3001
|
+
logger.debug("Getting secret");
|
|
3074
3002
|
await this.ensureInitialized();
|
|
3075
3003
|
if (!this.encryptionClient) {
|
|
3076
3004
|
return {
|
|
@@ -3095,6 +3023,7 @@ var Secrets = class {
|
|
|
3095
3023
|
apiResult.data.encryptedValue.data
|
|
3096
3024
|
);
|
|
3097
3025
|
if (decryptResult.failure) {
|
|
3026
|
+
logger.error("Failed to decrypt secret");
|
|
3098
3027
|
return {
|
|
3099
3028
|
failure: {
|
|
3100
3029
|
type: "DecryptionError",
|
|
@@ -3103,6 +3032,7 @@ var Secrets = class {
|
|
|
3103
3032
|
};
|
|
3104
3033
|
}
|
|
3105
3034
|
if (typeof decryptResult.data !== "string") {
|
|
3035
|
+
logger.error("Decrypted secret value is not a string");
|
|
3106
3036
|
return {
|
|
3107
3037
|
failure: {
|
|
3108
3038
|
type: "DecryptionError",
|
|
@@ -3127,6 +3057,7 @@ var Secrets = class {
|
|
|
3127
3057
|
* @returns A Result containing an object mapping secret names to their decrypted values
|
|
3128
3058
|
*/
|
|
3129
3059
|
async getMany(names) {
|
|
3060
|
+
logger.debug(`Getting ${names.length} secrets.`);
|
|
3130
3061
|
await this.ensureInitialized();
|
|
3131
3062
|
if (!this.encryptionClient) {
|
|
3132
3063
|
return {
|
|
@@ -3173,6 +3104,9 @@ var Secrets = class {
|
|
|
3173
3104
|
}));
|
|
3174
3105
|
const decryptResult = await this.encryptionClient.bulkDecryptModels(dataToDecrypt);
|
|
3175
3106
|
if (decryptResult.failure) {
|
|
3107
|
+
logger.error(
|
|
3108
|
+
`Failed to decrypt secrets: ${decryptResult.failure.message}`
|
|
3109
|
+
);
|
|
3176
3110
|
return {
|
|
3177
3111
|
failure: {
|
|
3178
3112
|
type: "DecryptionError",
|
|
@@ -3198,6 +3132,7 @@ var Secrets = class {
|
|
|
3198
3132
|
* @returns A Result containing the list of secrets or an error
|
|
3199
3133
|
*/
|
|
3200
3134
|
async list() {
|
|
3135
|
+
logger.debug("Listing secrets.");
|
|
3201
3136
|
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
3202
3137
|
const apiResult = await this.apiRequest(
|
|
3203
3138
|
"GET",
|
|
@@ -3223,6 +3158,7 @@ var Secrets = class {
|
|
|
3223
3158
|
* @returns A Result containing the API response or an error
|
|
3224
3159
|
*/
|
|
3225
3160
|
async delete(name) {
|
|
3161
|
+
logger.debug("Deleting secret");
|
|
3226
3162
|
const workspaceId = extractWorkspaceIdFromCrn(this.config.workspaceCRN);
|
|
3227
3163
|
return await this.apiRequest("POST", "/delete", {
|
|
3228
3164
|
body: {
|