latchkey 2.6.0 → 2.7.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 +63 -7
- package/dist/scripts/recordBrowserSession.js +3 -3
- package/dist/scripts/recordBrowserSession.js.map +1 -1
- package/dist/src/{apiCredentials.d.ts → apiCredentials/base.d.ts} +6 -6
- package/dist/src/apiCredentials/base.d.ts.map +1 -0
- package/dist/src/{apiCredentials.js → apiCredentials/base.js} +5 -5
- package/dist/src/apiCredentials/base.js.map +1 -0
- package/dist/src/{apiCredentialsSerialization.d.ts → apiCredentials/serialization.d.ts} +5 -5
- package/dist/src/apiCredentials/serialization.d.ts.map +1 -0
- package/dist/src/{apiCredentialsSerialization.js → apiCredentials/serialization.js} +9 -9
- package/dist/src/apiCredentials/serialization.js.map +1 -0
- package/dist/src/{apiCredentialStore.d.ts → apiCredentials/store.d.ts} +3 -3
- package/dist/src/apiCredentials/store.d.ts.map +1 -0
- package/dist/src/{apiCredentialStore.js → apiCredentials/store.js} +2 -2
- package/dist/src/apiCredentials/store.js.map +1 -0
- package/dist/src/apiCredentials/utils.d.ts +13 -0
- package/dist/src/apiCredentials/utils.d.ts.map +1 -0
- package/dist/src/apiCredentials/utils.js +27 -0
- package/dist/src/apiCredentials/utils.js.map +1 -0
- package/dist/src/cli.js +42 -39
- package/dist/src/cli.js.map +1 -1
- package/dist/src/cliCommands.d.ts +6 -3
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +243 -190
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/config.d.ts +36 -2
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +112 -17
- package/dist/src/config.js.map +1 -1
- package/dist/src/configDataStore.d.ts +44 -0
- package/dist/src/configDataStore.d.ts.map +1 -1
- package/dist/src/configDataStore.js +27 -0
- package/dist/src/configDataStore.js.map +1 -1
- package/dist/src/curl.d.ts +41 -8
- package/dist/src/curl.d.ts.map +1 -1
- package/dist/src/curl.js +80 -75
- package/dist/src/curl.js.map +1 -1
- package/dist/src/curlInjection.d.ts +46 -0
- package/dist/src/curlInjection.d.ts.map +1 -0
- package/dist/src/curlInjection.js +99 -0
- package/dist/src/curlInjection.js.map +1 -0
- package/dist/src/errorMessages.d.ts +14 -0
- package/dist/src/errorMessages.d.ts.map +1 -0
- package/dist/src/errorMessages.js +22 -0
- package/dist/src/errorMessages.js.map +1 -0
- package/dist/src/gateway/client.d.ts +32 -0
- package/dist/src/gateway/client.d.ts.map +1 -0
- package/dist/src/gateway/client.js +89 -0
- package/dist/src/gateway/client.js.map +1 -0
- package/dist/src/gateway/gatewayEndpoint.d.ts +43 -0
- package/dist/src/gateway/gatewayEndpoint.d.ts.map +1 -0
- package/dist/src/gateway/gatewayEndpoint.js +297 -0
- package/dist/src/gateway/gatewayEndpoint.js.map +1 -0
- package/dist/src/gateway/latchkeyEndpoint.d.ts +105 -0
- package/dist/src/gateway/latchkeyEndpoint.d.ts.map +1 -0
- package/dist/src/gateway/latchkeyEndpoint.js +144 -0
- package/dist/src/gateway/latchkeyEndpoint.js.map +1 -0
- package/dist/src/gateway/server.d.ts +20 -0
- package/dist/src/gateway/server.d.ts.map +1 -0
- package/dist/src/gateway/server.js +90 -0
- package/dist/src/gateway/server.js.map +1 -0
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/permissions.d.ts +2 -1
- package/dist/src/permissions.d.ts.map +1 -1
- package/dist/src/permissions.js +8 -4
- package/dist/src/permissions.js.map +1 -1
- package/dist/src/{registry.d.ts → serviceRegistry.d.ts} +4 -4
- package/dist/src/serviceRegistry.d.ts.map +1 -0
- package/dist/src/{registry.js → serviceRegistry.js} +4 -4
- package/dist/src/serviceRegistry.js.map +1 -0
- package/dist/src/services/aws.d.ts +2 -2
- package/dist/src/services/aws.d.ts.map +1 -1
- package/dist/src/services/aws.js +17 -10
- package/dist/src/services/aws.js.map +1 -1
- package/dist/src/services/core/base.d.ts +2 -2
- package/dist/src/services/core/base.d.ts.map +1 -1
- package/dist/src/services/core/base.js +3 -3
- package/dist/src/services/core/base.js.map +1 -1
- package/dist/src/services/core/registered.d.ts +2 -2
- package/dist/src/services/core/registered.d.ts.map +1 -1
- package/dist/src/services/core/registered.js +2 -2
- package/dist/src/services/core/registered.js.map +1 -1
- package/dist/src/services/discord.d.ts +1 -1
- package/dist/src/services/discord.d.ts.map +1 -1
- package/dist/src/services/discord.js +1 -1
- package/dist/src/services/discord.js.map +1 -1
- package/dist/src/services/dropbox.d.ts +1 -1
- package/dist/src/services/dropbox.d.ts.map +1 -1
- package/dist/src/services/dropbox.js +1 -1
- package/dist/src/services/dropbox.js.map +1 -1
- package/dist/src/services/github.d.ts +1 -1
- package/dist/src/services/github.d.ts.map +1 -1
- package/dist/src/services/github.js +1 -1
- package/dist/src/services/github.js.map +1 -1
- package/dist/src/services/google/base.d.ts +2 -2
- package/dist/src/services/google/base.d.ts.map +1 -1
- package/dist/src/services/google/base.js +3 -3
- package/dist/src/services/google/base.js.map +1 -1
- package/dist/src/services/google/directions.d.ts +1 -1
- package/dist/src/services/google/directions.d.ts.map +1 -1
- package/dist/src/services/linear.d.ts +1 -1
- package/dist/src/services/linear.d.ts.map +1 -1
- package/dist/src/services/linear.js +1 -1
- package/dist/src/services/linear.js.map +1 -1
- package/dist/src/services/notion.d.ts +1 -1
- package/dist/src/services/notion.d.ts.map +1 -1
- package/dist/src/services/notion.js +1 -1
- package/dist/src/services/notion.js.map +1 -1
- package/dist/src/services/sentry.d.ts +2 -2
- package/dist/src/services/sentry.d.ts.map +1 -1
- package/dist/src/services/sentry.js +6 -3
- package/dist/src/services/sentry.js.map +1 -1
- package/dist/src/services/slack.d.ts +3 -3
- package/dist/src/services/slack.d.ts.map +1 -1
- package/dist/src/services/slack.js +5 -5
- package/dist/src/services/slack.js.map +1 -1
- package/dist/src/services/telegram.d.ts +2 -2
- package/dist/src/services/telegram.d.ts.map +1 -1
- package/dist/src/services/telegram.js +2 -2
- package/dist/src/services/telegram.js.map +1 -1
- package/dist/src/sharedOperations.d.ts +44 -0
- package/dist/src/sharedOperations.d.ts.map +1 -0
- package/dist/src/sharedOperations.js +131 -0
- package/dist/src/sharedOperations.js.map +1 -0
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +4 -0
- package/dist/src/version.js.map +1 -0
- package/dist/tests/apiCredentialStore.test.js +2 -2
- package/dist/tests/apiCredentialStore.test.js.map +1 -1
- package/dist/tests/apiCredentials.test.js +37 -36
- package/dist/tests/apiCredentials.test.js.map +1 -1
- package/dist/tests/cli.test.js +241 -55
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/config.test.d.ts +2 -0
- package/dist/tests/config.test.d.ts.map +1 -0
- package/dist/tests/config.test.js +150 -0
- package/dist/tests/config.test.js.map +1 -0
- package/dist/tests/gateway.test.d.ts +2 -0
- package/dist/tests/gateway.test.d.ts.map +1 -0
- package/dist/tests/gateway.test.js +566 -0
- package/dist/tests/gateway.test.js.map +1 -0
- package/dist/tests/gatewayClient.test.d.ts +2 -0
- package/dist/tests/gatewayClient.test.d.ts.map +1 -0
- package/dist/tests/gatewayClient.test.js +85 -0
- package/dist/tests/gatewayClient.test.js.map +1 -0
- package/dist/tests/latchkeyEndpoint.test.d.ts +2 -0
- package/dist/tests/latchkeyEndpoint.test.d.ts.map +1 -0
- package/dist/tests/latchkeyEndpoint.test.js +385 -0
- package/dist/tests/latchkeyEndpoint.test.js.map +1 -0
- package/dist/tests/permissions.test.js +18 -3
- package/dist/tests/permissions.test.js.map +1 -1
- package/dist/tests/serviceRegistry.test.d.ts +2 -0
- package/dist/tests/serviceRegistry.test.d.ts.map +1 -0
- package/dist/tests/{registry.test.js → serviceRegistry.test.js} +17 -17
- package/dist/tests/serviceRegistry.test.js.map +1 -0
- package/dist/tests/servicesAgainstRecordings.test.js +3 -3
- package/dist/tests/servicesAgainstRecordings.test.js.map +1 -1
- package/dist/tests/sharedOperations.test.d.ts +2 -0
- package/dist/tests/sharedOperations.test.d.ts.map +1 -0
- package/dist/tests/sharedOperations.test.js +264 -0
- package/dist/tests/sharedOperations.test.js.map +1 -0
- package/package.json +8 -2
- package/dist/src/apiCredentialStore.d.ts.map +0 -1
- package/dist/src/apiCredentialStore.js.map +0 -1
- package/dist/src/apiCredentials.d.ts.map +0 -1
- package/dist/src/apiCredentials.js.map +0 -1
- package/dist/src/apiCredentialsSerialization.d.ts.map +0 -1
- package/dist/src/apiCredentialsSerialization.js.map +0 -1
- package/dist/src/registry.d.ts.map +0 -1
- package/dist/src/registry.js.map +0 -1
- package/dist/tests/registry.test.d.ts +0 -2
- package/dist/tests/registry.test.d.ts.map +0 -1
- package/dist/tests/registry.test.js.map +0 -1
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP handler for the `/gateway/<target-url>` proxy endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Forwards the incoming HTTP request through latchkey's credential injection
|
|
5
|
+
* pipeline (via `curl`) to the target URL and streams the upstream response
|
|
6
|
+
* back to the client.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { tmpdir } from 'node:os';
|
|
11
|
+
import { CredentialsExpiredError, NoCredentialsForServiceError, NoServiceForUrlError, prepareCurlInvocation, RequestNotPermittedError, UrlExtractionFailedError, } from '../curlInjection.js';
|
|
12
|
+
import { PermissionCheckError } from '../permissions.js';
|
|
13
|
+
import { ErrorMessages } from '../errorMessages.js';
|
|
14
|
+
/**
|
|
15
|
+
* Headers that should not be forwarded between client and upstream (hop-by-hop).
|
|
16
|
+
*/
|
|
17
|
+
const HOP_BY_HOP_HEADERS = new Set([
|
|
18
|
+
'connection',
|
|
19
|
+
'keep-alive',
|
|
20
|
+
'proxy-authenticate',
|
|
21
|
+
'proxy-authorization',
|
|
22
|
+
'te',
|
|
23
|
+
'trailers',
|
|
24
|
+
'transfer-encoding',
|
|
25
|
+
'upgrade',
|
|
26
|
+
'host',
|
|
27
|
+
]);
|
|
28
|
+
export const GATEWAY_PATH_PREFIX = '/gateway/';
|
|
29
|
+
export class BodyTooLargeError extends Error {
|
|
30
|
+
constructor() {
|
|
31
|
+
super(ErrorMessages.requestBodyTooLarge);
|
|
32
|
+
this.name = 'BodyTooLargeError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function sendErrorResponse(response, statusCode, message) {
|
|
36
|
+
response.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
37
|
+
response.end(JSON.stringify({ error: message }));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Send a 502 describing a failure of the upstream curl invocation. The
|
|
41
|
+
* error message is taken from curl's stderr when available, so callers see
|
|
42
|
+
* the actual failure reason (DNS, connection refused, TLS, ...) that an
|
|
43
|
+
* equivalent passthrough-mode call would have shown. When stderr is empty
|
|
44
|
+
* we fall back to a generic placeholder.
|
|
45
|
+
*/
|
|
46
|
+
function sendUpstreamCurlFailure(response, result) {
|
|
47
|
+
const stderrMessage = result.stderr.trim();
|
|
48
|
+
const message = stderrMessage === '' ? ErrorMessages.upstreamRequestFailed : stderrMessage;
|
|
49
|
+
sendErrorResponse(response, 502, message);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Extract the target URL from a raw gateway request URL.
|
|
53
|
+
* Strips the `/gateway/` prefix and returns the target URL.
|
|
54
|
+
* Returns null if the path doesn't start with `/gateway/` or the target URL is invalid.
|
|
55
|
+
*/
|
|
56
|
+
export function extractTargetUrl(rawUrl) {
|
|
57
|
+
const prefix = GATEWAY_PATH_PREFIX;
|
|
58
|
+
if (!rawUrl.startsWith(prefix)) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const targetUrl = rawUrl.slice(prefix.length);
|
|
62
|
+
if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return targetUrl;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build curl arguments from an HTTP request's components.
|
|
69
|
+
* Strips hop-by-hop headers and constructs a curl-compatible argument array.
|
|
70
|
+
*/
|
|
71
|
+
export function buildCurlArguments(method, headers, targetUrl, hasBody) {
|
|
72
|
+
const args = [];
|
|
73
|
+
if (method !== 'GET') {
|
|
74
|
+
args.push('-X', method);
|
|
75
|
+
}
|
|
76
|
+
for (const [name, value] of headers) {
|
|
77
|
+
if (HOP_BY_HOP_HEADERS.has(name.toLowerCase())) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
args.push('-H', `${name}: ${value}`);
|
|
81
|
+
}
|
|
82
|
+
if (hasBody) {
|
|
83
|
+
args.push('--data-binary', '@-');
|
|
84
|
+
}
|
|
85
|
+
args.push(targetUrl);
|
|
86
|
+
return args;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Parse response headers from curl's -D output.
|
|
90
|
+
* Returns the status code from the last status line and all response headers.
|
|
91
|
+
*/
|
|
92
|
+
export function parseResponseHeaders(headerDump) {
|
|
93
|
+
const headers = new Map();
|
|
94
|
+
let statusCode = 0;
|
|
95
|
+
// curl may output multiple status lines (e.g. 100 Continue, redirects).
|
|
96
|
+
// We parse from the beginning and reset on each new status line,
|
|
97
|
+
// so we end up with the headers from the final response.
|
|
98
|
+
const lines = headerDump.split(/\r?\n/);
|
|
99
|
+
for (const line of lines) {
|
|
100
|
+
// Status line: "HTTP/1.1 200 OK" or "HTTP/2 200"
|
|
101
|
+
const statusMatch = /^HTTP\/[\d.]+ (\d+)/.exec(line);
|
|
102
|
+
if (statusMatch !== null) {
|
|
103
|
+
statusCode = parseInt(statusMatch[1], 10);
|
|
104
|
+
headers.clear();
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// Header line: "Content-Type: application/json"
|
|
108
|
+
const colonIndex = line.indexOf(':');
|
|
109
|
+
if (colonIndex > 0) {
|
|
110
|
+
const name = line.slice(0, colonIndex).trim();
|
|
111
|
+
const value = line.slice(colonIndex + 1).trim();
|
|
112
|
+
const lowerName = name.toLowerCase();
|
|
113
|
+
const existing = headers.get(lowerName);
|
|
114
|
+
if (existing !== undefined) {
|
|
115
|
+
existing.push(value);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
headers.set(lowerName, [value]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { statusCode, headers };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Read the full request body, enforcing a size limit.
|
|
126
|
+
*/
|
|
127
|
+
function readRequestBody(request, maxBodySize) {
|
|
128
|
+
return new Promise((resolve, reject) => {
|
|
129
|
+
const contentLength = request.headers['content-length'];
|
|
130
|
+
if (contentLength !== undefined) {
|
|
131
|
+
const size = parseInt(contentLength, 10);
|
|
132
|
+
if (!isNaN(size) && size > maxBodySize) {
|
|
133
|
+
reject(new BodyTooLargeError());
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const chunks = [];
|
|
138
|
+
let totalSize = 0;
|
|
139
|
+
request.on('data', (chunk) => {
|
|
140
|
+
totalSize += chunk.length;
|
|
141
|
+
if (totalSize > maxBodySize) {
|
|
142
|
+
request.destroy();
|
|
143
|
+
reject(new BodyTooLargeError());
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
chunks.push(chunk);
|
|
147
|
+
});
|
|
148
|
+
request.on('end', () => {
|
|
149
|
+
if (totalSize === 0) {
|
|
150
|
+
resolve(null);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
resolve(Buffer.concat(chunks));
|
|
154
|
+
});
|
|
155
|
+
request.on('error', reject);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Forward parsed upstream response to the client.
|
|
160
|
+
*/
|
|
161
|
+
function forwardResponse(response, parsed, body) {
|
|
162
|
+
for (const [name, values] of parsed.headers) {
|
|
163
|
+
if (HOP_BY_HOP_HEADERS.has(name)) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (values.length === 1) {
|
|
167
|
+
response.setHeader(name, values[0]);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
response.setHeader(name, [...values]);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
response.writeHead(parsed.statusCode);
|
|
174
|
+
response.end(body);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Execute a proxied request through the credential injection pipeline.
|
|
178
|
+
*/
|
|
179
|
+
export async function handleGatewayRequest(request, response, targetUrl, deps, apiCredentialStore, options) {
|
|
180
|
+
// Read body
|
|
181
|
+
let body;
|
|
182
|
+
try {
|
|
183
|
+
body = await readRequestBody(request, options.maxBodySize);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (error instanceof BodyTooLargeError) {
|
|
187
|
+
const method = request.method ?? 'UNKNOWN';
|
|
188
|
+
deps.log(`${method} ${targetUrl} -> 413`);
|
|
189
|
+
sendErrorResponse(response, 413, error.message);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
// Build curl arguments from the incoming request
|
|
195
|
+
const method = request.method ?? 'GET';
|
|
196
|
+
const headerMap = new Map();
|
|
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);
|
|
206
|
+
let allArguments;
|
|
207
|
+
try {
|
|
208
|
+
allArguments = await prepareCurlInvocation(curlArguments, apiCredentialStore, {
|
|
209
|
+
registry: deps.registry,
|
|
210
|
+
checkPermission: deps.checkPermission,
|
|
211
|
+
permissionsConfigPath: deps.config.permissionsConfigPath,
|
|
212
|
+
permissionsDoNotUseBuiltinSchemas: deps.config.permissionsDoNotUseBuiltinSchemas,
|
|
213
|
+
passthroughUnknown: deps.config.passthroughUnknown,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
if (error instanceof RequestNotPermittedError) {
|
|
218
|
+
deps.log(`${method} ${targetUrl} -> 403`);
|
|
219
|
+
sendErrorResponse(response, 403, error.message);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (error instanceof PermissionCheckError) {
|
|
223
|
+
deps.log(`${method} ${targetUrl} -> 403`);
|
|
224
|
+
sendErrorResponse(response, 403, `Error: ${error.message}`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (error instanceof UrlExtractionFailedError ||
|
|
228
|
+
error instanceof NoServiceForUrlError ||
|
|
229
|
+
error instanceof NoCredentialsForServiceError ||
|
|
230
|
+
error instanceof CredentialsExpiredError) {
|
|
231
|
+
deps.log(`${method} ${targetUrl} -> 400`);
|
|
232
|
+
sendErrorResponse(response, 400, error.message);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
// Create temp directory for header dump
|
|
238
|
+
const tempDir = mkdtempSync(join(tmpdir(), 'latchkey-gw-'));
|
|
239
|
+
const headerFile = join(tempDir, 'headers');
|
|
240
|
+
try {
|
|
241
|
+
// Add curl flags for capturing response metadata. `-sS` silences the
|
|
242
|
+
// progress meter (which would otherwise pollute the captured response
|
|
243
|
+
// body) while still letting error messages reach stderr, so
|
|
244
|
+
// `sendUpstreamCurlFailure` can surface the real failure reason to the
|
|
245
|
+
// client instead of the generic fallback.
|
|
246
|
+
const curlArgs = ['-sS', '-D', headerFile, ...allArguments];
|
|
247
|
+
const result = await deps.runCurlAsync(curlArgs, {
|
|
248
|
+
stdin: body ?? undefined,
|
|
249
|
+
});
|
|
250
|
+
if (result.returncode !== 0) {
|
|
251
|
+
// Try to read headers in case curl got a response before failing
|
|
252
|
+
let headerDump;
|
|
253
|
+
try {
|
|
254
|
+
headerDump = readFileSync(headerFile, 'utf-8');
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
deps.log(`${method} ${targetUrl} -> 502`);
|
|
258
|
+
sendUpstreamCurlFailure(response, result);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (headerDump.trim() === '') {
|
|
262
|
+
deps.log(`${method} ${targetUrl} -> 502`);
|
|
263
|
+
sendUpstreamCurlFailure(response, result);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
// We got headers — forward whatever we have
|
|
267
|
+
const parsed = parseResponseHeaders(headerDump);
|
|
268
|
+
forwardResponse(response, parsed, result.stdout);
|
|
269
|
+
deps.log(`${method} ${targetUrl} -> ${String(parsed.statusCode)}`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
// Read response headers
|
|
273
|
+
let headerDump;
|
|
274
|
+
try {
|
|
275
|
+
headerDump = readFileSync(headerFile, 'utf-8');
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
deps.log(`${method} ${targetUrl} -> 502`);
|
|
279
|
+
sendUpstreamCurlFailure(response, result);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const parsed = parseResponseHeaders(headerDump);
|
|
283
|
+
const statusCode = parsed.statusCode || 200;
|
|
284
|
+
forwardResponse(response, { statusCode, headers: parsed.headers }, result.stdout);
|
|
285
|
+
deps.log(`${method} ${targetUrl} -> ${String(statusCode)}`);
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
// Clean up temp files
|
|
289
|
+
try {
|
|
290
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// Ignore cleanup errors
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=gatewayEndpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gatewayEndpoint.js","sourceRoot":"","sources":["../../../src/gateway/gatewayEndpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP handler for the /latchkey/ RPC endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Accepts POST requests with a JSON body containing a command and optional params.
|
|
5
|
+
* Dispatches to shared operation functions and returns a uniform response envelope.
|
|
6
|
+
*/
|
|
7
|
+
import * as http from 'node:http';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import type { ApiCredentialStore } from '../apiCredentials/store.js';
|
|
10
|
+
import type { CliDependencies } from '../cliCommands.js';
|
|
11
|
+
import type { EncryptedStorage } from '../encryptedStorage.js';
|
|
12
|
+
export declare const LatchkeyRequestSchema: z.ZodDiscriminatedUnion<"command", [z.ZodObject<{
|
|
13
|
+
command: z.ZodLiteral<"services list">;
|
|
14
|
+
params: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
builtin: z.ZodOptional<z.ZodBoolean>;
|
|
16
|
+
viable: z.ZodOptional<z.ZodBoolean>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
builtin?: boolean | undefined;
|
|
19
|
+
viable?: boolean | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
builtin?: boolean | undefined;
|
|
22
|
+
viable?: boolean | undefined;
|
|
23
|
+
}>>;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
command: "services list";
|
|
26
|
+
params?: {
|
|
27
|
+
builtin?: boolean | undefined;
|
|
28
|
+
viable?: boolean | undefined;
|
|
29
|
+
} | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
command: "services list";
|
|
32
|
+
params?: {
|
|
33
|
+
builtin?: boolean | undefined;
|
|
34
|
+
viable?: boolean | undefined;
|
|
35
|
+
} | undefined;
|
|
36
|
+
}>, z.ZodObject<{
|
|
37
|
+
command: z.ZodLiteral<"services info">;
|
|
38
|
+
params: z.ZodObject<{
|
|
39
|
+
serviceName: z.ZodString;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
serviceName: string;
|
|
42
|
+
}, {
|
|
43
|
+
serviceName: string;
|
|
44
|
+
}>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
params: {
|
|
47
|
+
serviceName: string;
|
|
48
|
+
};
|
|
49
|
+
command: "services info";
|
|
50
|
+
}, {
|
|
51
|
+
params: {
|
|
52
|
+
serviceName: string;
|
|
53
|
+
};
|
|
54
|
+
command: "services info";
|
|
55
|
+
}>, z.ZodObject<{
|
|
56
|
+
command: z.ZodLiteral<"auth list">;
|
|
57
|
+
params: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
command: "auth list";
|
|
60
|
+
params?: {} | undefined;
|
|
61
|
+
}, {
|
|
62
|
+
command: "auth list";
|
|
63
|
+
params?: {} | undefined;
|
|
64
|
+
}>, z.ZodObject<{
|
|
65
|
+
command: z.ZodLiteral<"auth browser">;
|
|
66
|
+
params: z.ZodObject<{
|
|
67
|
+
serviceName: z.ZodString;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
serviceName: string;
|
|
70
|
+
}, {
|
|
71
|
+
serviceName: string;
|
|
72
|
+
}>;
|
|
73
|
+
}, "strip", z.ZodTypeAny, {
|
|
74
|
+
params: {
|
|
75
|
+
serviceName: string;
|
|
76
|
+
};
|
|
77
|
+
command: "auth browser";
|
|
78
|
+
}, {
|
|
79
|
+
params: {
|
|
80
|
+
serviceName: string;
|
|
81
|
+
};
|
|
82
|
+
command: "auth browser";
|
|
83
|
+
}>, z.ZodObject<{
|
|
84
|
+
command: z.ZodLiteral<"auth browser-prepare">;
|
|
85
|
+
params: z.ZodObject<{
|
|
86
|
+
serviceName: z.ZodString;
|
|
87
|
+
}, "strip", z.ZodTypeAny, {
|
|
88
|
+
serviceName: string;
|
|
89
|
+
}, {
|
|
90
|
+
serviceName: string;
|
|
91
|
+
}>;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
params: {
|
|
94
|
+
serviceName: string;
|
|
95
|
+
};
|
|
96
|
+
command: "auth browser-prepare";
|
|
97
|
+
}, {
|
|
98
|
+
params: {
|
|
99
|
+
serviceName: string;
|
|
100
|
+
};
|
|
101
|
+
command: "auth browser-prepare";
|
|
102
|
+
}>]>;
|
|
103
|
+
export type LatchkeyRequest = z.infer<typeof LatchkeyRequestSchema>;
|
|
104
|
+
export declare function handleLatchkeyRequest(request: http.IncomingMessage, response: http.ServerResponse, deps: CliDependencies, apiCredentialStore: ApiCredentialStore, encryptedStorage: EncryptedStorage): Promise<void>;
|
|
105
|
+
//# sourceMappingURL=latchkeyEndpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"latchkeyEndpoint.d.ts","sourceRoot":"","sources":["../../../src/gateway/latchkeyEndpoint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAwD/D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAoFpE,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,IAAI,CAAC,eAAe,EAC7B,QAAQ,EAAE,IAAI,CAAC,cAAc,EAC7B,IAAI,EAAE,eAAe,EACrB,kBAAkB,EAAE,kBAAkB,EACtC,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,IAAI,CAAC,CAuDf"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP handler for the /latchkey/ RPC endpoint.
|
|
3
|
+
*
|
|
4
|
+
* Accepts POST requests with a JSON body containing a command and optional params.
|
|
5
|
+
* Dispatches to shared operation functions and returns a uniform response envelope.
|
|
6
|
+
*/
|
|
7
|
+
import { text } from 'node:stream/consumers';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { servicesList, servicesInfo, authList, authBrowser, authBrowserPrepare, UnknownServiceError, BrowserNotConfiguredError, PreparationRequiredError, } from '../sharedOperations.js';
|
|
10
|
+
import { BrowserDisabledError, BrowserFlowsNotSupportedError, GraphicalEnvironmentNotFoundError, } from '../playwrightUtils.js';
|
|
11
|
+
import { LoginCancelledError, LoginFailedError } from '../services/index.js';
|
|
12
|
+
const serviceNameParamsMessage = "missing required argument 'service_name'";
|
|
13
|
+
const serviceNameParams = z.object({
|
|
14
|
+
serviceName: z.string({ required_error: serviceNameParamsMessage }),
|
|
15
|
+
}, { required_error: serviceNameParamsMessage });
|
|
16
|
+
const ServicesListRequestSchema = z.object({
|
|
17
|
+
command: z.literal('services list'),
|
|
18
|
+
params: z
|
|
19
|
+
.object({
|
|
20
|
+
builtin: z.boolean().optional(),
|
|
21
|
+
viable: z.boolean().optional(),
|
|
22
|
+
})
|
|
23
|
+
.optional(),
|
|
24
|
+
});
|
|
25
|
+
const ServicesInfoRequestSchema = z.object({
|
|
26
|
+
command: z.literal('services info'),
|
|
27
|
+
params: serviceNameParams,
|
|
28
|
+
});
|
|
29
|
+
const AuthListRequestSchema = z.object({
|
|
30
|
+
command: z.literal('auth list'),
|
|
31
|
+
params: z.object({}).optional(),
|
|
32
|
+
});
|
|
33
|
+
const AuthBrowserRequestSchema = z.object({
|
|
34
|
+
command: z.literal('auth browser'),
|
|
35
|
+
params: serviceNameParams,
|
|
36
|
+
});
|
|
37
|
+
const AuthBrowserPrepareRequestSchema = z.object({
|
|
38
|
+
command: z.literal('auth browser-prepare'),
|
|
39
|
+
params: serviceNameParams,
|
|
40
|
+
});
|
|
41
|
+
export const LatchkeyRequestSchema = z.discriminatedUnion('command', [
|
|
42
|
+
ServicesListRequestSchema,
|
|
43
|
+
ServicesInfoRequestSchema,
|
|
44
|
+
AuthListRequestSchema,
|
|
45
|
+
AuthBrowserRequestSchema,
|
|
46
|
+
AuthBrowserPrepareRequestSchema,
|
|
47
|
+
]);
|
|
48
|
+
const KNOWN_ERROR_CLASSES = [
|
|
49
|
+
UnknownServiceError,
|
|
50
|
+
BrowserDisabledError,
|
|
51
|
+
GraphicalEnvironmentNotFoundError,
|
|
52
|
+
BrowserNotConfiguredError,
|
|
53
|
+
BrowserFlowsNotSupportedError,
|
|
54
|
+
PreparationRequiredError,
|
|
55
|
+
LoginCancelledError,
|
|
56
|
+
LoginFailedError,
|
|
57
|
+
];
|
|
58
|
+
function isKnownError(error) {
|
|
59
|
+
return KNOWN_ERROR_CLASSES.some((ErrorClass) => error instanceof ErrorClass);
|
|
60
|
+
}
|
|
61
|
+
function sendJsonResponse(response, statusCode, body) {
|
|
62
|
+
response.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
63
|
+
response.end(JSON.stringify(body));
|
|
64
|
+
}
|
|
65
|
+
function sendSuccess(response, result) {
|
|
66
|
+
sendJsonResponse(response, 200, { result });
|
|
67
|
+
}
|
|
68
|
+
function sendErrorResponse(response, statusCode, message) {
|
|
69
|
+
sendJsonResponse(response, statusCode, { error: message });
|
|
70
|
+
}
|
|
71
|
+
function describeRequest(parsed) {
|
|
72
|
+
const command = parsed.command;
|
|
73
|
+
if ('params' in parsed && parsed.params && 'serviceName' in parsed.params) {
|
|
74
|
+
return `${command} ${parsed.params.serviceName}`;
|
|
75
|
+
}
|
|
76
|
+
return command;
|
|
77
|
+
}
|
|
78
|
+
async function dispatch(parsed, deps, apiCredentialStore, encryptedStorage) {
|
|
79
|
+
switch (parsed.command) {
|
|
80
|
+
case 'services list':
|
|
81
|
+
return servicesList(deps.registry, apiCredentialStore, deps.config, parsed.params ?? {});
|
|
82
|
+
case 'services info':
|
|
83
|
+
return servicesInfo(deps.registry, apiCredentialStore, deps.config, parsed.params.serviceName);
|
|
84
|
+
case 'auth list':
|
|
85
|
+
return authList(deps.registry, apiCredentialStore);
|
|
86
|
+
case 'auth browser':
|
|
87
|
+
await authBrowser(deps.registry, apiCredentialStore, encryptedStorage, deps.config, parsed.params.serviceName);
|
|
88
|
+
return null;
|
|
89
|
+
case 'auth browser-prepare':
|
|
90
|
+
return authBrowserPrepare(deps.registry, apiCredentialStore, encryptedStorage, deps.config, parsed.params.serviceName);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export async function handleLatchkeyRequest(request, response, deps, apiCredentialStore, encryptedStorage) {
|
|
94
|
+
if (request.method !== 'POST') {
|
|
95
|
+
sendErrorResponse(response, 405, 'Method not allowed. Use POST.');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const bodyText = await text(request);
|
|
99
|
+
let bodyJson;
|
|
100
|
+
try {
|
|
101
|
+
bodyJson = JSON.parse(bodyText);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error instanceof SyntaxError) {
|
|
105
|
+
sendErrorResponse(response, 400, `Invalid JSON: ${error.message}`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
const parseResult = LatchkeyRequestSchema.safeParse(bodyJson);
|
|
111
|
+
if (!parseResult.success) {
|
|
112
|
+
const message = parseResult.error.errors
|
|
113
|
+
.map((e) => {
|
|
114
|
+
if (e.code === 'invalid_union_discriminator') {
|
|
115
|
+
const received = bodyJson?.command;
|
|
116
|
+
if (typeof received === 'string') {
|
|
117
|
+
return `unknown command '${received}'`;
|
|
118
|
+
}
|
|
119
|
+
return "missing required field 'command'";
|
|
120
|
+
}
|
|
121
|
+
return e.message;
|
|
122
|
+
})
|
|
123
|
+
.join('; ');
|
|
124
|
+
sendErrorResponse(response, 400, message);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const parsed = parseResult.data;
|
|
128
|
+
const description = describeRequest(parsed);
|
|
129
|
+
try {
|
|
130
|
+
const result = await dispatch(parsed, deps, apiCredentialStore, encryptedStorage);
|
|
131
|
+
deps.log(`POST /latchkey/ ${description} -> 200`);
|
|
132
|
+
sendSuccess(response, result);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (isKnownError(error)) {
|
|
136
|
+
deps.log(`POST /latchkey/ ${description} -> 400 (error)`);
|
|
137
|
+
sendErrorResponse(response, 400, error.message);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
deps.errorLog(`Unexpected error handling POST /latchkey/ ${description}: ${error instanceof Error ? error.message : String(error)}`);
|
|
141
|
+
sendErrorResponse(response, 500, 'Internal error');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=latchkeyEndpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"latchkeyEndpoint.js","sourceRoot":"","sources":["../../../src/gateway/latchkeyEndpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local HTTP gateway server.
|
|
3
|
+
*
|
|
4
|
+
* Routes incoming requests to either the `/gateway/<target-url>` proxy handler
|
|
5
|
+
* or the `/latchkey/` RPC endpoint.
|
|
6
|
+
*/
|
|
7
|
+
import * as http from 'node:http';
|
|
8
|
+
import type { ApiCredentialStore } from '../apiCredentials/store.js';
|
|
9
|
+
import type { CliDependencies } from '../cliCommands.js';
|
|
10
|
+
import type { EncryptedStorage } from '../encryptedStorage.js';
|
|
11
|
+
import { type GatewayOptions } from './gatewayEndpoint.js';
|
|
12
|
+
export interface GatewayServer {
|
|
13
|
+
readonly server: http.Server;
|
|
14
|
+
readonly close: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Start the gateway HTTP server.
|
|
18
|
+
*/
|
|
19
|
+
export declare function startGateway(deps: CliDependencies, apiCredentialStore: ApiCredentialStore, encryptedStorage: EncryptedStorage, options: GatewayOptions): Promise<GatewayServer>;
|
|
20
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/gateway/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAY9B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,eAAe,EACrB,kBAAkB,EAAE,kBAAkB,EACtC,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAmGxB"}
|