latchkey 2.7.3 → 2.9.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/README.md +55 -5
- package/dist/scripts/cryptFile.js +2 -2
- package/dist/scripts/cryptFile.js.map +1 -1
- package/dist/scripts/recordBrowserSession.js +3 -2
- package/dist/scripts/recordBrowserSession.js.map +1 -1
- package/dist/src/cli.js +5 -4
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts +1 -1
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +44 -6
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/config.d.ts +34 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +53 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/curlInjection.d.ts +1 -1
- package/dist/src/curlInjection.d.ts.map +1 -1
- package/dist/src/curlInjection.js +16 -1
- package/dist/src/curlInjection.js.map +1 -1
- package/dist/src/encryptedStorage.d.ts +9 -25
- package/dist/src/encryptedStorage.d.ts.map +1 -1
- package/dist/src/encryptedStorage.js +9 -52
- package/dist/src/encryptedStorage.js.map +1 -1
- package/dist/src/encryption.d.ts +45 -0
- package/dist/src/encryption.d.ts.map +1 -1
- package/dist/src/encryption.js +69 -0
- package/dist/src/encryption.js.map +1 -1
- package/dist/src/gateway/client.d.ts +12 -2
- package/dist/src/gateway/client.d.ts.map +1 -1
- package/dist/src/gateway/client.js +31 -4
- package/dist/src/gateway/client.js.map +1 -1
- package/dist/src/gateway/extensions.d.ts +59 -0
- package/dist/src/gateway/extensions.d.ts.map +1 -0
- package/dist/src/gateway/extensions.js +170 -0
- package/dist/src/gateway/extensions.js.map +1 -0
- package/dist/src/gateway/gatewayEndpoint.d.ts +22 -1
- package/dist/src/gateway/gatewayEndpoint.d.ts.map +1 -1
- package/dist/src/gateway/gatewayEndpoint.js +52 -15
- package/dist/src/gateway/gatewayEndpoint.js.map +1 -1
- package/dist/src/gateway/password.d.ts +16 -0
- package/dist/src/gateway/password.d.ts.map +1 -0
- package/dist/src/gateway/password.js +24 -0
- package/dist/src/gateway/password.js.map +1 -0
- package/dist/src/gateway/permissionsOverride.d.ts +65 -0
- package/dist/src/gateway/permissionsOverride.d.ts.map +1 -0
- package/dist/src/gateway/permissionsOverride.js +171 -0
- package/dist/src/gateway/permissionsOverride.js.map +1 -0
- package/dist/src/gateway/server.d.ts.map +1 -1
- package/dist/src/gateway/server.js +100 -15
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/oauthUtils.d.ts +11 -2
- package/dist/src/oauthUtils.d.ts.map +1 -1
- package/dist/src/oauthUtils.js +25 -4
- package/dist/src/oauthUtils.js.map +1 -1
- package/dist/src/permissions.d.ts +3 -6
- package/dist/src/permissions.d.ts.map +1 -1
- package/dist/src/permissions.js +6 -13
- package/dist/src/permissions.js.map +1 -1
- package/dist/src/serviceRegistry.d.ts.map +1 -1
- package/dist/src/serviceRegistry.js +2 -1
- package/dist/src/serviceRegistry.js.map +1 -1
- package/dist/src/services/index.d.ts +1 -0
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +1 -0
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/notion-mcp.d.ts +29 -0
- package/dist/src/services/notion-mcp.d.ts.map +1 -0
- package/dist/src/services/notion-mcp.js +156 -0
- package/dist/src/services/notion-mcp.js.map +1 -0
- package/dist/src/services/notion.d.ts.map +1 -1
- package/dist/src/services/notion.js +3 -2
- package/dist/src/services/notion.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tests/apiCredentialStore.test.js +2 -2
- package/dist/tests/apiCredentialStore.test.js.map +1 -1
- package/dist/tests/cli.test.js +98 -53
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/config.test.js +37 -0
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/encryptedStorage.test.js +19 -39
- package/dist/tests/encryptedStorage.test.js.map +1 -1
- package/dist/tests/gateway.test.js +184 -7
- package/dist/tests/gateway.test.js.map +1 -1
- package/dist/tests/gatewayClient.test.js +74 -0
- package/dist/tests/gatewayClient.test.js.map +1 -1
- package/dist/tests/gatewayExtensions.test.d.ts +2 -0
- package/dist/tests/gatewayExtensions.test.d.ts.map +1 -0
- package/dist/tests/gatewayExtensions.test.js +398 -0
- package/dist/tests/gatewayExtensions.test.js.map +1 -0
- package/dist/tests/latchkeyEndpoint.test.js +7 -6
- package/dist/tests/latchkeyEndpoint.test.js.map +1 -1
- package/dist/tests/migrations.test.js +2 -2
- package/dist/tests/migrations.test.js.map +1 -1
- package/dist/tests/oauthUtils.test.d.ts +2 -0
- package/dist/tests/oauthUtils.test.d.ts.map +1 -0
- package/dist/tests/oauthUtils.test.js +63 -0
- package/dist/tests/oauthUtils.test.js.map +1 -0
- package/dist/tests/permissions.test.js +14 -10
- package/dist/tests/permissions.test.js.map +1 -1
- package/dist/tests/permissionsOverride.test.d.ts +2 -0
- package/dist/tests/permissionsOverride.test.d.ts.map +1 -0
- package/dist/tests/permissionsOverride.test.js +136 -0
- package/dist/tests/permissionsOverride.test.js.map +1 -0
- package/dist/tests/resolveEncryptionKey.test.d.ts +2 -0
- package/dist/tests/resolveEncryptionKey.test.d.ts.map +1 -0
- package/dist/tests/resolveEncryptionKey.test.js +26 -0
- package/dist/tests/resolveEncryptionKey.test.js.map +1 -0
- package/dist/tests/sharedOperations.test.js +34 -50
- package/dist/tests/sharedOperations.test.js.map +1 -1
- package/package.json +2 -2
- package/dist/tests/encryptedStorageKeyGeneration.test.d.ts +0 -2
- package/dist/tests/encryptedStorageKeyGeneration.test.d.ts.map +0 -1
- package/dist/tests/encryptedStorageKeyGeneration.test.js +0 -22
- package/dist/tests/encryptedStorageKeyGeneration.test.js.map +0 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extensions: user-supplied HTTP handlers mounted on the gateway.
|
|
3
|
+
*
|
|
4
|
+
* The gateway scans `extensionsDirectory` for `*.mjs` files at startup
|
|
5
|
+
* and dynamically imports each one. Each module's default export must be
|
|
6
|
+
* a function `(request, response) => boolean | Promise<boolean>`:
|
|
7
|
+
*
|
|
8
|
+
* - return `true` when the extension has handled the request (i.e. it
|
|
9
|
+
* has written / will write the response). The gateway will not consult
|
|
10
|
+
* any further extensions.
|
|
11
|
+
* - return `false` to defer to the next extension. The handler must not
|
|
12
|
+
* touch the response in this case.
|
|
13
|
+
*
|
|
14
|
+
* Extensions only see Node's raw HTTP request / response. They do NOT have
|
|
15
|
+
* access to credential storage, the curl-injection pipeline, or the service
|
|
16
|
+
* registry. Each extension request is run through the same
|
|
17
|
+
* `permissions.json` machinery as `/gateway/...` proxy requests, by
|
|
18
|
+
* synthesising a request whose URL uses fixed placeholder values
|
|
19
|
+
* (representing "this gateway") while preserving the inbound method, path,
|
|
20
|
+
* and headers.
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { pathToFileURL } from 'node:url';
|
|
25
|
+
import { PermissionCheckError } from '../permissions.js';
|
|
26
|
+
import { RequestNotPermittedError } from '../curlInjection.js';
|
|
27
|
+
import { GATEWAY_INTERNAL_HEADERS, HOP_BY_HOP_HEADERS } from './gatewayEndpoint.js';
|
|
28
|
+
/**
|
|
29
|
+
* Placeholder URL parts that stand in for "this gateway" when extension
|
|
30
|
+
* requests are run through the permission check. They use RFC 2606's
|
|
31
|
+
* reserved `.invalid` TLD so the synthetic URL is guaranteed never to
|
|
32
|
+
* resolve to a real host. Detent schemas matching extension routes should
|
|
33
|
+
* key on these exact values.
|
|
34
|
+
*/
|
|
35
|
+
export const EXTENSION_PLACEHOLDER_SCHEME = 'https';
|
|
36
|
+
export const EXTENSION_PLACEHOLDER_HOST = 'latchkey-self.invalid';
|
|
37
|
+
export const EXTENSION_PLACEHOLDER_PORT = 1;
|
|
38
|
+
const EXTENSION_FILE_SUFFIX = '.mjs';
|
|
39
|
+
export class ExtensionLoadError extends Error {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'ExtensionLoadError';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function isExtensionModuleShape(value) {
|
|
46
|
+
return (typeof value === 'object' &&
|
|
47
|
+
value !== null &&
|
|
48
|
+
'default' in value &&
|
|
49
|
+
typeof value.default === 'function');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Load every extension module in `directory` and return the resulting
|
|
53
|
+
* ordered list. Extensions are tried in alphabetical order of filename, so
|
|
54
|
+
* the loader returns them in that order. Returns an empty list if the
|
|
55
|
+
* directory does not exist. Throws `ExtensionLoadError` on the first file
|
|
56
|
+
* that fails to import or has the wrong shape.
|
|
57
|
+
*/
|
|
58
|
+
export async function loadExtensions(directory) {
|
|
59
|
+
if (!existsSync(directory)) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
if (!statSync(directory).isDirectory()) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const fileNames = readdirSync(directory, { withFileTypes: true })
|
|
66
|
+
.filter((entry) => entry.isFile())
|
|
67
|
+
.filter((entry) => entry.name.endsWith(EXTENSION_FILE_SUFFIX))
|
|
68
|
+
.map((entry) => entry.name)
|
|
69
|
+
.sort();
|
|
70
|
+
const extensions = [];
|
|
71
|
+
for (const fileName of fileNames) {
|
|
72
|
+
const filePath = join(directory, fileName);
|
|
73
|
+
let importedModule;
|
|
74
|
+
try {
|
|
75
|
+
importedModule = (await import(pathToFileURL(filePath).href));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
79
|
+
throw new ExtensionLoadError(`Failed to load extension '${filePath}': ${message}`);
|
|
80
|
+
}
|
|
81
|
+
if (!isExtensionModuleShape(importedModule)) {
|
|
82
|
+
throw new ExtensionLoadError(`Extension '${filePath}' must export a default function ` +
|
|
83
|
+
`(request, response) => boolean | Promise<boolean>.`);
|
|
84
|
+
}
|
|
85
|
+
extensions.push({ handler: importedModule.default, sourceFile: filePath });
|
|
86
|
+
}
|
|
87
|
+
return extensions;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build the synthetic `Request` fed to the permission check. The URL uses
|
|
91
|
+
* fixed placeholder values for protocol/host/port (representing "this
|
|
92
|
+
* gateway") with the inbound path and query string preserved verbatim. The
|
|
93
|
+
* inbound method and headers are forwarded, minus hop-by-hop and
|
|
94
|
+
* gateway-internal headers (so the password and permissions-override
|
|
95
|
+
* headers cannot influence schema matching). The body is intentionally
|
|
96
|
+
* omitted: the permission check operates on URL/method/headers only.
|
|
97
|
+
*/
|
|
98
|
+
function buildExtensionPermissionCheckRequest(request) {
|
|
99
|
+
const url = `${EXTENSION_PLACEHOLDER_SCHEME}://${EXTENSION_PLACEHOLDER_HOST}` +
|
|
100
|
+
`:${String(EXTENSION_PLACEHOLDER_PORT)}${request.url ?? ''}`;
|
|
101
|
+
const headers = new Headers();
|
|
102
|
+
const rawHeaders = request.rawHeaders;
|
|
103
|
+
for (let index = 0; index < rawHeaders.length; index += 2) {
|
|
104
|
+
const name = rawHeaders[index];
|
|
105
|
+
const value = rawHeaders[index + 1];
|
|
106
|
+
const lowerName = name.toLowerCase();
|
|
107
|
+
if (HOP_BY_HOP_HEADERS.has(lowerName) || GATEWAY_INTERNAL_HEADERS.has(lowerName)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
headers.append(name, value);
|
|
111
|
+
}
|
|
112
|
+
return new Request(url, {
|
|
113
|
+
method: (request.method ?? 'GET').toUpperCase(),
|
|
114
|
+
headers,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function sendErrorResponse(response, statusCode, message) {
|
|
118
|
+
if (response.headersSent)
|
|
119
|
+
return;
|
|
120
|
+
response.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
121
|
+
response.end(JSON.stringify({ error: message }));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Run the permission check for an inbound extension request and offer it to
|
|
125
|
+
* each loaded extension in order. Returns true when an extension claimed
|
|
126
|
+
* the request (i.e. responded or threw). When false, no extension touched
|
|
127
|
+
* the response and the caller is responsible for sending a fallback
|
|
128
|
+
* (typically `404`).
|
|
129
|
+
*/
|
|
130
|
+
export async function dispatchExtensionRequest(request, response, extensions, deps, permissionsConfigPath) {
|
|
131
|
+
const method = (request.method ?? 'GET').toUpperCase();
|
|
132
|
+
const pathAndQuery = request.url ?? '';
|
|
133
|
+
let allowed;
|
|
134
|
+
try {
|
|
135
|
+
allowed = await deps.checkPermission(buildExtensionPermissionCheckRequest(request), permissionsConfigPath, deps.config.permissionsDoNotUseBuiltinSchemas);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
if (error instanceof PermissionCheckError) {
|
|
139
|
+
deps.log(`${method} ${pathAndQuery} -> 403 (extension)`);
|
|
140
|
+
sendErrorResponse(response, 403, `Error: ${error.message}`);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
if (!allowed) {
|
|
146
|
+
const notPermitted = new RequestNotPermittedError();
|
|
147
|
+
deps.log(`${method} ${pathAndQuery} -> 403 (extension)`);
|
|
148
|
+
sendErrorResponse(response, 403, notPermitted.message);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
for (const extension of extensions) {
|
|
152
|
+
let handled;
|
|
153
|
+
try {
|
|
154
|
+
handled = await extension.handler(request, response);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
158
|
+
deps.errorLog(`Unexpected error in extension '${extension.sourceFile}' ` +
|
|
159
|
+
`(${method} ${pathAndQuery}): ${message}`);
|
|
160
|
+
sendErrorResponse(response, 500, 'Internal error');
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
if (handled) {
|
|
164
|
+
deps.log(`${method} ${pathAndQuery} -> ${String(response.statusCode)} (extension)`);
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/gateway/extensions.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
import * as http from 'node:http';
|
|
9
9
|
import type { ApiCredentialStore } from '../apiCredentials/store.js';
|
|
10
10
|
import type { CliDependencies } from '../cliCommands.js';
|
|
11
|
+
/**
|
|
12
|
+
* Headers that should not be forwarded between client and upstream (hop-by-hop).
|
|
13
|
+
*/
|
|
14
|
+
export declare const HOP_BY_HOP_HEADERS: ReadonlySet<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Headers that the gateway consumes itself and must not forward to upstream
|
|
17
|
+
* (in addition to hop-by-hop headers).
|
|
18
|
+
*/
|
|
19
|
+
export declare const GATEWAY_INTERNAL_HEADERS: ReadonlySet<string>;
|
|
11
20
|
export declare const GATEWAY_PATH_PREFIX = "/gateway/";
|
|
12
21
|
export declare class BodyTooLargeError extends Error {
|
|
13
22
|
constructor();
|
|
@@ -16,6 +25,17 @@ export interface GatewayOptions {
|
|
|
16
25
|
readonly port: number;
|
|
17
26
|
readonly host: string;
|
|
18
27
|
readonly maxBodySize: number;
|
|
28
|
+
/**
|
|
29
|
+
* When set, the gateway requires every incoming request to present this
|
|
30
|
+
* value in the `X-Latchkey-Gateway-Password` header. When null, no
|
|
31
|
+
* authentication is enforced.
|
|
32
|
+
*/
|
|
33
|
+
readonly password: string | null;
|
|
34
|
+
/**
|
|
35
|
+
* HMAC key used to verify per-request `X-Latchkey-Gateway-Permissions-Override`
|
|
36
|
+
* JWTs.
|
|
37
|
+
*/
|
|
38
|
+
readonly permissionsOverrideSigningKey: Buffer;
|
|
19
39
|
}
|
|
20
40
|
/**
|
|
21
41
|
* Extract the target URL from a raw gateway request URL.
|
|
@@ -25,7 +45,8 @@ export interface GatewayOptions {
|
|
|
25
45
|
export declare function extractTargetUrl(rawUrl: string): string | null;
|
|
26
46
|
/**
|
|
27
47
|
* Build curl arguments from an HTTP request's components.
|
|
28
|
-
*
|
|
48
|
+
*
|
|
49
|
+
* Hop-by-hop headers and gateway-internal headers are stripped.
|
|
29
50
|
*/
|
|
30
51
|
export declare function buildCurlArguments(method: string, headers: ReadonlyMap<string, string>, targetUrl: string, hasBody: boolean): readonly string[];
|
|
31
52
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatewayEndpoint.d.ts","sourceRoot":"","sources":["../../../src/gateway/gatewayEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"gatewayEndpoint.d.ts","sourceRoot":"","sources":["../../../src/gateway/gatewayEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAmBzD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAUjD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAGvD,CAAC;AAEH,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,qBAAa,iBAAkB,SAAQ,KAAK;;CAK3C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,6BAA6B,EAAE,MAAM,CAAC;CAChD;AAwBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU9D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf,SAAS,MAAM,EAAE,CAsBnB;AAcD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;CACjD,CAiCA;AAkED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,IAAI,CAAC,eAAe,EAC7B,QAAQ,EAAE,IAAI,CAAC,cAAc,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,eAAe,EACrB,kBAAkB,EAAE,kBAAkB,EACtC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAmJf"}
|
|
@@ -11,10 +11,12 @@ import { tmpdir } from 'node:os';
|
|
|
11
11
|
import { CredentialsExpiredError, NoCredentialsForServiceError, NoServiceForUrlError, prepareCurlInvocation, RequestNotPermittedError, UrlExtractionFailedError, } from '../curlInjection.js';
|
|
12
12
|
import { PermissionCheckError } from '../permissions.js';
|
|
13
13
|
import { ErrorMessages } from '../errorMessages.js';
|
|
14
|
+
import { GATEWAY_PASSWORD_HEADER } from './password.js';
|
|
15
|
+
import { InvalidPermissionsOverrideError, PERMISSIONS_OVERRIDE_HEADER, PermissionsOverrideFileMissingError, resolveRequestPermissionsConfig, } from './permissionsOverride.js';
|
|
14
16
|
/**
|
|
15
17
|
* Headers that should not be forwarded between client and upstream (hop-by-hop).
|
|
16
18
|
*/
|
|
17
|
-
const HOP_BY_HOP_HEADERS = new Set([
|
|
19
|
+
export const HOP_BY_HOP_HEADERS = new Set([
|
|
18
20
|
'connection',
|
|
19
21
|
'keep-alive',
|
|
20
22
|
'proxy-authenticate',
|
|
@@ -25,6 +27,14 @@ const HOP_BY_HOP_HEADERS = new Set([
|
|
|
25
27
|
'upgrade',
|
|
26
28
|
'host',
|
|
27
29
|
]);
|
|
30
|
+
/**
|
|
31
|
+
* Headers that the gateway consumes itself and must not forward to upstream
|
|
32
|
+
* (in addition to hop-by-hop headers).
|
|
33
|
+
*/
|
|
34
|
+
export const GATEWAY_INTERNAL_HEADERS = new Set([
|
|
35
|
+
GATEWAY_PASSWORD_HEADER,
|
|
36
|
+
PERMISSIONS_OVERRIDE_HEADER,
|
|
37
|
+
]);
|
|
28
38
|
export const GATEWAY_PATH_PREFIX = '/gateway/';
|
|
29
39
|
export class BodyTooLargeError extends Error {
|
|
30
40
|
constructor() {
|
|
@@ -66,7 +76,8 @@ export function extractTargetUrl(rawUrl) {
|
|
|
66
76
|
}
|
|
67
77
|
/**
|
|
68
78
|
* Build curl arguments from an HTTP request's components.
|
|
69
|
-
*
|
|
79
|
+
*
|
|
80
|
+
* Hop-by-hop headers and gateway-internal headers are stripped.
|
|
70
81
|
*/
|
|
71
82
|
export function buildCurlArguments(method, headers, targetUrl, hasBody) {
|
|
72
83
|
const args = [];
|
|
@@ -74,7 +85,8 @@ export function buildCurlArguments(method, headers, targetUrl, hasBody) {
|
|
|
74
85
|
args.push('-X', method);
|
|
75
86
|
}
|
|
76
87
|
for (const [name, value] of headers) {
|
|
77
|
-
|
|
88
|
+
const lowerName = name.toLowerCase();
|
|
89
|
+
if (HOP_BY_HOP_HEADERS.has(lowerName) || GATEWAY_INTERNAL_HEADERS.has(lowerName)) {
|
|
78
90
|
continue;
|
|
79
91
|
}
|
|
80
92
|
args.push('-H', `${name}: ${value}`);
|
|
@@ -85,6 +97,17 @@ export function buildCurlArguments(method, headers, targetUrl, hasBody) {
|
|
|
85
97
|
args.push(targetUrl);
|
|
86
98
|
return args;
|
|
87
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Build a `Map<string, string>` view of an `IncomingMessage`'s `rawHeaders`,
|
|
102
|
+
* preserving original case.
|
|
103
|
+
*/
|
|
104
|
+
function rawHeadersToMap(rawHeaders) {
|
|
105
|
+
const map = new Map();
|
|
106
|
+
for (let index = 0; index < rawHeaders.length; index += 2) {
|
|
107
|
+
map.set(rawHeaders[index], rawHeaders[index + 1]);
|
|
108
|
+
}
|
|
109
|
+
return map;
|
|
110
|
+
}
|
|
88
111
|
/**
|
|
89
112
|
* Parse response headers from curl's -D output.
|
|
90
113
|
* Returns the status code from the last status line and all response headers.
|
|
@@ -177,6 +200,27 @@ function forwardResponse(response, parsed, body) {
|
|
|
177
200
|
* Execute a proxied request through the credential injection pipeline.
|
|
178
201
|
*/
|
|
179
202
|
export async function handleGatewayRequest(request, response, targetUrl, deps, apiCredentialStore, options) {
|
|
203
|
+
// Resolve the permissions config for this request. When the client
|
|
204
|
+
// supplied a permissions-override JWT, validate it and use the referenced
|
|
205
|
+
// file; otherwise fall back to the gateway's default config path.
|
|
206
|
+
let permissionsConfigPath;
|
|
207
|
+
try {
|
|
208
|
+
permissionsConfigPath = resolveRequestPermissionsConfig(request.headers, deps.config.permissionsConfigPath, options.permissionsOverrideSigningKey);
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
const method = request.method ?? 'UNKNOWN';
|
|
212
|
+
if (error instanceof InvalidPermissionsOverrideError) {
|
|
213
|
+
deps.log(`${method} ${targetUrl} -> 401 (permissions override)`);
|
|
214
|
+
sendErrorResponse(response, 401, error.message);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (error instanceof PermissionsOverrideFileMissingError) {
|
|
218
|
+
deps.log(`${method} ${targetUrl} -> 400 (permissions override)`);
|
|
219
|
+
sendErrorResponse(response, 400, error.message);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
180
224
|
// Read body
|
|
181
225
|
let body;
|
|
182
226
|
try {
|
|
@@ -191,24 +235,17 @@ export async function handleGatewayRequest(request, response, targetUrl, deps, a
|
|
|
191
235
|
}
|
|
192
236
|
throw error;
|
|
193
237
|
}
|
|
194
|
-
// Build curl arguments from the incoming request
|
|
238
|
+
// Build curl arguments from the incoming request. `buildCurlArguments`
|
|
239
|
+
// strips hop-by-hop and gateway-internal headers itself, so we just hand
|
|
240
|
+
// it the raw header map.
|
|
195
241
|
const method = request.method ?? 'GET';
|
|
196
|
-
const
|
|
197
|
-
const rawHeaders = request.rawHeaders;
|
|
198
|
-
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
199
|
-
const name = rawHeaders[i];
|
|
200
|
-
const value = rawHeaders[i + 1];
|
|
201
|
-
if (!HOP_BY_HOP_HEADERS.has(name.toLowerCase())) {
|
|
202
|
-
headerMap.set(name, value);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
const curlArguments = buildCurlArguments(method, headerMap, targetUrl, body !== null);
|
|
242
|
+
const curlArguments = buildCurlArguments(method, rawHeadersToMap(request.rawHeaders), targetUrl, body !== null);
|
|
206
243
|
let allArguments;
|
|
207
244
|
try {
|
|
208
245
|
allArguments = await prepareCurlInvocation(curlArguments, apiCredentialStore, {
|
|
209
246
|
registry: deps.registry,
|
|
210
247
|
checkPermission: deps.checkPermission,
|
|
211
|
-
permissionsConfigPath
|
|
248
|
+
permissionsConfigPath,
|
|
212
249
|
permissionsDoNotUseBuiltinSchemas: deps.config.permissionsDoNotUseBuiltinSchemas,
|
|
213
250
|
passthroughUnknown: deps.config.passthroughUnknown,
|
|
214
251
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatewayEndpoint.js","sourceRoot":"","sources":["../../../src/gateway/gatewayEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"gatewayEndpoint.js","sourceRoot":"","sources":["../../../src/gateway/gatewayEndpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared definitions for the optional gateway password used to authenticate
|
|
3
|
+
* requests between the latchkey CLI (in gateway mode) and the `latchkey
|
|
4
|
+
* gateway` server.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* HTTP header used to carry the shared secret. Lowercased to match how
|
|
8
|
+
* Node's `http.IncomingMessage.headers` exposes header names.
|
|
9
|
+
*/
|
|
10
|
+
export declare const GATEWAY_PASSWORD_HEADER = "x-latchkey-gateway-password";
|
|
11
|
+
/**
|
|
12
|
+
* Compare two passwords in constant time relative to their length.
|
|
13
|
+
* Returns false when the values differ in length or contents.
|
|
14
|
+
*/
|
|
15
|
+
export declare function passwordsMatch(expected: string, provided: string): boolean;
|
|
16
|
+
//# sourceMappingURL=password.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.d.ts","sourceRoot":"","sources":["../../../src/gateway/password.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,gCAAgC,CAAC;AAErE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO1E"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared definitions for the optional gateway password used to authenticate
|
|
3
|
+
* requests between the latchkey CLI (in gateway mode) and the `latchkey
|
|
4
|
+
* gateway` server.
|
|
5
|
+
*/
|
|
6
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
7
|
+
/**
|
|
8
|
+
* HTTP header used to carry the shared secret. Lowercased to match how
|
|
9
|
+
* Node's `http.IncomingMessage.headers` exposes header names.
|
|
10
|
+
*/
|
|
11
|
+
export const GATEWAY_PASSWORD_HEADER = 'x-latchkey-gateway-password';
|
|
12
|
+
/**
|
|
13
|
+
* Compare two passwords in constant time relative to their length.
|
|
14
|
+
* Returns false when the values differ in length or contents.
|
|
15
|
+
*/
|
|
16
|
+
export function passwordsMatch(expected, provided) {
|
|
17
|
+
const expectedBytes = Buffer.from(expected, 'utf-8');
|
|
18
|
+
const providedBytes = Buffer.from(provided, 'utf-8');
|
|
19
|
+
if (expectedBytes.length !== providedBytes.length) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return timingSafeEqual(expectedBytes, providedBytes);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=password.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password.js","sourceRoot":"","sources":["../../../src/gateway/password.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,6BAA6B,CAAC;AAErE;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAgB;IAC/D,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,aAAa,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional `x-latchkey-gateway-permissions-override` header support.
|
|
3
|
+
*
|
|
4
|
+
* The header carries a minimal HS256 JWT whose only payload field is
|
|
5
|
+
* `permissionsConfig`, an absolute path to a `permissions.json` file.
|
|
6
|
+
* When the gateway receives such a header on a `/gateway/...` request and
|
|
7
|
+
* the JWT is valid, it uses the referenced permissions config instead of
|
|
8
|
+
* the default one for that single request.
|
|
9
|
+
*
|
|
10
|
+
* The signing key is derived from the Latchkey encryption key via HKDF-like
|
|
11
|
+
* HMAC-SHA256 with a domain-separation label, so the encryption key itself
|
|
12
|
+
* is never used to sign or verify these JWTs directly.
|
|
13
|
+
*/
|
|
14
|
+
import type * as http from 'node:http';
|
|
15
|
+
/**
|
|
16
|
+
* HTTP header used to carry the permissions-override JWT. Lowercased to match
|
|
17
|
+
* how Node's `http.IncomingMessage.headers` exposes header names.
|
|
18
|
+
*/
|
|
19
|
+
export declare const PERMISSIONS_OVERRIDE_HEADER = "x-latchkey-gateway-permissions-override";
|
|
20
|
+
export declare class InvalidPermissionsOverrideError extends Error {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
export declare class PermissionsOverrideFileMissingError extends Error {
|
|
24
|
+
constructor(filePath: string);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Derive the HS256 signing key used for permissions-override JWTs from the
|
|
28
|
+
* Latchkey encryption key. The encryption key is base64-encoded; the
|
|
29
|
+
* derived key is the raw HMAC-SHA256 output (32 bytes).
|
|
30
|
+
*/
|
|
31
|
+
export declare function derivePermissionsOverrideSigningKey(encryptionKeyBase64: string): Buffer;
|
|
32
|
+
/**
|
|
33
|
+
* Build a permissions-override JWT for the given absolute path. The path is
|
|
34
|
+
* not validated here; callers that want to ensure the file exists must do
|
|
35
|
+
* so before calling this function.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createPermissionsOverrideJwt(permissionsConfigPath: string, signingKey: Buffer): string;
|
|
38
|
+
interface PermissionsOverridePayload {
|
|
39
|
+
readonly permissionsConfig: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Verify a permissions-override JWT and return its payload. Throws
|
|
43
|
+
* `InvalidPermissionsOverrideError` on any structural, signature, or content
|
|
44
|
+
* issue (i.e. anything that should be reported as "the JWT is invalid").
|
|
45
|
+
*
|
|
46
|
+
* This intentionally does not check that the referenced file exists; that
|
|
47
|
+
* concern is handled by `resolvePermissionsOverride` so that file-system
|
|
48
|
+
* errors can be reported separately from JWT errors.
|
|
49
|
+
*/
|
|
50
|
+
export declare function verifyPermissionsOverrideJwt(token: string, signingKey: Buffer): PermissionsOverridePayload;
|
|
51
|
+
/**
|
|
52
|
+
* Verify a permissions-override JWT and additionally require the referenced
|
|
53
|
+
* file to exist as a regular file. Returns the absolute path on success.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolvePermissionsOverride(token: string, signingKey: Buffer): string;
|
|
56
|
+
/**
|
|
57
|
+
* Apply the optional `X-Latchkey-Gateway-Permissions-Override` header to a
|
|
58
|
+
* request: when absent, return the default config path; when present,
|
|
59
|
+
* validate the JWT and return the referenced path. Throws
|
|
60
|
+
* `InvalidPermissionsOverrideError` (=> 401) or
|
|
61
|
+
* `PermissionsOverrideFileMissingError` (=> 400) on invalid input.
|
|
62
|
+
*/
|
|
63
|
+
export declare function resolveRequestPermissionsConfig(headers: http.IncomingHttpHeaders, defaultConfigPath: string, signingKey: Buffer): string;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=permissionsOverride.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionsOverride.d.ts","sourceRoot":"","sources":["../../../src/gateway/permissionsOverride.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAGvC;;;GAGG;AACH,eAAO,MAAM,2BAA2B,4CAA4C,CAAC;AAYrF,qBAAa,+BAAgC,SAAQ,KAAK;gBAC5C,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mCAAoC,SAAQ,KAAK;gBAChD,QAAQ,EAAE,MAAM;CAI7B;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,CAGvF;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,qBAAqB,EAAE,MAAM,EAC7B,UAAU,EAAE,MAAM,GACjB,MAAM,CAWR;AAED,UAAU,0BAA0B;IAClC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAwCD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,0BAA0B,CAyD5B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAMpF;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,IAAI,CAAC,mBAAmB,EACjC,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,GACjB,MAAM,CAKR"}
|