@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/env.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment-variable names the tunnel reads.
|
|
3
|
+
*
|
|
4
|
+
* Every setting is `TUNNEL_`-prefixed, matching the repo convention of naming a
|
|
5
|
+
* variable after the package that owns it (`MASTRA_*`, `TEAMS_*`,
|
|
6
|
+
* `WEB_SEARCH_*`). The gate's original names were unprefixed (`AUTH_SUBJECT`,
|
|
7
|
+
* `PUBLIC_DOMAIN`, ...), which is a real hazard for a package that runs as a
|
|
8
|
+
* WRAPPER: the tunnel and the app it wraps share one environment, so a generic
|
|
9
|
+
* name is one the wrapped app may already use for something else, and
|
|
10
|
+
* `PUBLIC_DOMAIN` in particular reads like an app-wide setting rather than a
|
|
11
|
+
* portr detail. `EMAIL_AUTH_ALLOW` was worse than generic - it sat in
|
|
12
|
+
* `@dbx-tools/email`'s `EMAIL_*` namespace while configuring the gate, not email.
|
|
13
|
+
*
|
|
14
|
+
* Each entry is an {@link EnvKey} list, EARLIEST-WINS, whose first element is the
|
|
15
|
+
* current name and whose remaining elements are the deprecated originals. A
|
|
16
|
+
* deployment set up against the old names keeps working; nothing needs a
|
|
17
|
+
* coordinated rename. Read them through `env.string` / `env.positiveInt` /
|
|
18
|
+
* `env.list`, which accept the list directly.
|
|
19
|
+
*
|
|
20
|
+
* Not renamed:
|
|
21
|
+
*
|
|
22
|
+
* - `DATABRICKS_APP_PORT` - the Databricks Apps runtime contract. The platform
|
|
23
|
+
* sets it; the gate honours it.
|
|
24
|
+
* - `PORTR_TOKEN` / `PORTR_SERVER` / `PORTR_AUTO_ADD_PATH` - upstream
|
|
25
|
+
* [portr](https://github.com/amalshaji/portr)'s own namespace, and
|
|
26
|
+
* `PORTR_AUTO_ADD_PATH` is passed straight to that binary. Renaming these
|
|
27
|
+
* would rename someone else's contract.
|
|
28
|
+
*
|
|
29
|
+
* @module
|
|
30
|
+
*/
|
|
31
|
+
/** Access allow-list patterns (domain / glob / `/regex/`). */
|
|
32
|
+
export const ALLOW_ENV = ["TUNNEL_AUTH_ALLOW", "EMAIL_AUTH_ALLOW"];
|
|
33
|
+
/** Subject line for the code email. */
|
|
34
|
+
export const SUBJECT_ENV = ["TUNNEL_AUTH_SUBJECT", "AUTH_SUBJECT"];
|
|
35
|
+
/** Display name used in the code email copy. */
|
|
36
|
+
export const BRAND_NAME_ENV = ["TUNNEL_AUTH_BRAND_NAME", "AUTH_BRAND_NAME"];
|
|
37
|
+
/** Line shown immediately above the code in the email. */
|
|
38
|
+
export const MESSAGE_ENV = ["TUNNEL_AUTH_MESSAGE", "AUTH_MESSAGE"];
|
|
39
|
+
/** Session lifetime, in seconds. */
|
|
40
|
+
export const SESSION_TTL_ENV = ["TUNNEL_AUTH_SESSION_TTL", "AUTH_SESSION_TTL"];
|
|
41
|
+
/** One-time-code lifetime, in seconds. */
|
|
42
|
+
export const CODE_TTL_ENV = ["TUNNEL_AUTH_CODE_TTL", "AUTH_CODE_TTL"];
|
|
43
|
+
/** HS256 signing secret for the session JWT. */
|
|
44
|
+
export const JWT_SECRET_ENV = ["TUNNEL_AUTH_JWT_SECRET", "AUTH_JWT_SECRET"];
|
|
45
|
+
/** The public `<subdomain>.<server>` portr should serve on. */
|
|
46
|
+
export const PUBLIC_DOMAIN_ENV = ["TUNNEL_PUBLIC_DOMAIN", "PUBLIC_DOMAIN"];
|
|
47
|
+
/** Run the tunnel OPEN, with no gate. Ignored unless truthy. */
|
|
48
|
+
export const INSECURE_ENV = "TUNNEL_INSECURE";
|
|
49
|
+
/** Extra `x-` request headers tunnel traffic may forward. */
|
|
50
|
+
export const FORWARD_HEADERS_ENV = "TUNNEL_FORWARD_HEADERS";
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Vudi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Qkc7QUFJSCw4REFBOEQ7QUFDOUQsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFXLENBQUMsbUJBQW1CLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztBQUUzRSx1Q0FBdUM7QUFDdkMsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFXLENBQUMscUJBQXFCLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFFM0UsZ0RBQWdEO0FBQ2hELE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBVyxDQUFDLHdCQUF3QixFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFFcEYsMERBQTBEO0FBQzFELE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBVyxDQUFDLHFCQUFxQixFQUFFLGNBQWMsQ0FBQyxDQUFDO0FBRTNFLG9DQUFvQztBQUNwQyxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQVcsQ0FBQyx5QkFBeUIsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO0FBRXZGLDBDQUEwQztBQUMxQyxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQVcsQ0FBQyxzQkFBc0IsRUFBRSxlQUFlLENBQUMsQ0FBQztBQUU5RSxnREFBZ0Q7QUFDaEQsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFXLENBQUMsd0JBQXdCLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztBQUVwRiwrREFBK0Q7QUFDL0QsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQVcsQ0FBQyxzQkFBc0IsRUFBRSxlQUFlLENBQUMsQ0FBQztBQUVuRixnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFXLGlCQUFpQixDQUFDO0FBRXRELDZEQUE2RDtBQUM3RCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBVyx3QkFBd0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRW52aXJvbm1lbnQtdmFyaWFibGUgbmFtZXMgdGhlIHR1bm5lbCByZWFkcy5cbiAqXG4gKiBFdmVyeSBzZXR0aW5nIGlzIGBUVU5ORUxfYC1wcmVmaXhlZCwgbWF0Y2hpbmcgdGhlIHJlcG8gY29udmVudGlvbiBvZiBuYW1pbmcgYVxuICogdmFyaWFibGUgYWZ0ZXIgdGhlIHBhY2thZ2UgdGhhdCBvd25zIGl0IChgTUFTVFJBXypgLCBgVEVBTVNfKmAsXG4gKiBgV0VCX1NFQVJDSF8qYCkuIFRoZSBnYXRlJ3Mgb3JpZ2luYWwgbmFtZXMgd2VyZSB1bnByZWZpeGVkIChgQVVUSF9TVUJKRUNUYCxcbiAqIGBQVUJMSUNfRE9NQUlOYCwgLi4uKSwgd2hpY2ggaXMgYSByZWFsIGhhemFyZCBmb3IgYSBwYWNrYWdlIHRoYXQgcnVucyBhcyBhXG4gKiBXUkFQUEVSOiB0aGUgdHVubmVsIGFuZCB0aGUgYXBwIGl0IHdyYXBzIHNoYXJlIG9uZSBlbnZpcm9ubWVudCwgc28gYSBnZW5lcmljXG4gKiBuYW1lIGlzIG9uZSB0aGUgd3JhcHBlZCBhcHAgbWF5IGFscmVhZHkgdXNlIGZvciBzb21ldGhpbmcgZWxzZSwgYW5kXG4gKiBgUFVCTElDX0RPTUFJTmAgaW4gcGFydGljdWxhciByZWFkcyBsaWtlIGFuIGFwcC13aWRlIHNldHRpbmcgcmF0aGVyIHRoYW4gYVxuICogcG9ydHIgZGV0YWlsLiBgRU1BSUxfQVVUSF9BTExPV2Agd2FzIHdvcnNlIHRoYW4gZ2VuZXJpYyAtIGl0IHNhdCBpblxuICogYEBkYngtdG9vbHMvZW1haWxgJ3MgYEVNQUlMXypgIG5hbWVzcGFjZSB3aGlsZSBjb25maWd1cmluZyB0aGUgZ2F0ZSwgbm90IGVtYWlsLlxuICpcbiAqIEVhY2ggZW50cnkgaXMgYW4ge0BsaW5rIEVudktleX0gbGlzdCwgRUFSTElFU1QtV0lOUywgd2hvc2UgZmlyc3QgZWxlbWVudCBpcyB0aGVcbiAqIGN1cnJlbnQgbmFtZSBhbmQgd2hvc2UgcmVtYWluaW5nIGVsZW1lbnRzIGFyZSB0aGUgZGVwcmVjYXRlZCBvcmlnaW5hbHMuIEFcbiAqIGRlcGxveW1lbnQgc2V0IHVwIGFnYWluc3QgdGhlIG9sZCBuYW1lcyBrZWVwcyB3b3JraW5nOyBub3RoaW5nIG5lZWRzIGFcbiAqIGNvb3JkaW5hdGVkIHJlbmFtZS4gUmVhZCB0aGVtIHRocm91Z2ggYGVudi5zdHJpbmdgIC8gYGVudi5wb3NpdGl2ZUludGAgL1xuICogYGVudi5saXN0YCwgd2hpY2ggYWNjZXB0IHRoZSBsaXN0IGRpcmVjdGx5LlxuICpcbiAqIE5vdCByZW5hbWVkOlxuICpcbiAqICAgLSBgREFUQUJSSUNLU19BUFBfUE9SVGAgLSB0aGUgRGF0YWJyaWNrcyBBcHBzIHJ1bnRpbWUgY29udHJhY3QuIFRoZSBwbGF0Zm9ybVxuICogICAgIHNldHMgaXQ7IHRoZSBnYXRlIGhvbm91cnMgaXQuXG4gKiAgIC0gYFBPUlRSX1RPS0VOYCAvIGBQT1JUUl9TRVJWRVJgIC8gYFBPUlRSX0FVVE9fQUREX1BBVEhgIC0gdXBzdHJlYW1cbiAqICAgICBbcG9ydHJdKGh0dHBzOi8vZ2l0aHViLmNvbS9hbWFsc2hhamkvcG9ydHIpJ3Mgb3duIG5hbWVzcGFjZSwgYW5kXG4gKiAgICAgYFBPUlRSX0FVVE9fQUREX1BBVEhgIGlzIHBhc3NlZCBzdHJhaWdodCB0byB0aGF0IGJpbmFyeS4gUmVuYW1pbmcgdGhlc2VcbiAqICAgICB3b3VsZCByZW5hbWUgc29tZW9uZSBlbHNlJ3MgY29udHJhY3QuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB0eXBlIHsgRW52S2V5IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuLyoqIEFjY2VzcyBhbGxvdy1saXN0IHBhdHRlcm5zIChkb21haW4gLyBnbG9iIC8gYC9yZWdleC9gKS4gKi9cbmV4cG9ydCBjb25zdCBBTExPV19FTlY6IEVudktleSA9IFtcIlRVTk5FTF9BVVRIX0FMTE9XXCIsIFwiRU1BSUxfQVVUSF9BTExPV1wiXTtcblxuLyoqIFN1YmplY3QgbGluZSBmb3IgdGhlIGNvZGUgZW1haWwuICovXG5leHBvcnQgY29uc3QgU1VCSkVDVF9FTlY6IEVudktleSA9IFtcIlRVTk5FTF9BVVRIX1NVQkpFQ1RcIiwgXCJBVVRIX1NVQkpFQ1RcIl07XG5cbi8qKiBEaXNwbGF5IG5hbWUgdXNlZCBpbiB0aGUgY29kZSBlbWFpbCBjb3B5LiAqL1xuZXhwb3J0IGNvbnN0IEJSQU5EX05BTUVfRU5WOiBFbnZLZXkgPSBbXCJUVU5ORUxfQVVUSF9CUkFORF9OQU1FXCIsIFwiQVVUSF9CUkFORF9OQU1FXCJdO1xuXG4vKiogTGluZSBzaG93biBpbW1lZGlhdGVseSBhYm92ZSB0aGUgY29kZSBpbiB0aGUgZW1haWwuICovXG5leHBvcnQgY29uc3QgTUVTU0FHRV9FTlY6IEVudktleSA9IFtcIlRVTk5FTF9BVVRIX01FU1NBR0VcIiwgXCJBVVRIX01FU1NBR0VcIl07XG5cbi8qKiBTZXNzaW9uIGxpZmV0aW1lLCBpbiBzZWNvbmRzLiAqL1xuZXhwb3J0IGNvbnN0IFNFU1NJT05fVFRMX0VOVjogRW52S2V5ID0gW1wiVFVOTkVMX0FVVEhfU0VTU0lPTl9UVExcIiwgXCJBVVRIX1NFU1NJT05fVFRMXCJdO1xuXG4vKiogT25lLXRpbWUtY29kZSBsaWZldGltZSwgaW4gc2Vjb25kcy4gKi9cbmV4cG9ydCBjb25zdCBDT0RFX1RUTF9FTlY6IEVudktleSA9IFtcIlRVTk5FTF9BVVRIX0NPREVfVFRMXCIsIFwiQVVUSF9DT0RFX1RUTFwiXTtcblxuLyoqIEhTMjU2IHNpZ25pbmcgc2VjcmV0IGZvciB0aGUgc2Vzc2lvbiBKV1QuICovXG5leHBvcnQgY29uc3QgSldUX1NFQ1JFVF9FTlY6IEVudktleSA9IFtcIlRVTk5FTF9BVVRIX0pXVF9TRUNSRVRcIiwgXCJBVVRIX0pXVF9TRUNSRVRcIl07XG5cbi8qKiBUaGUgcHVibGljIGA8c3ViZG9tYWluPi48c2VydmVyPmAgcG9ydHIgc2hvdWxkIHNlcnZlIG9uLiAqL1xuZXhwb3J0IGNvbnN0IFBVQkxJQ19ET01BSU5fRU5WOiBFbnZLZXkgPSBbXCJUVU5ORUxfUFVCTElDX0RPTUFJTlwiLCBcIlBVQkxJQ19ET01BSU5cIl07XG5cbi8qKiBSdW4gdGhlIHR1bm5lbCBPUEVOLCB3aXRoIG5vIGdhdGUuIElnbm9yZWQgdW5sZXNzIHRydXRoeS4gKi9cbmV4cG9ydCBjb25zdCBJTlNFQ1VSRV9FTlY6IEVudktleSA9IFwiVFVOTkVMX0lOU0VDVVJFXCI7XG5cbi8qKiBFeHRyYSBgeC1gIHJlcXVlc3QgaGVhZGVycyB0dW5uZWwgdHJhZmZpYyBtYXkgZm9yd2FyZC4gKi9cbmV4cG9ydCBjb25zdCBGT1JXQVJEX0hFQURFUlNfRU5WOiBFbnZLZXkgPSBcIlRVTk5FTF9GT1JXQVJEX0hFQURFUlNcIjtcbiJdfQ==
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbound header policy for tunnel traffic.
|
|
3
|
+
*
|
|
4
|
+
* Everything the gate forwards arrives from the PUBLIC internet through the
|
|
5
|
+
* portr client, so every header on it is attacker-controlled. The headers an app
|
|
6
|
+
* trusts are precisely the ones a caller must not be able to write, because the
|
|
7
|
+
* app cannot tell a header the Databricks front door set from one a browser
|
|
8
|
+
* typed.
|
|
9
|
+
*
|
|
10
|
+
* ## Policy shape: strip by default, allow by pattern
|
|
11
|
+
*
|
|
12
|
+
* Enumerating what to remove is a losing game - a deny-list is only correct until
|
|
13
|
+
* the platform adds a header or a library starts trusting another one - so the
|
|
14
|
+
* policy is inverted. EVERY `x-`-prefixed request header is dropped from tunnel
|
|
15
|
+
* traffic unless it matches a configured pattern. That fails CLOSED: a header
|
|
16
|
+
* nobody thought about is removed rather than trusted.
|
|
17
|
+
*
|
|
18
|
+
* The allow-list is zero-to-many literals, globs, or `/regex/`es, compiled by
|
|
19
|
+
* shared-core's {@link pattern.toPatternMatcher}, and is UNIONED with
|
|
20
|
+
* {@link DEFAULT_FORWARD_HEADERS} so extending it never silently breaks the
|
|
21
|
+
* built-in surfaces. Configure it with `forwardHeaders` /
|
|
22
|
+
* `TUNNEL_FORWARD_HEADERS`.
|
|
23
|
+
*
|
|
24
|
+
* Non-`x-` headers are untouched. Standard ones (`content-type`, `accept`,
|
|
25
|
+
* `authorization`, `cookie`, ...) are the app's normal input and the gate has no
|
|
26
|
+
* business rewriting them.
|
|
27
|
+
*
|
|
28
|
+
* ## The headers no pattern can forward
|
|
29
|
+
*
|
|
30
|
+
* {@link PROTECTED_HEADERS} is stripped BEFORE the allow-list is consulted, so a
|
|
31
|
+
* permissive pattern (`x-*`, or a careless `*`) cannot re-open impersonation:
|
|
32
|
+
*
|
|
33
|
+
* | Header | What an app does with it | Why spoofing it matters |
|
|
34
|
+
* | -------------------------------- | ------------------------------- | ----------------------- |
|
|
35
|
+
* | `x-forwarded-access-token` | OBO auth (AppKit `asUser`) | Paste any workspace token and every call runs as its owner. The gate's verified email says nothing about who a pasted credential belongs to. |
|
|
36
|
+
* | `x-forwarded-user` | Caller identity | Impersonate another user. The gate sets this itself, from a verified session. |
|
|
37
|
+
* | `x-forwarded-email` | Caller identity | Same. |
|
|
38
|
+
* | `x-forwarded-preferred-username` | Display name from the IdP | Same. |
|
|
39
|
+
* | `x-forwarded-host` | The originally-requested host | Poison absolute URLs the app builds (the classic reset-link attack). |
|
|
40
|
+
* | `x-forwarded-proto` / `-port` | Original scheme / port | Convince the app a plaintext request arrived over TLS. |
|
|
41
|
+
* | `x-forwarded-for` | Client IP | Forge the audit trail, and fan out per-IP rate-limit keys (see below). |
|
|
42
|
+
* | `x-real-ip` | Client IP | Same. |
|
|
43
|
+
* | `x-request-id` | Request correlation UUID | Forge or collide trace ids, making logs unreliable. |
|
|
44
|
+
*
|
|
45
|
+
* The identity four are AppKit's OBO contract; the rest are the `X-Forwarded-*`
|
|
46
|
+
* set the Databricks Apps reverse proxy documents passing to an app
|
|
47
|
+
* ({@link https://docs.databricks.com/aws/en/dev-tools/databricks-apps/http-headers}),
|
|
48
|
+
* plus the conventional `x-forwarded-proto`/`-port`/`x-real-ip` an app or one of
|
|
49
|
+
* its libraries may read even though the table omits them.
|
|
50
|
+
*
|
|
51
|
+
* Stripping the `x-forwarded-*` transport trio is safe because `http-proxy-3` is
|
|
52
|
+
* configured with `xfwd: true` and re-adds them AFTER this policy runs - from the
|
|
53
|
+
* real socket, not from the caller's claim. The app therefore sees the honest
|
|
54
|
+
* (loopback) values instead of whatever the internet asserted. The gate reads the
|
|
55
|
+
* client IP for rate limiting from the raw inbound headers BEFORE stripping, and
|
|
56
|
+
* takes the RIGHTMOST `x-forwarded-for` entry, which is the only one a proxy
|
|
57
|
+
* appended rather than a client supplied.
|
|
58
|
+
*
|
|
59
|
+
* @module
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* Headers the gate strips UNCONDITIONALLY, before the allow-list is consulted -
|
|
63
|
+
* the platform-shaped set documented in this module's table.
|
|
64
|
+
*
|
|
65
|
+
* These answer WHO a request is and WHERE it came from, and on tunnel traffic
|
|
66
|
+
* only the gate may answer that: it injects {@link token.USER_ID_HEADER} /
|
|
67
|
+
* {@link token.USER_EMAIL_HEADER} itself after verifying a session, and the proxy
|
|
68
|
+
* re-derives the transport headers from the real socket.
|
|
69
|
+
*
|
|
70
|
+
* The identity names come from the shared `token` constants, so a renamed wire
|
|
71
|
+
* contract cannot leave a stale spelling here. `x-forwarded-preferred-username`
|
|
72
|
+
* has no constant because nothing in this repo READS it - it is listed precisely
|
|
73
|
+
* so a host app that does read it cannot be fed one.
|
|
74
|
+
*/
|
|
75
|
+
export declare const PROTECTED_HEADERS: readonly string[];
|
|
76
|
+
/**
|
|
77
|
+
* The `x-` headers forwarded when a deployment configures nothing.
|
|
78
|
+
*
|
|
79
|
+
* These are the header NAMESPACES this repo's own UI sends and its own server
|
|
80
|
+
* reads - Mastra thread/model routing (`x-mastra-thread-id`, `x-mastra-model`)
|
|
81
|
+
* and MLflow trace correlation (`x-mlflow-trace-id`) - so a dbx-tools app keeps
|
|
82
|
+
* working behind the tunnel with no configuration.
|
|
83
|
+
*
|
|
84
|
+
* Deliberately GLOBS rather than the exact constants from
|
|
85
|
+
* `@dbx-tools/shared-mastra`: importing them would make the gate - a
|
|
86
|
+
* transport-level component that has no other opinion about Mastra - depend on
|
|
87
|
+
* an agent package for three strings, and a namespace glob also covers the next
|
|
88
|
+
* header those packages add. The namespaces are the stable part of the contract.
|
|
89
|
+
*/
|
|
90
|
+
export declare const DEFAULT_FORWARD_HEADERS: readonly string[];
|
|
91
|
+
/** A compiled inbound-header policy. Build one with {@link toHeaderPolicy}. */
|
|
92
|
+
export interface HeaderPolicy {
|
|
93
|
+
/** The allow-list entries backing this policy (for diagnostics and tests). */
|
|
94
|
+
readonly patterns: readonly string[];
|
|
95
|
+
/** Whether `name` survives on tunnel traffic. */
|
|
96
|
+
forwards(name: string): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Delete every disallowed header from a mutable Node header bag, returning the
|
|
99
|
+
* lower-cased names removed (for debug logging).
|
|
100
|
+
*/
|
|
101
|
+
apply(headers: Record<string, unknown>): string[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Compile the inbound-header policy. `configured` entries are UNIONED with
|
|
105
|
+
* {@link DEFAULT_FORWARD_HEADERS}; each may be a literal name, a glob
|
|
106
|
+
* (`x-myapp-*`), or a `/regex/`. Matching is case-insensitive.
|
|
107
|
+
*/
|
|
108
|
+
export declare function toHeaderPolicy(configured?: readonly string[]): HeaderPolicy;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbound header policy for tunnel traffic.
|
|
3
|
+
*
|
|
4
|
+
* Everything the gate forwards arrives from the PUBLIC internet through the
|
|
5
|
+
* portr client, so every header on it is attacker-controlled. The headers an app
|
|
6
|
+
* trusts are precisely the ones a caller must not be able to write, because the
|
|
7
|
+
* app cannot tell a header the Databricks front door set from one a browser
|
|
8
|
+
* typed.
|
|
9
|
+
*
|
|
10
|
+
* ## Policy shape: strip by default, allow by pattern
|
|
11
|
+
*
|
|
12
|
+
* Enumerating what to remove is a losing game - a deny-list is only correct until
|
|
13
|
+
* the platform adds a header or a library starts trusting another one - so the
|
|
14
|
+
* policy is inverted. EVERY `x-`-prefixed request header is dropped from tunnel
|
|
15
|
+
* traffic unless it matches a configured pattern. That fails CLOSED: a header
|
|
16
|
+
* nobody thought about is removed rather than trusted.
|
|
17
|
+
*
|
|
18
|
+
* The allow-list is zero-to-many literals, globs, or `/regex/`es, compiled by
|
|
19
|
+
* shared-core's {@link pattern.toPatternMatcher}, and is UNIONED with
|
|
20
|
+
* {@link DEFAULT_FORWARD_HEADERS} so extending it never silently breaks the
|
|
21
|
+
* built-in surfaces. Configure it with `forwardHeaders` /
|
|
22
|
+
* `TUNNEL_FORWARD_HEADERS`.
|
|
23
|
+
*
|
|
24
|
+
* Non-`x-` headers are untouched. Standard ones (`content-type`, `accept`,
|
|
25
|
+
* `authorization`, `cookie`, ...) are the app's normal input and the gate has no
|
|
26
|
+
* business rewriting them.
|
|
27
|
+
*
|
|
28
|
+
* ## The headers no pattern can forward
|
|
29
|
+
*
|
|
30
|
+
* {@link PROTECTED_HEADERS} is stripped BEFORE the allow-list is consulted, so a
|
|
31
|
+
* permissive pattern (`x-*`, or a careless `*`) cannot re-open impersonation:
|
|
32
|
+
*
|
|
33
|
+
* | Header | What an app does with it | Why spoofing it matters |
|
|
34
|
+
* | -------------------------------- | ------------------------------- | ----------------------- |
|
|
35
|
+
* | `x-forwarded-access-token` | OBO auth (AppKit `asUser`) | Paste any workspace token and every call runs as its owner. The gate's verified email says nothing about who a pasted credential belongs to. |
|
|
36
|
+
* | `x-forwarded-user` | Caller identity | Impersonate another user. The gate sets this itself, from a verified session. |
|
|
37
|
+
* | `x-forwarded-email` | Caller identity | Same. |
|
|
38
|
+
* | `x-forwarded-preferred-username` | Display name from the IdP | Same. |
|
|
39
|
+
* | `x-forwarded-host` | The originally-requested host | Poison absolute URLs the app builds (the classic reset-link attack). |
|
|
40
|
+
* | `x-forwarded-proto` / `-port` | Original scheme / port | Convince the app a plaintext request arrived over TLS. |
|
|
41
|
+
* | `x-forwarded-for` | Client IP | Forge the audit trail, and fan out per-IP rate-limit keys (see below). |
|
|
42
|
+
* | `x-real-ip` | Client IP | Same. |
|
|
43
|
+
* | `x-request-id` | Request correlation UUID | Forge or collide trace ids, making logs unreliable. |
|
|
44
|
+
*
|
|
45
|
+
* The identity four are AppKit's OBO contract; the rest are the `X-Forwarded-*`
|
|
46
|
+
* set the Databricks Apps reverse proxy documents passing to an app
|
|
47
|
+
* ({@link https://docs.databricks.com/aws/en/dev-tools/databricks-apps/http-headers}),
|
|
48
|
+
* plus the conventional `x-forwarded-proto`/`-port`/`x-real-ip` an app or one of
|
|
49
|
+
* its libraries may read even though the table omits them.
|
|
50
|
+
*
|
|
51
|
+
* Stripping the `x-forwarded-*` transport trio is safe because `http-proxy-3` is
|
|
52
|
+
* configured with `xfwd: true` and re-adds them AFTER this policy runs - from the
|
|
53
|
+
* real socket, not from the caller's claim. The app therefore sees the honest
|
|
54
|
+
* (loopback) values instead of whatever the internet asserted. The gate reads the
|
|
55
|
+
* client IP for rate limiting from the raw inbound headers BEFORE stripping, and
|
|
56
|
+
* takes the RIGHTMOST `x-forwarded-for` entry, which is the only one a proxy
|
|
57
|
+
* appended rather than a client supplied.
|
|
58
|
+
*
|
|
59
|
+
* @module
|
|
60
|
+
*/
|
|
61
|
+
import { pattern, token } from "@dbx-tools/shared-core";
|
|
62
|
+
/**
|
|
63
|
+
* Headers the gate strips UNCONDITIONALLY, before the allow-list is consulted -
|
|
64
|
+
* the platform-shaped set documented in this module's table.
|
|
65
|
+
*
|
|
66
|
+
* These answer WHO a request is and WHERE it came from, and on tunnel traffic
|
|
67
|
+
* only the gate may answer that: it injects {@link token.USER_ID_HEADER} /
|
|
68
|
+
* {@link token.USER_EMAIL_HEADER} itself after verifying a session, and the proxy
|
|
69
|
+
* re-derives the transport headers from the real socket.
|
|
70
|
+
*
|
|
71
|
+
* The identity names come from the shared `token` constants, so a renamed wire
|
|
72
|
+
* contract cannot leave a stale spelling here. `x-forwarded-preferred-username`
|
|
73
|
+
* has no constant because nothing in this repo READS it - it is listed precisely
|
|
74
|
+
* so a host app that does read it cannot be fed one.
|
|
75
|
+
*/
|
|
76
|
+
export const PROTECTED_HEADERS = [
|
|
77
|
+
token.ACCESS_TOKEN_HEADER,
|
|
78
|
+
token.USER_ID_HEADER,
|
|
79
|
+
token.USER_EMAIL_HEADER,
|
|
80
|
+
"x-forwarded-preferred-username",
|
|
81
|
+
"x-forwarded-host",
|
|
82
|
+
"x-forwarded-proto",
|
|
83
|
+
"x-forwarded-port",
|
|
84
|
+
"x-forwarded-for",
|
|
85
|
+
"x-real-ip",
|
|
86
|
+
"x-request-id",
|
|
87
|
+
];
|
|
88
|
+
/**
|
|
89
|
+
* The `x-` headers forwarded when a deployment configures nothing.
|
|
90
|
+
*
|
|
91
|
+
* These are the header NAMESPACES this repo's own UI sends and its own server
|
|
92
|
+
* reads - Mastra thread/model routing (`x-mastra-thread-id`, `x-mastra-model`)
|
|
93
|
+
* and MLflow trace correlation (`x-mlflow-trace-id`) - so a dbx-tools app keeps
|
|
94
|
+
* working behind the tunnel with no configuration.
|
|
95
|
+
*
|
|
96
|
+
* Deliberately GLOBS rather than the exact constants from
|
|
97
|
+
* `@dbx-tools/shared-mastra`: importing them would make the gate - a
|
|
98
|
+
* transport-level component that has no other opinion about Mastra - depend on
|
|
99
|
+
* an agent package for three strings, and a namespace glob also covers the next
|
|
100
|
+
* header those packages add. The namespaces are the stable part of the contract.
|
|
101
|
+
*/
|
|
102
|
+
export const DEFAULT_FORWARD_HEADERS = [
|
|
103
|
+
"x-mastra-*",
|
|
104
|
+
"x-mlflow-*",
|
|
105
|
+
// Sent by fetch/XHR wrappers to mark an AJAX request; harmless and widely read.
|
|
106
|
+
"x-requested-with",
|
|
107
|
+
];
|
|
108
|
+
/**
|
|
109
|
+
* Compile the inbound-header policy. `configured` entries are UNIONED with
|
|
110
|
+
* {@link DEFAULT_FORWARD_HEADERS}; each may be a literal name, a glob
|
|
111
|
+
* (`x-myapp-*`), or a `/regex/`. Matching is case-insensitive.
|
|
112
|
+
*/
|
|
113
|
+
export function toHeaderPolicy(configured = []) {
|
|
114
|
+
const patterns = [...DEFAULT_FORWARD_HEADERS, ...configured];
|
|
115
|
+
const allowed = pattern.toPatternMatcher(patterns);
|
|
116
|
+
const protectedNames = new Set(PROTECTED_HEADERS);
|
|
117
|
+
const forwards = (name) => {
|
|
118
|
+
const lower = name.toLowerCase();
|
|
119
|
+
if (protectedNames.has(lower))
|
|
120
|
+
return false;
|
|
121
|
+
if (!lower.startsWith("x-"))
|
|
122
|
+
return true;
|
|
123
|
+
return allowed(lower);
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
patterns,
|
|
127
|
+
forwards,
|
|
128
|
+
apply: (headers) => {
|
|
129
|
+
const removed = [];
|
|
130
|
+
for (const name of Object.keys(headers)) {
|
|
131
|
+
if (forwards(name))
|
|
132
|
+
continue;
|
|
133
|
+
delete headers[name];
|
|
134
|
+
removed.push(name.toLowerCase());
|
|
135
|
+
}
|
|
136
|
+
return removed;
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhZGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oZWFkZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJERztBQUVILE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFrQixNQUFNLHdCQUF3QixDQUFDO0FBRXhFOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBc0I7SUFDbEQsS0FBSyxDQUFDLG1CQUFtQjtJQUN6QixLQUFLLENBQUMsY0FBYztJQUNwQixLQUFLLENBQUMsaUJBQWlCO0lBQ3ZCLGdDQUFnQztJQUNoQyxrQkFBa0I7SUFDbEIsbUJBQW1CO0lBQ25CLGtCQUFrQjtJQUNsQixpQkFBaUI7SUFDakIsV0FBVztJQUNYLGNBQWM7Q0FDZixDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFzQjtJQUN4RCxZQUFZO0lBQ1osWUFBWTtJQUNaLGdGQUFnRjtJQUNoRixrQkFBa0I7Q0FDbkIsQ0FBQztBQWVGOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLGFBQWdDLEVBQUU7SUFDL0QsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLHVCQUF1QixFQUFFLEdBQUcsVUFBVSxDQUFDLENBQUM7SUFDN0QsTUFBTSxPQUFPLEdBQXNCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0RSxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRWxELE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBWSxFQUFXLEVBQUU7UUFDekMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pDLElBQUksY0FBYyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUM1QyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQztRQUN6QyxPQUFPLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4QixDQUFDLENBQUM7SUFFRixPQUFPO1FBQ0wsUUFBUTtRQUNSLFFBQVE7UUFDUixLQUFLLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNqQixNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7WUFDN0IsS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3hDLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQztvQkFBRSxTQUFTO2dCQUM3QixPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDckIsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUNuQyxDQUFDO1lBQ0QsT0FBTyxPQUFPLENBQUM7UUFDakIsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJbmJvdW5kIGhlYWRlciBwb2xpY3kgZm9yIHR1bm5lbCB0cmFmZmljLlxuICpcbiAqIEV2ZXJ5dGhpbmcgdGhlIGdhdGUgZm9yd2FyZHMgYXJyaXZlcyBmcm9tIHRoZSBQVUJMSUMgaW50ZXJuZXQgdGhyb3VnaCB0aGVcbiAqIHBvcnRyIGNsaWVudCwgc28gZXZlcnkgaGVhZGVyIG9uIGl0IGlzIGF0dGFja2VyLWNvbnRyb2xsZWQuIFRoZSBoZWFkZXJzIGFuIGFwcFxuICogdHJ1c3RzIGFyZSBwcmVjaXNlbHkgdGhlIG9uZXMgYSBjYWxsZXIgbXVzdCBub3QgYmUgYWJsZSB0byB3cml0ZSwgYmVjYXVzZSB0aGVcbiAqIGFwcCBjYW5ub3QgdGVsbCBhIGhlYWRlciB0aGUgRGF0YWJyaWNrcyBmcm9udCBkb29yIHNldCBmcm9tIG9uZSBhIGJyb3dzZXJcbiAqIHR5cGVkLlxuICpcbiAqICMjIFBvbGljeSBzaGFwZTogc3RyaXAgYnkgZGVmYXVsdCwgYWxsb3cgYnkgcGF0dGVyblxuICpcbiAqIEVudW1lcmF0aW5nIHdoYXQgdG8gcmVtb3ZlIGlzIGEgbG9zaW5nIGdhbWUgLSBhIGRlbnktbGlzdCBpcyBvbmx5IGNvcnJlY3QgdW50aWxcbiAqIHRoZSBwbGF0Zm9ybSBhZGRzIGEgaGVhZGVyIG9yIGEgbGlicmFyeSBzdGFydHMgdHJ1c3RpbmcgYW5vdGhlciBvbmUgLSBzbyB0aGVcbiAqIHBvbGljeSBpcyBpbnZlcnRlZC4gRVZFUlkgYHgtYC1wcmVmaXhlZCByZXF1ZXN0IGhlYWRlciBpcyBkcm9wcGVkIGZyb20gdHVubmVsXG4gKiB0cmFmZmljIHVubGVzcyBpdCBtYXRjaGVzIGEgY29uZmlndXJlZCBwYXR0ZXJuLiBUaGF0IGZhaWxzIENMT1NFRDogYSBoZWFkZXJcbiAqIG5vYm9keSB0aG91Z2h0IGFib3V0IGlzIHJlbW92ZWQgcmF0aGVyIHRoYW4gdHJ1c3RlZC5cbiAqXG4gKiBUaGUgYWxsb3ctbGlzdCBpcyB6ZXJvLXRvLW1hbnkgbGl0ZXJhbHMsIGdsb2JzLCBvciBgL3JlZ2V4L2BlcywgY29tcGlsZWQgYnlcbiAqIHNoYXJlZC1jb3JlJ3Mge0BsaW5rIHBhdHRlcm4udG9QYXR0ZXJuTWF0Y2hlcn0sIGFuZCBpcyBVTklPTkVEIHdpdGhcbiAqIHtAbGluayBERUZBVUxUX0ZPUldBUkRfSEVBREVSU30gc28gZXh0ZW5kaW5nIGl0IG5ldmVyIHNpbGVudGx5IGJyZWFrcyB0aGVcbiAqIGJ1aWx0LWluIHN1cmZhY2VzLiBDb25maWd1cmUgaXQgd2l0aCBgZm9yd2FyZEhlYWRlcnNgIC9cbiAqIGBUVU5ORUxfRk9SV0FSRF9IRUFERVJTYC5cbiAqXG4gKiBOb24tYHgtYCBoZWFkZXJzIGFyZSB1bnRvdWNoZWQuIFN0YW5kYXJkIG9uZXMgKGBjb250ZW50LXR5cGVgLCBgYWNjZXB0YCxcbiAqIGBhdXRob3JpemF0aW9uYCwgYGNvb2tpZWAsIC4uLikgYXJlIHRoZSBhcHAncyBub3JtYWwgaW5wdXQgYW5kIHRoZSBnYXRlIGhhcyBub1xuICogYnVzaW5lc3MgcmV3cml0aW5nIHRoZW0uXG4gKlxuICogIyMgVGhlIGhlYWRlcnMgbm8gcGF0dGVybiBjYW4gZm9yd2FyZFxuICpcbiAqIHtAbGluayBQUk9URUNURURfSEVBREVSU30gaXMgc3RyaXBwZWQgQkVGT1JFIHRoZSBhbGxvdy1saXN0IGlzIGNvbnN1bHRlZCwgc28gYVxuICogcGVybWlzc2l2ZSBwYXR0ZXJuIChgeC0qYCwgb3IgYSBjYXJlbGVzcyBgKmApIGNhbm5vdCByZS1vcGVuIGltcGVyc29uYXRpb246XG4gKlxuICogfCBIZWFkZXIgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFdoYXQgYW4gYXBwIGRvZXMgd2l0aCBpdCAgICAgICAgfCBXaHkgc3Bvb2ZpbmcgaXQgbWF0dGVycyB8XG4gKiB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHxcbiAqIHwgYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgICAgICAgfCBPQk8gYXV0aCAoQXBwS2l0IGBhc1VzZXJgKSAgICAgIHwgUGFzdGUgYW55IHdvcmtzcGFjZSB0b2tlbiBhbmQgZXZlcnkgY2FsbCBydW5zIGFzIGl0cyBvd25lci4gVGhlIGdhdGUncyB2ZXJpZmllZCBlbWFpbCBzYXlzIG5vdGhpbmcgYWJvdXQgd2hvIGEgcGFzdGVkIGNyZWRlbnRpYWwgYmVsb25ncyB0by4gfFxuICogfCBgeC1mb3J3YXJkZWQtdXNlcmAgICAgICAgICAgICAgICB8IENhbGxlciBpZGVudGl0eSAgICAgICAgICAgICAgICAgfCBJbXBlcnNvbmF0ZSBhbm90aGVyIHVzZXIuIFRoZSBnYXRlIHNldHMgdGhpcyBpdHNlbGYsIGZyb20gYSB2ZXJpZmllZCBzZXNzaW9uLiB8XG4gKiB8IGB4LWZvcndhcmRlZC1lbWFpbGAgICAgICAgICAgICAgIHwgQ2FsbGVyIGlkZW50aXR5ICAgICAgICAgICAgICAgICB8IFNhbWUuIHxcbiAqIHwgYHgtZm9yd2FyZGVkLXByZWZlcnJlZC11c2VybmFtZWAgfCBEaXNwbGF5IG5hbWUgZnJvbSB0aGUgSWRQICAgICAgIHwgU2FtZS4gfFxuICogfCBgeC1mb3J3YXJkZWQtaG9zdGAgICAgICAgICAgICAgICB8IFRoZSBvcmlnaW5hbGx5LXJlcXVlc3RlZCBob3N0ICAgIHwgUG9pc29uIGFic29sdXRlIFVSTHMgdGhlIGFwcCBidWlsZHMgKHRoZSBjbGFzc2ljIHJlc2V0LWxpbmsgYXR0YWNrKS4gfFxuICogfCBgeC1mb3J3YXJkZWQtcHJvdG9gIC8gYC1wb3J0YCAgICB8IE9yaWdpbmFsIHNjaGVtZSAvIHBvcnQgICAgICAgICAgfCBDb252aW5jZSB0aGUgYXBwIGEgcGxhaW50ZXh0IHJlcXVlc3QgYXJyaXZlZCBvdmVyIFRMUy4gfFxuICogfCBgeC1mb3J3YXJkZWQtZm9yYCAgICAgICAgICAgICAgICB8IENsaWVudCBJUCAgICAgICAgICAgICAgICAgICAgICAgfCBGb3JnZSB0aGUgYXVkaXQgdHJhaWwsIGFuZCBmYW4gb3V0IHBlci1JUCByYXRlLWxpbWl0IGtleXMgKHNlZSBiZWxvdykuIHxcbiAqIHwgYHgtcmVhbC1pcGAgICAgICAgICAgICAgICAgICAgICAgfCBDbGllbnQgSVAgICAgICAgICAgICAgICAgICAgICAgIHwgU2FtZS4gfFxuICogfCBgeC1yZXF1ZXN0LWlkYCAgICAgICAgICAgICAgICAgICB8IFJlcXVlc3QgY29ycmVsYXRpb24gVVVJRCAgICAgICAgfCBGb3JnZSBvciBjb2xsaWRlIHRyYWNlIGlkcywgbWFraW5nIGxvZ3MgdW5yZWxpYWJsZS4gfFxuICpcbiAqIFRoZSBpZGVudGl0eSBmb3VyIGFyZSBBcHBLaXQncyBPQk8gY29udHJhY3Q7IHRoZSByZXN0IGFyZSB0aGUgYFgtRm9yd2FyZGVkLSpgXG4gKiBzZXQgdGhlIERhdGFicmlja3MgQXBwcyByZXZlcnNlIHByb3h5IGRvY3VtZW50cyBwYXNzaW5nIHRvIGFuIGFwcFxuICogKHtAbGluayBodHRwczovL2RvY3MuZGF0YWJyaWNrcy5jb20vYXdzL2VuL2Rldi10b29scy9kYXRhYnJpY2tzLWFwcHMvaHR0cC1oZWFkZXJzfSksXG4gKiBwbHVzIHRoZSBjb252ZW50aW9uYWwgYHgtZm9yd2FyZGVkLXByb3RvYC9gLXBvcnRgL2B4LXJlYWwtaXBgIGFuIGFwcCBvciBvbmUgb2ZcbiAqIGl0cyBsaWJyYXJpZXMgbWF5IHJlYWQgZXZlbiB0aG91Z2ggdGhlIHRhYmxlIG9taXRzIHRoZW0uXG4gKlxuICogU3RyaXBwaW5nIHRoZSBgeC1mb3J3YXJkZWQtKmAgdHJhbnNwb3J0IHRyaW8gaXMgc2FmZSBiZWNhdXNlIGBodHRwLXByb3h5LTNgIGlzXG4gKiBjb25maWd1cmVkIHdpdGggYHhmd2Q6IHRydWVgIGFuZCByZS1hZGRzIHRoZW0gQUZURVIgdGhpcyBwb2xpY3kgcnVucyAtIGZyb20gdGhlXG4gKiByZWFsIHNvY2tldCwgbm90IGZyb20gdGhlIGNhbGxlcidzIGNsYWltLiBUaGUgYXBwIHRoZXJlZm9yZSBzZWVzIHRoZSBob25lc3RcbiAqIChsb29wYmFjaykgdmFsdWVzIGluc3RlYWQgb2Ygd2hhdGV2ZXIgdGhlIGludGVybmV0IGFzc2VydGVkLiBUaGUgZ2F0ZSByZWFkcyB0aGVcbiAqIGNsaWVudCBJUCBmb3IgcmF0ZSBsaW1pdGluZyBmcm9tIHRoZSByYXcgaW5ib3VuZCBoZWFkZXJzIEJFRk9SRSBzdHJpcHBpbmcsIGFuZFxuICogdGFrZXMgdGhlIFJJR0hUTU9TVCBgeC1mb3J3YXJkZWQtZm9yYCBlbnRyeSwgd2hpY2ggaXMgdGhlIG9ubHkgb25lIGEgcHJveHlcbiAqIGFwcGVuZGVkIHJhdGhlciB0aGFuIGEgY2xpZW50IHN1cHBsaWVkLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBwYXR0ZXJuLCB0b2tlbiwgdHlwZSBQcmVkaWNhdGUgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuXG4vKipcbiAqIEhlYWRlcnMgdGhlIGdhdGUgc3RyaXBzIFVOQ09ORElUSU9OQUxMWSwgYmVmb3JlIHRoZSBhbGxvdy1saXN0IGlzIGNvbnN1bHRlZCAtXG4gKiB0aGUgcGxhdGZvcm0tc2hhcGVkIHNldCBkb2N1bWVudGVkIGluIHRoaXMgbW9kdWxlJ3MgdGFibGUuXG4gKlxuICogVGhlc2UgYW5zd2VyIFdITyBhIHJlcXVlc3QgaXMgYW5kIFdIRVJFIGl0IGNhbWUgZnJvbSwgYW5kIG9uIHR1bm5lbCB0cmFmZmljXG4gKiBvbmx5IHRoZSBnYXRlIG1heSBhbnN3ZXIgdGhhdDogaXQgaW5qZWN0cyB7QGxpbmsgdG9rZW4uVVNFUl9JRF9IRUFERVJ9IC9cbiAqIHtAbGluayB0b2tlbi5VU0VSX0VNQUlMX0hFQURFUn0gaXRzZWxmIGFmdGVyIHZlcmlmeWluZyBhIHNlc3Npb24sIGFuZCB0aGUgcHJveHlcbiAqIHJlLWRlcml2ZXMgdGhlIHRyYW5zcG9ydCBoZWFkZXJzIGZyb20gdGhlIHJlYWwgc29ja2V0LlxuICpcbiAqIFRoZSBpZGVudGl0eSBuYW1lcyBjb21lIGZyb20gdGhlIHNoYXJlZCBgdG9rZW5gIGNvbnN0YW50cywgc28gYSByZW5hbWVkIHdpcmVcbiAqIGNvbnRyYWN0IGNhbm5vdCBsZWF2ZSBhIHN0YWxlIHNwZWxsaW5nIGhlcmUuIGB4LWZvcndhcmRlZC1wcmVmZXJyZWQtdXNlcm5hbWVgXG4gKiBoYXMgbm8gY29uc3RhbnQgYmVjYXVzZSBub3RoaW5nIGluIHRoaXMgcmVwbyBSRUFEUyBpdCAtIGl0IGlzIGxpc3RlZCBwcmVjaXNlbHlcbiAqIHNvIGEgaG9zdCBhcHAgdGhhdCBkb2VzIHJlYWQgaXQgY2Fubm90IGJlIGZlZCBvbmUuXG4gKi9cbmV4cG9ydCBjb25zdCBQUk9URUNURURfSEVBREVSUzogcmVhZG9ubHkgc3RyaW5nW10gPSBbXG4gIHRva2VuLkFDQ0VTU19UT0tFTl9IRUFERVIsXG4gIHRva2VuLlVTRVJfSURfSEVBREVSLFxuICB0b2tlbi5VU0VSX0VNQUlMX0hFQURFUixcbiAgXCJ4LWZvcndhcmRlZC1wcmVmZXJyZWQtdXNlcm5hbWVcIixcbiAgXCJ4LWZvcndhcmRlZC1ob3N0XCIsXG4gIFwieC1mb3J3YXJkZWQtcHJvdG9cIixcbiAgXCJ4LWZvcndhcmRlZC1wb3J0XCIsXG4gIFwieC1mb3J3YXJkZWQtZm9yXCIsXG4gIFwieC1yZWFsLWlwXCIsXG4gIFwieC1yZXF1ZXN0LWlkXCIsXG5dO1xuXG4vKipcbiAqIFRoZSBgeC1gIGhlYWRlcnMgZm9yd2FyZGVkIHdoZW4gYSBkZXBsb3ltZW50IGNvbmZpZ3VyZXMgbm90aGluZy5cbiAqXG4gKiBUaGVzZSBhcmUgdGhlIGhlYWRlciBOQU1FU1BBQ0VTIHRoaXMgcmVwbydzIG93biBVSSBzZW5kcyBhbmQgaXRzIG93biBzZXJ2ZXJcbiAqIHJlYWRzIC0gTWFzdHJhIHRocmVhZC9tb2RlbCByb3V0aW5nIChgeC1tYXN0cmEtdGhyZWFkLWlkYCwgYHgtbWFzdHJhLW1vZGVsYClcbiAqIGFuZCBNTGZsb3cgdHJhY2UgY29ycmVsYXRpb24gKGB4LW1sZmxvdy10cmFjZS1pZGApIC0gc28gYSBkYngtdG9vbHMgYXBwIGtlZXBzXG4gKiB3b3JraW5nIGJlaGluZCB0aGUgdHVubmVsIHdpdGggbm8gY29uZmlndXJhdGlvbi5cbiAqXG4gKiBEZWxpYmVyYXRlbHkgR0xPQlMgcmF0aGVyIHRoYW4gdGhlIGV4YWN0IGNvbnN0YW50cyBmcm9tXG4gKiBgQGRieC10b29scy9zaGFyZWQtbWFzdHJhYDogaW1wb3J0aW5nIHRoZW0gd291bGQgbWFrZSB0aGUgZ2F0ZSAtIGFcbiAqIHRyYW5zcG9ydC1sZXZlbCBjb21wb25lbnQgdGhhdCBoYXMgbm8gb3RoZXIgb3BpbmlvbiBhYm91dCBNYXN0cmEgLSBkZXBlbmQgb25cbiAqIGFuIGFnZW50IHBhY2thZ2UgZm9yIHRocmVlIHN0cmluZ3MsIGFuZCBhIG5hbWVzcGFjZSBnbG9iIGFsc28gY292ZXJzIHRoZSBuZXh0XG4gKiBoZWFkZXIgdGhvc2UgcGFja2FnZXMgYWRkLiBUaGUgbmFtZXNwYWNlcyBhcmUgdGhlIHN0YWJsZSBwYXJ0IG9mIHRoZSBjb250cmFjdC5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfRk9SV0FSRF9IRUFERVJTOiByZWFkb25seSBzdHJpbmdbXSA9IFtcbiAgXCJ4LW1hc3RyYS0qXCIsXG4gIFwieC1tbGZsb3ctKlwiLFxuICAvLyBTZW50IGJ5IGZldGNoL1hIUiB3cmFwcGVycyB0byBtYXJrIGFuIEFKQVggcmVxdWVzdDsgaGFybWxlc3MgYW5kIHdpZGVseSByZWFkLlxuICBcIngtcmVxdWVzdGVkLXdpdGhcIixcbl07XG5cbi8qKiBBIGNvbXBpbGVkIGluYm91bmQtaGVhZGVyIHBvbGljeS4gQnVpbGQgb25lIHdpdGgge0BsaW5rIHRvSGVhZGVyUG9saWN5fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSGVhZGVyUG9saWN5IHtcbiAgLyoqIFRoZSBhbGxvdy1saXN0IGVudHJpZXMgYmFja2luZyB0aGlzIHBvbGljeSAoZm9yIGRpYWdub3N0aWNzIGFuZCB0ZXN0cykuICovXG4gIHJlYWRvbmx5IHBhdHRlcm5zOiByZWFkb25seSBzdHJpbmdbXTtcbiAgLyoqIFdoZXRoZXIgYG5hbWVgIHN1cnZpdmVzIG9uIHR1bm5lbCB0cmFmZmljLiAqL1xuICBmb3J3YXJkcyhuYW1lOiBzdHJpbmcpOiBib29sZWFuO1xuICAvKipcbiAgICogRGVsZXRlIGV2ZXJ5IGRpc2FsbG93ZWQgaGVhZGVyIGZyb20gYSBtdXRhYmxlIE5vZGUgaGVhZGVyIGJhZywgcmV0dXJuaW5nIHRoZVxuICAgKiBsb3dlci1jYXNlZCBuYW1lcyByZW1vdmVkIChmb3IgZGVidWcgbG9nZ2luZykuXG4gICAqL1xuICBhcHBseShoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIENvbXBpbGUgdGhlIGluYm91bmQtaGVhZGVyIHBvbGljeS4gYGNvbmZpZ3VyZWRgIGVudHJpZXMgYXJlIFVOSU9ORUQgd2l0aFxuICoge0BsaW5rIERFRkFVTFRfRk9SV0FSRF9IRUFERVJTfTsgZWFjaCBtYXkgYmUgYSBsaXRlcmFsIG5hbWUsIGEgZ2xvYlxuICogKGB4LW15YXBwLSpgKSwgb3IgYSBgL3JlZ2V4L2AuIE1hdGNoaW5nIGlzIGNhc2UtaW5zZW5zaXRpdmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0hlYWRlclBvbGljeShjb25maWd1cmVkOiByZWFkb25seSBzdHJpbmdbXSA9IFtdKTogSGVhZGVyUG9saWN5IHtcbiAgY29uc3QgcGF0dGVybnMgPSBbLi4uREVGQVVMVF9GT1JXQVJEX0hFQURFUlMsIC4uLmNvbmZpZ3VyZWRdO1xuICBjb25zdCBhbGxvd2VkOiBQcmVkaWNhdGU8c3RyaW5nPiA9IHBhdHRlcm4udG9QYXR0ZXJuTWF0Y2hlcihwYXR0ZXJucyk7XG4gIGNvbnN0IHByb3RlY3RlZE5hbWVzID0gbmV3IFNldChQUk9URUNURURfSEVBREVSUyk7XG5cbiAgY29uc3QgZm9yd2FyZHMgPSAobmFtZTogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gICAgY29uc3QgbG93ZXIgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKHByb3RlY3RlZE5hbWVzLmhhcyhsb3dlcikpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIWxvd2VyLnN0YXJ0c1dpdGgoXCJ4LVwiKSkgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGFsbG93ZWQobG93ZXIpO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgcGF0dGVybnMsXG4gICAgZm9yd2FyZHMsXG4gICAgYXBwbHk6IChoZWFkZXJzKSA9PiB7XG4gICAgICBjb25zdCByZW1vdmVkOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKGhlYWRlcnMpKSB7XG4gICAgICAgIGlmIChmb3J3YXJkcyhuYW1lKSkgY29udGludWU7XG4gICAgICAgIGRlbGV0ZSBoZWFkZXJzW25hbWVdO1xuICAgICAgICByZW1vdmVkLnB1c2gobmFtZS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZW1vdmVkO1xuICAgIH0sXG4gIH07XG59XG4iXX0=
|
package/lib/src/otp.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* the hash, and the entry is deleted on success or once attempts are exhausted.
|
|
10
10
|
*
|
|
11
11
|
* The session JWT is a short-lived HS256 token (via `jose`) carrying only the
|
|
12
|
-
* email. Its signing key comes from `
|
|
12
|
+
* email. Its signing key comes from `TUNNEL_AUTH_JWT_SECRET`; when unset the gate uses an
|
|
13
13
|
* ephemeral per-process key rather than refusing service, so an unset secret
|
|
14
14
|
* degrades to "sessions don't survive a restart", not "nobody can log in". Note
|
|
15
15
|
* what this does NOT weaken: a caller still needs a code delivered to an
|
package/lib/src/otp.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* the hash, and the entry is deleted on success or once attempts are exhausted.
|
|
10
10
|
*
|
|
11
11
|
* The session JWT is a short-lived HS256 token (via `jose`) carrying only the
|
|
12
|
-
* email. Its signing key comes from `
|
|
12
|
+
* email. Its signing key comes from `TUNNEL_AUTH_JWT_SECRET`; when unset the gate uses an
|
|
13
13
|
* ephemeral per-process key rather than refusing service, so an unset secret
|
|
14
14
|
* degrades to "sessions don't survive a restart", not "nobody can log in". Note
|
|
15
15
|
* what this does NOT weaken: a caller still needs a code delivered to an
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { createHash, randomBytes, randomInt, timingSafeEqual } from "node:crypto";
|
|
23
23
|
import { CacheManager } from "@databricks/appkit";
|
|
24
|
-
import { log } from "@dbx-tools/shared-core";
|
|
24
|
+
import { env, log } from "@dbx-tools/shared-core";
|
|
25
25
|
import { jwtVerify, SignJWT } from "jose";
|
|
26
|
+
import { JWT_SECRET_ENV } from "./env.js";
|
|
26
27
|
const logger = log.logger("tunnel:otp");
|
|
27
28
|
/** JWT issuer/audience so a token minted for this gate isn't accepted elsewhere. */
|
|
28
29
|
const JWT_AUD = "dbx-tools-tunnel-auth";
|
|
@@ -91,19 +92,19 @@ export class CodeStore {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
/**
|
|
94
|
-
* Resolve the HS256 signing key. Prefers `
|
|
95
|
+
* Resolve the HS256 signing key. Prefers `TUNNEL_AUTH_JWT_SECRET`; when unset, mints an
|
|
95
96
|
* ephemeral per-process key (fail-open) and warns once. Memoized.
|
|
96
97
|
*/
|
|
97
98
|
let cachedKey;
|
|
98
99
|
function signingKey() {
|
|
99
100
|
if (cachedKey)
|
|
100
101
|
return cachedKey;
|
|
101
|
-
const secret =
|
|
102
|
+
const secret = env.text(JWT_SECRET_ENV);
|
|
102
103
|
if (secret) {
|
|
103
104
|
cachedKey = new TextEncoder().encode(secret);
|
|
104
105
|
}
|
|
105
106
|
else {
|
|
106
|
-
logger.warn(
|
|
107
|
+
logger.warn(`${JWT_SECRET_ENV[0]} is not set - using an ephemeral per-process key; sessions will not survive a restart`);
|
|
107
108
|
cachedKey = randomBytes(32);
|
|
108
109
|
}
|
|
109
110
|
return cachedKey;
|
|
@@ -134,4 +135,4 @@ export async function verifySession(token) {
|
|
|
134
135
|
return undefined;
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL290cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFMUMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUV4QyxvRkFBb0Y7QUFDcEYsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLENBQUM7QUFFeEMsb0ZBQW9GO0FBQ3BGLE1BQU0sV0FBVyxHQUFHLGFBQWEsQ0FBQztBQUVsQyw4QkFBOEI7QUFDOUIsU0FBUyxNQUFNLENBQUMsS0FBYTtJQUMzQixPQUFPLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFFRCw2REFBNkQ7QUFDN0QsU0FBUyxZQUFZLENBQUMsQ0FBUyxFQUFFLENBQVM7SUFDeEMsSUFBSSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxNQUFNO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDeEMsT0FBTyxlQUFlLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUN2RSxDQUFDO0FBVUQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFNBQVM7SUFFRDtJQUNB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QUFNLFVBQVUsZUFBZTtJQUM3QixTQUFTLEdBQUcsU0FBUyxDQUFDO0FBQ3hCLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQUMsS0FBYSxFQUFFLFVBQWtCO0lBQ2pFLE9BQU8sSUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQztTQUMxQixrQkFBa0IsQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQztTQUNwQyxVQUFVLENBQUMsS0FBSyxDQUFDO1NBQ2pCLFdBQVcsQ0FBQyxPQUFPLENBQUM7U0FDcEIsV0FBVyxFQUFFO1NBQ2IsaUJBQWlCLENBQUMsR0FBRyxVQUFVLEdBQUcsQ0FBQztTQUNuQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztBQUN4QixDQUFDO0FBRUQscUZBQXFGO0FBQ3JGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUFDLEtBQXlCO0lBQzNELElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0IsSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ2hGLE9BQU8sT0FBTyxPQUFPLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ3ZFLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT25lLXRpbWUtY29kZSBzdG9yZSArIHNlc3Npb24gSldUIGZvciB0aGUgZW1haWwtT1RQIHR1bm5lbCBnYXRlLlxuICpcbiAqIFRoZSBjb2RlIHN0b3JlIGlzIGJhY2tlZCBieSBBcHBLaXQncyBgQ2FjaGVNYW5hZ2VyYCAoYXV0by1jb25maWd1cmVkIHRvIG1lbW9yeSxcbiAqIG9yIExha2ViYXNlIHdoZW4gdGhlIGFwcCB3aXJlcyBhIHBlcnNpc3RlbnQgYENhY2hlU3RvcmFnZWApLCBzbyBUVEwgRVhQSVJZIGFuZFxuICogZXZpY3Rpb24gYXJlIHRoZSBjYWNoZSdzIGpvYiAtIG5vIGhhbmQtcm9sbGVkIE1hcCBvciB0aW1lcnMuIEEgNi1kaWdpdCBjb2RlIGlzXG4gKiBnZW5lcmF0ZWQgd2l0aCBgY3J5cHRvLnJhbmRvbUludGAgYW5kIHN0b3JlZCBhcyBhIFNIQS0yNTYgaGFzaCB3aXRoIGFuIGF0dGVtcHRcbiAqIGNvdW50ZXIgKG5ldmVyIHRoZSBwbGFpbnRleHQsIG5ldmVyIGluIHRoZSBKV1QpOyBgdmVyaWZ5YCBpcyBjb25zdGFudC10aW1lIG9uXG4gKiB0aGUgaGFzaCwgYW5kIHRoZSBlbnRyeSBpcyBkZWxldGVkIG9uIHN1Y2Nlc3Mgb3Igb25jZSBhdHRlbXB0cyBhcmUgZXhoYXVzdGVkLlxuICpcbiAqIFRoZSBzZXNzaW9uIEpXVCBpcyBhIHNob3J0LWxpdmVkIEhTMjU2IHRva2VuICh2aWEgYGpvc2VgKSBjYXJyeWluZyBvbmx5IHRoZVxuICogZW1haWwuIEl0cyBzaWduaW5nIGtleSBjb21lcyBmcm9tIGBBVVRIX0pXVF9TRUNSRVRgOyB3aGVuIHVuc2V0IHRoZSBnYXRlIHVzZXMgYW5cbiAqIGVwaGVtZXJhbCBwZXItcHJvY2VzcyBrZXkgcmF0aGVyIHRoYW4gcmVmdXNpbmcgc2VydmljZSwgc28gYW4gdW5zZXQgc2VjcmV0XG4gKiBkZWdyYWRlcyB0byBcInNlc3Npb25zIGRvbid0IHN1cnZpdmUgYSByZXN0YXJ0XCIsIG5vdCBcIm5vYm9keSBjYW4gbG9nIGluXCIuIE5vdGVcbiAqIHdoYXQgdGhpcyBkb2VzIE5PVCB3ZWFrZW46IGEgY2FsbGVyIHN0aWxsIG5lZWRzIGEgY29kZSBkZWxpdmVyZWQgdG8gYW5cbiAqIGFsbG93LWxpc3RlZCBhZGRyZXNzLCBiZWNhdXNlIHRoZSBzaWduaW5nIGtleSBvbmx5IHZhbGlkYXRlcyBhbiBBTFJFQURZLWlzc3VlZFxuICogc2Vzc2lvbi4gU2V0IGl0IGluIGFueSBkZXBsb3ltZW50IHJ1bm5pbmcgbW9yZSB0aGFuIG9uZSBpbnN0YW5jZSwgb3Igc2Vzc2lvbnNcbiAqIG1pbnRlZCBieSBvbmUgd2lsbCBub3QgdmVyaWZ5IG9uIGFub3RoZXIuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUhhc2gsIHJhbmRvbUJ5dGVzLCByYW5kb21JbnQsIHRpbWluZ1NhZmVFcXVhbCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgQ2FjaGVNYW5hZ2VyIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGp3dFZlcmlmeSwgU2lnbkpXVCB9IGZyb20gXCJqb3NlXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6b3RwXCIpO1xuXG4vKiogSldUIGlzc3Vlci9hdWRpZW5jZSBzbyBhIHRva2VuIG1pbnRlZCBmb3IgdGhpcyBnYXRlIGlzbid0IGFjY2VwdGVkIGVsc2V3aGVyZS4gKi9cbmNvbnN0IEpXVF9BVUQgPSBcImRieC10b29scy10dW5uZWwtYXV0aFwiO1xuXG4vKiogQ2FjaGUta2V5IHByZWZpeCBmb3IgcGVuZGluZyBjb2RlcywgbmFtZXNwYWNlZCBhd2F5IGZyb20gYW55IG90aGVyIGNhY2hlIHVzZS4gKi9cbmNvbnN0IENPREVfUFJFRklYID0gXCJ0dW5uZWw6b3RwOlwiO1xuXG4vKiogU0hBLTI1NiBoZXggb2YgYSB2YWx1ZS4gKi9cbmZ1bmN0aW9uIHNoYTI1Nih2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHZhbHVlKS5kaWdlc3QoXCJoZXhcIik7XG59XG5cbi8qKiBDb25zdGFudC10aW1lIGNvbXBhcmUgb2YgdHdvIGVxdWFsLWxlbmd0aCBoZXggZGlnZXN0cy4gKi9cbmZ1bmN0aW9uIHNhZmVFcXVhbEhleChhOiBzdHJpbmcsIGI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0aW1pbmdTYWZlRXF1YWwoQnVmZmVyLmZyb20oYSwgXCJoZXhcIiksIEJ1ZmZlci5mcm9tKGIsIFwiaGV4XCIpKTtcbn1cblxuaW50ZXJmYWNlIENvZGVFbnRyeSB7XG4gIGhhc2g6IHN0cmluZztcbiAgYXR0ZW1wdHM6IG51bWJlcjtcbn1cblxuLyoqIFJlc3VsdCBvZiB7QGxpbmsgQ29kZVN0b3JlLnZlcmlmeX0uICovXG5leHBvcnQgdHlwZSBWZXJpZnlPdXRjb21lID0gXCJva1wiIHwgXCJpbnZhbGlkXCIgfCBcImV4cGlyZWRcIiB8IFwidG9vLW1hbnktYXR0ZW1wdHNcIjtcblxuLyoqXG4gKiBQZW5kaW5nIG9uZS10aW1lIGNvZGVzLCBzdG9yZWQgaW4gQXBwS2l0J3MgY2FjaGUga2V5ZWQgYnkgbG93ZXJjYXNlZCBlbWFpbC5cbiAqIEV4cGlyeSBpcyB0aGUgY2FjaGUncyBUVEwgKG5vIG1hbnVhbCBjbG9jayk7IGEgbWlzcyBtZWFucyBleHBpcmVkLW9yLW5ldmVyLlxuICovXG5leHBvcnQgY2xhc3MgQ29kZVN0b3JlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSB0dGxTZWNvbmRzOiBudW1iZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBtYXhBdHRlbXB0czogbnVtYmVyLFxuICApIHt9XG5cbiAgcHJpdmF0ZSBjYWNoZSgpOiBDYWNoZU1hbmFnZXIge1xuICAgIHJldHVybiBDYWNoZU1hbmFnZXIuZ2V0SW5zdGFuY2VTeW5jKCk7XG4gIH1cblxuICBwcml2YXRlIGtleShlbWFpbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7Q09ERV9QUkVGSVh9JHtlbWFpbC50b0xvd2VyQ2FzZSgpfWA7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUsIHN0b3JlIChoYXNoZWQsIHdpdGggdGhlIGNhY2hlIFRUTCksIGFuZCBSRVRVUk4gYSBmcmVzaCA2LWRpZ2l0XG4gICAqIGNvZGUuIFRoZSBjYWxsZXIgZW1haWxzIHRoZSByZXR1cm5lZCBwbGFpbnRleHQ7IG9ubHkgdGhlIGhhc2ggaXMgcmV0YWluZWQuXG4gICAqIFJlcGxhY2VzIGFueSBwZW5kaW5nIGNvZGUgZm9yIHRoZSBhZGRyZXNzLlxuICAgKi9cbiAgYXN5bmMgaXNzdWUoZW1haWw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgY29kZSA9IFN0cmluZyhyYW5kb21JbnQoMCwgMV8wMDBfMDAwKSkucGFkU3RhcnQoNiwgXCIwXCIpO1xuICAgIGNvbnN0IGVudHJ5OiBDb2RlRW50cnkgPSB7IGhhc2g6IHNoYTI1Nihjb2RlKSwgYXR0ZW1wdHM6IDAgfTtcbiAgICBhd2FpdCB0aGlzLmNhY2hlKCkuc2V0KHRoaXMua2V5KGVtYWlsKSwgZW50cnksIHsgdHRsOiB0aGlzLnR0bFNlY29uZHMgfSk7XG4gICAgcmV0dXJuIGNvZGU7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgYGNvZGVgIGZvciBgZW1haWxgLiBBIGNhY2hlIG1pc3MgaXMgYGV4cGlyZWRgIChUVEwgZWxhcHNlZCBvciBuZXZlclxuICAgKiBpc3N1ZWQpLiBEZWxldGVzIHRoZSBlbnRyeSBvbiBzdWNjZXNzIG9yIHdoZW4gYXR0ZW1wdHMgYXJlIGV4aGF1c3RlZCwgc28gYVxuICAgKiBjb2RlIGlzIHNpbmdsZS11c2UgYW5kIGNhbid0IGJlIGJydXRlLWZvcmNlZCBwYXN0IHRoZSBjYXAuIEFuIGF0dGVtcHRcbiAgICogaW5jcmVtZW50cyB0aGUgc3RvcmVkIGNvdW50ZXIgKHJlLXBlcnNpc3RlZCB3aXRoIGEgZnJlc2ggVFRMIHdpbmRvdykuXG4gICAqL1xuICBhc3luYyB2ZXJpZnkoZW1haWw6IHN0cmluZywgY29kZTogc3RyaW5nKTogUHJvbWlzZTxWZXJpZnlPdXRjb21lPiB7XG4gICAgY29uc3Qga2V5ID0gdGhpcy5rZXkoZW1haWwpO1xuICAgIGNvbnN0IGVudHJ5ID0gYXdhaXQgdGhpcy5jYWNoZSgpLmdldDxDb2RlRW50cnk+KGtleSk7XG4gICAgaWYgKCFlbnRyeSkgcmV0dXJuIFwiZXhwaXJlZFwiO1xuICAgIGNvbnN0IGF0dGVtcHRzID0gZW50cnkuYXR0ZW1wdHMgKyAxO1xuICAgIGlmIChzYWZlRXF1YWxIZXgoZW50cnkuaGFzaCwgc2hhMjU2KGNvZGUpKSkge1xuICAgICAgYXdhaXQgdGhpcy5jYWNoZSgpLmRlbGV0ZShrZXkpO1xuICAgICAgcmV0dXJuIFwib2tcIjtcbiAgICB9XG4gICAgaWYgKGF0dGVtcHRzID49IHRoaXMubWF4QXR0ZW1wdHMpIHtcbiAgICAgIGF3YWl0IHRoaXMuY2FjaGUoKS5kZWxldGUoa2V5KTtcbiAgICAgIHJldHVybiBcInRvby1tYW55LWF0dGVtcHRzXCI7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuY2FjaGUoKS5zZXQoa2V5LCB7IC4uLmVudHJ5LCBhdHRlbXB0cyB9LCB7IHR0bDogdGhpcy50dGxTZWNvbmRzIH0pO1xuICAgIHJldHVybiBcImludmFsaWRcIjtcbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIEhTMjU2IHNpZ25pbmcga2V5LiBQcmVmZXJzIGBBVVRIX0pXVF9TRUNSRVRgOyB3aGVuIHVuc2V0LCBtaW50cyBhblxuICogZXBoZW1lcmFsIHBlci1wcm9jZXNzIGtleSAoZmFpbC1vcGVuKSBhbmQgd2FybnMgb25jZS4gTWVtb2l6ZWQuXG4gKi9cbmxldCBjYWNoZWRLZXk6IFVpbnQ4QXJyYXkgfCB1bmRlZmluZWQ7XG5mdW5jdGlvbiBzaWduaW5nS2V5KCk6IFVpbnQ4QXJyYXkge1xuICBpZiAoY2FjaGVkS2V5KSByZXR1cm4gY2FjaGVkS2V5O1xuICBjb25zdCBzZWNyZXQgPSBwcm9jZXNzLmVudi5BVVRIX0pXVF9TRUNSRVQ/LnRyaW0oKTtcbiAgaWYgKHNlY3JldCkge1xuICAgIGNhY2hlZEtleSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWNyZXQpO1xuICB9IGVsc2Uge1xuICAgIGxvZ2dlci53YXJuKFxuICAgICAgXCJBVVRIX0pXVF9TRUNSRVQgaXMgbm90IHNldCAtIHVzaW5nIGFuIGVwaGVtZXJhbCBwZXItcHJvY2VzcyBrZXk7IHNlc3Npb25zIHdpbGwgbm90IHN1cnZpdmUgYSByZXN0YXJ0XCIsXG4gICAgKTtcbiAgICBjYWNoZWRLZXkgPSByYW5kb21CeXRlcygzMik7XG4gIH1cbiAgcmV0dXJuIGNhY2hlZEtleTtcbn1cblxuLyoqIFJlc2V0IHRoZSBtZW1vaXplZCBrZXkgKHRlc3RzLCBvciBhZnRlciBjaGFuZ2luZyB0aGUgZW52IGluLXByb2Nlc3MpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0U2lnbmluZ0tleSgpOiB2b2lkIHtcbiAgY2FjaGVkS2V5ID0gdW5kZWZpbmVkO1xufVxuXG4vKiogTWludCBhIHNob3J0LWxpdmVkIHNlc3Npb24gSldUIGZvciBgZW1haWxgLCBleHBpcmluZyBpbiBgdHRsU2Vjb25kc2AuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnblNlc3Npb24oZW1haWw6IHN0cmluZywgdHRsU2Vjb25kczogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIG5ldyBTaWduSldUKHsgZW1haWwgfSlcbiAgICAuc2V0UHJvdGVjdGVkSGVhZGVyKHsgYWxnOiBcIkhTMjU2XCIgfSlcbiAgICAuc2V0U3ViamVjdChlbWFpbClcbiAgICAuc2V0QXVkaWVuY2UoSldUX0FVRClcbiAgICAuc2V0SXNzdWVkQXQoKVxuICAgIC5zZXRFeHBpcmF0aW9uVGltZShgJHt0dGxTZWNvbmRzfXNgKVxuICAgIC5zaWduKHNpZ25pbmdLZXkoKSk7XG59XG5cbi8qKiBWYWxpZGF0ZSBhIHNlc3Npb24gSldULCByZXR1cm5pbmcgdGhlIGVtYWlsIGl0IHdhcyBtaW50ZWQgZm9yLCBvciBgdW5kZWZpbmVkYC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlTZXNzaW9uKHRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBpZiAoIXRva2VuKSByZXR1cm4gdW5kZWZpbmVkO1xuICB0cnkge1xuICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgand0VmVyaWZ5KHRva2VuLCBzaWduaW5nS2V5KCksIHsgYXVkaWVuY2U6IEpXVF9BVUQgfSk7XG4gICAgcmV0dXJuIHR5cGVvZiBwYXlsb2FkLmVtYWlsID09PSBcInN0cmluZ1wiID8gcGF5bG9hZC5lbWFpbCA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
|
|
138
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL290cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFMUMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUV4QyxvRkFBb0Y7QUFDcEYsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLENBQUM7QUFFeEMsb0ZBQW9GO0FBQ3BGLE1BQU0sV0FBVyxHQUFHLGFBQWEsQ0FBQztBQUVsQyw4QkFBOEI7QUFDOUIsU0FBUyxNQUFNLENBQUMsS0FBYTtJQUMzQixPQUFPLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFFRCw2REFBNkQ7QUFDN0QsU0FBUyxZQUFZLENBQUMsQ0FBUyxFQUFFLENBQVM7SUFDeEMsSUFBSSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxNQUFNO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDeEMsT0FBTyxlQUFlLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztB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Q0FBQztJQUM5QixDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSxNQUFNLFVBQVUsZUFBZTtJQUM3QixTQUFTLEdBQUcsU0FBUyxDQUFDO0FBQ3hCLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQUMsS0FBYSxFQUFFLFVBQWtCO0lBQ2pFLE9BQU8sSUFBSSxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQztTQUMxQixrQkFBa0IsQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQztTQUNwQyxVQUFVLENBQUMsS0FBSyxDQUFDO1NBQ2pCLFdBQVcsQ0FBQyxPQUFPLENBQUM7U0FDcEIsV0FBVyxFQUFFO1NBQ2IsaUJBQWlCLENBQUMsR0FBRyxVQUFVLEdBQUcsQ0FBQztTQUNuQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztBQUN4QixDQUFDO0FBRUQscUZBQXFGO0FBQ3JGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsYUFBYSxDQUFDLEtBQXlCO0lBQzNELElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDN0IsSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sU0FBUyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ2hGLE9BQU8sT0FBTyxPQUFPLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ3ZFLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT25lLXRpbWUtY29kZSBzdG9yZSArIHNlc3Npb24gSldUIGZvciB0aGUgZW1haWwtT1RQIHR1bm5lbCBnYXRlLlxuICpcbiAqIFRoZSBjb2RlIHN0b3JlIGlzIGJhY2tlZCBieSBBcHBLaXQncyBgQ2FjaGVNYW5hZ2VyYCAoYXV0by1jb25maWd1cmVkIHRvIG1lbW9yeSxcbiAqIG9yIExha2ViYXNlIHdoZW4gdGhlIGFwcCB3aXJlcyBhIHBlcnNpc3RlbnQgYENhY2hlU3RvcmFnZWApLCBzbyBUVEwgRVhQSVJZIGFuZFxuICogZXZpY3Rpb24gYXJlIHRoZSBjYWNoZSdzIGpvYiAtIG5vIGhhbmQtcm9sbGVkIE1hcCBvciB0aW1lcnMuIEEgNi1kaWdpdCBjb2RlIGlzXG4gKiBnZW5lcmF0ZWQgd2l0aCBgY3J5cHRvLnJhbmRvbUludGAgYW5kIHN0b3JlZCBhcyBhIFNIQS0yNTYgaGFzaCB3aXRoIGFuIGF0dGVtcHRcbiAqIGNvdW50ZXIgKG5ldmVyIHRoZSBwbGFpbnRleHQsIG5ldmVyIGluIHRoZSBKV1QpOyBgdmVyaWZ5YCBpcyBjb25zdGFudC10aW1lIG9uXG4gKiB0aGUgaGFzaCwgYW5kIHRoZSBlbnRyeSBpcyBkZWxldGVkIG9uIHN1Y2Nlc3Mgb3Igb25jZSBhdHRlbXB0cyBhcmUgZXhoYXVzdGVkLlxuICpcbiAqIFRoZSBzZXNzaW9uIEpXVCBpcyBhIHNob3J0LWxpdmVkIEhTMjU2IHRva2VuICh2aWEgYGpvc2VgKSBjYXJyeWluZyBvbmx5IHRoZVxuICogZW1haWwuIEl0cyBzaWduaW5nIGtleSBjb21lcyBmcm9tIGBUVU5ORUxfQVVUSF9KV1RfU0VDUkVUYDsgd2hlbiB1bnNldCB0aGUgZ2F0ZSB1c2VzIGFuXG4gKiBlcGhlbWVyYWwgcGVyLXByb2Nlc3Mga2V5IHJhdGhlciB0aGFuIHJlZnVzaW5nIHNlcnZpY2UsIHNvIGFuIHVuc2V0IHNlY3JldFxuICogZGVncmFkZXMgdG8gXCJzZXNzaW9ucyBkb24ndCBzdXJ2aXZlIGEgcmVzdGFydFwiLCBub3QgXCJub2JvZHkgY2FuIGxvZyBpblwiLiBOb3RlXG4gKiB3aGF0IHRoaXMgZG9lcyBOT1Qgd2Vha2VuOiBhIGNhbGxlciBzdGlsbCBuZWVkcyBhIGNvZGUgZGVsaXZlcmVkIHRvIGFuXG4gKiBhbGxvdy1saXN0ZWQgYWRkcmVzcywgYmVjYXVzZSB0aGUgc2lnbmluZyBrZXkgb25seSB2YWxpZGF0ZXMgYW4gQUxSRUFEWS1pc3N1ZWRcbiAqIHNlc3Npb24uIFNldCBpdCBpbiBhbnkgZGVwbG95bWVudCBydW5uaW5nIG1vcmUgdGhhbiBvbmUgaW5zdGFuY2UsIG9yIHNlc3Npb25zXG4gKiBtaW50ZWQgYnkgb25lIHdpbGwgbm90IHZlcmlmeSBvbiBhbm90aGVyLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVIYXNoLCByYW5kb21CeXRlcywgcmFuZG9tSW50LCB0aW1pbmdTYWZlRXF1YWwgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IENhY2hlTWFuYWdlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGVudiwgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGp3dFZlcmlmeSwgU2lnbkpXVCB9IGZyb20gXCJqb3NlXCI7XG5pbXBvcnQgeyBKV1RfU0VDUkVUX0VOViB9IGZyb20gXCIuL2Vudi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOm90cFwiKTtcblxuLyoqIEpXVCBpc3N1ZXIvYXVkaWVuY2Ugc28gYSB0b2tlbiBtaW50ZWQgZm9yIHRoaXMgZ2F0ZSBpc24ndCBhY2NlcHRlZCBlbHNld2hlcmUuICovXG5jb25zdCBKV1RfQVVEID0gXCJkYngtdG9vbHMtdHVubmVsLWF1dGhcIjtcblxuLyoqIENhY2hlLWtleSBwcmVmaXggZm9yIHBlbmRpbmcgY29kZXMsIG5hbWVzcGFjZWQgYXdheSBmcm9tIGFueSBvdGhlciBjYWNoZSB1c2UuICovXG5jb25zdCBDT0RFX1BSRUZJWCA9IFwidHVubmVsOm90cDpcIjtcblxuLyoqIFNIQS0yNTYgaGV4IG9mIGEgdmFsdWUuICovXG5mdW5jdGlvbiBzaGEyNTYodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZSh2YWx1ZSkuZGlnZXN0KFwiaGV4XCIpO1xufVxuXG4vKiogQ29uc3RhbnQtdGltZSBjb21wYXJlIG9mIHR3byBlcXVhbC1sZW5ndGggaGV4IGRpZ2VzdHMuICovXG5mdW5jdGlvbiBzYWZlRXF1YWxIZXgoYTogc3RyaW5nLCBiOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKGEubGVuZ3RoICE9PSBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdGltaW5nU2FmZUVxdWFsKEJ1ZmZlci5mcm9tKGEsIFwiaGV4XCIpLCBCdWZmZXIuZnJvbShiLCBcImhleFwiKSk7XG59XG5cbmludGVyZmFjZSBDb2RlRW50cnkge1xuICBoYXNoOiBzdHJpbmc7XG4gIGF0dGVtcHRzOiBudW1iZXI7XG59XG5cbi8qKiBSZXN1bHQgb2Yge0BsaW5rIENvZGVTdG9yZS52ZXJpZnl9LiAqL1xuZXhwb3J0IHR5cGUgVmVyaWZ5T3V0Y29tZSA9IFwib2tcIiB8IFwiaW52YWxpZFwiIHwgXCJleHBpcmVkXCIgfCBcInRvby1tYW55LWF0dGVtcHRzXCI7XG5cbi8qKlxuICogUGVuZGluZyBvbmUtdGltZSBjb2Rlcywgc3RvcmVkIGluIEFwcEtpdCdzIGNhY2hlIGtleWVkIGJ5IGxvd2VyY2FzZWQgZW1haWwuXG4gKiBFeHBpcnkgaXMgdGhlIGNhY2hlJ3MgVFRMIChubyBtYW51YWwgY2xvY2spOyBhIG1pc3MgbWVhbnMgZXhwaXJlZC1vci1uZXZlci5cbiAqL1xuZXhwb3J0IGNsYXNzIENvZGVTdG9yZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdHRsU2Vjb25kczogbnVtYmVyLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbWF4QXR0ZW1wdHM6IG51bWJlcixcbiAgKSB7fVxuXG4gIHByaXZhdGUgY2FjaGUoKTogQ2FjaGVNYW5hZ2VyIHtcbiAgICByZXR1cm4gQ2FjaGVNYW5hZ2VyLmdldEluc3RhbmNlU3luYygpO1xuICB9XG5cbiAgcHJpdmF0ZSBrZXkoZW1haWw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke0NPREVfUFJFRklYfSR7ZW1haWwudG9Mb3dlckNhc2UoKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlLCBzdG9yZSAoaGFzaGVkLCB3aXRoIHRoZSBjYWNoZSBUVEwpLCBhbmQgUkVUVVJOIGEgZnJlc2ggNi1kaWdpdFxuICAgKiBjb2RlLiBUaGUgY2FsbGVyIGVtYWlscyB0aGUgcmV0dXJuZWQgcGxhaW50ZXh0OyBvbmx5IHRoZSBoYXNoIGlzIHJldGFpbmVkLlxuICAgKiBSZXBsYWNlcyBhbnkgcGVuZGluZyBjb2RlIGZvciB0aGUgYWRkcmVzcy5cbiAgICovXG4gIGFzeW5jIGlzc3VlKGVtYWlsOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGNvZGUgPSBTdHJpbmcocmFuZG9tSW50KDAsIDFfMDAwXzAwMCkpLnBhZFN0YXJ0KDYsIFwiMFwiKTtcbiAgICBjb25zdCBlbnRyeTogQ29kZUVudHJ5ID0geyBoYXNoOiBzaGEyNTYoY29kZSksIGF0dGVtcHRzOiAwIH07XG4gICAgYXdhaXQgdGhpcy5jYWNoZSgpLnNldCh0aGlzLmtleShlbWFpbCksIGVudHJ5LCB7IHR0bDogdGhpcy50dGxTZWNvbmRzIH0pO1xuICAgIHJldHVybiBjb2RlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGBjb2RlYCBmb3IgYGVtYWlsYC4gQSBjYWNoZSBtaXNzIGlzIGBleHBpcmVkYCAoVFRMIGVsYXBzZWQgb3IgbmV2ZXJcbiAgICogaXNzdWVkKS4gRGVsZXRlcyB0aGUgZW50cnkgb24gc3VjY2VzcyBvciB3aGVuIGF0dGVtcHRzIGFyZSBleGhhdXN0ZWQsIHNvIGFcbiAgICogY29kZSBpcyBzaW5nbGUtdXNlIGFuZCBjYW4ndCBiZSBicnV0ZS1mb3JjZWQgcGFzdCB0aGUgY2FwLiBBbiBhdHRlbXB0XG4gICAqIGluY3JlbWVudHMgdGhlIHN0b3JlZCBjb3VudGVyIChyZS1wZXJzaXN0ZWQgd2l0aCBhIGZyZXNoIFRUTCB3aW5kb3cpLlxuICAgKi9cbiAgYXN5bmMgdmVyaWZ5KGVtYWlsOiBzdHJpbmcsIGNvZGU6IHN0cmluZyk6IFByb21pc2U8VmVyaWZ5T3V0Y29tZT4ge1xuICAgIGNvbnN0IGtleSA9IHRoaXMua2V5KGVtYWlsKTtcbiAgICBjb25zdCBlbnRyeSA9IGF3YWl0IHRoaXMuY2FjaGUoKS5nZXQ8Q29kZUVudHJ5PihrZXkpO1xuICAgIGlmICghZW50cnkpIHJldHVybiBcImV4cGlyZWRcIjtcbiAgICBjb25zdCBhdHRlbXB0cyA9IGVudHJ5LmF0dGVtcHRzICsgMTtcbiAgICBpZiAoc2FmZUVxdWFsSGV4KGVudHJ5Lmhhc2gsIHNoYTI1Nihjb2RlKSkpIHtcbiAgICAgIGF3YWl0IHRoaXMuY2FjaGUoKS5kZWxldGUoa2V5KTtcbiAgICAgIHJldHVybiBcIm9rXCI7XG4gICAgfVxuICAgIGlmIChhdHRlbXB0cyA+PSB0aGlzLm1heEF0dGVtcHRzKSB7XG4gICAgICBhd2FpdCB0aGlzLmNhY2hlKCkuZGVsZXRlKGtleSk7XG4gICAgICByZXR1cm4gXCJ0b28tbWFueS1hdHRlbXB0c1wiO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLmNhY2hlKCkuc2V0KGtleSwgeyAuLi5lbnRyeSwgYXR0ZW1wdHMgfSwgeyB0dGw6IHRoaXMudHRsU2Vjb25kcyB9KTtcbiAgICByZXR1cm4gXCJpbnZhbGlkXCI7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBIUzI1NiBzaWduaW5nIGtleS4gUHJlZmVycyBgVFVOTkVMX0FVVEhfSldUX1NFQ1JFVGA7IHdoZW4gdW5zZXQsIG1pbnRzIGFuXG4gKiBlcGhlbWVyYWwgcGVyLXByb2Nlc3Mga2V5IChmYWlsLW9wZW4pIGFuZCB3YXJucyBvbmNlLiBNZW1vaXplZC5cbiAqL1xubGV0IGNhY2hlZEtleTogVWludDhBcnJheSB8IHVuZGVmaW5lZDtcbmZ1bmN0aW9uIHNpZ25pbmdLZXkoKTogVWludDhBcnJheSB7XG4gIGlmIChjYWNoZWRLZXkpIHJldHVybiBjYWNoZWRLZXk7XG4gIGNvbnN0IHNlY3JldCA9IGVudi50ZXh0KEpXVF9TRUNSRVRfRU5WKTtcbiAgaWYgKHNlY3JldCkge1xuICAgIGNhY2hlZEtleSA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzZWNyZXQpO1xuICB9IGVsc2Uge1xuICAgIGxvZ2dlci53YXJuKFxuICAgICAgYCR7SldUX1NFQ1JFVF9FTlZbMF19IGlzIG5vdCBzZXQgLSB1c2luZyBhbiBlcGhlbWVyYWwgcGVyLXByb2Nlc3Mga2V5OyBzZXNzaW9ucyB3aWxsIG5vdCBzdXJ2aXZlIGEgcmVzdGFydGAsXG4gICAgKTtcbiAgICBjYWNoZWRLZXkgPSByYW5kb21CeXRlcygzMik7XG4gIH1cbiAgcmV0dXJuIGNhY2hlZEtleTtcbn1cblxuLyoqIFJlc2V0IHRoZSBtZW1vaXplZCBrZXkgKHRlc3RzLCBvciBhZnRlciBjaGFuZ2luZyB0aGUgZW52IGluLXByb2Nlc3MpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0U2lnbmluZ0tleSgpOiB2b2lkIHtcbiAgY2FjaGVkS2V5ID0gdW5kZWZpbmVkO1xufVxuXG4vKiogTWludCBhIHNob3J0LWxpdmVkIHNlc3Npb24gSldUIGZvciBgZW1haWxgLCBleHBpcmluZyBpbiBgdHRsU2Vjb25kc2AuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnblNlc3Npb24oZW1haWw6IHN0cmluZywgdHRsU2Vjb25kczogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIG5ldyBTaWduSldUKHsgZW1haWwgfSlcbiAgICAuc2V0UHJvdGVjdGVkSGVhZGVyKHsgYWxnOiBcIkhTMjU2XCIgfSlcbiAgICAuc2V0U3ViamVjdChlbWFpbClcbiAgICAuc2V0QXVkaWVuY2UoSldUX0FVRClcbiAgICAuc2V0SXNzdWVkQXQoKVxuICAgIC5zZXRFeHBpcmF0aW9uVGltZShgJHt0dGxTZWNvbmRzfXNgKVxuICAgIC5zaWduKHNpZ25pbmdLZXkoKSk7XG59XG5cbi8qKiBWYWxpZGF0ZSBhIHNlc3Npb24gSldULCByZXR1cm5pbmcgdGhlIGVtYWlsIGl0IHdhcyBtaW50ZWQgZm9yLCBvciBgdW5kZWZpbmVkYC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlTZXNzaW9uKHRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBpZiAoIXRva2VuKSByZXR1cm4gdW5kZWZpbmVkO1xuICB0cnkge1xuICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgand0VmVyaWZ5KHRva2VuLCBzaWduaW5nS2V5KCksIHsgYXVkaWVuY2U6IEpXVF9BVUQgfSk7XG4gICAgcmV0dXJuIHR5cGVvZiBwYXlsb2FkLmVtYWlsID09PSBcInN0cmluZ1wiID8gcGF5bG9hZC5lbWFpbCA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
|
package/lib/src/plugin.d.ts
CHANGED
|
@@ -19,10 +19,10 @@ import { Plugin, type BasePluginConfig } from "@databricks/appkit";
|
|
|
19
19
|
import type { AuthStatus } from "@dbx-tools/shared-email";
|
|
20
20
|
/** Options for the {@link authGate} plugin (all resolvable from env - see below). */
|
|
21
21
|
export interface AuthGateConfig extends BasePluginConfig {
|
|
22
|
-
/** Allow-list patterns (domain / glob / `/regex/`). Empty = allow nobody. Env
|
|
22
|
+
/** Allow-list patterns (domain / glob / `/regex/`). Empty = allow nobody. Env TUNNEL_AUTH_ALLOW. */
|
|
23
23
|
allow?: string | string[];
|
|
24
24
|
/**
|
|
25
|
-
* Subject line for the code email. Env
|
|
25
|
+
* Subject line for the code email. Env TUNNEL_AUTH_SUBJECT.
|
|
26
26
|
*
|
|
27
27
|
* Defaults to "Your verification code". The wording of the subject and
|
|
28
28
|
* {@link message} is deliberately the conventional phrasing rather than
|
|
@@ -32,7 +32,7 @@ export interface AuthGateConfig extends BasePluginConfig {
|
|
|
32
32
|
*/
|
|
33
33
|
subject?: string;
|
|
34
34
|
/**
|
|
35
|
-
* Display name used in the code email copy. Env
|
|
35
|
+
* Display name used in the code email copy. Env TUNNEL_AUTH_BRAND_NAME.
|
|
36
36
|
*
|
|
37
37
|
* Defaults to the brand context's `name` - the app's own `branding/brand.yaml`
|
|
38
38
|
* when it has one, else the dbx-tools default. Set this only to override the
|
|
@@ -40,15 +40,15 @@ export interface AuthGateConfig extends BasePluginConfig {
|
|
|
40
40
|
*/
|
|
41
41
|
brandName?: string;
|
|
42
42
|
/**
|
|
43
|
-
* Line shown immediately above the code in the email. Env
|
|
43
|
+
* Line shown immediately above the code in the email. Env TUNNEL_AUTH_MESSAGE.
|
|
44
44
|
*
|
|
45
45
|
* Keep the code on its OWN line directly after this text - that adjacency is
|
|
46
46
|
* what the platform code-detection heuristics key on.
|
|
47
47
|
*/
|
|
48
48
|
message?: string;
|
|
49
|
-
/** Session lifetime (seconds). Env
|
|
49
|
+
/** Session lifetime (seconds). Env TUNNEL_AUTH_SESSION_TTL. Default 43200 (12h). */
|
|
50
50
|
sessionTtlSeconds?: number;
|
|
51
|
-
/** One-time-code lifetime (seconds). Env
|
|
51
|
+
/** One-time-code lifetime (seconds). Env TUNNEL_AUTH_CODE_TTL. Default 600 (10m). */
|
|
52
52
|
codeTtlSeconds?: number;
|
|
53
53
|
/** Max verify attempts per issued code. Default 5. */
|
|
54
54
|
maxAttempts?: number;
|
package/lib/src/plugin.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { Plugin, toPlugin } from "@databricks/appkit";
|
|
19
19
|
import { brand, env, log, string } from "@dbx-tools/shared-core";
|
|
20
20
|
import { looksLikeEmail, matchesAllowlist } from "./allowlist.js";
|
|
21
|
+
import { ALLOW_ENV, BRAND_NAME_ENV, CODE_TTL_ENV, MESSAGE_ENV, SESSION_TTL_ENV, SUBJECT_ENV, } from "./env.js";
|
|
21
22
|
import { CodeStore, signSession, verifySession } from "./otp.js";
|
|
22
23
|
import { RateLimiter } from "./rate-limit.js";
|
|
23
24
|
const logger = log.logger("tunnel:auth");
|
|
@@ -39,13 +40,15 @@ const DEFAULTS = {
|
|
|
39
40
|
export function resolveAuthGateConfig(config) {
|
|
40
41
|
return {
|
|
41
42
|
// Both sources are unioned rather than one overriding: a deployment-wide
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
// TUNNEL_AUTH_ALLOW and a per-invocation `--allow` should both grant access.
|
|
44
|
+
// Hence `parseList` on each rather than `env.list`, which stops at the first
|
|
45
|
+
// source that yields anything.
|
|
46
|
+
allow: [...string.parseList(config.allow), ...string.parseList(env.text(ALLOW_ENV))],
|
|
47
|
+
subject: env.string(config.subject, SUBJECT_ENV) ?? DEFAULTS.subject,
|
|
48
|
+
brandName: env.string(config.brandName, BRAND_NAME_ENV) ?? DEFAULTS.brandName,
|
|
49
|
+
message: env.string(config.message, MESSAGE_ENV) ?? DEFAULTS.message,
|
|
50
|
+
sessionTtlSeconds: env.positiveInt(config.sessionTtlSeconds, SESSION_TTL_ENV, DEFAULTS.sessionTtlSeconds),
|
|
51
|
+
codeTtlSeconds: env.positiveInt(config.codeTtlSeconds, CODE_TTL_ENV, DEFAULTS.codeTtlSeconds),
|
|
49
52
|
maxAttempts: config.maxAttempts ?? DEFAULTS.maxAttempts,
|
|
50
53
|
};
|
|
51
54
|
}
|
|
@@ -124,4 +127,4 @@ export class AuthGatePlugin extends Plugin {
|
|
|
124
127
|
}
|
|
125
128
|
/** Factory: `authGate({ allow, subject, ... })` for an AppKit `plugins` array. */
|
|
126
129
|
export const authGate = toPlugin(AuthGatePlugin);
|
|
127
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUE4QyxNQUFNLG9CQUFvQixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU5QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBa0V6QyxNQUFNLFFBQVEsR0FBRztJQUNmLE9BQU8sRUFBRSx3QkFBd0I7SUFDakMsOEVBQThFO0lBQzlFLCtFQUErRTtJQUMvRSxrRUFBa0U7SUFDbEUsaUVBQWlFO0lBQ2pFLGdGQUFnRjtJQUNoRiw4Q0FBOEM7SUFDOUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJO0lBQ3pDLE9BQU8sRUFBRSw0QkFBNEI7SUFDckMsaUJBQWlCLEVBQUUsS0FBSztJQUN4QixjQUFjLEVBQUUsR0FBRztJQUNuQixXQUFXLEVBQUUsQ0FBQztDQUNmLENBQUM7QUFFRixrRkFBa0Y7QUFDbEYsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE1BQXNCO0lBQzFELE9BQU87UUFDTCx5RUFBeUU7UUFDekUsNEVBQTRFO1FBQzVFLEtBQUssRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxNQUFNLENB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UyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzdDLE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7SUFDMUYsQ0FBQzs7QUFHSCxrRkFBa0Y7QUFDbEYsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYGF1dGhHYXRlKClgIC0gdGhlIEFwcEtpdCBwbHVnaW4gYmVoaW5kIHRoZSB0dW5uZWwncyBlbWFpbC1PVFAgZ2F0ZS5cbiAqXG4gKiBJdCBoYXMgTk8gcm91dGVzIG9mIGl0cyBvd246IHRoZSB0dW5uZWwgUFJPWFkgKG5vdCBhbiBIVFRQIHNlcnZlcikgY2FsbHMgdGhlXG4gKiBoYW5kbGVycyB0aGlzIHBsdWdpbiBleHBvc2VzIHZpYSB7QGxpbmsgQXV0aEdhdGVQbHVnaW4uZXhwb3J0c30uIFRoZSBwbHVnaW5cbiAqIG93bnMgdGhlIGFsbG93LWxpc3QsIHRoZSBwZXItZW1haWwvcGVyLUlQIHJhdGUgbGltaXRlcnMsIHRoZSBDYWNoZU1hbmFnZXItYmFja2VkXG4gKiBvbmUtdGltZS1jb2RlIHN0b3JlLCBhbmQgdGhlIHNlc3Npb24gSldULiBgY3JlYXRlQXBwYCAod2l0aCBubyBgc2VydmVyKClgKSBpc1xuICogdXNlZCBvbmx5IHRvIGF1dG8taW5pdCBgQ2FjaGVNYW5hZ2VyYCArIHByaW1lIHRoZSBzaWJsaW5nIGBlbWFpbGAgdHJhbnNwb3J0O1xuICogdGhpcyBwbHVnaW4gaXMgd2hlcmUgdGhlIGdhdGUgbG9naWMgbGl2ZXMuXG4gKlxuICogT3B0aW9ucyBjb21lIGZyb20gQ0xJIGZsYWdzIE9SIGVudiwgd2l0aCBzZW5zaWJsZSBkZWZhdWx0cyAtIHNlZVxuICoge0BsaW5rIHJlc29sdmVBdXRoR2F0ZUNvbmZpZ30uIFRoZSBvbmUgcnVudGltZSBkZXBlbmRlbmN5IHRoZSBwbHVnaW4gY2FuJ3RcbiAqIHJlc29sdmUgaXRzZWxmIGlzIEhPVyB0byBlbWFpbCB0aGUgY29kZSwgc28gaXQgdGFrZXMgYSBgc2VuZENvZGVgIGNhbGxiYWNrIHRoZVxuICogYXBwIHdpcmVzIHRvIHRoZSBlbWFpbCBwbHVnaW4uXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IFBsdWdpbiwgdG9QbHVnaW4sIHR5cGUgQmFzZVBsdWdpbkNvbmZpZywgdHlwZSBQbHVnaW5NYW5pZmVzdCB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGJyYW5kLCBlbnYsIGxvZywgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgQXV0aFN0YXR1cyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1lbWFpbFwiO1xuaW1wb3J0IHsgbG9va3NMaWtlRW1haWwsIG1hdGNoZXNBbGxvd2xpc3QgfSBmcm9tIFwiLi9hbGxvd2xpc3QudHNcIjtcbmltcG9ydCB7IENvZGVTdG9yZSwgc2lnblNlc3Npb24sIHZlcmlmeVNlc3Npb24gfSBmcm9tIFwiLi9vdHAudHNcIjtcbmltcG9ydCB7IFJhdGVMaW1pdGVyIH0gZnJvbSBcIi4vcmF0ZS1saW1pdC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOmF1dGhcIik7XG5cbi8qKiBPcHRpb25zIGZvciB0aGUge0BsaW5rIGF1dGhHYXRlfSBwbHVnaW4gKGFsbCByZXNvbHZhYmxlIGZyb20gZW52IC0gc2VlIGJlbG93KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aEdhdGVDb25maWcgZXh0ZW5kcyBCYXNlUGx1Z2luQ29uZmlnIHtcbiAgLyoqIEFsbG93LWxpc3QgcGF0dGVybnMgKGRvbWFpbiAvIGdsb2IgLyBgL3JlZ2V4L2ApLiBFbXB0eSA9IGFsbG93IG5vYm9keS4gRW52IEVNQUlMX0FVVEhfQUxMT1cuICovXG4gIGFsbG93Pzogc3RyaW5nIHwgc3RyaW5nW107XG4gIC8qKlxuICAgKiBTdWJqZWN0IGxpbmUgZm9yIHRoZSBjb2RlIGVtYWlsLiBFbnYgQVVUSF9TVUJKRUNULlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byBcIllvdXIgdmVyaWZpY2F0aW9uIGNvZGVcIi4gVGhlIHdvcmRpbmcgb2YgdGhlIHN1YmplY3QgYW5kXG4gICAqIHtAbGluayBtZXNzYWdlfSBpcyBkZWxpYmVyYXRlbHkgdGhlIGNvbnZlbnRpb25hbCBwaHJhc2luZyByYXRoZXIgdGhhblxuICAgKiBhbnl0aGluZyBicmFuZGVkOiBpT1MsIEdtYWlsLCBPdXRsb29rLCBhbmQgQW5kcm9pZCBhbGwgZGV0ZWN0IGEgb25lLXRpbWVcbiAgICogY29kZSBmcm9tIHRoaXMgc2hhcGUgYW5kIG9mZmVyIHRvIGF1dG9maWxsIGl0LCBhbmQgYSBub3ZlbCBwaHJhc2luZyBpcyB3aGF0XG4gICAqIGJyZWFrcyB0aGF0IGRldGVjdGlvbi5cbiAgICovXG4gIHN1YmplY3Q/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBEaXNwbGF5IG5hbWUgdXNlZCBpbiB0aGUgY29kZSBlbWFpbCBjb3B5LiBFbnYgQVVUSF9CUkFORF9OQU1FLlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byB0aGUgYnJhbmQgY29udGV4dCdzIGBuYW1lYCAtIHRoZSBhcHAncyBvd24gYGJyYW5kaW5nL2JyYW5kLnlhbWxgXG4gICAqIHdoZW4gaXQgaGFzIG9uZSwgZWxzZSB0aGUgZGJ4LXRvb2xzIGRlZmF1bHQuIFNldCB0aGlzIG9ubHkgdG8gb3ZlcnJpZGUgdGhlXG4gICAqIGJyYW5kIGZvciB0aGlzIGdhdGUuXG4gICAqL1xuICBicmFuZE5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBMaW5lIHNob3duIGltbWVkaWF0ZWx5IGFib3ZlIHRoZSBjb2RlIGluIHRoZSBlbWFpbC4gRW52IEFVVEhfTUVTU0FHRS5cbiAgICpcbiAgICogS2VlcCB0aGUgY29kZSBvbiBpdHMgT1dOIGxpbmUgZGlyZWN0bHkgYWZ0ZXIgdGhpcyB0ZXh0IC0gdGhhdCBhZGphY2VuY3kgaXNcbiAgICogd2hhdCB0aGUgcGxhdGZvcm0gY29kZS1kZXRlY3Rpb24gaGV1cmlzdGljcyBrZXkgb24uXG4gICAqL1xuICBtZXNzYWdlPzogc3RyaW5nO1xuICAvKiogU2Vzc2lvbiBsaWZldGltZSAoc2Vjb25kcykuIEVudiBBVVRIX1NFU1NJT05fVFRMLiBEZWZhdWx0IDQzMjAwICgxMmgpLiAqL1xuICBzZXNzaW9uVHRsU2Vjb25kcz86IG51bWJlcjtcbiAgLyoqIE9uZS10aW1lLWNvZGUgbGlmZXRpbWUgKHNlY29uZHMpLiBFbnYgQVVUSF9DT0RFX1RUTC4gRGVmYXVsdCA2MDAgKDEwbSkuICovXG4gIGNvZGVUdGxTZWNvbmRzPzogbnVtYmVyO1xuICAvKiogTWF4IHZlcmlmeSBhdHRlbXB0cyBwZXIgaXNzdWVkIGNvZGUuIERlZmF1bHQgNS4gKi9cbiAgbWF4QXR0ZW1wdHM/OiBudW1iZXI7XG4gIC8qKiBEZWxpdmVyIGEgY29kZSB0byBhbiBhZGRyZXNzLiBXaXJlZCBieSB0aGUgYXBwIHRvIHRoZSBlbWFpbCBwbHVnaW4uICovXG4gIHNlbmRDb2RlPzogKGVtYWlsOiBzdHJpbmcsIGNvZGU6IHN0cmluZywgb3B0czogU2VuZENvZGVPcHRpb25zKSA9PiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKiogQnJhbmRpbmcvbWVzc2FnaW5nIHBhc3NlZCB0byB7QGxpbmsgQXV0aEdhdGVDb25maWcuc2VuZENvZGV9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZW5kQ29kZU9wdGlvbnMge1xuICBzdWJqZWN0OiBzdHJpbmc7XG4gIGJyYW5kTmFtZTogc3RyaW5nO1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBMaWZldGltZSBvZiB0aGUgY29kZSBiZWluZyBzZW50LCBpbiBzZWNvbmRzIC0gdGhlIFJFU09MVkVEXG4gICAqIHtAbGluayBBdXRoR2F0ZUNvbmZpZy5jb2RlVHRsU2Vjb25kc30sIHNvIHRoZSBlbWFpbCBjYW4gc3RhdGUgdGhlIHJlYWxcbiAgICogZXhwaXJ5IChcIlRoaXMgY29kZSBleHBpcmVzIGluIDEwIG1pbnV0ZXNcIikgaW5zdGVhZCBvZiBhIHZhZ3VlIFwic2hvcnRseVwiXG4gICAqIHRoYXQgZHJpZnRzIGZyb20gdGhlIGNvbmZpZ3VyZWQgVFRMLlxuICAgKi9cbiAgY29kZVR0bFNlY29uZHM6IG51bWJlcjtcbn1cblxuLyoqIFJlc29sdmVkIGdhdGUgY29uZmlnIHdpdGggZW52IGZhbGxiYWNrcyArIGRlZmF1bHRzIGFwcGxpZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVkQXV0aEdhdGVDb25maWcge1xuICBhbGxvdzogc3RyaW5nW107XG4gIHN1YmplY3Q6IHN0cmluZztcbiAgYnJhbmROYW1lOiBzdHJpbmc7XG4gIG1lc3NhZ2U6IHN0cmluZztcbiAgc2Vzc2lvblR0bFNlY29uZHM6IG51bWJlcjtcbiAgY29kZVR0bFNlY29uZHM6IG51bWJlcjtcbiAgbWF4QXR0ZW1wdHM6IG51bWJlcjtcbn1cblxuY29uc3QgREVGQVVMVFMgPSB7XG4gIHN1YmplY3Q6IFwiWW91ciB2ZXJpZmljYXRpb24gY29kZVwiLFxuICAvLyBUaGUgcmVwby13aWRlIGJyYW5kIGNvbnRleHQncyBkaXNwbGF5IG5hbWUsIE5PVCBhIGhhcmRjb2RlZCBwcm9kdWN0IHN0cmluZzpcbiAgLy8gdGhpcyBuYW1lIGlzIHdoYXQgdGhlIHJlY2lwaWVudCByZWFkcyBpbiB0aGUgY29kZSBlbWFpbCwgc28gaXQgaGFzIHRvIGJlIHRoZVxuICAvLyBzYW1lIGlkZW50aXR5IHRoZSByZXN0IG9mIHRoZSBhcHAgcHJlc2VudHMuIEEgaG9zdCB3aXRoIGl0cyBvd25cbiAgLy8gYGJyYW5kaW5nL2JyYW5kLnlhbWxgIG92ZXJyaWRlcyBpdCBieSBwYXNzaW5nIGBicmFuZE5hbWVgIChzZWVcbiAgLy8ge0BsaW5rIHN0YXJ0R2F0ZUFwcH0sIHdoaWNoIHJlc29sdmVzIHRoZSBvbi1kaXNrIGNvbnRleHQpOyB0aGUgc2hhcmVkIGRlZmF1bHRcbiAgLy8gaXMgdGhlIGZhbGxiYWNrIHdoZW4gbm90aGluZyBpcyBjb25maWd1cmVkLlxuICBicmFuZE5hbWU6IGJyYW5kLmRlZmF1bHRCcmFuZENvbnRleHQubmFtZSxcbiAgbWVzc2FnZTogXCJZb3VyIHZlcmlmaWNhdGlvbiBjb2RlIGlzOlwiLFxuICBzZXNzaW9uVHRsU2Vjb25kczogNDMyMDAsXG4gIGNvZGVUdGxTZWNvbmRzOiA2MDAsXG4gIG1heEF0dGVtcHRzOiA1LFxufTtcblxuLyoqIE1lcmdlIHtAbGluayBBdXRoR2F0ZUNvbmZpZ30gb3ZlciBlbnYgb3ZlciBkZWZhdWx0cyBpbnRvIGEgcmVzb2x2ZWQgY29uZmlnLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVBdXRoR2F0ZUNvbmZpZyhjb25maWc6IEF1dGhHYXRlQ29uZmlnKTogUmVzb2x2ZWRBdXRoR2F0ZUNvbmZpZyB7XG4gIHJldHVybiB7XG4gICAgLy8gQm90aCBzb3VyY2VzIGFyZSB1bmlvbmVkIHJhdGhlciB0aGFuIG9uZSBvdmVycmlkaW5nOiBhIGRlcGxveW1lbnQtd2lkZVxuICAgIC8vIEVNQUlMX0FVVEhfQUxMT1cgYW5kIGEgcGVyLWludm9jYXRpb24gYC0tYWxsb3dgIHNob3VsZCBib3RoIGdyYW50IGFjY2Vzcy5cbiAgICBhbGxvdzogWy4uLnN0cmluZy5wYXJzZUxpc3QoY29uZmlnLmFsbG93KSwgLi4uc3RyaW5nLnBhcnNlTGlzdChwcm9jZXNzLmVudi5FTUFJTF9BVVRIX0FMTE9XKV0sXG4gICAgc3ViamVjdDogZW52LnN0cmluZyhjb25maWcuc3ViamVjdCwgXCJBVVRIX1NVQkpFQ1RcIikgPz8gREVGQVVMVFMuc3ViamVjdCxcbiAgICBicmFuZE5hbWU6IGVudi5zdHJpbmcoY29uZmlnLmJyYW5kTmFtZSwgXCJBVVRIX0JSQU5EX05BTUVcIikgPz8gREVGQVVMVFMuYnJhbmROYW1lLFxuICAgIG1lc3NhZ2U6IGVudi5zdHJpbmcoY29uZmlnLm1lc3NhZ2UsIFwiQVVUSF9NRVNTQUdFXCIpID8/IERFRkFVTFRTLm1lc3NhZ2UsXG4gICAgc2Vzc2lvblR0bFNlY29uZHM6IGVudi5wb3NpdGl2ZUludChcbiAgICAgIGNvbmZpZy5zZXNzaW9uVHRsU2Vjb25kcyxcbiAgICAgIFwiQVVUSF9TRVNTSU9OX1RUTFwiLFxuICAgICAgREVGQVVMVFMuc2Vzc2lvblR0bFNlY29uZHMsXG4gICAgKSxcbiAgICBjb2RlVHRsU2Vjb25kczogZW52LnBvc2l0aXZlSW50KFxuICAgICAgY29uZmlnLmNvZGVUdGxTZWNvbmRzLFxuICAgICAgXCJBVVRIX0NPREVfVFRMXCIsXG4gICAgICBERUZBVUxUUy5jb2RlVHRsU2Vjb25kcyxcbiAgICApLFxuICAgIG1heEF0dGVtcHRzOiBjb25maWcubWF4QXR0ZW1wdHMgPz8gREVGQVVMVFMubWF4QXR0ZW1wdHMsXG4gIH07XG59XG5cbi8qKiBUaGUgaGFuZGxlcnMgdGhlIHByb3h5IGNhbGxzIGluLXByb2Nlc3MgKHJldHVybmVkIGJ5IHtAbGluayBBdXRoR2F0ZVBsdWdpbi5leHBvcnRzfSkuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhHYXRlQXBpIHtcbiAgLyoqIEhhbmRsZSBhIGNvZGUgcmVxdWVzdC4gQWx3YXlzIHJlc29sdmVzIGB7IG9rOiB0cnVlIH1gIChhbnRpLWVudW1lcmF0aW9uKS4gKi9cbiAgcmVxdWVzdChlbWFpbDogc3RyaW5nLCBpcDogc3RyaW5nKTogUHJvbWlzZTx7IG9rOiB0cnVlOyByZXRyeUFmdGVyPzogbnVtYmVyIH0+O1xuICAvKiogSGFuZGxlIGEgY29kZSB2ZXJpZmljYXRpb24uIE9uIHN1Y2Nlc3MgcmV0dXJucyB0aGUgc2Vzc2lvbiB0b2tlbiB0byBjb29raWUuICovXG4gIHZlcmlmeShcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGNvZGU6IHN0cmluZyxcbiAgICBpcDogc3RyaW5nLFxuICApOiBQcm9taXNlPHsgb2s6IGJvb2xlYW47IHRva2VuPzogc3RyaW5nOyByZXRyeUFmdGVyPzogbnVtYmVyIH0+O1xuICAvKiogUmVzb2x2ZSB0aGUgYXV0aGVudGljYXRlZCBlbWFpbCBmb3IgYSBzZXNzaW9uIHRva2VuLCBvciB1bmRlZmluZWQuICovXG4gIHNlc3Npb24odG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZCk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPjtcbiAgLyoqIFNlc3Npb24gVFRMIGluIHNlY29uZHMgKGZvciB0aGUgY29va2llIE1heC1BZ2UpLiAqL1xuICByZWFkb25seSBzZXNzaW9uVHRsU2Vjb25kczogbnVtYmVyO1xuICAvKiogVGhlIGdhdGUgc3RhdHVzIHBheWxvYWQgKGBlbmFibGVkYCBpcyBhbHdheXMgdHJ1ZSB3aGVuIHRoaXMgcGx1Z2luIHJ1bnMpLiAqL1xuICBzdGF0dXModG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZCk6IFByb21pc2U8QXV0aFN0YXR1cz47XG59XG5cbi8qKiBBcHBLaXQgcGx1Z2luIG93bmluZyB0aGUgZW1haWwtT1RQIGdhdGUncyBsb2dpYyAobm8gSFRUUCByb3V0ZXM7IHByb3h5LWRyaXZlbikuICovXG5leHBvcnQgY2xhc3MgQXV0aEdhdGVQbHVnaW4gZXh0ZW5kcyBQbHVnaW48QXV0aEdhdGVDb25maWc+IHtcbiAgc3RhdGljIG1hbmlmZXN0ID0ge1xuICAgIG5hbWU6IFwiYXV0aEdhdGVcIixcbiAgICBkaXNwbGF5TmFtZTogXCJBdXRoIEdhdGVcIixcbiAgICBkZXNjcmlwdGlvbjogXCJFbWFpbCBvbmUtdGltZS1wYXNzd29yZCBhY2Nlc3MgZ2F0ZSBmb3IgYSBwdWJsaWMgdHVubmVsLlwiLFxuICAgIHN0YWJpbGl0eTogXCJiZXRhXCIsXG4gICAgcmVzb3VyY2VzOiB7IHJlcXVpcmVkOiBbXSwgb3B0aW9uYWw6IFtdIH0sXG4gIH0gc2F0aXNmaWVzIFBsdWdpbk1hbmlmZXN0PFwiYXV0aEdhdGVcIj47XG5cbiAgcHJpdmF0ZSByZXNvbHZlZCE6IFJlc29sdmVkQXV0aEdhdGVDb25maWc7XG4gIHByaXZhdGUgY29kZXMhOiBDb2RlU3RvcmU7XG4gIC8vIFJlcXVlc3RpbmcgYSBjb2RlIGlzIGVtYWlsLXNwYW0tcHJvbmU7IHZlcmlmeWluZyBpcyBhIGJydXRlLWZvcmNlIHN1cmZhY2UuXG4gIC8vIFBlci1lbWFpbCBBTkQgcGVyLUlQIHNvIG5laXRoZXIgYXhpcyBhbG9uZSBpcyBhIGJ5cGFzcy5cbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0TGltaXRlciA9IG5ldyBSYXRlTGltaXRlcig1LCAxNSAqIDYwICogMTAwMCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdmVyaWZ5TGltaXRlciA9IG5ldyBSYXRlTGltaXRlcigxMCwgMTUgKiA2MCAqIDEwMDApO1xuXG4gIG92ZXJyaWRlIGFzeW5jIHNldHVwKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMucmVzb2x2ZWQgPSByZXNvbHZlQXV0aEdhdGVDb25maWcodGhpcy5jb25maWcpO1xuICAgIHRoaXMuY29kZXMgPSBuZXcgQ29kZVN0b3JlKHRoaXMucmVzb2x2ZWQuY29kZVR0bFNlY29uZHMsIHRoaXMucmVzb2x2ZWQubWF4QXR0ZW1wdHMpO1xuICAgIGxvZ2dlci5pbmZvKFwicmVhZHlcIiwge1xuICAgICAgcGF0dGVybnM6IHRoaXMucmVzb2x2ZWQuYWxsb3cubGVuZ3RoLFxuICAgICAgc2Vzc2lvblR0bFNlY29uZHM6IHRoaXMucmVzb2x2ZWQuc2Vzc2lvblR0bFNlY29uZHMsXG4gICAgfSk7XG4gIH1cblxuICBvdmVycmlkZSBleHBvcnRzKCk6IEF1dGhHYXRlQXBpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc2Vzc2lvblR0bFNlY29uZHM6IHRoaXMucmVzb2x2ZWQuc2Vzc2lvblR0bFNlY29uZHMsXG4gICAgICByZXF1ZXN0OiAoZW1haWwsIGlwKSA9PiB0aGlzLmhhbmRsZVJlcXVlc3QoZW1haWwsIGlwKSxcbiAgICAgIHZlcmlmeTogKGVtYWlsLCBjb2RlLCBpcCkgPT4gdGhpcy5oYW5kbGVWZXJpZnkoZW1haWwsIGNvZGUsIGlwKSxcbiAgICAgIHNlc3Npb246ICh0b2tlbikgPT4gdmVyaWZ5U2Vzc2lvbih0b2tlbiksXG4gICAgICBzdGF0dXM6IGFzeW5jICh0b2tlbikgPT4gKHtcbiAgICAgICAgYXV0aGVudGljYXRlZDogQm9vbGVhbihhd2FpdCB2ZXJpZnlTZXNzaW9uKHRva2VuKSksXG4gICAgICAgIGVtYWlsOiAoYXdhaXQgdmVyaWZ5U2Vzc2lvbih0b2tlbikpID8/IHVuZGVmaW5lZCxcbiAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgIH0pLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhbmRsZVJlcXVlc3QoXG4gICAgZW1haWw6IHN0cmluZyxcbiAgICBpcDogc3RyaW5nLFxuICApOiBQcm9taXNlPHsgb2s6IHRydWU7IHJldHJ5QWZ0ZXI/OiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IGFkZHJlc3MgPSBlbWFpbC50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBieUlwID0gdGhpcy5yZXF1ZXN0TGltaXRlci5oaXQoYGlwOiR7aXB9YCk7XG4gICAgY29uc3QgYnlFbWFpbCA9IHRoaXMucmVxdWVzdExpbWl0ZXIuaGl0KGBlbWFpbDoke2FkZHJlc3N9YCk7XG4gICAgaWYgKCFieUlwLmFsbG93ZWQgfHwgIWJ5RW1haWwuYWxsb3dlZCkge1xuICAgICAgcmV0dXJuIHsgb2s6IHRydWUsIHJldHJ5QWZ0ZXI6IGJ5SXAucmV0cnlBZnRlciA/PyBieUVtYWlsLnJldHJ5QWZ0ZXIgfTtcbiAgICB9XG4gICAgaWYgKGxvb2tzTGlrZUVtYWlsKGFkZHJlc3MpICYmIG1hdGNoZXNBbGxvd2xpc3QoYWRkcmVzcywgdGhpcy5yZXNvbHZlZC5hbGxvdykpIHtcbiAgICAgIGNvbnN0IGNvZGUgPSBhd2FpdCB0aGlzLmNvZGVzLmlzc3VlKGFkZHJlc3MpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5jb25maWcuc2VuZENvZGU/LihhZGRyZXNzLCBjb2RlLCB7XG4gICAgICAgICAgc3ViamVjdDogdGhpcy5yZXNvbHZlZC5zdWJqZWN0LFxuICAgICAgICAgIGJyYW5kTmFtZTogdGhpcy5yZXNvbHZlZC5icmFuZE5hbWUsXG4gICAgICAgICAgbWVzc2FnZTogdGhpcy5yZXNvbHZlZC5tZXNzYWdlLFxuICAgICAgICAgIGNvZGVUdGxTZWNvbmRzOiB0aGlzLnJlc29sdmVkLmNvZGVUdGxTZWNvbmRzLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIHNlbmQgT1RQIGVtYWlsXCIsIHsgZXJyb3IgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IG9rOiB0cnVlIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhbmRsZVZlcmlmeShcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGNvZGU6IHN0cmluZyxcbiAgICBpcDogc3RyaW5nLFxuICApOiBQcm9taXNlPHsgb2s6IGJvb2xlYW47IHRva2VuPzogc3RyaW5nOyByZXRyeUFmdGVyPzogbnVtYmVyIH0+IHtcbiAgICBjb25zdCBhZGRyZXNzID0gZW1haWwudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3QgYnlJcCA9IHRoaXMudmVyaWZ5TGltaXRlci5oaXQoYGlwOiR7aXB9YCk7XG4gICAgY29uc3QgYnlFbWFpbCA9IHRoaXMudmVyaWZ5TGltaXRlci5oaXQoYGVtYWlsOiR7YWRkcmVzc31gKTtcbiAgICBpZiAoIWJ5SXAuYWxsb3dlZCB8fCAhYnlFbWFpbC5hbGxvd2VkKSB7XG4gICAgICByZXR1cm4geyBvazogZmFsc2UsIHJldHJ5QWZ0ZXI6IGJ5SXAucmV0cnlBZnRlciA/PyBieUVtYWlsLnJldHJ5QWZ0ZXIgfTtcbiAgICB9XG4gICAgaWYgKChhd2FpdCB0aGlzLmNvZGVzLnZlcmlmeShhZGRyZXNzLCBjb2RlLnRyaW0oKSkpICE9PSBcIm9rXCIpIHJldHVybiB7IG9rOiBmYWxzZSB9O1xuICAgIHRoaXMucmVxdWVzdExpbWl0ZXIucmVzZXQoYGVtYWlsOiR7YWRkcmVzc31gKTtcbiAgICB0aGlzLnZlcmlmeUxpbWl0ZXIucmVzZXQoYGVtYWlsOiR7YWRkcmVzc31gKTtcbiAgICByZXR1cm4geyBvazogdHJ1ZSwgdG9rZW46IGF3YWl0IHNpZ25TZXNzaW9uKGFkZHJlc3MsIHRoaXMucmVzb2x2ZWQuc2Vzc2lvblR0bFNlY29uZHMpIH07XG4gIH1cbn1cblxuLyoqIEZhY3Rvcnk6IGBhdXRoR2F0ZSh7IGFsbG93LCBzdWJqZWN0LCAuLi4gfSlgIGZvciBhbiBBcHBLaXQgYHBsdWdpbnNgIGFycmF5LiAqL1xuZXhwb3J0IGNvbnN0IGF1dGhHYXRlID0gdG9QbHVnaW4oQXV0aEdhdGVQbHVnaW4pO1xuIl19
|
|
130
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUE4QyxNQUFNLG9CQUFvQixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEUsT0FBTyxFQUNMLFNBQVMsRUFDVCxjQUFjLEVBQ2QsWUFBWSxFQUNaLFdBQVcsRUFDWCxlQUFlLEVBQ2YsV0FBVyxHQUNaLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNqRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFOUMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQWtFekMsTUFBTSxRQUFRLEdBQUc7SUFDZixPQUFPLEVBQUUsd0JBQXdCO0lBQ2pDLDhFQUE4RTtJQUM5RSwrRUFBK0U7SUFDL0Usa0VBQWtFO0lBQ2xFLGlFQUFpRTtJQUNqRSxnRkFBZ0Y7SUFDaEYsOENBQThDO0lBQzlDLFNBQVMsRUFBRSxLQUFLLENBQUMsbUJBQW1CLENBQUMsSUFBSTtJQUN6QyxPQUFPLEVBQUUsNEJBQTRCO0lBQ3JDLGlCQUFpQixFQUFFLEtBQUs7SUFDeEIsY0FBYyxFQUFFLEdBQUc7SUFDbkIsV0FBVyxFQUFFLENBQUM7Q0FDZixDQUFDO0FBRUYsa0ZBQWtGO0FBQ2xGLE1BQU0sVUFBVSxxQkFBcUIsQ0FBQyxNQUFzQjtJQUMxRCxPQUFPO1FBQ0wseUVBQXlFO1FBQ3pF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QUssRUFBRSxDQUFDO1FBQ25GLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLFNBQVMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUM5QyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxTQUFTLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDN0MsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztJQUMxRixDQUFDOztBQUdILGtGQUFrRjtBQUNsRixNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBgYXV0aEdhdGUoKWAgLSB0aGUgQXBwS2l0IHBsdWdpbiBiZWhpbmQgdGhlIHR1bm5lbCdzIGVtYWlsLU9UUCBnYXRlLlxuICpcbiAqIEl0IGhhcyBOTyByb3V0ZXMgb2YgaXRzIG93bjogdGhlIHR1bm5lbCBQUk9YWSAobm90IGFuIEhUVFAgc2VydmVyKSBjYWxscyB0aGVcbiAqIGhhbmRsZXJzIHRoaXMgcGx1Z2luIGV4cG9zZXMgdmlhIHtAbGluayBBdXRoR2F0ZVBsdWdpbi5leHBvcnRzfS4gVGhlIHBsdWdpblxuICogb3ducyB0aGUgYWxsb3ctbGlzdCwgdGhlIHBlci1lbWFpbC9wZXItSVAgcmF0ZSBsaW1pdGVycywgdGhlIENhY2hlTWFuYWdlci1iYWNrZWRcbiAqIG9uZS10aW1lLWNvZGUgc3RvcmUsIGFuZCB0aGUgc2Vzc2lvbiBKV1QuIGBjcmVhdGVBcHBgICh3aXRoIG5vIGBzZXJ2ZXIoKWApIGlzXG4gKiB1c2VkIG9ubHkgdG8gYXV0by1pbml0IGBDYWNoZU1hbmFnZXJgICsgcHJpbWUgdGhlIHNpYmxpbmcgYGVtYWlsYCB0cmFuc3BvcnQ7XG4gKiB0aGlzIHBsdWdpbiBpcyB3aGVyZSB0aGUgZ2F0ZSBsb2dpYyBsaXZlcy5cbiAqXG4gKiBPcHRpb25zIGNvbWUgZnJvbSBDTEkgZmxhZ3MgT1IgZW52LCB3aXRoIHNlbnNpYmxlIGRlZmF1bHRzIC0gc2VlXG4gKiB7QGxpbmsgcmVzb2x2ZUF1dGhHYXRlQ29uZmlnfS4gVGhlIG9uZSBydW50aW1lIGRlcGVuZGVuY3kgdGhlIHBsdWdpbiBjYW4ndFxuICogcmVzb2x2ZSBpdHNlbGYgaXMgSE9XIHRvIGVtYWlsIHRoZSBjb2RlLCBzbyBpdCB0YWtlcyBhIGBzZW5kQ29kZWAgY2FsbGJhY2sgdGhlXG4gKiBhcHAgd2lyZXMgdG8gdGhlIGVtYWlsIHBsdWdpbi5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgUGx1Z2luLCB0b1BsdWdpbiwgdHlwZSBCYXNlUGx1Z2luQ29uZmlnLCB0eXBlIFBsdWdpbk1hbmlmZXN0IH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgYnJhbmQsIGVudiwgbG9nLCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBBdXRoU3RhdHVzIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWVtYWlsXCI7XG5pbXBvcnQgeyBsb29rc0xpa2VFbWFpbCwgbWF0Y2hlc0FsbG93bGlzdCB9IGZyb20gXCIuL2FsbG93bGlzdC50c1wiO1xuaW1wb3J0IHtcbiAgQUxMT1dfRU5WLFxuICBCUkFORF9OQU1FX0VOVixcbiAgQ09ERV9UVExfRU5WLFxuICBNRVNTQUdFX0VOVixcbiAgU0VTU0lPTl9UVExfRU5WLFxuICBTVUJKRUNUX0VOVixcbn0gZnJvbSBcIi4vZW52LnRzXCI7XG5pbXBvcnQgeyBDb2RlU3RvcmUsIHNpZ25TZXNzaW9uLCB2ZXJpZnlTZXNzaW9uIH0gZnJvbSBcIi4vb3RwLnRzXCI7XG5pbXBvcnQgeyBSYXRlTGltaXRlciB9IGZyb20gXCIuL3JhdGUtbGltaXQudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDphdXRoXCIpO1xuXG4vKiogT3B0aW9ucyBmb3IgdGhlIHtAbGluayBhdXRoR2F0ZX0gcGx1Z2luIChhbGwgcmVzb2x2YWJsZSBmcm9tIGVudiAtIHNlZSBiZWxvdykuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhHYXRlQ29uZmlnIGV4dGVuZHMgQmFzZVBsdWdpbkNvbmZpZyB7XG4gIC8qKiBBbGxvdy1saXN0IHBhdHRlcm5zIChkb21haW4gLyBnbG9iIC8gYC9yZWdleC9gKS4gRW1wdHkgPSBhbGxvdyBub2JvZHkuIEVudiBUVU5ORUxfQVVUSF9BTExPVy4gKi9cbiAgYWxsb3c/OiBzdHJpbmcgfCBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIFN1YmplY3QgbGluZSBmb3IgdGhlIGNvZGUgZW1haWwuIEVudiBUVU5ORUxfQVVUSF9TVUJKRUNULlxuICAgKlxuICAgKiBEZWZhdWx0cyB0byBcIllvdXIgdmVyaWZpY2F0aW9uIGNvZGVcIi4gVGhlIHdvcmRpbmcgb2YgdGhlIHN1YmplY3QgYW5kXG4gICAqIHtAbGluayBtZXNzYWdlfSBpcyBkZWxpYmVyYXRlbHkgdGhlIGNvbnZlbnRpb25hbCBwaHJhc2luZyByYXRoZXIgdGhhblxuICAgKiBhbnl0aGluZyBicmFuZGVkOiBpT1MsIEdtYWlsLCBPdXRsb29rLCBhbmQgQW5kcm9pZCBhbGwgZGV0ZWN0IGEgb25lLXRpbWVcbiAgICogY29kZSBmcm9tIHRoaXMgc2hhcGUgYW5kIG9mZmVyIHRvIGF1dG9maWxsIGl0LCBhbmQgYSBub3ZlbCBwaHJhc2luZyBpcyB3aGF0XG4gICAqIGJyZWFrcyB0aGF0IGRldGVjdGlvbi5cbiAgICovXG4gIHN1YmplY3Q/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBEaXNwbGF5IG5hbWUgdXNlZCBpbiB0aGUgY29kZSBlbWFpbCBjb3B5LiBFbnYgVFVOTkVMX0FVVEhfQlJBTkRfTkFNRS5cbiAgICpcbiAgICogRGVmYXVsdHMgdG8gdGhlIGJyYW5kIGNvbnRleHQncyBgbmFtZWAgLSB0aGUgYXBwJ3Mgb3duIGBicmFuZGluZy9icmFuZC55YW1sYFxuICAgKiB3aGVuIGl0IGhhcyBvbmUsIGVsc2UgdGhlIGRieC10b29scyBkZWZhdWx0LiBTZXQgdGhpcyBvbmx5IHRvIG92ZXJyaWRlIHRoZVxuICAgKiBicmFuZCBmb3IgdGhpcyBnYXRlLlxuICAgKi9cbiAgYnJhbmROYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogTGluZSBzaG93biBpbW1lZGlhdGVseSBhYm92ZSB0aGUgY29kZSBpbiB0aGUgZW1haWwuIEVudiBUVU5ORUxfQVVUSF9NRVNTQUdFLlxuICAgKlxuICAgKiBLZWVwIHRoZSBjb2RlIG9uIGl0cyBPV04gbGluZSBkaXJlY3RseSBhZnRlciB0aGlzIHRleHQgLSB0aGF0IGFkamFjZW5jeSBpc1xuICAgKiB3aGF0IHRoZSBwbGF0Zm9ybSBjb2RlLWRldGVjdGlvbiBoZXVyaXN0aWNzIGtleSBvbi5cbiAgICovXG4gIG1lc3NhZ2U/OiBzdHJpbmc7XG4gIC8qKiBTZXNzaW9uIGxpZmV0aW1lIChzZWNvbmRzKS4gRW52IFRVTk5FTF9BVVRIX1NFU1NJT05fVFRMLiBEZWZhdWx0IDQzMjAwICgxMmgpLiAqL1xuICBzZXNzaW9uVHRsU2Vjb25kcz86IG51bWJlcjtcbiAgLyoqIE9uZS10aW1lLWNvZGUgbGlmZXRpbWUgKHNlY29uZHMpLiBFbnYgVFVOTkVMX0FVVEhfQ09ERV9UVEwuIERlZmF1bHQgNjAwICgxMG0pLiAqL1xuICBjb2RlVHRsU2Vjb25kcz86IG51bWJlcjtcbiAgLyoqIE1heCB2ZXJpZnkgYXR0ZW1wdHMgcGVyIGlzc3VlZCBjb2RlLiBEZWZhdWx0IDUuICovXG4gIG1heEF0dGVtcHRzPzogbnVtYmVyO1xuICAvKiogRGVsaXZlciBhIGNvZGUgdG8gYW4gYWRkcmVzcy4gV2lyZWQgYnkgdGhlIGFwcCB0byB0aGUgZW1haWwgcGx1Z2luLiAqL1xuICBzZW5kQ29kZT86IChlbWFpbDogc3RyaW5nLCBjb2RlOiBzdHJpbmcsIG9wdHM6IFNlbmRDb2RlT3B0aW9ucykgPT4gUHJvbWlzZTx2b2lkPjtcbn1cblxuLyoqIEJyYW5kaW5nL21lc3NhZ2luZyBwYXNzZWQgdG8ge0BsaW5rIEF1dGhHYXRlQ29uZmlnLnNlbmRDb2RlfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZENvZGVPcHRpb25zIHtcbiAgc3ViamVjdDogc3RyaW5nO1xuICBicmFuZE5hbWU6IHN0cmluZztcbiAgbWVzc2FnZTogc3RyaW5nO1xuICAvKipcbiAgICogTGlmZXRpbWUgb2YgdGhlIGNvZGUgYmVpbmcgc2VudCwgaW4gc2Vjb25kcyAtIHRoZSBSRVNPTFZFRFxuICAgKiB7QGxpbmsgQXV0aEdhdGVDb25maWcuY29kZVR0bFNlY29uZHN9LCBzbyB0aGUgZW1haWwgY2FuIHN0YXRlIHRoZSByZWFsXG4gICAqIGV4cGlyeSAoXCJUaGlzIGNvZGUgZXhwaXJlcyBpbiAxMCBtaW51dGVzXCIpIGluc3RlYWQgb2YgYSB2YWd1ZSBcInNob3J0bHlcIlxuICAgKiB0aGF0IGRyaWZ0cyBmcm9tIHRoZSBjb25maWd1cmVkIFRUTC5cbiAgICovXG4gIGNvZGVUdGxTZWNvbmRzOiBudW1iZXI7XG59XG5cbi8qKiBSZXNvbHZlZCBnYXRlIGNvbmZpZyB3aXRoIGVudiBmYWxsYmFja3MgKyBkZWZhdWx0cyBhcHBsaWVkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZEF1dGhHYXRlQ29uZmlnIHtcbiAgYWxsb3c6IHN0cmluZ1tdO1xuICBzdWJqZWN0OiBzdHJpbmc7XG4gIGJyYW5kTmFtZTogc3RyaW5nO1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIHNlc3Npb25UdGxTZWNvbmRzOiBudW1iZXI7XG4gIGNvZGVUdGxTZWNvbmRzOiBudW1iZXI7XG4gIG1heEF0dGVtcHRzOiBudW1iZXI7XG59XG5cbmNvbnN0IERFRkFVTFRTID0ge1xuICBzdWJqZWN0OiBcIllvdXIgdmVyaWZpY2F0aW9uIGNvZGVcIixcbiAgLy8gVGhlIHJlcG8td2lkZSBicmFuZCBjb250ZXh0J3MgZGlzcGxheSBuYW1lLCBOT1QgYSBoYXJkY29kZWQgcHJvZHVjdCBzdHJpbmc6XG4gIC8vIHRoaXMgbmFtZSBpcyB3aGF0IHRoZSByZWNpcGllbnQgcmVhZHMgaW4gdGhlIGNvZGUgZW1haWwsIHNvIGl0IGhhcyB0byBiZSB0aGVcbiAgLy8gc2FtZSBpZGVudGl0eSB0aGUgcmVzdCBvZiB0aGUgYXBwIHByZXNlbnRzLiBBIGhvc3Qgd2l0aCBpdHMgb3duXG4gIC8vIGBicmFuZGluZy9icmFuZC55YW1sYCBvdmVycmlkZXMgaXQgYnkgcGFzc2luZyBgYnJhbmROYW1lYCAoc2VlXG4gIC8vIHtAbGluayBzdGFydEdhdGVBcHB9LCB3aGljaCByZXNvbHZlcyB0aGUgb24tZGlzayBjb250ZXh0KTsgdGhlIHNoYXJlZCBkZWZhdWx0XG4gIC8vIGlzIHRoZSBmYWxsYmFjayB3aGVuIG5vdGhpbmcgaXMgY29uZmlndXJlZC5cbiAgYnJhbmROYW1lOiBicmFuZC5kZWZhdWx0QnJhbmRDb250ZXh0Lm5hbWUsXG4gIG1lc3NhZ2U6IFwiWW91ciB2ZXJpZmljYXRpb24gY29kZSBpczpcIixcbiAgc2Vzc2lvblR0bFNlY29uZHM6IDQzMjAwLFxuICBjb2RlVHRsU2Vjb25kczogNjAwLFxuICBtYXhBdHRlbXB0czogNSxcbn07XG5cbi8qKiBNZXJnZSB7QGxpbmsgQXV0aEdhdGVDb25maWd9IG92ZXIgZW52IG92ZXIgZGVmYXVsdHMgaW50byBhIHJlc29sdmVkIGNvbmZpZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQXV0aEdhdGVDb25maWcoY29uZmlnOiBBdXRoR2F0ZUNvbmZpZyk6IFJlc29sdmVkQXV0aEdhdGVDb25maWcge1xuICByZXR1cm4ge1xuICAgIC8vIEJvdGggc291cmNlcyBhcmUgdW5pb25lZCByYXRoZXIgdGhhbiBvbmUgb3ZlcnJpZGluZzogYSBkZXBsb3ltZW50LXdpZGVcbiAgICAvLyBUVU5ORUxfQVVUSF9BTExPVyBhbmQgYSBwZXItaW52b2NhdGlvbiBgLS1hbGxvd2Agc2hvdWxkIGJvdGggZ3JhbnQgYWNjZXNzLlxuICAgIC8vIEhlbmNlIGBwYXJzZUxpc3RgIG9uIGVhY2ggcmF0aGVyIHRoYW4gYGVudi5saXN0YCwgd2hpY2ggc3RvcHMgYXQgdGhlIGZpcnN0XG4gICAgLy8gc291cmNlIHRoYXQgeWllbGRzIGFueXRoaW5nLlxuICAgIGFsbG93OiBbLi4uc3RyaW5nLnBhcnNlTGlzdChjb25maWcuYWxsb3cpLCAuLi5zdHJpbmcucGFyc2VMaXN0KGVudi50ZXh0KEFMTE9XX0VOVikpXSxcbiAgICBzdWJqZWN0OiBlbnYuc3RyaW5nKGNvbmZpZy5zdWJqZWN0LCBTVUJKRUNUX0VOVikgPz8gREVGQVVMVFMuc3ViamVjdCxcbiAgICBicmFuZE5hbWU6IGVudi5zdHJpbmcoY29uZmlnLmJyYW5kTmFtZSwgQlJBTkRfTkFNRV9FTlYpID8/IERFRkFVTFRTLmJyYW5kTmFtZSxcbiAgICBtZXNzYWdlOiBlbnYuc3RyaW5nKGNvbmZpZy5tZXNzYWdlLCBNRVNTQUdFX0VOVikgPz8gREVGQVVMVFMubWVzc2FnZSxcbiAgICBzZXNzaW9uVHRsU2Vjb25kczogZW52LnBvc2l0aXZlSW50KFxuICAgICAgY29uZmlnLnNlc3Npb25UdGxTZWNvbmRzLFxuICAgICAgU0VTU0lPTl9UVExfRU5WLFxuICAgICAgREVGQVVMVFMuc2Vzc2lvblR0bFNlY29uZHMsXG4gICAgKSxcbiAgICBjb2RlVHRsU2Vjb25kczogZW52LnBvc2l0aXZlSW50KGNvbmZpZy5jb2RlVHRsU2Vjb25kcywgQ09ERV9UVExfRU5WLCBERUZBVUxUUy5jb2RlVHRsU2Vjb25kcyksXG4gICAgbWF4QXR0ZW1wdHM6IGNvbmZpZy5tYXhBdHRlbXB0cyA/PyBERUZBVUxUUy5tYXhBdHRlbXB0cyxcbiAgfTtcbn1cblxuLyoqIFRoZSBoYW5kbGVycyB0aGUgcHJveHkgY2FsbHMgaW4tcHJvY2VzcyAocmV0dXJuZWQgYnkge0BsaW5rIEF1dGhHYXRlUGx1Z2luLmV4cG9ydHN9KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aEdhdGVBcGkge1xuICAvKiogSGFuZGxlIGEgY29kZSByZXF1ZXN0LiBBbHdheXMgcmVzb2x2ZXMgYHsgb2s6IHRydWUgfWAgKGFudGktZW51bWVyYXRpb24pLiAqL1xuICByZXF1ZXN0KGVtYWlsOiBzdHJpbmcsIGlwOiBzdHJpbmcpOiBQcm9taXNlPHsgb2s6IHRydWU7IHJldHJ5QWZ0ZXI/OiBudW1iZXIgfT47XG4gIC8qKiBIYW5kbGUgYSBjb2RlIHZlcmlmaWNhdGlvbi4gT24gc3VjY2VzcyByZXR1cm5zIHRoZSBzZXNzaW9uIHRva2VuIHRvIGNvb2tpZS4gKi9cbiAgdmVyaWZ5KFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgY29kZTogc3RyaW5nLFxuICAgIGlwOiBzdHJpbmcsXG4gICk6IFByb21pc2U8eyBvazogYm9vbGVhbjsgdG9rZW4/OiBzdHJpbmc7IHJldHJ5QWZ0ZXI/OiBudW1iZXIgfT47XG4gIC8qKiBSZXNvbHZlIHRoZSBhdXRoZW50aWNhdGVkIGVtYWlsIGZvciBhIHNlc3Npb24gdG9rZW4sIG9yIHVuZGVmaW5lZC4gKi9cbiAgc2Vzc2lvbih0b2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+O1xuICAvKiogU2Vzc2lvbiBUVEwgaW4gc2Vjb25kcyAoZm9yIHRoZSBjb29raWUgTWF4LUFnZSkuICovXG4gIHJlYWRvbmx5IHNlc3Npb25UdGxTZWNvbmRzOiBudW1iZXI7XG4gIC8qKiBUaGUgZ2F0ZSBzdGF0dXMgcGF5bG9hZCAoYGVuYWJsZWRgIGlzIGFsd2F5cyB0cnVlIHdoZW4gdGhpcyBwbHVnaW4gcnVucykuICovXG4gIHN0YXR1cyh0b2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkKTogUHJvbWlzZTxBdXRoU3RhdHVzPjtcbn1cblxuLyoqIEFwcEtpdCBwbHVnaW4gb3duaW5nIHRoZSBlbWFpbC1PVFAgZ2F0ZSdzIGxvZ2ljIChubyBIVFRQIHJvdXRlczsgcHJveHktZHJpdmVuKS4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoR2F0ZVBsdWdpbiBleHRlbmRzIFBsdWdpbjxBdXRoR2F0ZUNvbmZpZz4ge1xuICBzdGF0aWMgbWFuaWZlc3QgPSB7XG4gICAgbmFtZTogXCJhdXRoR2F0ZVwiLFxuICAgIGRpc3BsYXlOYW1lOiBcIkF1dGggR2F0ZVwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIkVtYWlsIG9uZS10aW1lLXBhc3N3b3JkIGFjY2VzcyBnYXRlIGZvciBhIHB1YmxpYyB0dW5uZWwuXCIsXG4gICAgc3RhYmlsaXR5OiBcImJldGFcIixcbiAgICByZXNvdXJjZXM6IHsgcmVxdWlyZWQ6IFtdLCBvcHRpb25hbDogW10gfSxcbiAgfSBzYXRpc2ZpZXMgUGx1Z2luTWFuaWZlc3Q8XCJhdXRoR2F0ZVwiPjtcblxuICBwcml2YXRlIHJlc29sdmVkITogUmVzb2x2ZWRBdXRoR2F0ZUNvbmZpZztcbiAgcHJpdmF0ZSBjb2RlcyE6IENvZGVTdG9yZTtcbiAgLy8gUmVxdWVzdGluZyBhIGNvZGUgaXMgZW1haWwtc3BhbS1wcm9uZTsgdmVyaWZ5aW5nIGlzIGEgYnJ1dGUtZm9yY2Ugc3VyZmFjZS5cbiAgLy8gUGVyLWVtYWlsIEFORCBwZXItSVAgc28gbmVpdGhlciBheGlzIGFsb25lIGlzIGEgYnlwYXNzLlxuICBwcml2YXRlIHJlYWRvbmx5IHJlcXVlc3RMaW1pdGVyID0gbmV3IFJhdGVMaW1pdGVyKDUsIDE1ICogNjAgKiAxMDAwKTtcbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJpZnlMaW1pdGVyID0gbmV3IFJhdGVMaW1pdGVyKDEwLCAxNSAqIDYwICogMTAwMCk7XG5cbiAgb3ZlcnJpZGUgYXN5bmMgc2V0dXAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5yZXNvbHZlZCA9IHJlc29sdmVBdXRoR2F0ZUNvbmZpZyh0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy5jb2RlcyA9IG5ldyBDb2RlU3RvcmUodGhpcy5yZXNvbHZlZC5jb2RlVHRsU2Vjb25kcywgdGhpcy5yZXNvbHZlZC5tYXhBdHRlbXB0cyk7XG4gICAgbG9nZ2VyLmluZm8oXCJyZWFkeVwiLCB7XG4gICAgICBwYXR0ZXJuczogdGhpcy5yZXNvbHZlZC5hbGxvdy5sZW5ndGgsXG4gICAgICBzZXNzaW9uVHRsU2Vjb25kczogdGhpcy5yZXNvbHZlZC5zZXNzaW9uVHRsU2Vjb25kcyxcbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGV4cG9ydHMoKTogQXV0aEdhdGVBcGkge1xuICAgIHJldHVybiB7XG4gICAgICBzZXNzaW9uVHRsU2Vjb25kczogdGhpcy5yZXNvbHZlZC5zZXNzaW9uVHRsU2Vjb25kcyxcbiAgICAgIHJlcXVlc3Q6IChlbWFpbCwgaXApID0+IHRoaXMuaGFuZGxlUmVxdWVzdChlbWFpbCwgaXApLFxuICAgICAgdmVyaWZ5OiAoZW1haWwsIGNvZGUsIGlwKSA9PiB0aGlzLmhhbmRsZVZlcmlmeShlbWFpbCwgY29kZSwgaXApLFxuICAgICAgc2Vzc2lvbjogKHRva2VuKSA9PiB2ZXJpZnlTZXNzaW9uKHRva2VuKSxcbiAgICAgIHN0YXR1czogYXN5bmMgKHRva2VuKSA9PiAoe1xuICAgICAgICBhdXRoZW50aWNhdGVkOiBCb29sZWFuKGF3YWl0IHZlcmlmeVNlc3Npb24odG9rZW4pKSxcbiAgICAgICAgZW1haWw6IChhd2FpdCB2ZXJpZnlTZXNzaW9uKHRva2VuKSkgPz8gdW5kZWZpbmVkLFxuICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgfSksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlUmVxdWVzdChcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGlwOiBzdHJpbmcsXG4gICk6IFByb21pc2U8eyBvazogdHJ1ZTsgcmV0cnlBZnRlcj86IG51bWJlciB9PiB7XG4gICAgY29uc3QgYWRkcmVzcyA9IGVtYWlsLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgIGNvbnN0IGJ5SXAgPSB0aGlzLnJlcXVlc3RMaW1pdGVyLmhpdChgaXA6JHtpcH1gKTtcbiAgICBjb25zdCBieUVtYWlsID0gdGhpcy5yZXF1ZXN0TGltaXRlci5oaXQoYGVtYWlsOiR7YWRkcmVzc31gKTtcbiAgICBpZiAoIWJ5SXAuYWxsb3dlZCB8fCAhYnlFbWFpbC5hbGxvd2VkKSB7XG4gICAgICByZXR1cm4geyBvazogdHJ1ZSwgcmV0cnlBZnRlcjogYnlJcC5yZXRyeUFmdGVyID8/IGJ5RW1haWwucmV0cnlBZnRlciB9O1xuICAgIH1cbiAgICBpZiAobG9va3NMaWtlRW1haWwoYWRkcmVzcykgJiYgbWF0Y2hlc0FsbG93bGlzdChhZGRyZXNzLCB0aGlzLnJlc29sdmVkLmFsbG93KSkge1xuICAgICAgY29uc3QgY29kZSA9IGF3YWl0IHRoaXMuY29kZXMuaXNzdWUoYWRkcmVzcyk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmNvbmZpZy5zZW5kQ29kZT8uKGFkZHJlc3MsIGNvZGUsIHtcbiAgICAgICAgICBzdWJqZWN0OiB0aGlzLnJlc29sdmVkLnN1YmplY3QsXG4gICAgICAgICAgYnJhbmROYW1lOiB0aGlzLnJlc29sdmVkLmJyYW5kTmFtZSxcbiAgICAgICAgICBtZXNzYWdlOiB0aGlzLnJlc29sdmVkLm1lc3NhZ2UsXG4gICAgICAgICAgY29kZVR0bFNlY29uZHM6IHRoaXMucmVzb2x2ZWQuY29kZVR0bFNlY29uZHMsXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXCJmYWlsZWQgdG8gc2VuZCBPVFAgZW1haWxcIiwgeyBlcnJvciB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgb2s6IHRydWUgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlVmVyaWZ5KFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgY29kZTogc3RyaW5nLFxuICAgIGlwOiBzdHJpbmcsXG4gICk6IFByb21pc2U8eyBvazogYm9vbGVhbjsgdG9rZW4/OiBzdHJpbmc7IHJldHJ5QWZ0ZXI/OiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IGFkZHJlc3MgPSBlbWFpbC50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBieUlwID0gdGhpcy52ZXJpZnlMaW1pdGVyLmhpdChgaXA6JHtpcH1gKTtcbiAgICBjb25zdCBieUVtYWlsID0gdGhpcy52ZXJpZnlMaW1pdGVyLmhpdChgZW1haWw6JHthZGRyZXNzfWApO1xuICAgIGlmICghYnlJcC5hbGxvd2VkIHx8ICFieUVtYWlsLmFsbG93ZWQpIHtcbiAgICAgIHJldHVybiB7IG9rOiBmYWxzZSwgcmV0cnlBZnRlcjogYnlJcC5yZXRyeUFmdGVyID8/IGJ5RW1haWwucmV0cnlBZnRlciB9O1xuICAgIH1cbiAgICBpZiAoKGF3YWl0IHRoaXMuY29kZXMudmVyaWZ5KGFkZHJlc3MsIGNvZGUudHJpbSgpKSkgIT09IFwib2tcIikgcmV0dXJuIHsgb2s6IGZhbHNlIH07XG4gICAgdGhpcy5yZXF1ZXN0TGltaXRlci5yZXNldChgZW1haWw6JHthZGRyZXNzfWApO1xuICAgIHRoaXMudmVyaWZ5TGltaXRlci5yZXNldChgZW1haWw6JHthZGRyZXNzfWApO1xuICAgIHJldHVybiB7IG9rOiB0cnVlLCB0b2tlbjogYXdhaXQgc2lnblNlc3Npb24oYWRkcmVzcywgdGhpcy5yZXNvbHZlZC5zZXNzaW9uVHRsU2Vjb25kcykgfTtcbiAgfVxufVxuXG4vKiogRmFjdG9yeTogYGF1dGhHYXRlKHsgYWxsb3csIHN1YmplY3QsIC4uLiB9KWAgZm9yIGFuIEFwcEtpdCBgcGx1Z2luc2AgYXJyYXkuICovXG5leHBvcnQgY29uc3QgYXV0aEdhdGUgPSB0b1BsdWdpbihBdXRoR2F0ZVBsdWdpbik7XG4iXX0=
|