@dbx-tools/cli-tunnel 0.6.48 → 0.6.49
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 +93 -17
- package/index.ts +5 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -1
- package/lib/src/allowlist.d.ts +14 -9
- package/lib/src/allowlist.js +28 -53
- package/lib/src/cli.js +24 -16
- package/lib/src/env.d.ts +51 -0
- package/lib/src/env.js +51 -0
- package/lib/src/headers.d.ts +108 -0
- package/lib/src/headers.js +140 -0
- package/lib/src/otp.d.ts +1 -1
- package/lib/src/otp.js +7 -6
- package/lib/src/plugin.d.ts +6 -6
- package/lib/src/plugin.js +11 -8
- package/lib/src/portr.d.ts +3 -3
- package/lib/src/portr.js +10 -8
- package/lib/src/proxy.d.ts +8 -1
- package/lib/src/proxy.js +59 -19
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -6
- package/src/allowlist.ts +27 -55
- package/src/cli.ts +29 -15
- package/src/env.ts +62 -0
- package/src/headers.ts +155 -0
- package/src/otp.ts +6 -5
- package/src/plugin.ts +23 -17
- package/src/portr.ts +9 -7
- package/src/proxy.ts +71 -18
package/lib/src/portr.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* on cold start, so the portr binary and its config are placed under a writable,
|
|
6
6
|
* cwd-rooted `.home` unconditionally - it costs nothing where `$HOME` is writable.
|
|
7
7
|
* The install is idempotent (the installer skips when the on-PATH binary is
|
|
8
|
-
* current). The config is rendered from `
|
|
8
|
+
* current). The config is rendered from `TUNNEL_PUBLIC_DOMAIN` (`<subdomain>.<server>`)
|
|
9
9
|
* + `PORTR_TOKEN` and points portr at the PUBLIC port (the proxy listens there).
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
@@ -19,8 +19,8 @@ export interface PortrConfig {
|
|
|
19
19
|
port: number;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Resolve portr config from `
|
|
23
|
-
* `subdomain`.
|
|
22
|
+
* Resolve portr config from `TUNNEL_PUBLIC_DOMAIN` + `PORTR_TOKEN`, or an
|
|
23
|
+
* explicit `subdomain`. The domain is `<subdomain>.<server>` (e.g.
|
|
24
24
|
* `demo.apps.dbx.tools`). Returns `undefined` (no tunnel) when the token or a
|
|
25
25
|
* usable domain is absent.
|
|
26
26
|
*/
|
package/lib/src/portr.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* on cold start, so the portr binary and its config are placed under a writable,
|
|
6
6
|
* cwd-rooted `.home` unconditionally - it costs nothing where `$HOME` is writable.
|
|
7
7
|
* The install is idempotent (the installer skips when the on-PATH binary is
|
|
8
|
-
* current). The config is rendered from `
|
|
8
|
+
* current). The config is rendered from `TUNNEL_PUBLIC_DOMAIN` (`<subdomain>.<server>`)
|
|
9
9
|
* + `PORTR_TOKEN` and points portr at the PUBLIC port (the proxy listens there).
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
@@ -13,17 +13,19 @@
|
|
|
13
13
|
import { spawn, spawnSync } from "node:child_process";
|
|
14
14
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
15
15
|
import { delimiter, join } from "node:path";
|
|
16
|
-
import { log } from "@dbx-tools/shared-core";
|
|
16
|
+
import { env, log } from "@dbx-tools/shared-core";
|
|
17
|
+
import { PUBLIC_DOMAIN_ENV } from "./env.js";
|
|
17
18
|
const logger = log.logger("tunnel:portr");
|
|
18
19
|
/**
|
|
19
|
-
* Resolve portr config from `
|
|
20
|
-
* `subdomain`.
|
|
20
|
+
* Resolve portr config from `TUNNEL_PUBLIC_DOMAIN` + `PORTR_TOKEN`, or an
|
|
21
|
+
* explicit `subdomain`. The domain is `<subdomain>.<server>` (e.g.
|
|
21
22
|
* `demo.apps.dbx.tools`). Returns `undefined` (no tunnel) when the token or a
|
|
22
23
|
* usable domain is absent.
|
|
23
24
|
*/
|
|
24
25
|
export function resolvePortrConfig(opts) {
|
|
25
|
-
|
|
26
|
-
const
|
|
26
|
+
// PORTR_* is upstream portr's own namespace, so it keeps its name.
|
|
27
|
+
const token = env.string(opts.token, "PORTR_TOKEN");
|
|
28
|
+
const domain = env.string(opts.publicDomain, PUBLIC_DOMAIN_ENV);
|
|
27
29
|
if (!token)
|
|
28
30
|
return undefined;
|
|
29
31
|
let subdomain = opts.subdomain;
|
|
@@ -32,7 +34,7 @@ export function resolvePortrConfig(opts) {
|
|
|
32
34
|
subdomain ??= domain.split(".")[0];
|
|
33
35
|
server = domain.slice(domain.indexOf(".") + 1);
|
|
34
36
|
}
|
|
35
|
-
server ??=
|
|
37
|
+
server ??= env.text("PORTR_SERVER") ?? undefined;
|
|
36
38
|
if (!subdomain || !server || server === domain)
|
|
37
39
|
return undefined;
|
|
38
40
|
return { subdomain, server, token, port: opts.port };
|
|
@@ -88,4 +90,4 @@ export function startPortr(config, env) {
|
|
|
88
90
|
export function portrInstalled(env) {
|
|
89
91
|
return existsSync(join(env.HOME, ".portr", "bin", "portr"));
|
|
90
92
|
}
|
|
91
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
93
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9ydHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcG9ydHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMvRCxPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM1QyxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUU3QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBVTFDOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLElBS2xDO0lBQ0MsbUVBQW1FO0lBQ25FLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztJQUNwRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUNoRSxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzdCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDL0IsSUFBSSxNQUEwQixDQUFDO0lBQy9CLElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxTQUFTLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQyxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxD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LEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztBQUM5RCxDQUFDO0FBRUQsOEVBQThFO0FBQzlFLE1BQU0sVUFBVSxjQUFjLENBQUMsR0FBc0I7SUFDbkQsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQy9ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIHBvcnRyIGluc3RhbGwgKyBjb25maWcgKyBsYXVuY2ggZm9yIHRoZSB0dW5uZWwgQ0xJLlxuICpcbiAqIFNvbWUgaG9zdHMgKERhdGFicmlja3MgQXBwcyBhbW9uZyB0aGVtKSBtb3VudCB0aGUgY29udGFpbmVyJ3MgYCRIT01FYCByZWFkLW9ubHlcbiAqIG9uIGNvbGQgc3RhcnQsIHNvIHRoZSBwb3J0ciBiaW5hcnkgYW5kIGl0cyBjb25maWcgYXJlIHBsYWNlZCB1bmRlciBhIHdyaXRhYmxlLFxuICogY3dkLXJvb3RlZCBgLmhvbWVgIHVuY29uZGl0aW9uYWxseSAtIGl0IGNvc3RzIG5vdGhpbmcgd2hlcmUgYCRIT01FYCBpcyB3cml0YWJsZS5cbiAqIFRoZSBpbnN0YWxsIGlzIGlkZW1wb3RlbnQgKHRoZSBpbnN0YWxsZXIgc2tpcHMgd2hlbiB0aGUgb24tUEFUSCBiaW5hcnkgaXNcbiAqIGN1cnJlbnQpLiBUaGUgY29uZmlnIGlzIHJlbmRlcmVkIGZyb20gYFRVTk5FTF9QVUJMSUNfRE9NQUlOYCAoYDxzdWJkb21haW4+LjxzZXJ2ZXI+YClcbiAqICsgYFBPUlRSX1RPS0VOYCBhbmQgcG9pbnRzIHBvcnRyIGF0IHRoZSBQVUJMSUMgcG9ydCAodGhlIHByb3h5IGxpc3RlbnMgdGhlcmUpLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBzcGF3biwgc3Bhd25TeW5jIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgZXhpc3RzU3luYywgbWtkaXJTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGRlbGltaXRlciwgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGVudiwgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IFBVQkxJQ19ET01BSU5fRU5WIH0gZnJvbSBcIi4vZW52LnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6cG9ydHJcIik7XG5cbi8qKiBSZXNvbHZlZCBwb3J0ciB3aXJpbmcsIG9yIGB1bmRlZmluZWRgIHdoZW4gbm8gdHVubmVsIGlzIGNvbmZpZ3VyZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIFBvcnRyQ29uZmlnIHtcbiAgc3ViZG9tYWluOiBzdHJpbmc7XG4gIHNlcnZlcjogc3RyaW5nO1xuICB0b2tlbjogc3RyaW5nO1xuICBwb3J0OiBudW1iZXI7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBwb3J0ciBjb25maWcgZnJvbSBgVFVOTkVMX1BVQkxJQ19ET01BSU5gICsgYFBPUlRSX1RPS0VOYCwgb3IgYW5cbiAqIGV4cGxpY2l0IGBzdWJkb21haW5gLiBUaGUgZG9tYWluIGlzIGA8c3ViZG9tYWluPi48c2VydmVyPmAgKGUuZy5cbiAqIGBkZW1vLmFwcHMuZGJ4LnRvb2xzYCkuIFJldHVybnMgYHVuZGVmaW5lZGAgKG5vIHR1bm5lbCkgd2hlbiB0aGUgdG9rZW4gb3IgYVxuICogdXNhYmxlIGRvbWFpbiBpcyBhYnNlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlUG9ydHJDb25maWcob3B0czoge1xuICBwdWJsaWNEb21haW4/OiBzdHJpbmc7XG4gIHN1YmRvbWFpbj86IHN0cmluZztcbiAgdG9rZW4/OiBzdHJpbmc7XG4gIHBvcnQ6IG51bWJlcjtcbn0pOiBQb3J0ckNvbmZpZyB8IHVuZGVmaW5lZCB7XG4gIC8vIFBPUlRSXyogaXMgdXBzdHJlYW0gcG9ydHIncyBvd24gbmFtZXNwYWNlLCBzbyBpdCBrZWVwcyBpdHMgbmFtZS5cbiAgY29uc3QgdG9rZW4gPSBlbnYuc3RyaW5nKG9wdHMudG9rZW4sIFwiUE9SVFJfVE9LRU5cIik7XG4gIGNvbnN0IGRvbWFpbiA9IGVudi5zdHJpbmcob3B0cy5wdWJsaWNEb21haW4sIFBVQkxJQ19ET01BSU5fRU5WKTtcbiAgaWYgKCF0b2tlbikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgbGV0IHN1YmRvbWFpbiA9IG9wdHMuc3ViZG9tYWluO1xuICBsZXQgc2VydmVyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGlmIChkb21haW4pIHtcbiAgICBzdWJkb21haW4gPz89IGRvbWFpbi5zcGxpdChcIi5cIilbMF07XG4gICAgc2VydmVyID0gZG9tYWluLnNsaWNlKGRvbWFpbi5pbmRleE9mKFwiLlwiKSArIDEpO1xuICB9XG4gIHNlcnZlciA/Pz0gZW52LnRleHQoXCJQT1JUUl9TRVJWRVJcIikgPz8gdW5kZWZpbmVkO1xuICBpZiAoIXN1YmRvbWFpbiB8fCAhc2VydmVyIHx8IHNlcnZlciA9PT0gZG9tYWluKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4geyBzdWJkb21haW4sIHNlcnZlciwgdG9rZW4sIHBvcnQ6IG9wdHMucG9ydCB9O1xufVxuXG4vKiogVGhlIHdyaXRhYmxlIGhvbWUgcG9ydHIgaW5zdGFsbHMgKyBjb25maWd1cmVzIHVuZGVyIChBcHBzIGAkSE9NRWAgaXMgcmVhZC1vbmx5KS4gKi9cbmZ1bmN0aW9uIHBvcnRySG9tZSgpOiBzdHJpbmcge1xuICBjb25zdCBob21lID0gam9pbihwcm9jZXNzLmN3ZCgpLCBcIi5ob21lXCIpO1xuICBta2RpclN5bmMoam9pbihob21lLCBcIi5wb3J0clwiLCBcImJpblwiKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIHJldHVybiBob21lO1xufVxuXG4vKiogSW5zdGFsbCBwb3J0ciAoaWRlbXBvdGVudCkgaW50byB0aGUgY3dkLXJvb3RlZCBob21lIGFuZCByZXR1cm4gdGhlIGNoaWxkIGVudi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnN0YWxsUG9ydHIoKTogTm9kZUpTLlByb2Nlc3NFbnYge1xuICBjb25zdCBob21lID0gcG9ydHJIb21lKCk7XG4gIGNvbnN0IGVudjogTm9kZUpTLlByb2Nlc3NFbnYgPSB7XG4gICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgSE9NRTogaG9tZSxcbiAgICBQT1JUUl9BVVRPX0FERF9QQVRIOiBcIm5vXCIsXG4gICAgUEFUSDogW2pvaW4oaG9tZSwgXCIucG9ydHJcIiwgXCJiaW5cIiksIHByb2Nlc3MuZW52LlBBVEggPz8gXCJcIl0uam9pbihkZWxpbWl0ZXIpLFxuICB9O1xuICBsb2dnZXIuaW5mbyhcImluc3RhbGxpbmcgcG9ydHIgKGlkZW1wb3RlbnQpXCIpO1xuICBjb25zdCByZXMgPSBzcGF3blN5bmMoXCJiYXNoXCIsIFtcIi1jXCIsIFwiY3VybCAtc1NmIGh0dHBzOi8vaW5zdGFsbC5wb3J0ci5kZXYgfCBzaFwiXSwge1xuICAgIGVudixcbiAgICBzdGRpbzogXCJpbmhlcml0XCIsXG4gIH0pO1xuICBpZiAocmVzLnN0YXR1cyAhPT0gMCkgdGhyb3cgbmV3IEVycm9yKFwicG9ydHIgaW5zdGFsbCBmYWlsZWRcIik7XG4gIHJldHVybiBlbnY7XG59XG5cbi8qKiBSZW5kZXIgYH4vLnBvcnRyL2NvbmZpZy55YW1sYCBmb3IgdGhlIHJlc29sdmVkIHR1bm5lbC4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cml0ZVBvcnRyQ29uZmlnKGNvbmZpZzogUG9ydHJDb25maWcsIGVudjogTm9kZUpTLlByb2Nlc3NFbnYpOiB2b2lkIHtcbiAgY29uc3QgcGF0aCA9IGpvaW4oZW52LkhPTUUhLCBcIi5wb3J0clwiLCBcImNvbmZpZy55YW1sXCIpO1xuICB3cml0ZUZpbGVTeW5jKFxuICAgIHBhdGgsXG4gICAgW1xuICAgICAgYHNlcnZlcl91cmw6ICR7Y29uZmlnLnNlcnZlcn1gLFxuICAgICAgYHNzaF91cmw6ICR7Y29uZmlnLnNlcnZlcn06NDQ0NGAsXG4gICAgICBgc2VjcmV0X2tleTogJHtjb25maWcudG9rZW59YCxcbiAgICAgIFwiZGlzYWJsZV9kYXNoYm9hcmQ6IHRydWVcIixcbiAgICAgIFwiZGlzYWJsZV90dWk6IHRydWVcIixcbiAgICAgIFwidHVubmVsczpcIixcbiAgICAgIGAgIC0gbmFtZTogJHtjb25maWcuc3ViZG9tYWlufWAsXG4gICAgICBgICAgIHN1YmRvbWFpbjogJHtjb25maWcuc3ViZG9tYWlufWAsXG4gICAgICBgICAgIHBvcnQ6ICR7Y29uZmlnLnBvcnR9YCxcbiAgICAgIFwiXCIsXG4gICAgXS5qb2luKFwiXFxuXCIpLFxuICApO1xufVxuXG4vKiogTGF1bmNoIGBwb3J0ciBzdGFydGAgYXMgYSBjaGlsZCBwcm9jZXNzIChjYWxsZXIgc3VwZXJ2aXNlcyArIGtpbGxzIGl0KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGFydFBvcnRyKGNvbmZpZzogUG9ydHJDb25maWcsIGVudjogTm9kZUpTLlByb2Nlc3NFbnYpOiBSZXR1cm5UeXBlPHR5cGVvZiBzcGF3bj4ge1xuICAvLyBSZWNsYWltIHRoZSBzdWJkb21haW4gZnJvbSBhbnkgcG9ydHIgbGVmdCBieSBhIHByZXZpb3VzIGJvb3QgaW4gdGhpcyBjb250YWluZXIuXG4gIHNwYXduU3luYyhcInBraWxsXCIsIFtcIi14XCIsIFwicG9ydHJcIl0sIHsgc3RkaW86IFwiaWdub3JlXCIgfSk7XG4gIGxvZ2dlci5pbmZvKGBwb3J0ciB0dW5uZWxpbmcgaHR0cHM6Ly8ke2NvbmZpZy5zdWJkb21haW59LiR7Y29uZmlnLnNlcnZlcn0gLT4gOiR7Y29uZmlnLnBvcnR9YCk7XG4gIHJldHVybiBzcGF3bihcInBvcnRyXCIsIFtcInN0YXJ0XCJdLCB7IGVudiwgc3RkaW86IFwiaW5oZXJpdFwiIH0pO1xufVxuXG4vKiogVHJ1ZSB3aGVuIHRoZSBpbnN0YWxsZWQgcG9ydHIgYmluYXJ5IHBhdGggZXhpc3RzIChwb3N0LWluc3RhbGwgc2FuaXR5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwb3J0ckluc3RhbGxlZChlbnY6IE5vZGVKUy5Qcm9jZXNzRW52KTogYm9vbGVhbiB7XG4gIHJldHVybiBleGlzdHNTeW5jKGpvaW4oZW52LkhPTUUhLCBcIi5wb3J0clwiLCBcImJpblwiLCBcInBvcnRyXCIpKTtcbn1cbiJdfQ==
|
package/lib/src/proxy.d.ts
CHANGED
|
@@ -37,6 +37,13 @@ export interface ProxyOptions {
|
|
|
37
37
|
* operator passed `--insecure` / `TUNNEL_INSECURE=true`.
|
|
38
38
|
*/
|
|
39
39
|
gate?: AuthGateApi;
|
|
40
|
+
/**
|
|
41
|
+
* Extra `x-` request headers tunnel traffic may forward, as literals, globs, or
|
|
42
|
+
* `/regex/`es - unioned with {@link DEFAULT_FORWARD_HEADERS}. Every other `x-`
|
|
43
|
+
* header is stripped, and {@link PROTECTED_HEADERS} is stripped regardless. See
|
|
44
|
+
* `./headers.ts` for why the policy is an allow-list.
|
|
45
|
+
*/
|
|
46
|
+
forwardHeaders?: readonly string[];
|
|
40
47
|
}
|
|
41
48
|
/** Start the gate proxy. Resolves once it is listening. */
|
|
42
|
-
export declare function startProxy({ publicPort, appPort, gate }: ProxyOptions): Promise<void>;
|
|
49
|
+
export declare function startProxy({ publicPort, appPort, gate, forwardHeaders, }: ProxyOptions): Promise<void>;
|
package/lib/src/proxy.js
CHANGED
|
@@ -25,9 +25,10 @@
|
|
|
25
25
|
* @module
|
|
26
26
|
*/
|
|
27
27
|
import { createServer } from "node:http";
|
|
28
|
-
import { http, json, log } from "@dbx-tools/shared-core";
|
|
28
|
+
import { http, json, log, token } from "@dbx-tools/shared-core";
|
|
29
29
|
import { authRequestSchema, authVerifySchema, SESSION_COOKIE_NAME } from "@dbx-tools/shared-email";
|
|
30
30
|
import ProxyModule from "http-proxy-3";
|
|
31
|
+
import { toHeaderPolicy } from "./headers.js";
|
|
31
32
|
const logger = log.logger("tunnel:proxy");
|
|
32
33
|
/** Route prefix the login flow lives under (open, answered in-process). */
|
|
33
34
|
const AUTH_PREFIX = "/api/email/auth";
|
|
@@ -56,7 +57,7 @@ function sendJson(res, status, body, setCookie) {
|
|
|
56
57
|
res.end(JSON.stringify(body));
|
|
57
58
|
}
|
|
58
59
|
/** Start the gate proxy. Resolves once it is listening. */
|
|
59
|
-
export function startProxy({ publicPort, appPort, gate }) {
|
|
60
|
+
export function startProxy({ publicPort, appPort, gate, forwardHeaders, }) {
|
|
60
61
|
const proxy = ProxyModule.createProxyServer({
|
|
61
62
|
target: { host: "127.0.0.1", port: appPort },
|
|
62
63
|
ws: true,
|
|
@@ -69,6 +70,9 @@ export function startProxy({ publicPort, appPort, gate }) {
|
|
|
69
70
|
sendJson(r, 502, { error: "upstream unavailable" });
|
|
70
71
|
}
|
|
71
72
|
});
|
|
73
|
+
// Compiled once: the inbound-header allow-list applied to every gated request.
|
|
74
|
+
const headerPolicy = toHeaderPolicy(forwardHeaders);
|
|
75
|
+
logger.debug("inbound header policy", { forward: headerPolicy.patterns });
|
|
72
76
|
/** The session cookie for a verified email, as a Set-Cookie string. */
|
|
73
77
|
const sessionCookie = (token, maxAgeSeconds) => [
|
|
74
78
|
`${SESSION_COOKIE_NAME}=${token}`,
|
|
@@ -80,11 +84,25 @@ export function startProxy({ publicPort, appPort, gate }) {
|
|
|
80
84
|
]
|
|
81
85
|
.filter(Boolean)
|
|
82
86
|
.join("; ");
|
|
83
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* Client IP for rate-limiting: the portr client's forwarded XFF, else the socket.
|
|
89
|
+
*
|
|
90
|
+
* Deliberately the RIGHTMOST `x-forwarded-for` entry, not the leftmost. The
|
|
91
|
+
* list grows left-to-right as each hop appends, so the last entry is the one
|
|
92
|
+
* the nearest trusted proxy (portr) wrote and every earlier entry is a value
|
|
93
|
+
* the caller could have sent. Reading the leftmost lets a client vary one
|
|
94
|
+
* header to get a fresh rate-limit bucket per request, which defeats both the
|
|
95
|
+
* per-IP code-request and verify-attempt limiters. Called BEFORE
|
|
96
|
+
* {@link HeaderPolicy.apply} strips the header, so the honest hop value is
|
|
97
|
+
* still available here.
|
|
98
|
+
*/
|
|
84
99
|
const clientIp = (req) => {
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
100
|
+
const forwarded = req.headers["x-forwarded-for"];
|
|
101
|
+
const chain = (Array.isArray(forwarded) ? forwarded.join(",") : (forwarded ?? ""))
|
|
102
|
+
.split(",")
|
|
103
|
+
.map((entry) => entry.trim())
|
|
104
|
+
.filter(Boolean);
|
|
105
|
+
return chain.at(-1) ?? req.socket.remoteAddress ?? "unknown";
|
|
88
106
|
};
|
|
89
107
|
/**
|
|
90
108
|
* Remove the gate's session cookie from the `Cookie` header before forwarding,
|
|
@@ -106,14 +124,38 @@ export function startProxy({ publicPort, appPort, gate }) {
|
|
|
106
124
|
};
|
|
107
125
|
/**
|
|
108
126
|
* Present an OTP-authenticated caller to the app the SAME way a platform front
|
|
109
|
-
* door does: set
|
|
110
|
-
*
|
|
111
|
-
* needs no gate-specific code path.
|
|
112
|
-
*
|
|
127
|
+
* door does: set the front door's own identity headers to the verified address
|
|
128
|
+
* (AppKit reads {@link token.USER_ID_HEADER} for the OBO user id), so the app
|
|
129
|
+
* needs no gate-specific code path. The names come from
|
|
130
|
+
* `@dbx-tools/shared-core`'s `token` module - the same constants AppKit-side
|
|
131
|
+
* code reads them by - rather than being re-spelled here.
|
|
132
|
+
*
|
|
133
|
+
* What the gate CANNOT set is {@link token.ACCESS_TOKEN_HEADER}: an OTP session
|
|
134
|
+
* proves an email address, not possession of a Databricks credential, and
|
|
135
|
+
* there is no way to mint one for the caller. Its absence is exactly what
|
|
136
|
+
* `@dbx-tools/appkit`'s `identity` `"auto"` mode detects, so a gated request
|
|
137
|
+
* runs as the app's service principal instead of throwing.
|
|
113
138
|
*/
|
|
114
139
|
const injectIdentity = (req, email) => {
|
|
115
|
-
req.headers[
|
|
116
|
-
req.headers[
|
|
140
|
+
req.headers[token.USER_ID_HEADER] = email;
|
|
141
|
+
req.headers[token.USER_EMAIL_HEADER] = email;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Apply the inbound-header policy to a tunnel request: every `x-` header the
|
|
145
|
+
* allow-list does not name is deleted, and the platform identity/transport set
|
|
146
|
+
* is deleted regardless. See `./headers.ts` for the reasoning; the
|
|
147
|
+
* security-critical case is {@link token.ACCESS_TOKEN_HEADER}, which the gate
|
|
148
|
+
* never sets but an app running `identity: "auto"` treats as proof the request
|
|
149
|
+
* can do OBO.
|
|
150
|
+
*
|
|
151
|
+
* `xfwd: true` on the proxy re-adds `x-forwarded-for`/`-proto`/`-port`/`-host`
|
|
152
|
+
* afterwards from the real socket, so the app still sees those - it just sees
|
|
153
|
+
* the honest values rather than the caller's claim.
|
|
154
|
+
*/
|
|
155
|
+
const applyHeaderPolicy = (req) => {
|
|
156
|
+
const removed = headerPolicy.apply(req.headers);
|
|
157
|
+
if (removed.length)
|
|
158
|
+
logger.debug("stripped inbound headers", { removed });
|
|
117
159
|
};
|
|
118
160
|
const server = createServer(async (req, res) => {
|
|
119
161
|
const path = (req.url ?? "/").split("?")[0];
|
|
@@ -147,10 +189,9 @@ export function startProxy({ publicPort, appPort, gate }) {
|
|
|
147
189
|
if (path === `${AUTH_PREFIX}/logout` && req.method === "POST") {
|
|
148
190
|
return sendJson(res, 200, { ok: true }, `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Max-Age=0`);
|
|
149
191
|
}
|
|
150
|
-
// Anti-spoof:
|
|
151
|
-
// gate may
|
|
152
|
-
|
|
153
|
-
delete req.headers["x-forwarded-email"];
|
|
192
|
+
// Anti-spoof: apply the inbound-header allow-list to portr traffic - only the
|
|
193
|
+
// gate may assert identity, and it does so below for a verified session.
|
|
194
|
+
applyHeaderPolicy(req);
|
|
154
195
|
// Static (non-API) loads freely so the SPA + <AuthGate> can render. Strip the
|
|
155
196
|
// session cookie so it never leaks to the static handler.
|
|
156
197
|
if (!path.startsWith("/api/")) {
|
|
@@ -179,8 +220,7 @@ export function startProxy({ publicPort, appPort, gate }) {
|
|
|
179
220
|
proxy.ws(req, socket, head);
|
|
180
221
|
return;
|
|
181
222
|
}
|
|
182
|
-
|
|
183
|
-
delete req.headers["x-forwarded-email"];
|
|
223
|
+
applyHeaderPolicy(req);
|
|
184
224
|
if (!(req.url ?? "").startsWith("/api/")) {
|
|
185
225
|
stripSessionCookie(req);
|
|
186
226
|
proxy.ws(req, socket, head);
|
|
@@ -204,4 +244,4 @@ export function startProxy({ publicPort, appPort, gate }) {
|
|
|
204
244
|
});
|
|
205
245
|
});
|
|
206
246
|
}
|
|
207
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFFSCxPQUFPLEVBQUUsWUFBWSxFQUE2QyxNQUFNLFdBQVcsQ0FBQztBQUVwRixPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNuRyxPQUFPLFdBQVcsTUFBTSxjQUFjLENBQUM7QUFHdkMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUUxQywyRUFBMkU7QUFDM0UsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7QUFFdEMsaUZBQWlGO0FBQ2pGLFNBQVMsVUFBVSxDQUFDLElBQXdCO0lBQzFDLElBQUksQ0FBQyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDeEIsMEVBQTBFO0lBQzFFLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLE9BQU8sQ0FBQyxLQUFLLFdBQVcsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxLQUFLLFdBQVcsQ0FBQztBQUN2RixDQUFDO0FBRUQsc0VBQXNFO0FBQ3RFLFNBQVMsUUFBUSxDQUFDLEdBQW9CO0lBQ3BDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUM3QixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7UUFDZCxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FB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QUFDLENBQUMsQ0FBQztJQUVILE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUM3QixNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFO1lBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMseUJBQXlCLFVBQVUscUJBQXFCLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDL0UsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHR1bm5lbCBnYXRlIHJldmVyc2UtcHJveHkuXG4gKlxuICogQmluZHMgdGhlIFBVQkxJQyBwb3J0ICh0aGUgY29udGFpbmVyJ3MgYERBVEFCUklDS1NfQVBQX1BPUlRgKSBhbmQgZm9yd2FyZHMgdG9cbiAqIHRoZSByZWFsIGFwcCBvbiBhIHByaXZhdGUgbG9vcGJhY2sgcG9ydC4gSXQgaXMgdGhlIHNpbmdsZSBmcm9udCBkb29yIGZvciBib3RoXG4gKiB0cmFmZmljIHBhdGhzIGludG8gdGhlIGNvbnRhaW5lcjpcbiAqXG4gKiAgIC0gKipwb3J0ciBjbGllbnQqKiAoc2FtZSBjb250YWluZXIsIGNvbm5lY3RzIG92ZXIgTE9PUEJBQ0spIC0gdGhlIHB1YmxpY1xuICogICAgIHR1bm5lbC4gVGhpcyBpcyB3aGF0IHRoZSBnYXRlIHByb3RlY3RzLlxuICogICAtICoqdGhlIGhvc3RpbmcgcGxhdGZvcm0ncyBmcm9udCBkb29yKiogKERhdGFicmlja3MgQXBwcycgY29udHJvbCBwbGFuZSwgb3JcbiAqICAgICBhbnkgb3RoZXIgaG9zdCByZWFjaGluZyB0aGUgYDAuMC4wLjBgIHBvcnQgZnJvbSBhIE5PTi1sb29wYmFja1xuICogICAgIGNvbnRhaW5lci1uZXR3b3JrIGFkZHJlc3MpIC0gcGFzc2VkIHRocm91Z2ggVU5HQVRFRCwgcGVyIHRoZSBydWxlIFwiaWYgaXQnc1xuICogICAgIG5vdCBmcm9tIHRoZSBwb3J0ciBjbGllbnQsIGxldCBpdCBpblwiLiBUaGUgcGxhdGZvcm0gYWxyZWFkeSBhdXRoZW50aWNhdGVzXG4gKiAgICAgdGhhdCBwYXRoOyB0aGUgZ2F0ZSBleGlzdHMgZm9yIHRoZSB0dW5uZWwsIHdoaWNoIG5vdGhpbmcgZWxzZSBwcm90ZWN0cy5cbiAqXG4gKiBUaGUgZGlzdGluZ3Vpc2hlciBpcyB0aGUgY29ubmVjdGlvbidzIHNvdXJjZSBhZGRyZXNzOiBhIGxvb3BiYWNrXG4gKiBgcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzYCBpcyB0aGUgcG9ydHIgY2xpZW50OyBhbnl0aGluZyBlbHNlIGlzIHRoZSBwbGF0Zm9ybS5cbiAqXG4gKiBGb3IgcG9ydHIgdHJhZmZpYyB0aGUgZ2F0ZSBpcyBhIHN0YW5kYXJkIFNQQSBnYXRlOiBzdGF0aWMgYXNzZXRzICsgdGhlIGxvZ2luXG4gKiBmbG93IChgL2FwaS9lbWFpbC9hdXRoLypgLCBhbnN3ZXJlZCBJTi1QUk9DRVNTIGJ5IHRoaXMgcHJveHkgdmlhIHRoZVxuICoge0BsaW5rIEF1dGhHYXRlQXBpfSkgYXJlIG9wZW4gc28gdGhlIGJyb3dzZXIgY2FuIGxvYWQgdGhlIGNsaWVudCBhbmQgcmVuZGVyIHRoZVxuICogYDxBdXRoR2F0ZT5gOyBldmVyeSBvdGhlciBgL2FwaS8qYCBuZWVkcyBhIHZhbGlkIHNlc3Npb24gY29va2llIG9yIGdldHMgNDAxLlxuICogV2ViU29ja2V0IHVwZ3JhZGVzIGFyZSBnYXRlZCB0aGUgc2FtZSB3YXkgYW5kIGZvcndhcmRlZCB3aXRoIGBodHRwLXByb3h5LTNgLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIsIHR5cGUgSW5jb21pbmdNZXNzYWdlLCB0eXBlIFNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHR5cGUgeyBTb2NrZXQgfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB7IGh0dHAsIGpzb24sIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBhdXRoUmVxdWVzdFNjaGVtYSwgYXV0aFZlcmlmeVNjaGVtYSwgU0VTU0lPTl9DT09LSUVfTkFNRSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1lbWFpbFwiO1xuaW1wb3J0IFByb3h5TW9kdWxlIGZyb20gXCJodHRwLXByb3h5LTNcIjtcbmltcG9ydCB0eXBlIHsgQXV0aEdhdGVBcGkgfSBmcm9tIFwiLi9wbHVnaW4udHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDpwcm94eVwiKTtcblxuLyoqIFJvdXRlIHByZWZpeCB0aGUgbG9naW4gZmxvdyBsaXZlcyB1bmRlciAob3BlbiwgYW5zd2VyZWQgaW4tcHJvY2VzcykuICovXG5jb25zdCBBVVRIX1BSRUZJWCA9IFwiL2FwaS9lbWFpbC9hdXRoXCI7XG5cbi8qKiBUcnVlIHdoZW4gYSBzb2NrZXQgYWRkcmVzcyBpcyBsb29wYmFjayAodGhlIHBvcnRyIGNsaWVudCwgc2FtZSBjb250YWluZXIpLiAqL1xuZnVuY3Rpb24gaXNMb29wYmFjayhhZGRyOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFhZGRyKSByZXR1cm4gZmFsc2U7XG4gIC8vIE5vcm1hbGl6ZSBJUHY0LW1hcHBlZCBJUHY2IChgOjpmZmZmOjEyNy4wLjAuMWApIGFuZCBiYXJlIElQdjYgbG9vcGJhY2suXG4gIGNvbnN0IGEgPSBhZGRyLnJlcGxhY2UoL146OmZmZmY6LywgXCJcIik7XG4gIHJldHVybiBhID09PSBcIjEyNy4wLjAuMVwiIHx8IGEuc3RhcnRzV2l0aChcIjEyNy5cIikgfHwgYSA9PT0gXCI6OjFcIiB8fCBhID09PSBcImxvY2FsaG9zdFwiO1xufVxuXG4vKiogUmVhZCB0aGUgd2hvbGUgcmVxdWVzdCBib2R5IGFzIHRleHQgKHNtYWxsIEpTT04gcGF5bG9hZHMgb25seSkuICovXG5mdW5jdGlvbiByZWFkQm9keShyZXE6IEluY29taW5nTWVzc2FnZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGxldCBkYXRhID0gXCJcIjtcbiAgICByZXEub24oXCJkYXRhXCIsIChjaHVuaykgPT4gKGRhdGEgKz0gY2h1bmspKTtcbiAgICByZXEub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gICAgcmVxLm9uKFwiZXJyb3JcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzZW5kSnNvbihyZXM6IFNlcnZlclJlc3BvbnNlLCBzdGF0dXM6IG51bWJlciwgYm9keTogdW5rbm93biwgc2V0Q29va2llPzogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7IFwiY29udGVudC10eXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH07XG4gIGlmIChzZXRDb29raWUpIGhlYWRlcnNbXCJzZXQtY29va2llXCJdID0gc2V0Q29va2llO1xuICByZXMud3JpdGVIZWFkKHN0YXR1cywgaGVhZGVycyk7XG4gIHJlcy5lbmQoSlNPTi5zdHJpbmdpZnkoYm9keSkpO1xufVxuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIHN0YXJ0UHJveHl9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm94eU9wdGlvbnMge1xuICAvKiogUHVibGljIHBvcnQgdG8gbGlzdGVuIG9uICh0aGUgY29udGFpbmVyJ3MgREFUQUJSSUNLU19BUFBfUE9SVCkuICovXG4gIHB1YmxpY1BvcnQ6IG51bWJlcjtcbiAgLyoqIFByaXZhdGUgcG9ydCB0aGUgcmVhbCBhcHAgbGlzdGVucyBvbiAobG9vcGJhY2spLiAqL1xuICBhcHBQb3J0OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgaW4tcHJvY2VzcyBnYXRlIEFQSSwgb3IgYHVuZGVmaW5lZGAgdG8gcnVuIE9QRU4gKGluc2VjdXJlIG1vZGUpOiBldmVyeVxuICAgKiByZXF1ZXN0IC0gaW5jbHVkaW5nIHBvcnRyIHRyYWZmaWMgLSBpcyBmb3J3YXJkZWQgdW5nYXRlZC4gVXNlZCB3aGVuIHRoZVxuICAgKiBvcGVyYXRvciBwYXNzZWQgYC0taW5zZWN1cmVgIC8gYFRVTk5FTF9JTlNFQ1VSRT10cnVlYC5cbiAgICovXG4gIGdhdGU/OiBBdXRoR2F0ZUFwaTtcbn1cblxuLyoqIFN0YXJ0IHRoZSBnYXRlIHByb3h5LiBSZXNvbHZlcyBvbmNlIGl0IGlzIGxpc3RlbmluZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGFydFByb3h5KHsgcHVibGljUG9ydCwgYXBwUG9ydCwgZ2F0ZSB9OiBQcm94eU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcHJveHkgPSBQcm94eU1vZHVsZS5jcmVhdGVQcm94eVNlcnZlcih7XG4gICAgdGFyZ2V0OiB7IGhvc3Q6IFwiMTI3LjAuMC4xXCIsIHBvcnQ6IGFwcFBvcnQgfSxcbiAgICB3czogdHJ1ZSxcbiAgICB4ZndkOiB0cnVlLFxuICB9KTtcbiAgcHJveHkub24oXCJlcnJvclwiLCAoZXJyOiBFcnJvciwgX3JlcTogdW5rbm93biwgcmVzOiB1bmtub3duKSA9PiB7XG4gICAgbG9nZ2VyLndhcm4oXCJ1cHN0cmVhbSBwcm94eSBlcnJvclwiLCB7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBjb25zdCByID0gcmVzIGFzIFNlcnZlclJlc3BvbnNlIHwgdW5kZWZpbmVkO1xuICAgIGlmIChyICYmIFwid3JpdGVIZWFkXCIgaW4gciAmJiAhci5oZWFkZXJzU2VudCkge1xuICAgICAgc2VuZEpzb24ociwgNTAyLCB7IGVycm9yOiBcInVwc3RyZWFtIHVuYXZhaWxhYmxlXCIgfSk7XG4gICAgfVxuICB9KTtcblxuICAvKiogVGhlIHNlc3Npb24gY29va2llIGZvciBhIHZlcmlmaWVkIGVtYWlsLCBhcyBhIFNldC1Db29raWUgc3RyaW5nLiAqL1xuICBjb25zdCBzZXNzaW9uQ29va2llID0gKHRva2VuOiBzdHJpbmcsIG1heEFnZVNlY29uZHM6IG51bWJlcik6IHN0cmluZyA9PlxuICAgIFtcbiAgICAgIGAke1NFU1NJT05fQ09PS0lFX05BTUV9PSR7dG9rZW59YCxcbiAgICAgIFwiUGF0aD0vXCIsXG4gICAgICBcIkh0dHBPbmx5XCIsXG4gICAgICBcIlNhbWVTaXRlPUxheFwiLFxuICAgICAgYE1heC1BZ2U9JHttYXhBZ2VTZWNvbmRzfWAsXG4gICAgICBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gXCJwcm9kdWN0aW9uXCIgPyBcIlNlY3VyZVwiIDogXCJcIixcbiAgICBdXG4gICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAuam9pbihcIjsgXCIpO1xuXG4gIC8qKiBDbGllbnQgSVAgZm9yIHJhdGUtbGltaXRpbmc6IHRoZSBwb3J0ci1mb3J3YXJkZWQgWEZGLCBlbHNlIHRoZSBzb2NrZXQuICovXG4gIGNvbnN0IGNsaWVudElwID0gKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCBmd2QgPSByZXEuaGVhZGVyc1tcIngtZm9yd2FyZGVkLWZvclwiXTtcbiAgICBjb25zdCBmaXJzdCA9IEFycmF5LmlzQXJyYXkoZndkKSA/IGZ3ZFswXSA6IGZ3ZD8uc3BsaXQoXCIsXCIpWzBdO1xuICAgIHJldHVybiAoZmlyc3QgPz8gcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzID8/IFwidW5rbm93blwiKS50cmltKCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgZ2F0ZSdzIHNlc3Npb24gY29va2llIGZyb20gdGhlIGBDb29raWVgIGhlYWRlciBiZWZvcmUgZm9yd2FyZGluZyxcbiAgICogc28gdGhlIGFwcCBuZXZlciBzZWVzIGBkYnhfYXV0aGAgKGl0IGlzIHRoZSBwcm94eSdzIGNvbmNlcm4sIG5vdCB0aGUgYXBwJ3MpLlxuICAgKiBQcmVzZXJ2ZXMgYW55IG90aGVyIGNvb2tpZXMuIFJlbW92ZXMgdGhlIGhlYWRlciBlbnRpcmVseSB3aGVuIGl0IGJlY29tZXMgZW1wdHkuXG4gICAqL1xuICBjb25zdCBzdHJpcFNlc3Npb25Db29raWUgPSAocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiB2b2lkID0+IHtcbiAgICBjb25zdCByYXcgPSByZXEuaGVhZGVycy5jb29raWU7XG4gICAgaWYgKCFyYXcpIHJldHVybjtcbiAgICBjb25zdCBrZXB0ID0gcmF3XG4gICAgICAuc3BsaXQoXCI7XCIpXG4gICAgICAubWFwKChjKSA9PiBjLnRyaW0oKSlcbiAgICAgIC5maWx0ZXIoKGMpID0+IGMgJiYgIWMuc3RhcnRzV2l0aChgJHtTRVNTSU9OX0NPT0tJRV9OQU1FfT1gKSk7XG4gICAgaWYgKGtlcHQubGVuZ3RoKSByZXEuaGVhZGVycy5jb29raWUgPSBrZXB0LmpvaW4oXCI7IFwiKTtcbiAgICBlbHNlIGRlbGV0ZSByZXEuaGVhZGVycy5jb29raWU7XG4gIH07XG5cbiAgLyoqXG4gICAqIFByZXNlbnQgYW4gT1RQLWF1dGhlbnRpY2F0ZWQgY2FsbGVyIHRvIHRoZSBhcHAgdGhlIFNBTUUgd2F5IGEgcGxhdGZvcm0gZnJvbnRcbiAgICogZG9vciBkb2VzOiBzZXQgYHgtZm9yd2FyZGVkLXVzZXJgIC8gYHgtZm9yd2FyZGVkLWVtYWlsYCB0byB0aGUgdmVyaWZpZWRcbiAgICogYWRkcmVzcyAoQXBwS2l0IHJlYWRzIGB4LWZvcndhcmRlZC11c2VyYCBmb3IgdGhlIE9CTyB1c2VyIGlkKSwgc28gdGhlIGFwcFxuICAgKiBuZWVkcyBubyBnYXRlLXNwZWNpZmljIGNvZGUgcGF0aC4gQW55IGluYm91bmQgY29waWVzIGFyZSBvdmVyd3JpdHRlbiBzbyBhXG4gICAqIGNsaWVudCBjYW4ndCBzcG9vZiBpZGVudGl0eSB0aHJvdWdoIHRoZSBnYXRlLlxuICAgKi9cbiAgY29uc3QgaW5qZWN0SWRlbnRpdHkgPSAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIGVtYWlsOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICByZXEuaGVhZGVyc1tcIngtZm9yd2FyZGVkLXVzZXJcIl0gPSBlbWFpbDtcbiAgICByZXEuaGVhZGVyc1tcIngtZm9yd2FyZGVkLWVtYWlsXCJdID0gZW1haWw7XG4gIH07XG5cbiAgY29uc3Qgc2VydmVyID0gY3JlYXRlU2VydmVyKGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdITtcblxuICAgIC8vIEluc2VjdXJlL29wZW4gbW9kZSAobm8gZ2F0ZSkgT1Igbm9uLWxvb3BiYWNrIHRyYWZmaWMgKHRoZSBob3N0aW5nXG4gICAgLy8gcGxhdGZvcm0ncyBmcm9udCBkb29yIC8gY29udHJvbCBwbGFuZSk6IGZvcndhcmQgdW5nYXRlZC5cbiAgICBpZiAoIWdhdGUgfHwgIWlzTG9vcGJhY2socmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzKSkge1xuICAgICAgcHJveHkud2ViKHJlcSwgcmVzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyAtLS0gcG9ydHIgdHJhZmZpYzogdGhlIGdhdGUgYXBwbGllcyAtLS1cblxuICAgIC8vIFRoZSBsb2dpbiBmbG93IGlzIGFuc3dlcmVkIElOLVBST0NFU1MgKHRoZSBhcHAgaGFzIG5vIHNlcnZlciB0byBmb3J3YXJkIHRvKS5cbiAgICBpZiAocGF0aCA9PT0gYCR7QVVUSF9QUkVGSVh9L3N0YXR1c2ApIHtcbiAgICAgIGNvbnN0IHRva2VuID0gaHR0cC5wYXJzZUNvb2tpZXMocmVxLmhlYWRlcnMuY29va2llID8/IG51bGwpW1NFU1NJT05fQ09PS0lFX05BTUVdO1xuICAgICAgc2VuZEpzb24ocmVzLCAyMDAsIGF3YWl0IGdhdGUuc3RhdHVzKHRva2VuKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChwYXRoID09PSBgJHtBVVRIX1BSRUZJWH0vcmVxdWVzdGAgJiYgcmVxLm1ldGhvZCA9PT0gXCJQT1NUXCIpIHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IGF1dGhSZXF1ZXN0U2NoZW1hLnNhZmVQYXJzZShqc29uLnBhcnNlUmVjb3JkKGF3YWl0IHJlYWRCb2R5KHJlcSkpKTtcbiAgICAgIGlmICghcGFyc2VkLnN1Y2Nlc3MpIHJldHVybiBzZW5kSnNvbihyZXMsIDIwMCwgeyBvazogdHJ1ZSB9KTsgLy8gYW50aS1lbnVtZXJhdGlvblxuICAgICAgcmV0dXJuIHNlbmRKc29uKHJlcywgMjAwLCBhd2FpdCBnYXRlLnJlcXVlc3QocGFyc2VkLmRhdGEuZW1haWwsIGNsaWVudElwKHJlcSkpKTtcbiAgICB9XG4gICAgaWYgKHBhdGggPT09IGAke0FVVEhfUFJFRklYfS92ZXJpZnlgICYmIHJlcS5tZXRob2QgPT09IFwiUE9TVFwiKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBhdXRoVmVyaWZ5U2NoZW1hLnNhZmVQYXJzZShqc29uLnBhcnNlUmVjb3JkKGF3YWl0IHJlYWRCb2R5KHJlcSkpKTtcbiAgICAgIGlmICghcGFyc2VkLnN1Y2Nlc3MpIHJldHVybiBzZW5kSnNvbihyZXMsIDIwMCwgeyBvazogZmFsc2UgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnYXRlLnZlcmlmeShwYXJzZWQuZGF0YS5lbWFpbCwgcGFyc2VkLmRhdGEuY29kZSwgY2xpZW50SXAocmVxKSk7XG4gICAgICBjb25zdCBjb29raWUgPVxuICAgICAgICByZXN1bHQub2sgJiYgcmVzdWx0LnRva2VuID8gc2Vzc2lvbkNvb2tpZShyZXN1bHQudG9rZW4sIGdhdGUuc2Vzc2lvblR0bFNlY29uZHMpIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHNlbmRKc29uKFxuICAgICAgICByZXMsXG4gICAgICAgIDIwMCxcbiAgICAgICAgeyBvazogcmVzdWx0Lm9rLCAuLi4ocmVzdWx0LnJldHJ5QWZ0ZXIgPyB7IHJldHJ5QWZ0ZXI6IHJlc3VsdC5yZXRyeUFmdGVyIH0gOiB7fSkgfSxcbiAgICAgICAgY29va2llLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHBhdGggPT09IGAke0FVVEhfUFJFRklYfS9sb2dvdXRgICYmIHJlcS5tZXRob2QgPT09IFwiUE9TVFwiKSB7XG4gICAgICByZXR1cm4gc2VuZEpzb24oXG4gICAgICAgIHJlcyxcbiAgICAgICAgMjAwLFxuICAgICAgICB7IG9rOiB0cnVlIH0sXG4gICAgICAgIGAke1NFU1NJT05fQ09PS0lFX05BTUV9PTsgUGF0aD0vOyBIdHRwT25seTsgTWF4LUFnZT0wYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQW50aS1zcG9vZjogc3RyaXAgYW55IGluYm91bmQgaWRlbnRpdHkgaGVhZGVycyBvbiBwb3J0ciB0cmFmZmljIC0gb25seSB0aGVcbiAgICAvLyBnYXRlIG1heSBzZXQgdGhlbSwgYmVsb3csIGZvciBhIHZlcmlmaWVkIHNlc3Npb24uXG4gICAgZGVsZXRlIHJlcS5oZWFkZXJzW1wieC1mb3J3YXJkZWQtdXNlclwiXTtcbiAgICBkZWxldGUgcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1lbWFpbFwiXTtcblxuICAgIC8vIFN0YXRpYyAobm9uLUFQSSkgbG9hZHMgZnJlZWx5IHNvIHRoZSBTUEEgKyA8QXV0aEdhdGU+IGNhbiByZW5kZXIuIFN0cmlwIHRoZVxuICAgIC8vIHNlc3Npb24gY29va2llIHNvIGl0IG5ldmVyIGxlYWtzIHRvIHRoZSBzdGF0aWMgaGFuZGxlci5cbiAgICBpZiAoIXBhdGguc3RhcnRzV2l0aChcIi9hcGkvXCIpKSB7XG4gICAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICAgIHByb3h5LndlYihyZXEsIHJlcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRXZlcnkgb3RoZXIgL2FwaS8qIHJlcXVpcmVzIGEgdmFsaWQgc2Vzc2lvbi5cbiAgICBjb25zdCB0b2tlbiA9IGh0dHAucGFyc2VDb29raWVzKHJlcS5oZWFkZXJzLmNvb2tpZSA/PyBudWxsKVtTRVNTSU9OX0NPT0tJRV9OQU1FXTtcbiAgICBjb25zdCBlbWFpbCA9IGF3YWl0IGdhdGUuc2Vzc2lvbih0b2tlbik7XG4gICAgaWYgKGVtYWlsKSB7XG4gICAgICAvLyBQcmVzZW50IHRoZSBPVFAgdXNlciBsaWtlIGEgcGxhdGZvcm0gZnJvbnQgZG9vciwgYW5kIGRyb3AgdGhlIGdhdGVcbiAgICAgIC8vIGNvb2tpZSBzbyB0aGUgYXBwIHNlZXMgYSBjbGVhbiwgZnJvbnQtZG9vci1zaGFwZWQgcmVxdWVzdC5cbiAgICAgIGluamVjdElkZW50aXR5KHJlcSwgZW1haWwpO1xuICAgICAgc3RyaXBTZXNzaW9uQ29va2llKHJlcSk7XG4gICAgICBwcm94eS53ZWIocmVxLCByZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZW5kSnNvbihyZXMsIDQwMSwgeyBlcnJvcjogXCJhdXRoZW50aWNhdGlvbiByZXF1aXJlZFwiLCBsb2dpblBhdGg6IEFVVEhfUFJFRklYIH0pO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gV2ViU29ja2V0IHVwZ3JhZGVzOiBmb3J3YXJkIGZyb250LWRvb3IgdHJhZmZpYyB1bnRvdWNoZWQ7IGdhdGUgbG9vcGJhY2tcbiAgLy8gKHBvcnRyKSBBUEkgdXBncmFkZXMgdGhlIHNhbWUgd2F5IGFzIEhUVFAgKHN0cmlwIGNvb2tpZSArIGluamVjdCBpZGVudGl0eSkuXG4gIHNlcnZlci5vbihcInVwZ3JhZGVcIiwgKHJlcTogSW5jb21pbmdNZXNzYWdlLCBzb2NrZXQ6IFNvY2tldCwgaGVhZDogQnVmZmVyKSA9PiB7XG4gICAgaWYgKCFnYXRlIHx8ICFpc0xvb3BiYWNrKHJlcS5zb2NrZXQucmVtb3RlQWRkcmVzcykpIHtcbiAgICAgIHByb3h5LndzKHJlcSwgc29ja2V0LCBoZWFkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZGVsZXRlIHJlcS5oZWFkZXJzW1wieC1mb3J3YXJkZWQtdXNlclwiXTtcbiAgICBkZWxldGUgcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1lbWFpbFwiXTtcbiAgICBpZiAoIShyZXEudXJsID8/IFwiXCIpLnN0YXJ0c1dpdGgoXCIvYXBpL1wiKSkge1xuICAgICAgc3RyaXBTZXNzaW9uQ29va2llKHJlcSk7XG4gICAgICBwcm94eS53cyhyZXEsIHNvY2tldCwgaGVhZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRva2VuID0gaHR0cC5wYXJzZUNvb2tpZXMocmVxLmhlYWRlcnMuY29va2llID8/IG51bGwpW1NFU1NJT05fQ09PS0lFX05BTUVdO1xuICAgIHZvaWQgZ2F0ZS5zZXNzaW9uKHRva2VuKS50aGVuKChlbWFpbCkgPT4ge1xuICAgICAgaWYgKCFlbWFpbCkge1xuICAgICAgICBzb2NrZXQuZGVzdHJveSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpbmplY3RJZGVudGl0eShyZXEsIGVtYWlsKTtcbiAgICAgIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICAgICAgcHJveHkud3MocmVxLCBzb2NrZXQsIGhlYWQpO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBzZXJ2ZXIubGlzdGVuKHB1YmxpY1BvcnQsIFwiMC4wLjAuMFwiLCAoKSA9PiB7XG4gICAgICBsb2dnZXIuaW5mbyhgZ2F0ZSBwcm94eSBvbiAwLjAuMC4wOiR7cHVibGljUG9ydH0gLT4gYXBwIDEyNy4wLjAuMToke2FwcFBvcnR9YCk7XG4gICAgICByZXNvbHZlKCk7XG4gICAgfSk7XG4gIH0pO1xufVxuIl19
|
|
247
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJveHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJveHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFFSCxPQUFPLEVBQUUsWUFBWSxFQUE2QyxNQUFNLFdBQVcsQ0FBQztBQUVwRixPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkcsT0FBTyxXQUFXLE1BQU0sY0FBYyxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxjQUFjLEVBQXFCLE1BQU0sY0FBYyxDQUFDO0FBR2pFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7QUFFMUMsMkVBQTJFO0FBQzNFLE1BQU0sV0FBVyxHQUFHLGlCQUFpQixDQUFDO0FBRXRDLGlGQUFpRjtBQUNqRixTQUFTLFVBQVUsQ0FBQyxJQUF3QjtJQUMxQyxJQUFJLENBQUMsSUFBSTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3hCLDBFQUEwRTtJQUMxRSxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2QyxPQUFPLENBQUMsS0FBSyxXQUFXLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsS0FBSyxXQUFXLENBQUM7QUFDdkYsQ0FBQztBQUVELHNFQUFzRTtBQUN0RSxTQUFTLFFBQVEsQ0FBQyxHQUFvQjtJQUNwQyxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7UUFDN0IsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2QsR0FBRyxD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LEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDNUIsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDakYsS0FBSyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2pCLE9BQU87WUFDVCxDQUFDO1lBQ0QsY0FBYyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMzQixrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN4QixLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUM3QixNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFO1lBQ3hDLE1BQU0sQ0FBQyxJQUFJLENBQUMseUJBQXlCLFVBQVUscUJBQXFCLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDL0UsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHR1bm5lbCBnYXRlIHJldmVyc2UtcHJveHkuXG4gKlxuICogQmluZHMgdGhlIFBVQkxJQyBwb3J0ICh0aGUgY29udGFpbmVyJ3MgYERBVEFCUklDS1NfQVBQX1BPUlRgKSBhbmQgZm9yd2FyZHMgdG9cbiAqIHRoZSByZWFsIGFwcCBvbiBhIHByaXZhdGUgbG9vcGJhY2sgcG9ydC4gSXQgaXMgdGhlIHNpbmdsZSBmcm9udCBkb29yIGZvciBib3RoXG4gKiB0cmFmZmljIHBhdGhzIGludG8gdGhlIGNvbnRhaW5lcjpcbiAqXG4gKiAgIC0gKipwb3J0ciBjbGllbnQqKiAoc2FtZSBjb250YWluZXIsIGNvbm5lY3RzIG92ZXIgTE9PUEJBQ0spIC0gdGhlIHB1YmxpY1xuICogICAgIHR1bm5lbC4gVGhpcyBpcyB3aGF0IHRoZSBnYXRlIHByb3RlY3RzLlxuICogICAtICoqdGhlIGhvc3RpbmcgcGxhdGZvcm0ncyBmcm9udCBkb29yKiogKERhdGFicmlja3MgQXBwcycgY29udHJvbCBwbGFuZSwgb3JcbiAqICAgICBhbnkgb3RoZXIgaG9zdCByZWFjaGluZyB0aGUgYDAuMC4wLjBgIHBvcnQgZnJvbSBhIE5PTi1sb29wYmFja1xuICogICAgIGNvbnRhaW5lci1uZXR3b3JrIGFkZHJlc3MpIC0gcGFzc2VkIHRocm91Z2ggVU5HQVRFRCwgcGVyIHRoZSBydWxlIFwiaWYgaXQnc1xuICogICAgIG5vdCBmcm9tIHRoZSBwb3J0ciBjbGllbnQsIGxldCBpdCBpblwiLiBUaGUgcGxhdGZvcm0gYWxyZWFkeSBhdXRoZW50aWNhdGVzXG4gKiAgICAgdGhhdCBwYXRoOyB0aGUgZ2F0ZSBleGlzdHMgZm9yIHRoZSB0dW5uZWwsIHdoaWNoIG5vdGhpbmcgZWxzZSBwcm90ZWN0cy5cbiAqXG4gKiBUaGUgZGlzdGluZ3Vpc2hlciBpcyB0aGUgY29ubmVjdGlvbidzIHNvdXJjZSBhZGRyZXNzOiBhIGxvb3BiYWNrXG4gKiBgcmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzYCBpcyB0aGUgcG9ydHIgY2xpZW50OyBhbnl0aGluZyBlbHNlIGlzIHRoZSBwbGF0Zm9ybS5cbiAqXG4gKiBGb3IgcG9ydHIgdHJhZmZpYyB0aGUgZ2F0ZSBpcyBhIHN0YW5kYXJkIFNQQSBnYXRlOiBzdGF0aWMgYXNzZXRzICsgdGhlIGxvZ2luXG4gKiBmbG93IChgL2FwaS9lbWFpbC9hdXRoLypgLCBhbnN3ZXJlZCBJTi1QUk9DRVNTIGJ5IHRoaXMgcHJveHkgdmlhIHRoZVxuICoge0BsaW5rIEF1dGhHYXRlQXBpfSkgYXJlIG9wZW4gc28gdGhlIGJyb3dzZXIgY2FuIGxvYWQgdGhlIGNsaWVudCBhbmQgcmVuZGVyIHRoZVxuICogYDxBdXRoR2F0ZT5gOyBldmVyeSBvdGhlciBgL2FwaS8qYCBuZWVkcyBhIHZhbGlkIHNlc3Npb24gY29va2llIG9yIGdldHMgNDAxLlxuICogV2ViU29ja2V0IHVwZ3JhZGVzIGFyZSBnYXRlZCB0aGUgc2FtZSB3YXkgYW5kIGZvcndhcmRlZCB3aXRoIGBodHRwLXByb3h5LTNgLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIsIHR5cGUgSW5jb21pbmdNZXNzYWdlLCB0eXBlIFNlcnZlclJlc3BvbnNlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHR5cGUgeyBTb2NrZXQgfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB7IGh0dHAsIGpzb24sIGxvZywgdG9rZW4gfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgYXV0aFJlcXVlc3RTY2hlbWEsIGF1dGhWZXJpZnlTY2hlbWEsIFNFU1NJT05fQ09PS0lFX05BTUUgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZW1haWxcIjtcbmltcG9ydCBQcm94eU1vZHVsZSBmcm9tIFwiaHR0cC1wcm94eS0zXCI7XG5pbXBvcnQgeyB0b0hlYWRlclBvbGljeSwgdHlwZSBIZWFkZXJQb2xpY3kgfSBmcm9tIFwiLi9oZWFkZXJzLnRzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhHYXRlQXBpIH0gZnJvbSBcIi4vcGx1Z2luLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6cHJveHlcIik7XG5cbi8qKiBSb3V0ZSBwcmVmaXggdGhlIGxvZ2luIGZsb3cgbGl2ZXMgdW5kZXIgKG9wZW4sIGFuc3dlcmVkIGluLXByb2Nlc3MpLiAqL1xuY29uc3QgQVVUSF9QUkVGSVggPSBcIi9hcGkvZW1haWwvYXV0aFwiO1xuXG4vKiogVHJ1ZSB3aGVuIGEgc29ja2V0IGFkZHJlc3MgaXMgbG9vcGJhY2sgKHRoZSBwb3J0ciBjbGllbnQsIHNhbWUgY29udGFpbmVyKS4gKi9cbmZ1bmN0aW9uIGlzTG9vcGJhY2soYWRkcjogc3RyaW5nIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIGlmICghYWRkcikgcmV0dXJuIGZhbHNlO1xuICAvLyBOb3JtYWxpemUgSVB2NC1tYXBwZWQgSVB2NiAoYDo6ZmZmZjoxMjcuMC4wLjFgKSBhbmQgYmFyZSBJUHY2IGxvb3BiYWNrLlxuICBjb25zdCBhID0gYWRkci5yZXBsYWNlKC9eOjpmZmZmOi8sIFwiXCIpO1xuICByZXR1cm4gYSA9PT0gXCIxMjcuMC4wLjFcIiB8fCBhLnN0YXJ0c1dpdGgoXCIxMjcuXCIpIHx8IGEgPT09IFwiOjoxXCIgfHwgYSA9PT0gXCJsb2NhbGhvc3RcIjtcbn1cblxuLyoqIFJlYWQgdGhlIHdob2xlIHJlcXVlc3QgYm9keSBhcyB0ZXh0IChzbWFsbCBKU09OIHBheWxvYWRzIG9ubHkpLiAqL1xuZnVuY3Rpb24gcmVhZEJvZHkocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBQcm9taXNlPHN0cmluZz4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBsZXQgZGF0YSA9IFwiXCI7XG4gICAgcmVxLm9uKFwiZGF0YVwiLCAoY2h1bmspID0+IChkYXRhICs9IGNodW5rKSk7XG4gICAgcmVxLm9uKFwiZW5kXCIsICgpID0+IHJlc29sdmUoZGF0YSkpO1xuICAgIHJlcS5vbihcImVycm9yXCIsICgpID0+IHJlc29sdmUoZGF0YSkpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc2VuZEpzb24ocmVzOiBTZXJ2ZXJSZXNwb25zZSwgc3RhdHVzOiBudW1iZXIsIGJvZHk6IHVua25vd24sIHNldENvb2tpZT86IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0geyBcImNvbnRlbnQtdHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIiB9O1xuICBpZiAoc2V0Q29va2llKSBoZWFkZXJzW1wic2V0LWNvb2tpZVwiXSA9IHNldENvb2tpZTtcbiAgcmVzLndyaXRlSGVhZChzdGF0dXMsIGhlYWRlcnMpO1xuICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KGJvZHkpKTtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayBzdGFydFByb3h5fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJveHlPcHRpb25zIHtcbiAgLyoqIFB1YmxpYyBwb3J0IHRvIGxpc3RlbiBvbiAodGhlIGNvbnRhaW5lcidzIERBVEFCUklDS1NfQVBQX1BPUlQpLiAqL1xuICBwdWJsaWNQb3J0OiBudW1iZXI7XG4gIC8qKiBQcml2YXRlIHBvcnQgdGhlIHJlYWwgYXBwIGxpc3RlbnMgb24gKGxvb3BiYWNrKS4gKi9cbiAgYXBwUG9ydDogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEksIG9yIGB1bmRlZmluZWRgIHRvIHJ1biBPUEVOIChpbnNlY3VyZSBtb2RlKTogZXZlcnlcbiAgICogcmVxdWVzdCAtIGluY2x1ZGluZyBwb3J0ciB0cmFmZmljIC0gaXMgZm9yd2FyZGVkIHVuZ2F0ZWQuIFVzZWQgd2hlbiB0aGVcbiAgICogb3BlcmF0b3IgcGFzc2VkIGAtLWluc2VjdXJlYCAvIGBUVU5ORUxfSU5TRUNVUkU9dHJ1ZWAuXG4gICAqL1xuICBnYXRlPzogQXV0aEdhdGVBcGk7XG4gIC8qKlxuICAgKiBFeHRyYSBgeC1gIHJlcXVlc3QgaGVhZGVycyB0dW5uZWwgdHJhZmZpYyBtYXkgZm9yd2FyZCwgYXMgbGl0ZXJhbHMsIGdsb2JzLCBvclxuICAgKiBgL3JlZ2V4L2BlcyAtIHVuaW9uZWQgd2l0aCB7QGxpbmsgREVGQVVMVF9GT1JXQVJEX0hFQURFUlN9LiBFdmVyeSBvdGhlciBgeC1gXG4gICAqIGhlYWRlciBpcyBzdHJpcHBlZCwgYW5kIHtAbGluayBQUk9URUNURURfSEVBREVSU30gaXMgc3RyaXBwZWQgcmVnYXJkbGVzcy4gU2VlXG4gICAqIGAuL2hlYWRlcnMudHNgIGZvciB3aHkgdGhlIHBvbGljeSBpcyBhbiBhbGxvdy1saXN0LlxuICAgKi9cbiAgZm9yd2FyZEhlYWRlcnM/OiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqIFN0YXJ0IHRoZSBnYXRlIHByb3h5LiBSZXNvbHZlcyBvbmNlIGl0IGlzIGxpc3RlbmluZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGFydFByb3h5KHtcbiAgcHVibGljUG9ydCxcbiAgYXBwUG9ydCxcbiAgZ2F0ZSxcbiAgZm9yd2FyZEhlYWRlcnMsXG59OiBQcm94eU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcHJveHkgPSBQcm94eU1vZHVsZS5jcmVhdGVQcm94eVNlcnZlcih7XG4gICAgdGFyZ2V0OiB7IGhvc3Q6IFwiMTI3LjAuMC4xXCIsIHBvcnQ6IGFwcFBvcnQgfSxcbiAgICB3czogdHJ1ZSxcbiAgICB4ZndkOiB0cnVlLFxuICB9KTtcbiAgcHJveHkub24oXCJlcnJvclwiLCAoZXJyOiBFcnJvciwgX3JlcTogdW5rbm93biwgcmVzOiB1bmtub3duKSA9PiB7XG4gICAgbG9nZ2VyLndhcm4oXCJ1cHN0cmVhbSBwcm94eSBlcnJvclwiLCB7IGVycm9yOiBlcnIubWVzc2FnZSB9KTtcbiAgICBjb25zdCByID0gcmVzIGFzIFNlcnZlclJlc3BvbnNlIHwgdW5kZWZpbmVkO1xuICAgIGlmIChyICYmIFwid3JpdGVIZWFkXCIgaW4gciAmJiAhci5oZWFkZXJzU2VudCkge1xuICAgICAgc2VuZEpzb24ociwgNTAyLCB7IGVycm9yOiBcInVwc3RyZWFtIHVuYXZhaWxhYmxlXCIgfSk7XG4gICAgfVxuICB9KTtcblxuICAvLyBDb21waWxlZCBvbmNlOiB0aGUgaW5ib3VuZC1oZWFkZXIgYWxsb3ctbGlzdCBhcHBsaWVkIHRvIGV2ZXJ5IGdhdGVkIHJlcXVlc3QuXG4gIGNvbnN0IGhlYWRlclBvbGljeSA9IHRvSGVhZGVyUG9saWN5KGZvcndhcmRIZWFkZXJzKTtcbiAgbG9nZ2VyLmRlYnVnKFwiaW5ib3VuZCBoZWFkZXIgcG9saWN5XCIsIHsgZm9yd2FyZDogaGVhZGVyUG9saWN5LnBhdHRlcm5zIH0pO1xuXG4gIC8qKiBUaGUgc2Vzc2lvbiBjb29raWUgZm9yIGEgdmVyaWZpZWQgZW1haWwsIGFzIGEgU2V0LUNvb2tpZSBzdHJpbmcuICovXG4gIGNvbnN0IHNlc3Npb25Db29raWUgPSAodG9rZW46IHN0cmluZywgbWF4QWdlU2Vjb25kczogbnVtYmVyKTogc3RyaW5nID0+XG4gICAgW1xuICAgICAgYCR7U0VTU0lPTl9DT09LSUVfTkFNRX09JHt0b2tlbn1gLFxuICAgICAgXCJQYXRoPS9cIixcbiAgICAgIFwiSHR0cE9ubHlcIixcbiAgICAgIFwiU2FtZVNpdGU9TGF4XCIsXG4gICAgICBgTWF4LUFnZT0ke21heEFnZVNlY29uZHN9YCxcbiAgICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBcInByb2R1Y3Rpb25cIiA/IFwiU2VjdXJlXCIgOiBcIlwiLFxuICAgIF1cbiAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgIC5qb2luKFwiOyBcIik7XG5cbiAgLyoqXG4gICAqIENsaWVudCBJUCBmb3IgcmF0ZS1saW1pdGluZzogdGhlIHBvcnRyIGNsaWVudCdzIGZvcndhcmRlZCBYRkYsIGVsc2UgdGhlIHNvY2tldC5cbiAgICpcbiAgICogRGVsaWJlcmF0ZWx5IHRoZSBSSUdIVE1PU1QgYHgtZm9yd2FyZGVkLWZvcmAgZW50cnksIG5vdCB0aGUgbGVmdG1vc3QuIFRoZVxuICAgKiBsaXN0IGdyb3dzIGxlZnQtdG8tcmlnaHQgYXMgZWFjaCBob3AgYXBwZW5kcywgc28gdGhlIGxhc3QgZW50cnkgaXMgdGhlIG9uZVxuICAgKiB0aGUgbmVhcmVzdCB0cnVzdGVkIHByb3h5IChwb3J0cikgd3JvdGUgYW5kIGV2ZXJ5IGVhcmxpZXIgZW50cnkgaXMgYSB2YWx1ZVxuICAgKiB0aGUgY2FsbGVyIGNvdWxkIGhhdmUgc2VudC4gUmVhZGluZyB0aGUgbGVmdG1vc3QgbGV0cyBhIGNsaWVudCB2YXJ5IG9uZVxuICAgKiBoZWFkZXIgdG8gZ2V0IGEgZnJlc2ggcmF0ZS1saW1pdCBidWNrZXQgcGVyIHJlcXVlc3QsIHdoaWNoIGRlZmVhdHMgYm90aCB0aGVcbiAgICogcGVyLUlQIGNvZGUtcmVxdWVzdCBhbmQgdmVyaWZ5LWF0dGVtcHQgbGltaXRlcnMuIENhbGxlZCBCRUZPUkVcbiAgICoge0BsaW5rIEhlYWRlclBvbGljeS5hcHBseX0gc3RyaXBzIHRoZSBoZWFkZXIsIHNvIHRoZSBob25lc3QgaG9wIHZhbHVlIGlzXG4gICAqIHN0aWxsIGF2YWlsYWJsZSBoZXJlLlxuICAgKi9cbiAgY29uc3QgY2xpZW50SXAgPSAocmVxOiBJbmNvbWluZ01lc3NhZ2UpOiBzdHJpbmcgPT4ge1xuICAgIGNvbnN0IGZvcndhcmRlZCA9IHJlcS5oZWFkZXJzW1wieC1mb3J3YXJkZWQtZm9yXCJdO1xuICAgIGNvbnN0IGNoYWluID0gKEFycmF5LmlzQXJyYXkoZm9yd2FyZGVkKSA/IGZvcndhcmRlZC5qb2luKFwiLFwiKSA6IChmb3J3YXJkZWQgPz8gXCJcIikpXG4gICAgICAuc3BsaXQoXCIsXCIpXG4gICAgICAubWFwKChlbnRyeSkgPT4gZW50cnkudHJpbSgpKVxuICAgICAgLmZpbHRlcihCb29sZWFuKTtcbiAgICByZXR1cm4gY2hhaW4uYXQoLTEpID8/IHJlcS5zb2NrZXQucmVtb3RlQWRkcmVzcyA/PyBcInVua25vd25cIjtcbiAgfTtcblxuICAvKipcbiAgICogUmVtb3ZlIHRoZSBnYXRlJ3Mgc2Vzc2lvbiBjb29raWUgZnJvbSB0aGUgYENvb2tpZWAgaGVhZGVyIGJlZm9yZSBmb3J3YXJkaW5nLFxuICAgKiBzbyB0aGUgYXBwIG5ldmVyIHNlZXMgYGRieF9hdXRoYCAoaXQgaXMgdGhlIHByb3h5J3MgY29uY2Vybiwgbm90IHRoZSBhcHAncykuXG4gICAqIFByZXNlcnZlcyBhbnkgb3RoZXIgY29va2llcy4gUmVtb3ZlcyB0aGUgaGVhZGVyIGVudGlyZWx5IHdoZW4gaXQgYmVjb21lcyBlbXB0eS5cbiAgICovXG4gIGNvbnN0IHN0cmlwU2Vzc2lvbkNvb2tpZSA9IChyZXE6IEluY29taW5nTWVzc2FnZSk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IHJhdyA9IHJlcS5oZWFkZXJzLmNvb2tpZTtcbiAgICBpZiAoIXJhdykgcmV0dXJuO1xuICAgIGNvbnN0IGtlcHQgPSByYXdcbiAgICAgIC5zcGxpdChcIjtcIilcbiAgICAgIC5tYXAoKGMpID0+IGMudHJpbSgpKVxuICAgICAgLmZpbHRlcigoYykgPT4gYyAmJiAhYy5zdGFydHNXaXRoKGAke1NFU1NJT05fQ09PS0lFX05BTUV9PWApKTtcbiAgICBpZiAoa2VwdC5sZW5ndGgpIHJlcS5oZWFkZXJzLmNvb2tpZSA9IGtlcHQuam9pbihcIjsgXCIpO1xuICAgIGVsc2UgZGVsZXRlIHJlcS5oZWFkZXJzLmNvb2tpZTtcbiAgfTtcblxuICAvKipcbiAgICogUHJlc2VudCBhbiBPVFAtYXV0aGVudGljYXRlZCBjYWxsZXIgdG8gdGhlIGFwcCB0aGUgU0FNRSB3YXkgYSBwbGF0Zm9ybSBmcm9udFxuICAgKiBkb29yIGRvZXM6IHNldCB0aGUgZnJvbnQgZG9vcidzIG93biBpZGVudGl0eSBoZWFkZXJzIHRvIHRoZSB2ZXJpZmllZCBhZGRyZXNzXG4gICAqIChBcHBLaXQgcmVhZHMge0BsaW5rIHRva2VuLlVTRVJfSURfSEVBREVSfSBmb3IgdGhlIE9CTyB1c2VyIGlkKSwgc28gdGhlIGFwcFxuICAgKiBuZWVkcyBubyBnYXRlLXNwZWNpZmljIGNvZGUgcGF0aC4gVGhlIG5hbWVzIGNvbWUgZnJvbVxuICAgKiBgQGRieC10b29scy9zaGFyZWQtY29yZWAncyBgdG9rZW5gIG1vZHVsZSAtIHRoZSBzYW1lIGNvbnN0YW50cyBBcHBLaXQtc2lkZVxuICAgKiBjb2RlIHJlYWRzIHRoZW0gYnkgLSByYXRoZXIgdGhhbiBiZWluZyByZS1zcGVsbGVkIGhlcmUuXG4gICAqXG4gICAqIFdoYXQgdGhlIGdhdGUgQ0FOTk9UIHNldCBpcyB7QGxpbmsgdG9rZW4uQUNDRVNTX1RPS0VOX0hFQURFUn06IGFuIE9UUCBzZXNzaW9uXG4gICAqIHByb3ZlcyBhbiBlbWFpbCBhZGRyZXNzLCBub3QgcG9zc2Vzc2lvbiBvZiBhIERhdGFicmlja3MgY3JlZGVudGlhbCwgYW5kXG4gICAqIHRoZXJlIGlzIG5vIHdheSB0byBtaW50IG9uZSBmb3IgdGhlIGNhbGxlci4gSXRzIGFic2VuY2UgaXMgZXhhY3RseSB3aGF0XG4gICAqIGBAZGJ4LXRvb2xzL2FwcGtpdGAncyBgaWRlbnRpdHlgIGBcImF1dG9cImAgbW9kZSBkZXRlY3RzLCBzbyBhIGdhdGVkIHJlcXVlc3RcbiAgICogcnVucyBhcyB0aGUgYXBwJ3Mgc2VydmljZSBwcmluY2lwYWwgaW5zdGVhZCBvZiB0aHJvd2luZy5cbiAgICovXG4gIGNvbnN0IGluamVjdElkZW50aXR5ID0gKHJlcTogSW5jb21pbmdNZXNzYWdlLCBlbWFpbDogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9JRF9IRUFERVJdID0gZW1haWw7XG4gICAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9FTUFJTF9IRUFERVJdID0gZW1haWw7XG4gIH07XG5cbiAgLyoqXG4gICAqIEFwcGx5IHRoZSBpbmJvdW5kLWhlYWRlciBwb2xpY3kgdG8gYSB0dW5uZWwgcmVxdWVzdDogZXZlcnkgYHgtYCBoZWFkZXIgdGhlXG4gICAqIGFsbG93LWxpc3QgZG9lcyBub3QgbmFtZSBpcyBkZWxldGVkLCBhbmQgdGhlIHBsYXRmb3JtIGlkZW50aXR5L3RyYW5zcG9ydCBzZXRcbiAgICogaXMgZGVsZXRlZCByZWdhcmRsZXNzLiBTZWUgYC4vaGVhZGVycy50c2AgZm9yIHRoZSByZWFzb25pbmc7IHRoZVxuICAgKiBzZWN1cml0eS1jcml0aWNhbCBjYXNlIGlzIHtAbGluayB0b2tlbi5BQ0NFU1NfVE9LRU5fSEVBREVSfSwgd2hpY2ggdGhlIGdhdGVcbiAgICogbmV2ZXIgc2V0cyBidXQgYW4gYXBwIHJ1bm5pbmcgYGlkZW50aXR5OiBcImF1dG9cImAgdHJlYXRzIGFzIHByb29mIHRoZSByZXF1ZXN0XG4gICAqIGNhbiBkbyBPQk8uXG4gICAqXG4gICAqIGB4ZndkOiB0cnVlYCBvbiB0aGUgcHJveHkgcmUtYWRkcyBgeC1mb3J3YXJkZWQtZm9yYC9gLXByb3RvYC9gLXBvcnRgL2AtaG9zdGBcbiAgICogYWZ0ZXJ3YXJkcyBmcm9tIHRoZSByZWFsIHNvY2tldCwgc28gdGhlIGFwcCBzdGlsbCBzZWVzIHRob3NlIC0gaXQganVzdCBzZWVzXG4gICAqIHRoZSBob25lc3QgdmFsdWVzIHJhdGhlciB0aGFuIHRoZSBjYWxsZXIncyBjbGFpbS5cbiAgICovXG4gIGNvbnN0IGFwcGx5SGVhZGVyUG9saWN5ID0gKHJlcTogSW5jb21pbmdNZXNzYWdlKTogdm9pZCA9PiB7XG4gICAgY29uc3QgcmVtb3ZlZCA9IGhlYWRlclBvbGljeS5hcHBseShyZXEuaGVhZGVycyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gICAgaWYgKHJlbW92ZWQubGVuZ3RoKSBsb2dnZXIuZGVidWcoXCJzdHJpcHBlZCBpbmJvdW5kIGhlYWRlcnNcIiwgeyByZW1vdmVkIH0pO1xuICB9O1xuXG4gIGNvbnN0IHNlcnZlciA9IGNyZWF0ZVNlcnZlcihhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBjb25zdCBwYXRoID0gKHJlcS51cmwgPz8gXCIvXCIpLnNwbGl0KFwiP1wiKVswXSE7XG5cbiAgICAvLyBJbnNlY3VyZS9vcGVuIG1vZGUgKG5vIGdhdGUpIE9SIG5vbi1sb29wYmFjayB0cmFmZmljICh0aGUgaG9zdGluZ1xuICAgIC8vIHBsYXRmb3JtJ3MgZnJvbnQgZG9vciAvIGNvbnRyb2wgcGxhbmUpOiBmb3J3YXJkIHVuZ2F0ZWQuXG4gICAgaWYgKCFnYXRlIHx8ICFpc0xvb3BiYWNrKHJlcS5zb2NrZXQucmVtb3RlQWRkcmVzcykpIHtcbiAgICAgIHByb3h5LndlYihyZXEsIHJlcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gLS0tIHBvcnRyIHRyYWZmaWM6IHRoZSBnYXRlIGFwcGxpZXMgLS0tXG5cbiAgICAvLyBUaGUgbG9naW4gZmxvdyBpcyBhbnN3ZXJlZCBJTi1QUk9DRVNTICh0aGUgYXBwIGhhcyBubyBzZXJ2ZXIgdG8gZm9yd2FyZCB0bykuXG4gICAgaWYgKHBhdGggPT09IGAke0FVVEhfUFJFRklYfS9zdGF0dXNgKSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGh0dHAucGFyc2VDb29raWVzKHJlcS5oZWFkZXJzLmNvb2tpZSA/PyBudWxsKVtTRVNTSU9OX0NPT0tJRV9OQU1FXTtcbiAgICAgIHNlbmRKc29uKHJlcywgMjAwLCBhd2FpdCBnYXRlLnN0YXR1cyh0b2tlbikpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAocGF0aCA9PT0gYCR7QVVUSF9QUkVGSVh9L3JlcXVlc3RgICYmIHJlcS5tZXRob2QgPT09IFwiUE9TVFwiKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBhdXRoUmVxdWVzdFNjaGVtYS5zYWZlUGFyc2UoanNvbi5wYXJzZVJlY29yZChhd2FpdCByZWFkQm9keShyZXEpKSk7XG4gICAgICBpZiAoIXBhcnNlZC5zdWNjZXNzKSByZXR1cm4gc2VuZEpzb24ocmVzLCAyMDAsIHsgb2s6IHRydWUgfSk7IC8vIGFudGktZW51bWVyYXRpb25cbiAgICAgIHJldHVybiBzZW5kSnNvbihyZXMsIDIwMCwgYXdhaXQgZ2F0ZS5yZXF1ZXN0KHBhcnNlZC5kYXRhLmVtYWlsLCBjbGllbnRJcChyZXEpKSk7XG4gICAgfVxuICAgIGlmIChwYXRoID09PSBgJHtBVVRIX1BSRUZJWH0vdmVyaWZ5YCAmJiByZXEubWV0aG9kID09PSBcIlBPU1RcIikge1xuICAgICAgY29uc3QgcGFyc2VkID0gYXV0aFZlcmlmeVNjaGVtYS5zYWZlUGFyc2UoanNvbi5wYXJzZVJlY29yZChhd2FpdCByZWFkQm9keShyZXEpKSk7XG4gICAgICBpZiAoIXBhcnNlZC5zdWNjZXNzKSByZXR1cm4gc2VuZEpzb24ocmVzLCAyMDAsIHsgb2s6IGZhbHNlIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2F0ZS52ZXJpZnkocGFyc2VkLmRhdGEuZW1haWwsIHBhcnNlZC5kYXRhLmNvZGUsIGNsaWVudElwKHJlcSkpO1xuICAgICAgY29uc3QgY29va2llID1cbiAgICAgICAgcmVzdWx0Lm9rICYmIHJlc3VsdC50b2tlbiA/IHNlc3Npb25Db29raWUocmVzdWx0LnRva2VuLCBnYXRlLnNlc3Npb25UdGxTZWNvbmRzKSA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBzZW5kSnNvbihcbiAgICAgICAgcmVzLFxuICAgICAgICAyMDAsXG4gICAgICAgIHsgb2s6IHJlc3VsdC5vaywgLi4uKHJlc3VsdC5yZXRyeUFmdGVyID8geyByZXRyeUFmdGVyOiByZXN1bHQucmV0cnlBZnRlciB9IDoge30pIH0sXG4gICAgICAgIGNvb2tpZSxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChwYXRoID09PSBgJHtBVVRIX1BSRUZJWH0vbG9nb3V0YCAmJiByZXEubWV0aG9kID09PSBcIlBPU1RcIikge1xuICAgICAgcmV0dXJuIHNlbmRKc29uKFxuICAgICAgICByZXMsXG4gICAgICAgIDIwMCxcbiAgICAgICAgeyBvazogdHJ1ZSB9LFxuICAgICAgICBgJHtTRVNTSU9OX0NPT0tJRV9OQU1FfT07IFBhdGg9LzsgSHR0cE9ubHk7IE1heC1BZ2U9MGAsXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEFudGktc3Bvb2Y6IGFwcGx5IHRoZSBpbmJvdW5kLWhlYWRlciBhbGxvdy1saXN0IHRvIHBvcnRyIHRyYWZmaWMgLSBvbmx5IHRoZVxuICAgIC8vIGdhdGUgbWF5IGFzc2VydCBpZGVudGl0eSwgYW5kIGl0IGRvZXMgc28gYmVsb3cgZm9yIGEgdmVyaWZpZWQgc2Vzc2lvbi5cbiAgICBhcHBseUhlYWRlclBvbGljeShyZXEpO1xuXG4gICAgLy8gU3RhdGljIChub24tQVBJKSBsb2FkcyBmcmVlbHkgc28gdGhlIFNQQSArIDxBdXRoR2F0ZT4gY2FuIHJlbmRlci4gU3RyaXAgdGhlXG4gICAgLy8gc2Vzc2lvbiBjb29raWUgc28gaXQgbmV2ZXIgbGVha3MgdG8gdGhlIHN0YXRpYyBoYW5kbGVyLlxuICAgIGlmICghcGF0aC5zdGFydHNXaXRoKFwiL2FwaS9cIikpIHtcbiAgICAgIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICAgICAgcHJveHkud2ViKHJlcSwgcmVzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBFdmVyeSBvdGhlciAvYXBpLyogcmVxdWlyZXMgYSB2YWxpZCBzZXNzaW9uLlxuICAgIGNvbnN0IHRva2VuID0gaHR0cC5wYXJzZUNvb2tpZXMocmVxLmhlYWRlcnMuY29va2llID8/IG51bGwpW1NFU1NJT05fQ09PS0lFX05BTUVdO1xuICAgIGNvbnN0IGVtYWlsID0gYXdhaXQgZ2F0ZS5zZXNzaW9uKHRva2VuKTtcbiAgICBpZiAoZW1haWwpIHtcbiAgICAgIC8vIFByZXNlbnQgdGhlIE9UUCB1c2VyIGxpa2UgYSBwbGF0Zm9ybSBmcm9udCBkb29yLCBhbmQgZHJvcCB0aGUgZ2F0ZVxuICAgICAgLy8gY29va2llIHNvIHRoZSBhcHAgc2VlcyBhIGNsZWFuLCBmcm9udC1kb29yLXNoYXBlZCByZXF1ZXN0LlxuICAgICAgaW5qZWN0SWRlbnRpdHkocmVxLCBlbWFpbCk7XG4gICAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICAgIHByb3h5LndlYihyZXEsIHJlcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlbmRKc29uKHJlcywgNDAxLCB7IGVycm9yOiBcImF1dGhlbnRpY2F0aW9uIHJlcXVpcmVkXCIsIGxvZ2luUGF0aDogQVVUSF9QUkVGSVggfSk7XG4gICAgfVxuICB9KTtcblxuICAvLyBXZWJTb2NrZXQgdXBncmFkZXM6IGZvcndhcmQgZnJvbnQtZG9vciB0cmFmZmljIHVudG91Y2hlZDsgZ2F0ZSBsb29wYmFja1xuICAvLyAocG9ydHIpIEFQSSB1cGdyYWRlcyB0aGUgc2FtZSB3YXkgYXMgSFRUUCAoc3RyaXAgY29va2llICsgaW5qZWN0IGlkZW50aXR5KS5cbiAgc2VydmVyLm9uKFwidXBncmFkZVwiLCAocmVxOiBJbmNvbWluZ01lc3NhZ2UsIHNvY2tldDogU29ja2V0LCBoZWFkOiBCdWZmZXIpID0+IHtcbiAgICBpZiAoIWdhdGUgfHwgIWlzTG9vcGJhY2socmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzKSkge1xuICAgICAgcHJveHkud3MocmVxLCBzb2NrZXQsIGhlYWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhcHBseUhlYWRlclBvbGljeShyZXEpO1xuICAgIGlmICghKHJlcS51cmwgPz8gXCJcIikuc3RhcnRzV2l0aChcIi9hcGkvXCIpKSB7XG4gICAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICAgIHByb3h5LndzKHJlcSwgc29ja2V0LCBoZWFkKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdG9rZW4gPSBodHRwLnBhcnNlQ29va2llcyhyZXEuaGVhZGVycy5jb29raWUgPz8gbnVsbClbU0VTU0lPTl9DT09LSUVfTkFNRV07XG4gICAgdm9pZCBnYXRlLnNlc3Npb24odG9rZW4pLnRoZW4oKGVtYWlsKSA9PiB7XG4gICAgICBpZiAoIWVtYWlsKSB7XG4gICAgICAgIHNvY2tldC5kZXN0cm95KCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGluamVjdElkZW50aXR5KHJlcSwgZW1haWwpO1xuICAgICAgc3RyaXBTZXNzaW9uQ29va2llKHJlcSk7XG4gICAgICBwcm94eS53cyhyZXEsIHNvY2tldCwgaGVhZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIHNlcnZlci5saXN0ZW4ocHVibGljUG9ydCwgXCIwLjAuMC4wXCIsICgpID0+IHtcbiAgICAgIGxvZ2dlci5pbmZvKGBnYXRlIHByb3h5IG9uIDAuMC4wLjA6JHtwdWJsaWNQb3J0fSAtPiBhcHAgMTI3LjAuMC4xOiR7YXBwUG9ydH1gKTtcbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbiAgfSk7XG59XG4iXX0=
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/allowlist.ts","../src/app.ts","../src/cli.ts","../src/otp.ts","../src/plugin.ts","../src/portr.ts","../src/proxy.ts","../src/rate-limit.ts","../index.ts","../bin/dbx-tools-tunnel.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/allowlist.ts","../src/app.ts","../src/cli.ts","../src/env.ts","../src/headers.ts","../src/otp.ts","../src/plugin.ts","../src/portr.ts","../src/proxy.ts","../src/rate-limit.ts","../index.ts","../bin/dbx-tools-tunnel.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@clack/prompts": "^1.7.0",
|
|
31
31
|
"@databricks/appkit": "^0.43.0",
|
|
32
|
-
"@dbx-tools/appkit": "0.6.
|
|
33
|
-
"@dbx-tools/core": "0.6.
|
|
34
|
-
"@dbx-tools/email": "0.6.
|
|
35
|
-
"@dbx-tools/shared-core": "0.6.
|
|
36
|
-
"@dbx-tools/shared-email": "0.6.
|
|
32
|
+
"@dbx-tools/appkit": "0.6.49",
|
|
33
|
+
"@dbx-tools/core": "0.6.49",
|
|
34
|
+
"@dbx-tools/email": "0.6.49",
|
|
35
|
+
"@dbx-tools/shared-core": "0.6.49",
|
|
36
|
+
"@dbx-tools/shared-email": "0.6.49",
|
|
37
37
|
"commander": "^15.0.0",
|
|
38
38
|
"http-proxy-3": "^1.23.3",
|
|
39
39
|
"jose": "^6.2.3"
|
|
@@ -65,6 +65,14 @@
|
|
|
65
65
|
"types": "./lib/src/cli.d.ts",
|
|
66
66
|
"default": "./lib/src/cli.js"
|
|
67
67
|
},
|
|
68
|
+
"./env": {
|
|
69
|
+
"types": "./lib/src/env.d.ts",
|
|
70
|
+
"default": "./lib/src/env.js"
|
|
71
|
+
},
|
|
72
|
+
"./headers": {
|
|
73
|
+
"types": "./lib/src/headers.d.ts",
|
|
74
|
+
"default": "./lib/src/headers.js"
|
|
75
|
+
},
|
|
68
76
|
"./otp": {
|
|
69
77
|
"types": "./lib/src/otp.d.ts",
|
|
70
78
|
"default": "./lib/src/otp.js"
|
|
@@ -88,7 +96,7 @@
|
|
|
88
96
|
"./package.json": "./package.json"
|
|
89
97
|
}
|
|
90
98
|
},
|
|
91
|
-
"version": "0.6.
|
|
99
|
+
"version": "0.6.49",
|
|
92
100
|
"types": "./lib/index.d.ts",
|
|
93
101
|
"type": "module",
|
|
94
102
|
"exports": {
|
|
@@ -108,6 +116,14 @@
|
|
|
108
116
|
"types": "./lib/src/cli.d.ts",
|
|
109
117
|
"default": "./lib/src/cli.js"
|
|
110
118
|
},
|
|
119
|
+
"./env": {
|
|
120
|
+
"types": "./lib/src/env.d.ts",
|
|
121
|
+
"default": "./lib/src/env.js"
|
|
122
|
+
},
|
|
123
|
+
"./headers": {
|
|
124
|
+
"types": "./lib/src/headers.d.ts",
|
|
125
|
+
"default": "./lib/src/headers.js"
|
|
126
|
+
},
|
|
111
127
|
"./otp": {
|
|
112
128
|
"types": "./lib/src/otp.d.ts",
|
|
113
129
|
"default": "./lib/src/otp.js"
|
package/src/allowlist.ts
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unified access allow-list matching for the email-OTP gate.
|
|
3
3
|
*
|
|
4
|
-
* Each pattern in the configured list is one of three shapes
|
|
4
|
+
* Each pattern in the configured list is one of three shapes:
|
|
5
5
|
*
|
|
6
6
|
* - **domain shortcut** - `example.com` or `@example.com`: matches any
|
|
7
|
-
* address whose domain equals it
|
|
8
|
-
*
|
|
9
|
-
* - **glob** - contains `*` or `?`, e.g.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
7
|
+
* address whose domain equals it. This is the gate's OWN semantic (a bare
|
|
8
|
+
* value means "the domain", not "the whole address"), so it is handled here.
|
|
9
|
+
* - **glob** - contains `*` or `?`, e.g. `*@example.com`: matched against the
|
|
10
|
+
* WHOLE address with shell-style wildcards.
|
|
11
|
+
* - **regex** - wrapped in slashes, `/.../ [flags]`: tested against the whole
|
|
12
|
+
* address. An invalid regex never matches (it is skipped with a warning
|
|
13
|
+
* rather than throwing).
|
|
14
|
+
*
|
|
15
|
+
* Only the first shape is this module's business: the glob and regex shapes are
|
|
16
|
+
* delegated to `@dbx-tools/shared-core`'s {@link pattern.toPattern}, which is
|
|
17
|
+
* where that compilation lives for every allow-list in the repo (the tunnel's
|
|
18
|
+
* inbound-header policy uses the same one). Matching is case-insensitive
|
|
19
|
+
* throughout.
|
|
15
20
|
*
|
|
16
21
|
* An EMPTY list matches nobody (fail closed): an app that enables the gate but
|
|
17
22
|
* configures no patterns lets no one in, which is the safe default.
|
|
@@ -19,58 +24,25 @@
|
|
|
19
24
|
* @module
|
|
20
25
|
*/
|
|
21
26
|
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
const logger = log.logger("tunnel:allowlist");
|
|
25
|
-
|
|
26
|
-
/** Escape a string for literal use inside a `RegExp`. */
|
|
27
|
-
function escapeRegExp(value: string): string {
|
|
28
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** Compile a shell-style glob (`*`, `?`) into an anchored, case-insensitive RegExp. */
|
|
32
|
-
function globToRegExp(glob: string): RegExp {
|
|
33
|
-
const body = glob
|
|
34
|
-
.split(/([*?])/)
|
|
35
|
-
.map((part) => (part === "*" ? ".*" : part === "?" ? "." : escapeRegExp(part)))
|
|
36
|
-
.join("");
|
|
37
|
-
return new RegExp(`^${body}$`, "i");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Parse a `/pattern/flags` string into a RegExp, or `undefined` if malformed. */
|
|
41
|
-
function parseRegexLiteral(pattern: string): RegExp | undefined {
|
|
42
|
-
const match = /^\/(.+)\/([a-z]*)$/is.exec(pattern);
|
|
43
|
-
if (!match) return undefined;
|
|
44
|
-
try {
|
|
45
|
-
const flags = match[2]!.includes("i") ? match[2]! : `${match[2]!}i`;
|
|
46
|
-
return new RegExp(match[1]!, flags);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
logger.warn("ignoring invalid regex allow-list pattern", { pattern, error });
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
27
|
+
import { pattern } from "@dbx-tools/shared-core";
|
|
52
28
|
|
|
53
29
|
/** True when `email` matches a single allow-list `pattern`. */
|
|
54
|
-
function matchesPattern(email: string,
|
|
55
|
-
const trimmed =
|
|
30
|
+
function matchesPattern(email: string, entry: string): boolean {
|
|
31
|
+
const trimmed = entry.trim();
|
|
56
32
|
if (!trimmed) return false;
|
|
57
33
|
const address = email.trim().toLowerCase();
|
|
58
34
|
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return globToRegExp(trimmed).test(address);
|
|
35
|
+
// A bare value with no wildcard and no regex delimiters is a DOMAIN shortcut,
|
|
36
|
+
// the one shape shared-core cannot infer: there it would mean whole-string
|
|
37
|
+
// equality against the address, which is never what an operator writing
|
|
38
|
+
// `example.com` in an access list intends.
|
|
39
|
+
if (!trimmed.startsWith("/") && !trimmed.includes("*") && !trimmed.includes("?")) {
|
|
40
|
+
const domain = trimmed.replace(/^@/, "").toLowerCase();
|
|
41
|
+
const at = address.lastIndexOf("@");
|
|
42
|
+
return at >= 0 && address.slice(at + 1) === domain;
|
|
68
43
|
}
|
|
69
44
|
|
|
70
|
-
|
|
71
|
-
const domain = trimmed.replace(/^@/, "").toLowerCase();
|
|
72
|
-
const at = address.lastIndexOf("@");
|
|
73
|
-
return at >= 0 && address.slice(at + 1) === domain;
|
|
45
|
+
return pattern.toPattern(trimmed)?.(address) ?? false;
|
|
74
46
|
}
|
|
75
47
|
|
|
76
48
|
/**
|
|
@@ -79,7 +51,7 @@ function matchesPattern(email: string, pattern: string): boolean {
|
|
|
79
51
|
*/
|
|
80
52
|
export function matchesAllowlist(email: string, patterns: readonly string[] | undefined): boolean {
|
|
81
53
|
if (!email || !patterns || patterns.length === 0) return false;
|
|
82
|
-
return patterns.some((
|
|
54
|
+
return patterns.some((entry) => matchesPattern(email, entry));
|
|
83
55
|
}
|
|
84
56
|
|
|
85
57
|
/** Rough shape check so a clearly-invalid address is rejected before any work. */
|