@carlonicora/nestjs-neo4jsonapi 4.17.2 → 4.18.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/dist/bootstrap/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap/bootstrap.js +5 -25
- package/dist/bootstrap/bootstrap.js.map +1 -1
- package/dist/bootstrap/defaults.d.ts +1 -0
- package/dist/bootstrap/defaults.d.ts.map +1 -1
- package/dist/bootstrap/defaults.js +3 -0
- package/dist/bootstrap/defaults.js.map +1 -1
- package/dist/bootstrap/graceful-shutdown.d.ts +25 -0
- package/dist/bootstrap/graceful-shutdown.d.ts.map +1 -0
- package/dist/bootstrap/graceful-shutdown.js +72 -0
- package/dist/bootstrap/graceful-shutdown.js.map +1 -0
- package/dist/bootstrap/raw-body.config.d.ts +13 -0
- package/dist/bootstrap/raw-body.config.d.ts.map +1 -1
- package/dist/bootstrap/raw-body.config.js +26 -1
- package/dist/bootstrap/raw-body.config.js.map +1 -1
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +7 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/interfaces/config.s3.interface.d.ts +11 -0
- package/dist/config/interfaces/config.s3.interface.d.ts.map +1 -1
- package/dist/core/health/indicators/s3.health.d.ts.map +1 -1
- package/dist/core/health/indicators/s3.health.js +8 -38
- package/dist/core/health/indicators/s3.health.js.map +1 -1
- package/dist/core/llm/services/ai-connection-resolver.service.d.ts +8 -2
- package/dist/core/llm/services/ai-connection-resolver.service.d.ts.map +1 -1
- package/dist/core/llm/services/ai-connection-resolver.service.js +9 -0
- package/dist/core/llm/services/ai-connection-resolver.service.js.map +1 -1
- package/dist/core/llm/services/model.service.d.ts.map +1 -1
- package/dist/core/llm/services/model.service.js +8 -2
- package/dist/core/llm/services/model.service.js.map +1 -1
- package/dist/foundations/chunker/services/chunker.service.d.ts +12 -4
- package/dist/foundations/chunker/services/chunker.service.d.ts.map +1 -1
- package/dist/foundations/chunker/services/chunker.service.js +22 -14
- package/dist/foundations/chunker/services/chunker.service.js.map +1 -1
- package/dist/foundations/s3/cipher/index.d.ts +2 -0
- package/dist/foundations/s3/cipher/index.d.ts.map +1 -0
- package/dist/foundations/s3/cipher/index.js +18 -0
- package/dist/foundations/s3/cipher/index.js.map +1 -0
- package/dist/foundations/s3/cipher/s3-cipher.core.d.ts +85 -0
- package/dist/foundations/s3/cipher/s3-cipher.core.d.ts.map +1 -0
- package/dist/foundations/s3/cipher/s3-cipher.core.js +359 -0
- package/dist/foundations/s3/cipher/s3-cipher.core.js.map +1 -0
- package/dist/foundations/s3/controllers/s3.controller.d.ts +25 -1
- package/dist/foundations/s3/controllers/s3.controller.d.ts.map +1 -1
- package/dist/foundations/s3/controllers/s3.controller.js +143 -4
- package/dist/foundations/s3/controllers/s3.controller.js.map +1 -1
- package/dist/foundations/s3/entities/s3.meta.d.ts +2 -0
- package/dist/foundations/s3/entities/s3.meta.d.ts.map +1 -1
- package/dist/foundations/s3/entities/s3.meta.js +3 -1
- package/dist/foundations/s3/entities/s3.meta.js.map +1 -1
- package/dist/foundations/s3/index.d.ts +3 -0
- package/dist/foundations/s3/index.d.ts.map +1 -1
- package/dist/foundations/s3/index.js +3 -0
- package/dist/foundations/s3/index.js.map +1 -1
- package/dist/foundations/s3/s3.service.module.d.ts +1 -1
- package/dist/foundations/s3/s3.service.module.d.ts.map +1 -1
- package/dist/foundations/s3/s3.service.module.js +4 -3
- package/dist/foundations/s3/s3.service.module.js.map +1 -1
- package/dist/foundations/s3/services/s3-cipher.service.d.ts +33 -0
- package/dist/foundations/s3/services/s3-cipher.service.d.ts.map +1 -0
- package/dist/foundations/s3/services/s3-cipher.service.js +66 -0
- package/dist/foundations/s3/services/s3-cipher.service.js.map +1 -0
- package/dist/foundations/s3/services/s3.service.d.ts +37 -5
- package/dist/foundations/s3/services/s3.service.d.ts.map +1 -1
- package/dist/foundations/s3/services/s3.service.js +274 -207
- package/dist/foundations/s3/services/s3.service.js.map +1 -1
- package/dist/foundations/s3/storage-client.d.ts +8 -0
- package/dist/foundations/s3/storage-client.d.ts.map +1 -0
- package/dist/foundations/s3/storage-client.js +45 -0
- package/dist/foundations/s3/storage-client.js.map +1 -0
- package/dist/foundations/stripe/__tests__/mocks/stripe.mock.d.ts +66 -66
- package/package.json +2 -1
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3Cipher = exports.S3CipherKeyMissingError = exports.S3ObjectTokenError = exports.S3_OBJECT_TOKEN_TTL_SECONDS = exports.S3_ENCRYPTION_CONTEXT = exports.S3_ENCRYPTION_METADATA_VALUE = exports.S3_ENCRYPTION_METADATA_KEY = void 0;
|
|
4
|
+
exports.parseS3CipherKey = parseS3CipherKey;
|
|
5
|
+
exports.parseS3CipherOptions = parseS3CipherOptions;
|
|
6
|
+
exports.isEncryptedObjectMetadata = isEncryptedObjectMetadata;
|
|
7
|
+
exports.s3KeyFromObjectUrl = s3KeyFromObjectUrl;
|
|
8
|
+
const client_node_1 = require("@aws-crypto/client-node");
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const stream_1 = require("stream");
|
|
11
|
+
/**
|
|
12
|
+
* S3 cipher core — Nest-free so the sweep CLI can import it directly.
|
|
13
|
+
*
|
|
14
|
+
* Envelope encryption per object with the AWS Encryption SDK: a fresh data key
|
|
15
|
+
* per object, wrapped by a local AES-256 key (raw AES keyring). Retired keys stay
|
|
16
|
+
* in the decrypt keyring so rotation never strands old objects.
|
|
17
|
+
*/
|
|
18
|
+
exports.S3_ENCRYPTION_METADATA_KEY = "a360enc";
|
|
19
|
+
exports.S3_ENCRYPTION_METADATA_VALUE = "esdk-1";
|
|
20
|
+
exports.S3_ENCRYPTION_CONTEXT = { a360: "s3", v: "1" };
|
|
21
|
+
exports.S3_OBJECT_TOKEN_TTL_SECONDS = 3600;
|
|
22
|
+
const KEY_NAMESPACE = "a360ai";
|
|
23
|
+
const FRAME_LENGTH = 65536;
|
|
24
|
+
const SUITE_ID = client_node_1.AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA512_COMMIT_KEY;
|
|
25
|
+
const SIGNING_KEY_INFO = "a360ai/s3-url-signing";
|
|
26
|
+
const FALLBACK_SIGNING_KEY_INFO = "a360ai/s3-url-signing/jwt";
|
|
27
|
+
/** A raw AES keyring's provider info is the key name followed by tag length (4), IV length (4) and IV (12). */
|
|
28
|
+
const RAW_AES_PROVIDER_INFO_SUFFIX_BYTES = 20;
|
|
29
|
+
class S3ObjectTokenError extends Error {
|
|
30
|
+
constructor(reason, message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.reason = reason;
|
|
33
|
+
this.name = "S3ObjectTokenError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.S3ObjectTokenError = S3ObjectTokenError;
|
|
37
|
+
/**
|
|
38
|
+
* An encrypted object that no configured key opens. `keyIds` names the key(s) the object was
|
|
39
|
+
* encrypted with, when known; `objectKey` the storage key, when the caller knows it.
|
|
40
|
+
*/
|
|
41
|
+
class S3CipherKeyMissingError extends Error {
|
|
42
|
+
constructor(keyIds, objectKey) {
|
|
43
|
+
const object = objectKey ? `S3 object ${objectKey}` : "S3 object";
|
|
44
|
+
super(keyIds.length
|
|
45
|
+
? `${object} is encrypted with key ${keyIds.join(", ")}, which is not configured in S3_ENCRYPTION_KEY or S3_ENCRYPTION_RETIRED_KEYS`
|
|
46
|
+
: `${object} is encrypted but no matching S3_ENCRYPTION_KEY/RETIRED key is configured`);
|
|
47
|
+
this.keyIds = keyIds;
|
|
48
|
+
this.objectKey = objectKey;
|
|
49
|
+
this.name = "S3CipherKeyMissingError";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.S3CipherKeyMissingError = S3CipherKeyMissingError;
|
|
53
|
+
function parseS3CipherKey(raw, variable) {
|
|
54
|
+
const error = new Error(`${variable}: expected <keyId>:<base64 of 32 bytes>`);
|
|
55
|
+
const separator = raw.indexOf(":");
|
|
56
|
+
if (separator <= 0)
|
|
57
|
+
throw error;
|
|
58
|
+
const keyId = raw.slice(0, separator).trim();
|
|
59
|
+
const encoded = raw.slice(separator + 1).trim();
|
|
60
|
+
if (!keyId || !encoded || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded))
|
|
61
|
+
throw error;
|
|
62
|
+
const material = Buffer.from(encoded, "base64");
|
|
63
|
+
if (material.length !== 32)
|
|
64
|
+
throw error;
|
|
65
|
+
return { keyId, material };
|
|
66
|
+
}
|
|
67
|
+
function splitList(raw) {
|
|
68
|
+
return raw
|
|
69
|
+
.split(",")
|
|
70
|
+
.map((item) => item.trim())
|
|
71
|
+
.filter((item) => item.length > 0);
|
|
72
|
+
}
|
|
73
|
+
function parseS3CipherOptions(config) {
|
|
74
|
+
const key = config.key ? parseS3CipherKey(config.key, "S3_ENCRYPTION_KEY") : undefined;
|
|
75
|
+
if (config.enabled && !key) {
|
|
76
|
+
throw new Error("S3_ENCRYPTION_KEY: required when S3_ENCRYPTION_ENABLED is true");
|
|
77
|
+
}
|
|
78
|
+
const retiredKeys = splitList(config.retiredKeys ?? "").map((raw) => parseS3CipherKey(raw, "S3_ENCRYPTION_RETIRED_KEYS"));
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
for (const candidate of [...(key ? [key] : []), ...retiredKeys]) {
|
|
81
|
+
if (seen.has(candidate.keyId)) {
|
|
82
|
+
throw new Error(`S3_ENCRYPTION_RETIRED_KEYS: duplicate keyId "${candidate.keyId}" across S3_ENCRYPTION_KEY and S3_ENCRYPTION_RETIRED_KEYS`);
|
|
83
|
+
}
|
|
84
|
+
seen.add(candidate.keyId);
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
enabled: config.enabled,
|
|
88
|
+
key,
|
|
89
|
+
retiredKeys,
|
|
90
|
+
plaintextPrefixes: splitList(config.plaintextPrefixes ?? ""),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function isEncryptedObjectMetadata(metadata) {
|
|
94
|
+
return metadata?.[exports.S3_ENCRYPTION_METADATA_KEY] === exports.S3_ENCRYPTION_METADATA_VALUE;
|
|
95
|
+
}
|
|
96
|
+
function buildKeyring(key) {
|
|
97
|
+
return new client_node_1.RawAesKeyringNode({
|
|
98
|
+
keyNamespace: KEY_NAMESPACE,
|
|
99
|
+
keyName: key.keyId,
|
|
100
|
+
unencryptedMasterKey: new Uint8Array(key.material),
|
|
101
|
+
wrappingSuite: client_node_1.RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Delegates to the real decrypt keyring and records the key ids the message was encrypted with,
|
|
106
|
+
* so a message no configured key opens can be reported by key id instead of the SDK's
|
|
107
|
+
* "unencryptedDataKey has not been set". One instance per decryption.
|
|
108
|
+
*/
|
|
109
|
+
class KeyIdRecordingKeyring extends client_node_1.KeyringNode {
|
|
110
|
+
constructor(inner) {
|
|
111
|
+
super();
|
|
112
|
+
this.inner = inner;
|
|
113
|
+
this.storedKeyIds = [];
|
|
114
|
+
this.asked = false;
|
|
115
|
+
this.unwrapped = false;
|
|
116
|
+
}
|
|
117
|
+
async _onEncrypt(material) {
|
|
118
|
+
return this.inner.onEncrypt(material);
|
|
119
|
+
}
|
|
120
|
+
async _onDecrypt(material, encryptedDataKeys) {
|
|
121
|
+
this.asked = true;
|
|
122
|
+
for (const edk of encryptedDataKeys) {
|
|
123
|
+
if (edk.providerId !== KEY_NAMESPACE || !edk.rawInfo)
|
|
124
|
+
continue;
|
|
125
|
+
const name = Buffer.from(edk.rawInfo.subarray(0, -RAW_AES_PROVIDER_INFO_SUFFIX_BYTES)).toString("utf8");
|
|
126
|
+
if (name)
|
|
127
|
+
this.storedKeyIds.push(name);
|
|
128
|
+
}
|
|
129
|
+
const result = await this.inner.onDecrypt(material, encryptedDataKeys);
|
|
130
|
+
this.unwrapped = result.hasUnencryptedDataKey;
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/** A S3CipherKeyMissingError when the keyring was asked and no configured key unwrapped the data key; otherwise the SDK error. */
|
|
134
|
+
translate(error) {
|
|
135
|
+
return this.asked && !this.unwrapped ? new S3CipherKeyMissingError(this.storedKeyIds) : error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function deriveSigningKey(key) {
|
|
139
|
+
return Buffer.from((0, crypto_1.hkdfSync)("sha256", key.material, "", SIGNING_KEY_INFO, 32));
|
|
140
|
+
}
|
|
141
|
+
function deriveFallbackSigningKey(secret) {
|
|
142
|
+
return Buffer.from((0, crypto_1.hkdfSync)("sha256", Buffer.from(secret, "utf8"), "", FALLBACK_SIGNING_KEY_INFO, 32));
|
|
143
|
+
}
|
|
144
|
+
/** Key carried by an api object URL (`…/s3/objects/<payload>.<sig>`), WITHOUT verifying it; undefined otherwise. */
|
|
145
|
+
function s3KeyFromObjectUrl(url) {
|
|
146
|
+
try {
|
|
147
|
+
const match = new URL(url).pathname.match(/\/s3\/objects\/([^/]+)$/);
|
|
148
|
+
if (!match)
|
|
149
|
+
return undefined;
|
|
150
|
+
const token = match[1];
|
|
151
|
+
const separator = token.lastIndexOf(".");
|
|
152
|
+
if (separator <= 0)
|
|
153
|
+
return undefined;
|
|
154
|
+
const payload = JSON.parse(Buffer.from(token.slice(0, separator), "base64url").toString("utf8"));
|
|
155
|
+
return typeof payload?.k === "string" && payload.k.length > 0 ? payload.k : undefined;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Adapt an SDK stream to a native Node Duplex.
|
|
163
|
+
*
|
|
164
|
+
* - The SDK builds its streams on the `readable-stream` package, which fails `instanceof stream.Readable`
|
|
165
|
+
* (lib-storage's `Upload` rejects such a body), so callers get a native Duplex.
|
|
166
|
+
* - Destroying an SDK stream mid-message throws an uncatchable "Premature close" from its internal
|
|
167
|
+
* pipeline (verified on @aws-crypto/client-node 5.0.2), which would crash the process on an
|
|
168
|
+
* oversized upload or an aborted download. So the SDK stream is never destroyed: when the native
|
|
169
|
+
* side is destroyed, the SDK stream is ended and drained, and its output discarded.
|
|
170
|
+
* - Any SDK error destroys the native side, so the consumer sees it.
|
|
171
|
+
*/
|
|
172
|
+
function toNativeDuplex(sdkStream, onSdkStream, mapError = (error) => error) {
|
|
173
|
+
let sdkEnded = false;
|
|
174
|
+
const endSdk = () => {
|
|
175
|
+
if (sdkEnded)
|
|
176
|
+
return;
|
|
177
|
+
sdkEnded = true;
|
|
178
|
+
sdkStream.end();
|
|
179
|
+
};
|
|
180
|
+
const native = new stream_1.Duplex({
|
|
181
|
+
write(chunk, encoding, callback) {
|
|
182
|
+
if (sdkStream.write(chunk, encoding))
|
|
183
|
+
callback();
|
|
184
|
+
else
|
|
185
|
+
sdkStream.once("drain", () => callback());
|
|
186
|
+
},
|
|
187
|
+
final(callback) {
|
|
188
|
+
endSdk();
|
|
189
|
+
callback();
|
|
190
|
+
},
|
|
191
|
+
read() {
|
|
192
|
+
sdkStream.resume();
|
|
193
|
+
},
|
|
194
|
+
destroy(error, callback) {
|
|
195
|
+
// Drain and end the SDK stream instead of destroying it (see above); its output is discarded.
|
|
196
|
+
sdkStream.resume();
|
|
197
|
+
endSdk();
|
|
198
|
+
callback(error);
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
sdkStream.on("data", (chunk) => {
|
|
202
|
+
if (native.destroyed)
|
|
203
|
+
return;
|
|
204
|
+
if (!native.push(chunk))
|
|
205
|
+
sdkStream.pause();
|
|
206
|
+
});
|
|
207
|
+
sdkStream.on("end", () => {
|
|
208
|
+
if (!native.destroyed)
|
|
209
|
+
native.push(null);
|
|
210
|
+
});
|
|
211
|
+
sdkStream.on("error", (error) => native.destroy(mapError(error)));
|
|
212
|
+
onSdkStream?.((error) => native.destroy(error));
|
|
213
|
+
return native;
|
|
214
|
+
}
|
|
215
|
+
function assertEncryptionContext(context) {
|
|
216
|
+
for (const [name, value] of Object.entries(exports.S3_ENCRYPTION_CONTEXT)) {
|
|
217
|
+
if (context?.[name] !== value) {
|
|
218
|
+
throw new Error(`S3 cipher: encryption context mismatch on "${name}"`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
class S3Cipher {
|
|
223
|
+
constructor(options) {
|
|
224
|
+
this.options = options;
|
|
225
|
+
this.client = (0, client_node_1.buildClient)(client_node_1.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT);
|
|
226
|
+
const current = options.key ? buildKeyring(options.key) : undefined;
|
|
227
|
+
const retired = options.retiredKeys.map(buildKeyring);
|
|
228
|
+
this.encryptKeyring = current;
|
|
229
|
+
if (current) {
|
|
230
|
+
this.decryptKeyring = retired.length ? new client_node_1.MultiKeyringNode({ generator: current, children: retired }) : current;
|
|
231
|
+
}
|
|
232
|
+
else if (retired.length) {
|
|
233
|
+
this.decryptKeyring = new client_node_1.MultiKeyringNode({ children: retired });
|
|
234
|
+
}
|
|
235
|
+
const fallbackSigningKey = options.fallbackSigningSecret
|
|
236
|
+
? deriveFallbackSigningKey(options.fallbackSigningSecret)
|
|
237
|
+
: undefined;
|
|
238
|
+
this.signingKeys = [
|
|
239
|
+
...[...(options.key ? [options.key] : []), ...options.retiredKeys].map(deriveSigningKey),
|
|
240
|
+
...(fallbackSigningKey ? [fallbackSigningKey] : []),
|
|
241
|
+
];
|
|
242
|
+
this.tokenSigningKey = options.key ? deriveSigningKey(options.key) : fallbackSigningKey;
|
|
243
|
+
}
|
|
244
|
+
get enabled() {
|
|
245
|
+
return this.options.enabled;
|
|
246
|
+
}
|
|
247
|
+
get canDecrypt() {
|
|
248
|
+
return this.decryptKeyring !== undefined;
|
|
249
|
+
}
|
|
250
|
+
shouldEncrypt(key) {
|
|
251
|
+
if (!this.options.enabled)
|
|
252
|
+
return false;
|
|
253
|
+
return !this.options.plaintextPrefixes.some((prefix) => key.startsWith(prefix));
|
|
254
|
+
}
|
|
255
|
+
async encrypt(plaintext) {
|
|
256
|
+
const { result } = await this.client.encrypt(this.requireEncryptKeyring(), plaintext, {
|
|
257
|
+
suiteId: SUITE_ID,
|
|
258
|
+
encryptionContext: { ...exports.S3_ENCRYPTION_CONTEXT },
|
|
259
|
+
frameLength: FRAME_LENGTH,
|
|
260
|
+
});
|
|
261
|
+
return Buffer.from(result);
|
|
262
|
+
}
|
|
263
|
+
async decrypt(ciphertext) {
|
|
264
|
+
const keyring = new KeyIdRecordingKeyring(this.requireDecryptKeyring());
|
|
265
|
+
let result;
|
|
266
|
+
try {
|
|
267
|
+
result = await this.client.decrypt(keyring, ciphertext);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
throw keyring.translate(error);
|
|
271
|
+
}
|
|
272
|
+
assertEncryptionContext(result.messageHeader.encryptionContext);
|
|
273
|
+
return Buffer.from(result.plaintext);
|
|
274
|
+
}
|
|
275
|
+
encryptStream() {
|
|
276
|
+
return toNativeDuplex(this.client.encryptStream(this.requireEncryptKeyring(), {
|
|
277
|
+
suiteId: SUITE_ID,
|
|
278
|
+
encryptionContext: { ...exports.S3_ENCRYPTION_CONTEXT },
|
|
279
|
+
frameLength: FRAME_LENGTH,
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
decryptStream() {
|
|
283
|
+
const keyring = new KeyIdRecordingKeyring(this.requireDecryptKeyring());
|
|
284
|
+
const stream = this.client.decryptUnsignedMessageStream(keyring);
|
|
285
|
+
const native = toNativeDuplex(stream, (fail) => stream.once("MessageHeader", (header) => {
|
|
286
|
+
try {
|
|
287
|
+
assertEncryptionContext(header?.encryptionContext);
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
fail(error);
|
|
291
|
+
}
|
|
292
|
+
}), (error) => keyring.translate(error));
|
|
293
|
+
return native;
|
|
294
|
+
}
|
|
295
|
+
signObjectToken(input) {
|
|
296
|
+
const signingKey = this.tokenSigningKey;
|
|
297
|
+
if (!signingKey) {
|
|
298
|
+
throw new Error("S3 cipher: cannot sign an object token without S3_ENCRYPTION_KEY or JWT_SECRET");
|
|
299
|
+
}
|
|
300
|
+
const payload = { o: input.op, k: input.key };
|
|
301
|
+
if (input.contentType !== undefined)
|
|
302
|
+
payload.c = input.contentType;
|
|
303
|
+
if (input.filename !== undefined)
|
|
304
|
+
payload.f = input.filename;
|
|
305
|
+
if (input.expiresAt !== undefined) {
|
|
306
|
+
payload.e = input.expiresAt;
|
|
307
|
+
}
|
|
308
|
+
else if (input.expiresInSeconds !== undefined) {
|
|
309
|
+
payload.e = Math.floor(Date.now() / 1000) + input.expiresInSeconds;
|
|
310
|
+
}
|
|
311
|
+
const encoded = Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
312
|
+
return `${encoded}.${this.sign(signingKey, encoded)}`;
|
|
313
|
+
}
|
|
314
|
+
verifyObjectToken(token, op) {
|
|
315
|
+
const separator = typeof token === "string" ? token.lastIndexOf(".") : -1;
|
|
316
|
+
if (separator <= 0 || separator === token.length - 1) {
|
|
317
|
+
throw new S3ObjectTokenError("malformed", "Malformed object token");
|
|
318
|
+
}
|
|
319
|
+
const encoded = token.slice(0, separator);
|
|
320
|
+
const signature = Buffer.from(token.slice(separator + 1), "base64url");
|
|
321
|
+
const valid = this.signingKeys.some((signingKey) => {
|
|
322
|
+
const expected = Buffer.from(this.sign(signingKey, encoded), "base64url");
|
|
323
|
+
return expected.length === signature.length && (0, crypto_1.timingSafeEqual)(expected, signature);
|
|
324
|
+
});
|
|
325
|
+
if (!valid)
|
|
326
|
+
throw new S3ObjectTokenError("signature", "Invalid object token signature");
|
|
327
|
+
let payload;
|
|
328
|
+
try {
|
|
329
|
+
payload = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
throw new S3ObjectTokenError("malformed", "Malformed object token payload");
|
|
333
|
+
}
|
|
334
|
+
if (!payload || typeof payload !== "object" || typeof payload.k !== "string" || !payload.k) {
|
|
335
|
+
throw new S3ObjectTokenError("malformed", "Malformed object token payload");
|
|
336
|
+
}
|
|
337
|
+
if (payload.e !== undefined && payload.e < Math.floor(Date.now() / 1000)) {
|
|
338
|
+
throw new S3ObjectTokenError("expired", "Object token expired");
|
|
339
|
+
}
|
|
340
|
+
if (payload.o !== op)
|
|
341
|
+
throw new S3ObjectTokenError("op", `Object token is not valid for "${op}"`);
|
|
342
|
+
return payload;
|
|
343
|
+
}
|
|
344
|
+
sign(signingKey, encodedPayload) {
|
|
345
|
+
return (0, crypto_1.createHmac)("sha256", signingKey).update(encodedPayload).digest("base64url");
|
|
346
|
+
}
|
|
347
|
+
requireEncryptKeyring() {
|
|
348
|
+
if (!this.encryptKeyring)
|
|
349
|
+
throw new Error("S3 cipher: S3_ENCRYPTION_KEY is not configured");
|
|
350
|
+
return this.encryptKeyring;
|
|
351
|
+
}
|
|
352
|
+
requireDecryptKeyring() {
|
|
353
|
+
if (!this.decryptKeyring)
|
|
354
|
+
throw new Error("S3 cipher: no S3 encryption key is configured, cannot decrypt");
|
|
355
|
+
return this.decryptKeyring;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
exports.S3Cipher = S3Cipher;
|
|
359
|
+
//# sourceMappingURL=s3-cipher.core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-cipher.core.js","sourceRoot":"","sources":["../../../../src/foundations/s3/cipher/s3-cipher.core.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import { ConfigService } from "@nestjs/config";
|
|
2
|
+
import { FastifyReply, FastifyRequest } from "fastify";
|
|
1
3
|
import { ClsService } from "nestjs-cls";
|
|
2
4
|
import { S3KeyAccessPolicy } from "../../../common/interfaces/s3.key-access.policy.interface";
|
|
5
|
+
import { BaseConfigInterface } from "../../../config/interfaces/base.config.interface";
|
|
6
|
+
import { S3CipherService } from "../../s3/services/s3-cipher.service";
|
|
3
7
|
import { S3Service } from "../../s3/services/s3.service";
|
|
4
8
|
export declare class S3Controller {
|
|
5
9
|
private readonly service;
|
|
6
10
|
private readonly clsService;
|
|
11
|
+
private readonly cipher;
|
|
12
|
+
private readonly configService;
|
|
7
13
|
private readonly keyPolicy?;
|
|
8
|
-
constructor(service: S3Service, clsService: ClsService, keyPolicy?: S3KeyAccessPolicy);
|
|
14
|
+
constructor(service: S3Service, clsService: ClsService, cipher: S3CipherService, configService: ConfigService<BaseConfigInterface>, keyPolicy?: S3KeyAccessPolicy);
|
|
9
15
|
getPresignedUrl(key: string, contentType: string, isPublic: boolean): Promise<string>;
|
|
10
16
|
getSignedUrl(key: string, isPublic: boolean, filename?: string): Promise<import("../../..").JsonApiDataInterface>;
|
|
11
17
|
deleteFile(key: string): Promise<void>;
|
|
@@ -14,5 +20,23 @@ export declare class S3Controller {
|
|
|
14
20
|
* the bound policy, if any, and rejects a refusal (403).
|
|
15
21
|
*/
|
|
16
22
|
private assertKeyAccess;
|
|
23
|
+
/**
|
|
24
|
+
* Token-authorised upload. The raw body arrives as a stream (see setupS3ObjectUploadStreaming);
|
|
25
|
+
* it is counted against the upload cap and streamed to storage, where S3Service encrypts it.
|
|
26
|
+
*/
|
|
27
|
+
putObject(req: FastifyRequest, reply: FastifyReply, token: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Token-authorised download. Streams the (decrypted) object; never serves ciphertext.
|
|
30
|
+
*/
|
|
31
|
+
getObject(reply: FastifyReply, token: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* The browser may keep the file for as long as the link stays valid: the same link always
|
|
34
|
+
* names the same key, and an expiring link is re-minted with a new URL once it lapses.
|
|
35
|
+
* A permanent link (no expiry) is kept for one hour only: its key can be overwritten in place
|
|
36
|
+
* (the how-to seed rewrites `howtos/<slug>/<file>`), so a replaced file shows at most an hour late.
|
|
37
|
+
*/
|
|
38
|
+
private _cacheControl;
|
|
39
|
+
private _appOrigin;
|
|
40
|
+
private _verifyToken;
|
|
17
41
|
}
|
|
18
42
|
//# sourceMappingURL=s3.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.controller.d.ts","sourceRoot":"","sources":["../../../../src/foundations/s3/controllers/s3.controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"s3.controller.d.ts","sourceRoot":"","sources":["../../../../src/foundations/s3/controllers/s3.controller.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,OAAO,EAGL,iBAAiB,EAElB,MAAM,2DAA2D,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AASvF,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAKzD,qBACa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAG9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;gBANV,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,eAAe,EACvB,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAGjD,SAAS,CAAC,EAAE,iBAAiB;IAK1C,eAAe,CACL,GAAG,EAAE,MAAM,EACH,WAAW,EAAE,MAAM,EACtB,QAAQ,EAAE,OAAO;IAahC,YAAY,CACF,GAAG,EAAE,MAAM,EACN,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,MAAM;IAchC,UAAU,CAAe,GAAG,EAAE,MAAM;IAM1C;;;OAGG;YACW,eAAe;IAsB7B;;;OAGG;IAEG,SAAS,CACN,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,YAAY,EACV,KAAK,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,CAAC;IAwChB;;OAEG;IAEG,SAAS,CAAQ,KAAK,EAAE,YAAY,EAAkB,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BzF;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,YAAY;CAYrB"}
|
|
@@ -14,15 +14,23 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.S3Controller = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
+
const config_1 = require("@nestjs/config");
|
|
17
18
|
const nestjs_cls_1 = require("nestjs-cls");
|
|
19
|
+
const stream_1 = require("stream");
|
|
18
20
|
const jwt_auth_guard_1 = require("../../../common/guards/jwt.auth.guard");
|
|
19
21
|
const s3_key_access_policy_interface_1 = require("../../../common/interfaces/s3.key-access.policy.interface");
|
|
22
|
+
const s3_cipher_core_1 = require("../../s3/cipher/s3-cipher.core");
|
|
20
23
|
const s3_meta_1 = require("../../s3/entities/s3.meta");
|
|
24
|
+
const s3_cipher_service_1 = require("../../s3/services/s3-cipher.service");
|
|
21
25
|
const s3_service_1 = require("../../s3/services/s3.service");
|
|
26
|
+
/** How long the browser keeps a file reached through a permanent (non-expiring) link. */
|
|
27
|
+
const PERMANENT_LINK_CACHE_SECONDS = 3600;
|
|
22
28
|
let S3Controller = class S3Controller {
|
|
23
|
-
constructor(service, clsService, keyPolicy) {
|
|
29
|
+
constructor(service, clsService, cipher, configService, keyPolicy) {
|
|
24
30
|
this.service = service;
|
|
25
31
|
this.clsService = clsService;
|
|
32
|
+
this.cipher = cipher;
|
|
33
|
+
this.configService = configService;
|
|
26
34
|
this.keyPolicy = keyPolicy;
|
|
27
35
|
}
|
|
28
36
|
async getPresignedUrl(key, contentType, isPublic) {
|
|
@@ -66,6 +74,118 @@ let S3Controller = class S3Controller {
|
|
|
66
74
|
if (!allowed)
|
|
67
75
|
throw new common_1.ForbiddenException("You cannot access this file.");
|
|
68
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Token-authorised upload. The raw body arrives as a stream (see setupS3ObjectUploadStreaming);
|
|
79
|
+
* it is counted against the upload cap and streamed to storage, where S3Service encrypts it.
|
|
80
|
+
*/
|
|
81
|
+
async putObject(req, reply, token) {
|
|
82
|
+
const payload = this._verifyToken(token, "put");
|
|
83
|
+
const maxBytes = this.cipher.uploadMaxBytes;
|
|
84
|
+
let received = 0;
|
|
85
|
+
let tooLarge = false;
|
|
86
|
+
const counter = new stream_1.Transform({
|
|
87
|
+
transform(chunk, _encoding, callback) {
|
|
88
|
+
received += chunk.length;
|
|
89
|
+
if (received > maxBytes) {
|
|
90
|
+
tooLarge = true;
|
|
91
|
+
callback(new common_1.PayloadTooLargeException(`Upload exceeds ${maxBytes} bytes`));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
callback(null, chunk);
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
const body = req.body;
|
|
98
|
+
body.on("error", (error) => counter.destroy(error));
|
|
99
|
+
counter.on("error", () => {
|
|
100
|
+
body.unpipe(counter);
|
|
101
|
+
body.resume();
|
|
102
|
+
});
|
|
103
|
+
body.pipe(counter);
|
|
104
|
+
try {
|
|
105
|
+
await this.service.uploadStream({
|
|
106
|
+
key: payload.k,
|
|
107
|
+
contentType: payload.c ?? "application/octet-stream",
|
|
108
|
+
stream: counter,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (tooLarge)
|
|
113
|
+
throw new common_1.PayloadTooLargeException(`Upload exceeds ${maxBytes} bytes`);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
reply.status(204).send();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Token-authorised download. Streams the (decrypted) object; never serves ciphertext.
|
|
120
|
+
*/
|
|
121
|
+
async getObject(reply, token) {
|
|
122
|
+
const payload = this._verifyToken(token, "get");
|
|
123
|
+
let object;
|
|
124
|
+
try {
|
|
125
|
+
object = await this.service.downloadObject({ key: payload.k });
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (error instanceof s3_cipher_core_1.S3CipherKeyMissingError)
|
|
129
|
+
throw new common_1.InternalServerErrorException(error.message);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
if (!object) {
|
|
133
|
+
reply.status(404).send({ errors: [{ status: "404", title: "Not Found" }] });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
reply.header("Content-Type", object.contentType ?? "application/octet-stream");
|
|
137
|
+
if (payload.f)
|
|
138
|
+
reply.header("Content-Disposition", this.service.contentDispositionAttachment(payload.f));
|
|
139
|
+
reply.header("Cache-Control", this._cacheControl(payload));
|
|
140
|
+
reply.header("Accept-Ranges", "none");
|
|
141
|
+
// The web app embeds downloaded PDFs in an iframe, but a host that registers helmet (the corpus)
|
|
142
|
+
// denies framing by default. Let the app origin, and only it, frame this response.
|
|
143
|
+
const appOrigin = this._appOrigin();
|
|
144
|
+
if (appOrigin) {
|
|
145
|
+
reply.header("Content-Security-Policy", `frame-ancestors ${appOrigin}`);
|
|
146
|
+
reply.removeHeader("X-Frame-Options");
|
|
147
|
+
}
|
|
148
|
+
reply.send(object.stream);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The browser may keep the file for as long as the link stays valid: the same link always
|
|
152
|
+
* names the same key, and an expiring link is re-minted with a new URL once it lapses.
|
|
153
|
+
* A permanent link (no expiry) is kept for one hour only: its key can be overwritten in place
|
|
154
|
+
* (the how-to seed rewrites `howtos/<slug>/<file>`), so a replaced file shows at most an hour late.
|
|
155
|
+
*/
|
|
156
|
+
_cacheControl(payload) {
|
|
157
|
+
if (payload.e === undefined)
|
|
158
|
+
return `private, max-age=${PERMANENT_LINK_CACHE_SECONDS}`;
|
|
159
|
+
const remaining = Math.max(0, payload.e - Math.floor(Date.now() / 1000));
|
|
160
|
+
return `private, max-age=${remaining}`;
|
|
161
|
+
}
|
|
162
|
+
_appOrigin() {
|
|
163
|
+
const url = this.configService.get("app")?.url;
|
|
164
|
+
if (!url)
|
|
165
|
+
return undefined;
|
|
166
|
+
try {
|
|
167
|
+
const origin = new URL(url).origin;
|
|
168
|
+
return origin === "null" ? undefined : origin;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
_verifyToken(token, op) {
|
|
175
|
+
let payload;
|
|
176
|
+
try {
|
|
177
|
+
payload = this.cipher.verifyObjectToken(token, op);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (error instanceof s3_cipher_core_1.S3ObjectTokenError)
|
|
181
|
+
throw new common_1.UnauthorizedException(error.message);
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
// Only the server signs tokens, but a signed key must still be one the logged-in routes accept.
|
|
185
|
+
if (!(0, s3_key_access_policy_interface_1.isWellFormedS3Key)(payload.k))
|
|
186
|
+
throw new common_1.BadRequestException("Invalid S3 key");
|
|
187
|
+
return payload;
|
|
188
|
+
}
|
|
69
189
|
};
|
|
70
190
|
exports.S3Controller = S3Controller;
|
|
71
191
|
__decorate([
|
|
@@ -97,11 +217,30 @@ __decorate([
|
|
|
97
217
|
__metadata("design:paramtypes", [String]),
|
|
98
218
|
__metadata("design:returntype", Promise)
|
|
99
219
|
], S3Controller.prototype, "deleteFile", null);
|
|
220
|
+
__decorate([
|
|
221
|
+
(0, common_1.Put)(`${s3_meta_1.S3_OBJECTS_SEGMENT}/:token`),
|
|
222
|
+
__param(0, (0, common_1.Req)()),
|
|
223
|
+
__param(1, (0, common_1.Res)()),
|
|
224
|
+
__param(2, (0, common_1.Param)("token")),
|
|
225
|
+
__metadata("design:type", Function),
|
|
226
|
+
__metadata("design:paramtypes", [Object, Object, String]),
|
|
227
|
+
__metadata("design:returntype", Promise)
|
|
228
|
+
], S3Controller.prototype, "putObject", null);
|
|
229
|
+
__decorate([
|
|
230
|
+
(0, common_1.Get)(`${s3_meta_1.S3_OBJECTS_SEGMENT}/:token`),
|
|
231
|
+
__param(0, (0, common_1.Res)()),
|
|
232
|
+
__param(1, (0, common_1.Param)("token")),
|
|
233
|
+
__metadata("design:type", Function),
|
|
234
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
235
|
+
__metadata("design:returntype", Promise)
|
|
236
|
+
], S3Controller.prototype, "getObject", null);
|
|
100
237
|
exports.S3Controller = S3Controller = __decorate([
|
|
101
238
|
(0, common_1.Controller)(s3_meta_1.s3Meta.endpoint),
|
|
102
|
-
__param(
|
|
103
|
-
__param(
|
|
239
|
+
__param(4, (0, common_1.Optional)()),
|
|
240
|
+
__param(4, (0, common_1.Inject)(s3_key_access_policy_interface_1.S3_KEY_ACCESS_POLICY)),
|
|
104
241
|
__metadata("design:paramtypes", [s3_service_1.S3Service,
|
|
105
|
-
nestjs_cls_1.ClsService,
|
|
242
|
+
nestjs_cls_1.ClsService,
|
|
243
|
+
s3_cipher_service_1.S3CipherService,
|
|
244
|
+
config_1.ConfigService, Object])
|
|
106
245
|
], S3Controller);
|
|
107
246
|
//# sourceMappingURL=s3.controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.controller.js","sourceRoot":"","sources":["../../../../src/foundations/s3/controllers/s3.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"s3.controller.js","sourceRoot":"","sources":["../../../../src/foundations/s3/controllers/s3.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { DataMeta } from "../../../common/interfaces/datamodel.interface";
|
|
2
2
|
export declare const s3Meta: DataMeta;
|
|
3
|
+
/** Path segment of the token-verified object routes: `${s3Meta.endpoint}/${S3_OBJECTS_SEGMENT}/:token`. */
|
|
4
|
+
export declare const S3_OBJECTS_SEGMENT = "objects";
|
|
3
5
|
//# sourceMappingURL=s3.meta.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3.meta.d.ts","sourceRoot":"","sources":["../../../../src/foundations/s3/entities/s3.meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAE1E,eAAO,MAAM,MAAM,EAAE,QAKpB,CAAC"}
|
|
1
|
+
{"version":3,"file":"s3.meta.d.ts","sourceRoot":"","sources":["../../../../src/foundations/s3/entities/s3.meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAE1E,eAAO,MAAM,MAAM,EAAE,QAKpB,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,YAAY,CAAC"}
|