sliftutils 1.7.128 → 1.7.130

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.
Files changed (55) hide show
  1. package/bin/addmachine.js +9 -0
  2. package/bin/machineclient.js +9 -0
  3. package/bin/machineserver.js +10 -0
  4. package/index.d.ts +15 -0
  5. package/misc/dist/ownIPs.ts.cache +69 -0
  6. package/misc/ownIPs.d.ts +11 -0
  7. package/misc/ownIPs.ts +62 -0
  8. package/package.json +9 -3
  9. package/security/authorizedKeys/authorizedKeys.ts +34 -0
  10. package/security/authorizedKeys/daemon/authLog.ts +12 -5
  11. package/security/authorizedKeys/daemon/changes.ts +16 -1
  12. package/security/authorizedKeys/daemon/daemon.ts +43 -34
  13. package/security/authorizedKeys/daemon/dist/changes.ts.cache +40 -0
  14. package/security/authorizedKeys/daemon/dist/git.ts.cache +121 -0
  15. package/security/authorizedKeys/daemon/dist/notify.ts.cache +39 -0
  16. package/security/authorizedKeys/daemon/dist/paths.ts.cache +26 -0
  17. package/security/authorizedKeys/daemon/dist/repoFiles.ts.cache +114 -0
  18. package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
  19. package/security/authorizedKeys/daemon/dist/sessions.ts.cache +147 -0
  20. package/security/authorizedKeys/daemon/dist/state.ts.cache +76 -0
  21. package/security/authorizedKeys/daemon/dist/trust.ts.cache +295 -0
  22. package/security/authorizedKeys/daemon/notify.ts +8 -2
  23. package/security/authorizedKeys/daemon/paths.ts +0 -3
  24. package/security/authorizedKeys/daemon/repoFiles.ts +118 -0
  25. package/security/authorizedKeys/daemon/revocation.ts +0 -0
  26. package/security/authorizedKeys/daemon/rootKeys.ts +77 -10
  27. package/security/authorizedKeys/daemon/state.ts +21 -7
  28. package/security/authorizedKeys/daemon/trust.ts +37 -16
  29. package/security/authorizedKeys/daemon/userKeys.ts +5 -4
  30. package/security/authorizedKeys/dist/authorizedKeys.ts.cache +37 -3
  31. package/security/authorizedKeys/dist/keysRepo.ts.cache +111 -0
  32. package/security/authorizedKeys/dist/revokeSource.ts.cache +17 -4
  33. package/security/authorizedKeys/dist/secureSSH.ts.cache +147 -71
  34. package/security/authorizedKeys/dist/sources.ts.cache +52 -8
  35. package/security/authorizedKeys/dist/unrevoke.ts.cache +159 -44
  36. package/security/authorizedKeys/keysRepo.ts +111 -0
  37. package/security/authorizedKeys/secureSSH.ts +66 -58
  38. package/security/authorizedKeys/unrevoke.ts +160 -36
  39. package/security/helpers/dist/remoteSSH.ts.cache +19 -9
  40. package/security/machines/addMachine.ts +84 -0
  41. package/security/machines/dist/addMachine.ts.cache +88 -0
  42. package/security/machines/dist/identity.ts.cache +176 -0
  43. package/security/machines/dist/machines.ts.cache +264 -0
  44. package/security/machines/dist/trustClient.ts.cache +48 -0
  45. package/security/machines/dist/trustState.ts.cache +57 -0
  46. package/security/machines/identity.ts +199 -0
  47. package/security/machines/machines.ts +304 -0
  48. package/security/machines/trustClient.ts +51 -0
  49. package/security/machines/trustServer.ts +87 -0
  50. package/security/notifications/discord.ts +14 -5
  51. package/security/notifications/dist/discord.ts.cache +17 -8
  52. package/security/notifications/dist/remoteWebhook.ts.cache +78 -0
  53. package/security/notifications/dist/setupNotify.ts.cache +39 -0
  54. package/security/signedFiles/dist/signFiles.ts.cache +8 -10
  55. package/security/signedFiles/signFiles.ts +6 -10
@@ -1,11 +1,25 @@
1
1
  "use strict";
2
- // PORTED CODE: security/authorizedKeys/daemon/portsecureDaemon.js contains a plain JS port of everything here, so it can
3
- // resolve the same locations with no dependencies. Both sides must derive identical paths from a
4
- // repo url - if you change one, make the matching change in the other.
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
+ };
5
5
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
- //exports.sourceRepoPath = exports.sourceKeyPath = exports.sourceName = exports.REPOS_DIR = exports.REPO_KEYS_DIR = void 0;
7
- exports.REPO_KEYS_DIR = "/etc/portsecure/repo-keys";
6
+ //exports.findSourceKey = exports.findKey = exports.sourceRepoPath = exports.legacySourceKeyPath = exports.sourceKeyPath = exports.sourceName = exports.keysDir = exports.REPOS_DIR = exports.LEGACY_REPO_KEYS_DIR = exports.KEYS_DIR_NAME = void 0;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ const os_1 = __importDefault(require("os"));
9
+ const path_1 = __importDefault(require("path"));
10
+ // PORTED CODE: nothing here is duplicated any more, the daemon imports it directly. Kept in one
11
+ // place because the daemon and the deploy have to agree on where a source's key and checkout live.
12
+ // The user's own folder, so this works the same on a machine that has no /etc. The daemon runs as
13
+ // root, so on a host this is root's home.
14
+ exports.KEYS_DIR_NAME = "authorized_keys";
15
+ // Where keys used to go. Still read, so a host set up before this keeps working, but nothing is
16
+ // written here any more.
17
+ exports.LEGACY_REPO_KEYS_DIR = "/etc/portsecure/repo-keys";
8
18
  exports.REPOS_DIR = "/var/lib/portsecure/authorized-keys-repos";
19
+ function keysDir() {
20
+ return path_1.default.join(os_1.default.homedir(), exports.KEYS_DIR_NAME);
21
+ }
22
+ exports.keysDir = keysDir;
9
23
  /** A repo url reduced to something usable as a file name. Derived rather than configured, so the
10
24
  daemon and the deploy script always agree on where a source's key and checkout live. */
11
25
  function sourceName(repoURL) {
@@ -13,12 +27,42 @@ function sourceName(repoURL) {
13
27
  }
14
28
  exports.sourceName = sourceName;
15
29
  function sourceKeyPath(repoURL) {
16
- return `${exports.REPO_KEYS_DIR}/${sourceName(repoURL)}`;
30
+ return path_1.default.join(keysDir(), sourceName(repoURL));
17
31
  }
18
32
  exports.sourceKeyPath = sourceKeyPath;
33
+ function legacySourceKeyPath(repoURL) {
34
+ return `${exports.LEGACY_REPO_KEYS_DIR}/${sourceName(repoURL)}`;
35
+ }
36
+ exports.legacySourceKeyPath = legacySourceKeyPath;
19
37
  function sourceRepoPath(repoURL) {
20
38
  return `${exports.REPOS_DIR}/${sourceName(repoURL)}`;
21
39
  }
22
40
  exports.sourceRepoPath = sourceRepoPath;
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNvdXJjZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHlIQUF5SDtBQUN6SCxpR0FBaUc7QUFDakcsdUVBQXVFOzs7QUFFMUQsUUFBQSxhQUFhLEdBQUcsMkJBQTJCLENBQUM7QUFDNUMsUUFBQSxTQUFTLEdBQUcsMkNBQTJDLENBQUM7QUFFckU7MkZBQzJGO0FBQzNGLFNBQWdCLFVBQVUsQ0FBQyxPQUFlO0lBQ3RDLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0FBQ3hGLENBQUM7QUFGRCxnQ0FFQztBQUVELFNBQWdCLGFBQWEsQ0FBQyxPQUFlO0lBQ3pDLE9BQU8sR0FBRyxxQkFBYSxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO0FBQ3JELENBQUM7QUFGRCxzQ0FFQztBQUVELFNBQWdCLGNBQWMsQ0FBQyxPQUFlO0lBQzFDLE9BQU8sR0FBRyxpQkFBUyxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO0FBQ2pELENBQUM7QUFGRCx3Q0FFQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFBPUlRFRCBDT0RFOiBzZWN1cml0eS9hdXRob3JpemVkS2V5cy9kYWVtb24vcG9ydHNlY3VyZURhZW1vbi5qcyBjb250YWlucyBhIHBsYWluIEpTIHBvcnQgb2YgZXZlcnl0aGluZyBoZXJlLCBzbyBpdCBjYW5cbi8vIHJlc29sdmUgdGhlIHNhbWUgbG9jYXRpb25zIHdpdGggbm8gZGVwZW5kZW5jaWVzLiBCb3RoIHNpZGVzIG11c3QgZGVyaXZlIGlkZW50aWNhbCBwYXRocyBmcm9tIGFcbi8vIHJlcG8gdXJsIC0gaWYgeW91IGNoYW5nZSBvbmUsIG1ha2UgdGhlIG1hdGNoaW5nIGNoYW5nZSBpbiB0aGUgb3RoZXIuXG5cbmV4cG9ydCBjb25zdCBSRVBPX0tFWVNfRElSID0gXCIvZXRjL3BvcnRzZWN1cmUvcmVwby1rZXlzXCI7XG5leHBvcnQgY29uc3QgUkVQT1NfRElSID0gXCIvdmFyL2xpYi9wb3J0c2VjdXJlL2F1dGhvcml6ZWQta2V5cy1yZXBvc1wiO1xuXG4vKiogQSByZXBvIHVybCByZWR1Y2VkIHRvIHNvbWV0aGluZyB1c2FibGUgYXMgYSBmaWxlIG5hbWUuIERlcml2ZWQgcmF0aGVyIHRoYW4gY29uZmlndXJlZCwgc28gdGhlXG4gICAgZGFlbW9uIGFuZCB0aGUgZGVwbG95IHNjcmlwdCBhbHdheXMgYWdyZWUgb24gd2hlcmUgYSBzb3VyY2UncyBrZXkgYW5kIGNoZWNrb3V0IGxpdmUuICovXG5leHBvcnQgZnVuY3Rpb24gc291cmNlTmFtZShyZXBvVVJMOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gcmVwb1VSTC5yZXBsYWNlKC9bXkEtWmEtejAtOV0rL2csIFwiLVwiKS5yZXBsYWNlKC9eLSt8LSskL2csIFwiXCIpLnRvTG93ZXJDYXNlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzb3VyY2VLZXlQYXRoKHJlcG9VUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgJHtSRVBPX0tFWVNfRElSfS8ke3NvdXJjZU5hbWUocmVwb1VSTCl9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNvdXJjZVJlcG9QYXRoKHJlcG9VUkw6IHN0cmluZykge1xuICAgIHJldHVybiBgJHtSRVBPU19ESVJ9LyR7c291cmNlTmFtZShyZXBvVVJMKX1gO1xufVxuIl19
24
- /* _JS_SOURCE_HASH = "d4a51163d16ac57a8fa5966ca3b09eaebcbef4ca2200c706a7e125220c7db7b8"; */
41
+ async function pathExists(filePath) {
42
+ try {
43
+ await promises_1.default.access(filePath);
44
+ return true;
45
+ }
46
+ catch (e) {
47
+ return false;
48
+ }
49
+ }
50
+ /** The key for a source, wherever it happens to be. The user folder is where they go now, and the
51
+ old location is still read so a host that predates the move keeps working. */
52
+ async function findKey(config) {
53
+ let { current, legacy } = config;
54
+ if (await pathExists(current)) {
55
+ return current;
56
+ }
57
+ if (await pathExists(legacy)) {
58
+ return legacy;
59
+ }
60
+ return "";
61
+ }
62
+ exports.findKey = findKey;
63
+ async function findSourceKey(repoURL) {
64
+ return await findKey({ current: sourceKeyPath(repoURL), legacy: legacySourceKeyPath(repoURL) });
65
+ }
66
+ exports.findSourceKey = findSourceKey;
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNvdXJjZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMkRBQTZCO0FBQzdCLDRDQUFvQjtBQUNwQixnREFBd0I7QUFFeEIsZ0dBQWdHO0FBQ2hHLG1HQUFtRztBQUVuRyxrR0FBa0c7QUFDbEcsMENBQTBDO0FBQzdCLFFBQUEsYUFBYSxHQUFHLGlCQUFpQixDQUFDO0FBQy9DLGdHQUFnRztBQUNoRyx5QkFBeUI7QUFDWixRQUFBLG9CQUFvQixHQUFHLDJCQUEyQixDQUFDO0FBQ25ELFFBQUEsU0FBUyxHQUFHLDJDQUEyQyxDQUFDO0FBRXJFLFNBQWdCLE9BQU87SUFDbkIsT0FBTyxjQUFJLENBQUMsSUFBSSxDQUFDLFlBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxxQkFBYSxDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUZELDBCQUVDO0FBRUQ7MkZBQzJGO0FBQzNGLFNBQWdCLFVBQVUsQ0FBQyxPQUFlO0lBQ3RDLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0FBQ3hGLENBQUM7QUFGRCxnQ0FFQztBQUVELFNBQWdCLGFBQWEsQ0FBQyxPQUFlO0lBQ3pDLE9BQU8sY0FBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBRkQsc0NBRUM7QUFFRCxTQUFnQixtQkFBbUIsQ0FBQyxPQUFlO0lBQy9DLE9BQU8sR0FBRyw0QkFBb0IsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztBQUM1RCxDQUFDO0FBRkQsa0RBRUM7QUFFRCxTQUFnQixjQUFjLENBQUMsT0FBZTtJQUMxQyxPQUFPLEdBQUcsaUJBQVMsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztBQUNqRCxDQUFDO0FBRkQsd0NBRUM7QUFFRCxLQUFLLFVBQVUsVUFBVSxDQUFDLFFBQWdCO0lBQ3RDLElBQUksQ0FBQztRQUNELE1BQU0sa0JBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDMUIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0FBQ0wsQ0FBQztBQUVEO2lGQUNpRjtBQUMxRSxLQUFLLFVBQVUsT0FBTyxDQUFDLE1BQTJDO0lBQ3JFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBQ2pDLElBQUksTUFBTSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM1QixPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDO0lBQ0QsSUFBSSxNQUFNLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzNCLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNkLENBQUM7QUFURCwwQkFTQztBQUVNLEtBQUssVUFBVSxhQUFhLENBQUMsT0FBZTtJQUMvQyxPQUFPLE1BQU0sT0FBTyxDQUFDLEVBQUUsT0FBTyxFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsbUJBQW1CLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3BHLENBQUM7QUFGRCxzQ0FFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5cbi8vIFBPUlRFRCBDT0RFOiBub3RoaW5nIGhlcmUgaXMgZHVwbGljYXRlZCBhbnkgbW9yZSwgdGhlIGRhZW1vbiBpbXBvcnRzIGl0IGRpcmVjdGx5LiBLZXB0IGluIG9uZVxuLy8gcGxhY2UgYmVjYXVzZSB0aGUgZGFlbW9uIGFuZCB0aGUgZGVwbG95IGhhdmUgdG8gYWdyZWUgb24gd2hlcmUgYSBzb3VyY2UncyBrZXkgYW5kIGNoZWNrb3V0IGxpdmUuXG5cbi8vIFRoZSB1c2VyJ3Mgb3duIGZvbGRlciwgc28gdGhpcyB3b3JrcyB0aGUgc2FtZSBvbiBhIG1hY2hpbmUgdGhhdCBoYXMgbm8gL2V0Yy4gVGhlIGRhZW1vbiBydW5zIGFzXG4vLyByb290LCBzbyBvbiBhIGhvc3QgdGhpcyBpcyByb290J3MgaG9tZS5cbmV4cG9ydCBjb25zdCBLRVlTX0RJUl9OQU1FID0gXCJhdXRob3JpemVkX2tleXNcIjtcbi8vIFdoZXJlIGtleXMgdXNlZCB0byBnby4gU3RpbGwgcmVhZCwgc28gYSBob3N0IHNldCB1cCBiZWZvcmUgdGhpcyBrZWVwcyB3b3JraW5nLCBidXQgbm90aGluZyBpc1xuLy8gd3JpdHRlbiBoZXJlIGFueSBtb3JlLlxuZXhwb3J0IGNvbnN0IExFR0FDWV9SRVBPX0tFWVNfRElSID0gXCIvZXRjL3BvcnRzZWN1cmUvcmVwby1rZXlzXCI7XG5leHBvcnQgY29uc3QgUkVQT1NfRElSID0gXCIvdmFyL2xpYi9wb3J0c2VjdXJlL2F1dGhvcml6ZWQta2V5cy1yZXBvc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24ga2V5c0RpcigpIHtcbiAgICByZXR1cm4gcGF0aC5qb2luKG9zLmhvbWVkaXIoKSwgS0VZU19ESVJfTkFNRSk7XG59XG5cbi8qKiBBIHJlcG8gdXJsIHJlZHVjZWQgdG8gc29tZXRoaW5nIHVzYWJsZSBhcyBhIGZpbGUgbmFtZS4gRGVyaXZlZCByYXRoZXIgdGhhbiBjb25maWd1cmVkLCBzbyB0aGVcbiAgICBkYWVtb24gYW5kIHRoZSBkZXBsb3kgc2NyaXB0IGFsd2F5cyBhZ3JlZSBvbiB3aGVyZSBhIHNvdXJjZSdzIGtleSBhbmQgY2hlY2tvdXQgbGl2ZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb3VyY2VOYW1lKHJlcG9VUkw6IHN0cmluZykge1xuICAgIHJldHVybiByZXBvVVJMLnJlcGxhY2UoL1teQS1aYS16MC05XSsvZywgXCItXCIpLnJlcGxhY2UoL14tK3wtKyQvZywgXCJcIikudG9Mb3dlckNhc2UoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNvdXJjZUtleVBhdGgocmVwb1VSTDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHBhdGguam9pbihrZXlzRGlyKCksIHNvdXJjZU5hbWUocmVwb1VSTCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbGVnYWN5U291cmNlS2V5UGF0aChyZXBvVVJMOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYCR7TEVHQUNZX1JFUE9fS0VZU19ESVJ9LyR7c291cmNlTmFtZShyZXBvVVJMKX1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc291cmNlUmVwb1BhdGgocmVwb1VSTDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGAke1JFUE9TX0RJUn0vJHtzb3VyY2VOYW1lKHJlcG9VUkwpfWA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBhdGhFeGlzdHMoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZzLmFjY2VzcyhmaWxlUGF0aCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLyoqIFRoZSBrZXkgZm9yIGEgc291cmNlLCB3aGVyZXZlciBpdCBoYXBwZW5zIHRvIGJlLiBUaGUgdXNlciBmb2xkZXIgaXMgd2hlcmUgdGhleSBnbyBub3csIGFuZCB0aGVcbiAgICBvbGQgbG9jYXRpb24gaXMgc3RpbGwgcmVhZCBzbyBhIGhvc3QgdGhhdCBwcmVkYXRlcyB0aGUgbW92ZSBrZWVwcyB3b3JraW5nLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmRLZXkoY29uZmlnOiB7IGN1cnJlbnQ6IHN0cmluZzsgbGVnYWN5OiBzdHJpbmcgfSkge1xuICAgIGxldCB7IGN1cnJlbnQsIGxlZ2FjeSB9ID0gY29uZmlnO1xuICAgIGlmIChhd2FpdCBwYXRoRXhpc3RzKGN1cnJlbnQpKSB7XG4gICAgICAgIHJldHVybiBjdXJyZW50O1xuICAgIH1cbiAgICBpZiAoYXdhaXQgcGF0aEV4aXN0cyhsZWdhY3kpKSB7XG4gICAgICAgIHJldHVybiBsZWdhY3k7XG4gICAgfVxuICAgIHJldHVybiBcIlwiO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZFNvdXJjZUtleShyZXBvVVJMOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYXdhaXQgZmluZEtleSh7IGN1cnJlbnQ6IHNvdXJjZUtleVBhdGgocmVwb1VSTCksIGxlZ2FjeTogbGVnYWN5U291cmNlS2V5UGF0aChyZXBvVVJMKSB9KTtcbn1cbiJdfQ==
68
+ /* _JS_SOURCE_HASH = "d66a91022052069dc8a7c111312ca09502fb4974baa795ec49d4d0ebed0668bf"; */
@@ -3,17 +3,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
- //exports.main = exports.revokedKeysInRepo = exports.readRemoteRevocations = void 0;
6
+ //exports.main = exports.revokedKeysInRepo = exports.readRemoteRevocations = exports.revocationIdentity = exports.revocationIP = void 0;
7
7
  const promises_1 = __importDefault(require("fs/promises"));
8
8
  const os_1 = __importDefault(require("os"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const runPromise_1 = require("socket-function/src/runPromise");
11
11
  const authorizedKeys_1 = require("./authorizedKeys");
12
12
  const revokeSource_1 = require("./revokeSource");
13
+ const sources_1 = require("./sources");
13
14
  const signFiles_1 = require("../signedFiles/signFiles");
14
15
  const authorizedKeys_2 = require("./authorizedKeys");
15
- const paths_1 = require("../helpers/paths");
16
16
  const spawn_1 = require("../helpers/spawn");
17
+ const machines_1 = require("../machines/machines");
18
+ const keysRepo_1 = require("./keysRepo");
17
19
  const UNREVOKES_DIR = "unrevoked";
18
20
  const REVOCATIONS_DIR = "revocations";
19
21
  const GIT_KEYWORD = "git";
@@ -21,22 +23,41 @@ const COMMIT_MESSAGE = "unrevoke keys";
21
23
  const USAGE = `Usage: yarn unrevoke [keys-repo] [${GIT_KEYWORD}]
22
24
 
23
25
  Run this in a keys repo, or name one. It reads that repo's revoke repo and writes one unrevoke file
24
- naming every revocation in it, so the keys are accepted again once each machine's hour long wait
25
- passes. It signs the result, and with ${GIT_KEYWORD} it commits and pushes it too.
26
+ naming every revocation in it, so the keys are accepted again as each machine picks it up. It signs
27
+ the result, and with ${GIT_KEYWORD} it commits and pushes it too.
26
28
 
27
29
  Keys that were revoked should normally be deleted from the repo instead. Unrevoking only matters
28
30
  for a key you still want.`;
29
- /** Every revocation the revoke repo lists. Cloned read only into a temp directory, with whatever
30
- credentials this machine already has - the derived deploy key is for servers, and a person
31
- running this has their own access to the repo. */
31
+ /** Older revocation files carry the address under attempt only. */
32
+ function revocationIP(revocation) {
33
+ var _a;
34
+ return revocation.ip || ((_a = revocation.attempt) === null || _a === void 0 ? void 0 : _a.ip) || "";
35
+ }
36
+ exports.revocationIP = revocationIP;
37
+ /** What the revocation is about, which is what an unrevoke has to name to undo it. */
38
+ function revocationIdentity(revocation) {
39
+ return revocation.fingerprint || revocation.machineId || "";
40
+ }
41
+ exports.revocationIdentity = revocationIdentity;
42
+ /** Every revocation the revoke repo lists. Cloned read only into a temp directory.
43
+
44
+ A person running this has their own access to the repo, so their credentials are what is used.
45
+ On a machine that is already a portsecure host there may be no such credentials, but the source
46
+ deploy key is right there, and the key derived from it is one that repo definitely accepts. */
32
47
  async function readRemoteRevocations(config) {
33
48
  let { sourceURL } = config;
34
49
  let temporaryDirectory = await promises_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), "unrevoke-"));
35
50
  let repoPath = path_1.default.join(temporaryDirectory, "repo");
36
- let clone = await (0, spawn_1.spawnPromise)({
37
- command: "git",
38
- args: ["clone", "--depth", "1", (0, revokeSource_1.revokeRepoURL)(sourceURL), repoPath],
39
- });
51
+ let cloneArgs = ["clone", "--depth", "1", (0, revokeSource_1.revokeRepoURL)(sourceURL), repoPath];
52
+ let sourceKey = await (0, sources_1.findSourceKey)(sourceURL);
53
+ if (sourceKey) {
54
+ let derived = (0, revokeSource_1.deriveRevokeKey)(await promises_1.default.readFile(sourceKey, "utf8"));
55
+ let derivedKeyPath = path_1.default.join(temporaryDirectory, "key");
56
+ await promises_1.default.writeFile(derivedKeyPath, derived.privateKeyFile, { mode: 0o600 });
57
+ let sshCommand = `ssh -i ${derivedKeyPath} -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new`;
58
+ cloneArgs = ["-c", `core.sshCommand=${sshCommand}`, ...cloneArgs];
59
+ }
60
+ let clone = await (0, spawn_1.spawnPromise)({ command: "git", args: cloneArgs });
40
61
  if (clone.status !== 0) {
41
62
  await promises_1.default.rm(temporaryDirectory, { recursive: true, force: true });
42
63
  throw new Error(`Expected to be able to read ${(0, revokeSource_1.revokeRepoURL)(sourceURL)}.\n`
@@ -71,6 +92,10 @@ async function revokedKeysInRepo(config) {
71
92
  continue;
72
93
  }
73
94
  let parsed = JSON.parse(await promises_1.default.readFile(path_1.default.join(directory, name), "utf8"));
95
+ for (let allowed of parsed.allowed || []) {
96
+ unrevoked.add(`${allowed.fingerprint || allowed.machineId} ${allowed.ip}`);
97
+ }
98
+ // Named ids, for the unrevokes written before this was about pairs.
74
99
  for (let revocationId of parsed.revocationIds || []) {
75
100
  unrevoked.add(revocationId);
76
101
  }
@@ -79,47 +104,88 @@ async function revokedKeysInRepo(config) {
79
104
  catch (e) {
80
105
  // Nothing has been unrevoked.
81
106
  }
82
- let stillRevoked = revocations.filter(revocation => !unrevoked.has(revocation.revocationId));
107
+ let stillRevoked = revocations.filter(revocation => !unrevoked.has(revocation.revocationId)
108
+ && !unrevoked.has(`${revocation.fingerprint} ${revocationIP(revocation)}`));
83
109
  let keys = (0, authorizedKeys_1.normalizeKeys)(await promises_1.default.readFile(path_1.default.join(repoPath, "authorized_keys"), "utf8").catch(() => ""));
84
110
  return stillRevoked
85
111
  .filter(revocation => keys.some(key => (0, authorizedKeys_1.keyFingerprint)(key) === revocation.fingerprint))
86
112
  .map(revocation => ({ revocation, key: keys.find(key => (0, authorizedKeys_1.keyFingerprint)(key) === revocation.fingerprint) || "" }));
87
113
  }
88
114
  exports.revokedKeysInRepo = revokedKeysInRepo;
89
- /** The repo named, or the one we are standing in. Checked the same way securessh checks it: a git
90
- repo that actually holds keys and has an origin to clone from. */
91
- async function resolveKeysRepo(named) {
92
- let cwd = named && (0, paths_1.expandHome)(named) || undefined;
93
- // spawnPromise rather than runPromise, because these two are read for their value. runPromise
94
- // returns stdout and stderr joined, so one git warning ends up glued to the front of the path.
95
- let topLevel = await (0, spawn_1.spawnPromise)({ command: "git", args: ["rev-parse", "--show-toplevel"], cwd });
96
- let repoPath = topLevel.stdout.trim();
97
- if (topLevel.status !== 0 || !repoPath) {
98
- throw new Error(`Expected ${named || "the current directory"} to be inside a git repo, it is not.\n`
99
- + `${(topLevel.stdout + topLevel.stderr).trim()}\n${USAGE}`);
100
- }
115
+ /** Writes the addresses into the from= list of each key in the repo's authorized_keys, and says
116
+ which ones were actually new. Only the lines being changed are touched, so comments, ordering
117
+ and any key not involved come out of this byte for byte the same. */
118
+ async function allowAddressesInRepo(config) {
119
+ let { repoPath, addressesByFingerprint } = config;
120
+ let added = new Map();
121
+ let filePath = path_1.default.join(repoPath, "authorized_keys");
122
+ let contents;
101
123
  try {
102
- await (0, authorizedKeys_2.readRepoKeys)(repoPath);
124
+ contents = await promises_1.default.readFile(filePath, "utf8");
103
125
  }
104
126
  catch (e) {
105
- throw new Error(`Expected ${repoPath} to be a keys repo, it holds no keys.\n${e}\n${USAGE}`);
127
+ // A repo holding its keys as separate .pub files. Nothing to edit in one place, so the
128
+ // caller's listing is all whoever ran this gets.
129
+ console.log(`No authorized_keys in ${repoPath}, so the addresses were not added to any key.`);
130
+ return added;
106
131
  }
107
- let origin = await (0, spawn_1.spawnPromise)({ command: "git", args: ["remote", "get-url", "origin"], cwd: repoPath });
108
- let originURL = origin.stdout.trim();
109
- if (origin.status !== 0 || !originURL) {
110
- throw new Error(`Expected ${repoPath} to have an origin remote, it has none.\n${USAGE}`);
132
+ let lines = contents.split("\n");
133
+ for (let index = 0; index < lines.length; index++) {
134
+ let fingerprint = (0, authorizedKeys_1.keyFingerprint)(lines[index]);
135
+ let addresses = fingerprint && addressesByFingerprint.get(fingerprint);
136
+ if (!addresses || !addresses.length) {
137
+ continue;
138
+ }
139
+ let result = (0, authorizedKeys_1.allowAddresses)(lines[index], addresses);
140
+ lines[index] = result.keyLine;
141
+ added.set(fingerprint, [...(added.get(fingerprint) || []), ...result.added]);
142
+ }
143
+ if ([...added.values()].some(list => list.length)) {
144
+ await promises_1.default.writeFile(filePath, lines.join("\n"));
111
145
  }
112
- return { repoPath, originURL };
146
+ return added;
147
+ }
148
+ /** Puts each machine's addresses back into its own file, which is the machine equivalent of adding
149
+ an address to a key's from= list: without it the machine is allowed again in principle and
150
+ still rejected on sight, which revokes it once more. */
151
+ async function allowAddressesForMachines(config) {
152
+ let { repoPath, revocations } = config;
153
+ let added = new Map();
154
+ // Read the whole list, change what these revocations are about, write it back. Setting is by
155
+ // the whole set, so writing one machine at a time would delete every other machine.
156
+ let machines = await (0, machines_1.getMachines)(repoPath);
157
+ for (let revocation of revocations) {
158
+ let machineId = revocation.machineId;
159
+ let ip = revocationIP(revocation);
160
+ if (!machineId || !ip) {
161
+ continue;
162
+ }
163
+ let existing = machines.find(machine => machine.machineId === machineId);
164
+ if (!existing) {
165
+ // Removed from the repo since it was revoked, so there is nothing to allow. Deleting a
166
+ // machine is the stronger statement and it stands.
167
+ console.log(`machines/${machineId}.json is not in this repo, so ${ip} was not added to it`);
168
+ continue;
169
+ }
170
+ if (existing.ips.includes(ip)) {
171
+ continue;
172
+ }
173
+ existing.ips = [...existing.ips, ip];
174
+ added.set(machineId, [...(added.get(machineId) || []), ip]);
175
+ }
176
+ if (added.size) {
177
+ await (0, machines_1.setMachines)({ repoPath, machines });
178
+ }
179
+ return added;
113
180
  }
114
181
  async function main() {
115
- var _a;
116
182
  let argv = process.argv.slice(2);
117
183
  let pushToGit = argv.includes(GIT_KEYWORD);
118
184
  let positional = argv.filter(arg => arg !== GIT_KEYWORD);
119
185
  if (positional.length > 1) {
120
186
  throw new Error(`Expected at most a keys repo, was ${positional.length} argument(s)\n${USAGE}`);
121
187
  }
122
- let { repoPath, originURL } = await resolveKeysRepo(positional[0]);
188
+ let { repoPath, sourceURL: originURL } = await (0, keysRepo_1.resolveKeysRepo)(positional[0]);
123
189
  let revocations = await readRemoteRevocations({ sourceURL: originURL });
124
190
  if (!revocations.length) {
125
191
  console.log(`${(0, revokeSource_1.revokeRepoURL)(originURL)} lists no revocations, so there is nothing to undo.`);
@@ -132,36 +198,85 @@ async function main() {
132
198
  await promises_1.default.writeFile(path_1.default.join(directory, `${unrevokeId}.json`), JSON.stringify({
133
199
  unrevokeId,
134
200
  createdAt: new Date().toISOString(),
135
- // Named one by one rather than as a blanket "allow everything again", so this file only
136
- // ever undoes the revocations that existed when it was written.
137
- revocationIds: revocations.map(revocation => revocation.revocationId),
201
+ // What this file says: each of these keys is allowed from this address. Pairs, not keys,
202
+ // and not a blanket "allow everything again" - a key forgiven here for one address is
203
+ // still revoked the moment it is used from another.
204
+ allowed: revocations.map(revocation => ({
205
+ fingerprint: revocation.fingerprint,
206
+ machineId: revocation.machineId,
207
+ ip: revocationIP(revocation),
208
+ })),
138
209
  revocations: revocations.map(revocation => ({
139
210
  revocationId: revocation.revocationId,
140
211
  fingerprint: revocation.fingerprint,
212
+ machineId: revocation.machineId,
213
+ ip: revocationIP(revocation),
141
214
  revokedAt: revocation.revokedAt,
142
215
  revokedBy: revocation.revokedBy,
143
216
  attempt: revocation.attempt,
144
217
  })),
145
218
  }, undefined, 4) + "\n");
146
- console.log(`Wrote ${UNREVOKES_DIR}/${unrevokeId}.json covering ${revocations.length} revocation(s):`);
219
+ // Named the way the notifications name them. A fingerprint is not in authorized_keys and
220
+ // cannot be worked out by eye, so on its own it tells whoever is reading this nothing about
221
+ // which of their keys is being talked about.
222
+ let keysByFingerprint = new Map();
223
+ for (let key of await (0, authorizedKeys_2.readRepoKeys)(repoPath).catch(() => [])) {
224
+ keysByFingerprint.set((0, authorizedKeys_1.keyFingerprint)(key), key);
225
+ }
226
+ let describeKey = (revocation) => {
227
+ let key = keysByFingerprint.get(revocation.fingerprint || "") || revocation.key || "";
228
+ return key && (0, authorizedKeys_1.summarizeKey)(key) || `a key no longer in this repo (${revocation.fingerprint})`;
229
+ };
230
+ let addressesByIdentity = new Map();
147
231
  for (let revocation of revocations) {
148
- console.log(` ${revocation.fingerprint} revoked by ${revocation.revokedBy || "?"} from ${((_a = revocation.attempt) === null || _a === void 0 ? void 0 : _a.ip) || "?"}`);
232
+ let ip = revocationIP(revocation);
233
+ let identity = revocationIdentity(revocation);
234
+ let existing = addressesByIdentity.get(identity) || [];
235
+ if (ip && !existing.includes(ip)) {
236
+ existing.push(ip);
237
+ }
238
+ addressesByIdentity.set(identity, existing);
239
+ }
240
+ // Cancelling the revocation on its own would leave sshd refusing that address, and the machines
241
+ // revoking all over again, so the addresses go into the key's from= list and into the machine's
242
+ // own file here. We are in the repo that owns both, so there is nothing to hand back to whoever
243
+ // ran this.
244
+ let added = await allowAddressesInRepo({ repoPath, addressesByFingerprint: addressesByIdentity });
245
+ let addedForMachines = await allowAddressesForMachines({ repoPath, revocations });
246
+ console.log("");
247
+ for (let [identity, addresses] of addressesByIdentity) {
248
+ let entries = revocations.filter(entry => revocationIdentity(entry) === identity);
249
+ let machineId = entries[0].machineId;
250
+ console.log(`Unfreezing ${machineId && `machine ${machineId}` || describeKey(entries[0])}`);
251
+ console.log(`Allowing IP ${addresses.join(", ") || "(no address recorded)"}`);
252
+ let addedHere = machineId && addedForMachines.get(machineId) || added.get(identity) || [];
253
+ if (addedHere.length) {
254
+ let where = machineId && `machines/${machineId}.json` || `that key's from= list in authorized_keys`;
255
+ console.log(` added to ${where}: ${addedHere.join(", ")}`);
256
+ }
257
+ else {
258
+ console.log(` already allowed from ${addresses.join(", ") || "everywhere"}`);
259
+ }
260
+ for (let entry of entries) {
261
+ console.log(` frozen by ${entry.revokedBy || "?"} ${entry.revokedAt || "at an unrecorded time"}`);
262
+ }
263
+ console.log("");
149
264
  }
265
+ console.log(`Every other address stays frozen, and any of these used from anywhere else is`);
266
+ console.log(`frozen again.`);
150
267
  // Signed here rather than left as a step to remember. An unrevoke nobody signed does nothing at
151
268
  // all, and the repo would sit there looking done while every machine ignored it.
152
269
  await (0, signFiles_1.signRepo)({ repoPath });
153
270
  if (!pushToGit) {
154
- console.log(`\nCommit and push it, and each machine will wait an hour after seeing it before`);
155
- console.log(`those keys work again:`);
271
+ console.log(`\nCommit and push it, and those keys work again as each machine picks it up:`);
156
272
  console.log(`\`\`\`\ngit add -A\ngit commit -m "${COMMIT_MESSAGE}"\ngit push\n\`\`\``);
157
273
  return;
158
274
  }
159
275
  await (0, runPromise_1.runPromise)(`git add -A`, { cwd: repoPath });
160
276
  await (0, runPromise_1.runPromise)(`git commit -m "${COMMIT_MESSAGE}"`, { cwd: repoPath });
161
277
  await (0, runPromise_1.runPromise)(`git push`, { cwd: repoPath });
162
- console.log(`\nCommitted and pushed. Each machine waits an hour after seeing it before those`);
163
- console.log(`keys work again.`);
278
+ console.log(`\nCommitted and pushed. Those keys work again as each machine picks it up.`);
164
279
  }
165
280
  exports.main = main;
166
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5yZXZva2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1bnJldm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwyREFBNkI7QUFDN0IsNENBQW9CO0FBQ3BCLGdEQUF3QjtBQUN4QiwrREFBNEQ7QUFDNUQscURBQWlFO0FBQ2pFLGlEQUErQztBQUMvQyx3REFBb0Q7QUFDcEQscURBQWdEO0FBQ2hELDRDQUE4QztBQUM5Qyw0Q0FBZ0Q7QUFFaEQsTUFBTSxhQUFhLEdBQUcsV0FBVyxDQUFDO0FBQ2xDLE1BQU0sZUFBZSxHQUFHLGFBQWEsQ0FBQztBQUN0QyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUM7QUFDMUIsTUFBTSxjQUFjLEdBQUcsZUFBZSxDQUFDO0FBQ3ZDLE1BQU0sS0FBSyxHQUFHLHFDQUFxQyxXQUFXOzs7O3dDQUl0QixXQUFXOzs7MEJBR3pCLENBQUM7QUFXM0I7O3FEQUVxRDtBQUM5QyxLQUFLLFVBQVUscUJBQXFCLENBQUMsTUFBNkI7SUFDckUsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUMzQixJQUFJLGtCQUFrQixHQUFHLE1BQU0sa0JBQUUsQ0FBQyxPQUFPLENBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxZQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUMvRSxJQUFJLFFBQVEsR0FBRyxjQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3JELElBQUksS0FBSyxHQUFHLE1BQU0sSUFBQSxvQkFBWSxFQUFDO1FBQzNCLE9BQU8sRUFBRSxLQUFLO1FBQ2QsSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsSUFBQSw0QkFBYSxFQUFDLFNBQVMsQ0FBQyxFQUFFLFFBQVEsQ0FBQztLQUN0RSxDQUFDLENBQUM7SUFDSCxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFF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Q0FBQztRQUMvRixPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQ0FBc0MsY0FBYyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3ZGLE9BQU87SUFDWCxDQUFDO0lBQ0QsTUFBTSxJQUFBLHVCQUFVLEVBQUMsWUFBWSxFQUFFLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDbEQsTUFBTSxJQUFBLHVCQUFVLEVBQUMsa0JBQWtCLGNBQWMsR0FBRyxFQUFFLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDekUsTUFBTSxJQUFBLHVCQUFVLEVBQUMsVUFBVSxFQUFFLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpRkFBaUYsQ0FBQyxDQUFDO0lBQy9GLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBdERELG9CQXNEQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Qcm9taXNlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvcnVuUHJvbWlzZVwiO1xuaW1wb3J0IHsga2V5RmluZ2VycHJpbnQsIG5vcm1hbGl6ZUtleXMgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgcmV2b2tlUmVwb1VSTCB9IGZyb20gXCIuL3Jldm9rZVNvdXJjZVwiO1xuaW1wb3J0IHsgc2lnblJlcG8gfSBmcm9tIFwiLi4vc2lnbmVkRmlsZXMvc2lnbkZpbGVzXCI7XG5pbXBvcnQgeyByZWFkUmVwb0tleXMgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgZXhwYW5kSG9tZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BhdGhzXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vaGVscGVycy9zcGF3blwiO1xuXG5jb25zdCBVTlJFVk9LRVNfRElSID0gXCJ1bnJldm9rZWRcIjtcbmNvbnN0IFJFVk9DQVRJT05TX0RJUiA9IFwicmV2b2NhdGlvbnNcIjtcbmNvbnN0IEdJVF9LRVlXT1JEID0gXCJnaXRcIjtcbmNvbnN0IENPTU1JVF9NRVNTQUdFID0gXCJ1bnJldm9rZSBrZXlzXCI7XG5jb25zdCBVU0FHRSA9IGBVc2FnZTogeWFybiB1bnJldm9rZSBba2V5cy1yZXBvXSBbJHtHSVRfS0VZV09SRH1dXG5cblJ1biB0aGlzIGluIGEga2V5cyByZXBvLCBvciBuYW1lIG9uZS4gSXQgcmVhZHMgdGhhdCByZXBvJ3MgcmV2b2tlIHJlcG8gYW5kIHdyaXRlcyBvbmUgdW5yZXZva2UgZmlsZVxubmFtaW5nIGV2ZXJ5IHJldm9jYXRpb24gaW4gaXQsIHNvIHRoZSBrZXlzIGFyZSBhY2NlcHRlZCBhZ2FpbiBvbmNlIGVhY2ggbWFjaGluZSdzIGhvdXIgbG9uZyB3YWl0XG5wYXNzZXMuIEl0IHNpZ25zIHRoZSByZXN1bHQsIGFuZCB3aXRoICR7R0lUX0tFWVdPUkR9IGl0IGNvbW1pdHMgYW5kIHB1c2hlcyBpdCB0b28uXG5cbktleXMgdGhhdCB3ZXJlIHJldm9rZWQgc2hvdWxkIG5vcm1hbGx5IGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVwbyBpbnN0ZWFkLiBVbnJldm9raW5nIG9ubHkgbWF0dGVyc1xuZm9yIGEga2V5IHlvdSBzdGlsbCB3YW50LmA7XG5cbmV4cG9ydCB0eXBlIFJldm9jYXRpb24gPSB7XG4gICAgcmV2b2NhdGlvbklkOiBzdHJpbmc7XG4gICAgZmluZ2VycHJpbnQ6IHN0cmluZztcbiAgICBrZXk/OiBzdHJpbmc7XG4gICAgcmV2b2tlZEF0Pzogc3RyaW5nO1xuICAgIHJldm9rZWRCeT86IHN0cmluZztcbiAgICBhdHRlbXB0PzogeyBpcD86IHN0cmluZzsgdXNlcj86IHN0cmluZzsgcmVxdWlyZWQ/OiBzdHJpbmcgfTtcbn07XG5cbi8qKiBFdmVyeSByZXZvY2F0aW9uIHRoZSByZXZva2UgcmVwbyBsaXN0cy4gQ2xvbmVkIHJlYWQgb25seSBpbnRvIGEgdGVtcCBkaXJlY3RvcnksIHdpdGggd2hhdGV2ZXJcbiAgICBjcmVkZW50aWFscyB0aGlzIG1hY2hpbmUgYWxyZWFkeSBoYXMgLSB0aGUgZGVyaXZlZCBkZXBsb3kga2V5IGlzIGZvciBzZXJ2ZXJzLCBhbmQgYSBwZXJzb25cbiAgICBydW5uaW5nIHRoaXMgaGFzIHRoZWlyIG93biBhY2Nlc3MgdG8gdGhlIHJlcG8uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFJlbW90ZVJldm9jYXRpb25zKGNvbmZpZzogeyBzb3VyY2VVUkw6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgc291cmNlVVJMIH0gPSBjb25maWc7XG4gICAgbGV0IHRlbXBvcmFyeURpcmVjdG9yeSA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCBcInVucmV2b2tlLVwiKSk7XG4gICAgbGV0IHJlcG9QYXRoID0gcGF0aC5qb2luKHRlbXBvcmFyeURpcmVjdG9yeSwgXCJyZXBvXCIpO1xuICAgIGxldCBjbG9uZSA9IGF3YWl0IHNwYXduUHJvbWlzZSh7XG4gICAgICAgIGNvbW1hbmQ6IFwiZ2l0XCIsXG4gICAgICAgIGFyZ3M6IFtcImNsb25lXCIsIFwiLS1kZXB0aFwiLCBcIjFcIiwgcmV2b2tlUmVwb1VSTChzb3VyY2VVUkwpLCByZXBvUGF0aF0sXG4gICAgfSk7XG4gICAgaWYgKGNsb25lLnN0YXR1cyAhPT0gMCkge1xuICAgICAgICBhd2FpdCBmcy5ybSh0ZW1wb3JhcnlEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkIHRvIGJlIGFibGUgdG8gcmVhZCAke3Jldm9rZVJlcG9VUkwoc291cmNlVVJMKX0uXFxuYFxuICAgICAgICAgICAgKyBgJHsoY2xvbmUuc3Rkb3V0ICsgY2xvbmUuc3RkZXJyKS50cmltKCl9YFxuICAgICAgICApO1xuICAgIH1cbiAgICBsZXQgcmV2b2NhdGlvbnM6IFJldm9jYXRpb25bXSA9IFtdO1xuICAgIGxldCBkaXJlY3RvcnkgPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFJFVk9DQVRJT05TX0RJUik7XG4gICAgdHJ5IHtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBvZiAoYXdhaXQgZnMucmVhZGRpcihkaXJlY3RvcnkpKS5zb3J0KCkpIHtcbiAgICAgICAgICAgIGlmIChuYW1lLmVuZHNXaXRoKFwiLmpzb25cIikpIHtcbiAgICAgICAgICAgICAgICByZXZvY2F0aW9ucy5wdXNoKEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgbmFtZSksIFwidXRmOFwiKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBObyByZXZvY2F0aW9ucyBkaXJlY3RvcnkgYXQgYWxsIGp1c3QgbWVhbnMgbm90aGluZyBoYXMgZXZlciBiZWVuIHJldm9rZWQuXG4gICAgfVxuICAgIGF3YWl0IGZzLnJtKHRlbXBvcmFyeURpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIHJldHVybiByZXZvY2F0aW9ucztcbn1cblxuLyoqIFdoaWNoIGtleXMgaW4gYSByZXBvIGFyZSByZXZva2VkLiBXaGF0IHNpZ25maWxlcyBhbmQgc2VjdXJlc3NoIHJlZnVzZSBvdmVyLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJldm9rZWRLZXlzSW5SZXBvKGNvbmZpZzogeyByZXBvUGF0aDogc3RyaW5nOyBzb3VyY2VVUkw6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgcmVwb1BhdGgsIHNvdXJjZVVSTCB9ID0gY29uZmlnO1xuICAgIGxldCByZXZvY2F0aW9ucyA9IGF3YWl0IHJlYWRSZW1vdGVSZXZvY2F0aW9ucyh7IHNvdXJjZVVSTCB9KTtcbiAgICBsZXQgcmV2b2tlZEZpbmdlcnByaW50cyA9IG5ldyBTZXQocmV2b2NhdGlvbnMubWFwKHJldm9jYXRpb24gPT4gcmV2b2NhdGlvbi5maW5nZXJwcmludCkpO1xuICAgIGxldCB1bnJldm9rZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICB0cnkge1xuICAgICAgICBsZXQgZGlyZWN0b3J5ID0gcGF0aC5qb2luKHJlcG9QYXRoLCBVTlJFVk9LRVNfRElSKTtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBvZiBhd2FpdCBmcy5yZWFkZGlyKGRpcmVjdG9yeSkpIHtcbiAgICAgICAgICAgIGlmICghbmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gSlNPTi5wYXJzZShhd2FpdCBmcy5yZWFkRmlsZShwYXRoLmpvaW4oZGlyZWN0b3J5LCBuYW1lKSwgXCJ1dGY4XCIpKTtcbiAgICAgICAgICAgIGZvciAobGV0IHJldm9jYXRpb25JZCBvZiBwYXJzZWQucmV2b2NhdGlvbklkcyB8fCBbXSkge1xuICAgICAgICAgICAgICAgIHVucmV2b2tlZC5hZGQocmV2b2NhdGlvbklkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gTm90aGluZyBoYXMgYmVlbiB1bnJldm9rZWQuXG4gICAgfVxuICAgIGxldCBzdGlsbFJldm9rZWQgPSByZXZvY2F0aW9ucy5maWx0ZXIocmV2b2NhdGlvbiA9PiAhdW5yZXZva2VkLmhhcyhyZXZvY2F0aW9uLnJldm9jYXRpb25JZCkpO1xuICAgIGxldCBrZXlzID0gbm9ybWFsaXplS2V5cyhhd2FpdCBmcy5yZWFkRmlsZShwYXRoLmpvaW4ocmVwb1BhdGgsIFwiYXV0aG9yaXplZF9rZXlzXCIpLCBcInV0ZjhcIikuY2F0Y2goKCkgPT4gXCJcIikpO1xuICAgIHJldHVybiBzdGlsbFJldm9rZWRcbiAgICAgICAgLmZpbHRlcihyZXZvY2F0aW9uID0+IGtleXMuc29tZShrZXkgPT4ga2V5RmluZ2VycHJpbnQoa2V5KSA9PT0gcmV2b2NhdGlvbi5maW5nZXJwcmludCkpXG4gICAgICAgIC5tYXAocmV2b2NhdGlvbiA9PiAoeyByZXZvY2F0aW9uLCBrZXk6IGtleXMuZmluZChrZXkgPT4ga2V5RmluZ2VycHJpbnQoa2V5KSA9PT0gcmV2b2NhdGlvbi5maW5nZXJwcmludCkgfHwgXCJcIiB9KSk7XG59XG5cbi8qKiBUaGUgcmVwbyBuYW1lZCwgb3IgdGhlIG9uZSB3ZSBhcmUgc3RhbmRpbmcgaW4uIENoZWNrZWQgdGhlIHNhbWUgd2F5IHNlY3VyZXNzaCBjaGVja3MgaXQ6IGEgZ2l0XG4gICAgcmVwbyB0aGF0IGFjdHVhbGx5IGhvbGRzIGtleXMgYW5kIGhhcyBhbiBvcmlnaW4gdG8gY2xvbmUgZnJvbS4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVLZXlzUmVwbyhuYW1lZDogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgbGV0IGN3ZCA9IG5hbWVkICYmIGV4cGFuZEhvbWUobmFtZWQpIHx8IHVuZGVmaW5lZDtcbiAgICAvLyBzcGF3blByb21pc2UgcmF0aGVyIHRoYW4gcnVuUHJvbWlzZSwgYmVjYXVzZSB0aGVzZSB0d28gYXJlIHJlYWQgZm9yIHRoZWlyIHZhbHVlLiBydW5Qcm9taXNlXG4gICAgLy8gcmV0dXJucyBzdGRvdXQgYW5kIHN0ZGVyciBqb2luZWQsIHNvIG9uZSBnaXQgd2FybmluZyBlbmRzIHVwIGdsdWVkIHRvIHRoZSBmcm9udCBvZiB0aGUgcGF0aC5cbiAgICBsZXQgdG9wTGV2ZWwgPSBhd2FpdCBzcGF3blByb21pc2UoeyBjb21tYW5kOiBcImdpdFwiLCBhcmdzOiBbXCJyZXYtcGFyc2VcIiwgXCItLXNob3ctdG9wbGV2ZWxcIl0sIGN3ZCB9KTtcbiAgICBsZXQgcmVwb1BhdGggPSB0b3BMZXZlbC5zdGRvdXQudHJpbSgpO1xuICAgIGlmICh0b3BMZXZlbC5zdGF0dXMgIT09IDAgfHwgIXJlcG9QYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCAke25hbWVkIHx8IFwidGhlIGN1cnJlbnQgZGlyZWN0b3J5XCJ9IHRvIGJlIGluc2lkZSBhIGdpdCByZXBvLCBpdCBpcyBub3QuXFxuYFxuICAgICAgICAgICAgKyBgJHsodG9wTGV2ZWwuc3Rkb3V0ICsgdG9wTGV2ZWwuc3RkZXJyKS50cmltKCl9XFxuJHtVU0FHRX1gXG4gICAgICAgICk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHJlYWRSZXBvS2V5cyhyZXBvUGF0aCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkICR7cmVwb1BhdGh9IHRvIGJlIGEga2V5cyByZXBvLCBpdCBob2xkcyBubyBrZXlzLlxcbiR7ZX1cXG4ke1VTQUdFfWApO1xuICAgIH1cbiAgICBsZXQgb3JpZ2luID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogW1wicmVtb3RlXCIsIFwiZ2V0LXVybFwiLCBcIm9yaWdpblwiXSwgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBsZXQgb3JpZ2luVVJMID0gb3JpZ2luLnN0ZG91dC50cmltKCk7XG4gICAgaWYgKG9yaWdpbi5zdGF0dXMgIT09IDAgfHwgIW9yaWdpblVSTCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkICR7cmVwb1BhdGh9IHRvIGhhdmUgYW4gb3JpZ2luIHJlbW90ZSwgaXQgaGFzIG5vbmUuXFxuJHtVU0FHRX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcmVwb1BhdGgsIG9yaWdpblVSTCB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgICBsZXQgYXJndiA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbiAgICBsZXQgcHVzaFRvR2l0ID0gYXJndi5pbmNsdWRlcyhHSVRfS0VZV09SRCk7XG4gICAgbGV0IHBvc2l0aW9uYWwgPSBhcmd2LmZpbHRlcihhcmcgPT4gYXJnICE9PSBHSVRfS0VZV09SRCk7XG4gICAgaWYgKHBvc2l0aW9uYWwubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGF0IG1vc3QgYSBrZXlzIHJlcG8sIHdhcyAke3Bvc2l0aW9uYWwubGVuZ3RofSBhcmd1bWVudChzKVxcbiR7VVNBR0V9YCk7XG4gICAgfVxuICAgIGxldCB7IHJlcG9QYXRoLCBvcmlnaW5VUkwgfSA9IGF3YWl0IHJlc29sdmVLZXlzUmVwbyhwb3NpdGlvbmFsWzBdKTtcblxuICAgIGxldCByZXZvY2F0aW9ucyA9IGF3YWl0IHJlYWRSZW1vdGVSZXZvY2F0aW9ucyh7IHNvdXJjZVVSTDogb3JpZ2luVVJMIH0pO1xuICAgIGlmICghcmV2b2NhdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke3Jldm9rZVJlcG9VUkwob3JpZ2luVVJMKX0gbGlzdHMgbm8gcmV2b2NhdGlvbnMsIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG8gdW5kby5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBkaXJlY3RvcnkgPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFVOUkVWT0tFU19ESVIpO1xuICAgIGF3YWl0IGZzLm1rZGlyKGRpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgbGV0IHN0YW1wID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpLnJlcGxhY2UoL1s6Ll0vZywgXCItXCIpO1xuICAgIGxldCB1bnJldm9rZUlkID0gYCR7c3RhbXB9LXVucmV2b2tlYDtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgYCR7dW5yZXZva2VJZH0uanNvbmApLCBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHVucmV2b2tlSWQsXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAvLyBOYW1lZCBvbmUgYnkgb25lIHJhdGhlciB0aGFuIGFzIGEgYmxhbmtldCBcImFsbG93IGV2ZXJ5dGhpbmcgYWdhaW5cIiwgc28gdGhpcyBmaWxlIG9ubHlcbiAgICAgICAgLy8gZXZlciB1bmRvZXMgdGhlIHJldm9jYXRpb25zIHRoYXQgZXhpc3RlZCB3aGVuIGl0IHdhcyB3cml0dGVuLlxuICAgICAgICByZXZvY2F0aW9uSWRzOiByZXZvY2F0aW9ucy5tYXAocmV2b2NhdGlvbiA9PiByZXZvY2F0aW9uLnJldm9jYXRpb25JZCksXG4gICAgICAgIHJldm9jYXRpb25zOiByZXZvY2F0aW9ucy5tYXAocmV2b2NhdGlvbiA9PiAoe1xuICAgICAgICAgICAgcmV2b2NhdGlvbklkOiByZXZvY2F0aW9uLnJldm9jYXRpb25JZCxcbiAgICAgICAgICAgIGZpbmdlcnByaW50OiByZXZvY2F0aW9uLmZpbmdlcnByaW50LFxuICAgICAgICAgICAgcmV2b2tlZEF0OiByZXZvY2F0aW9uLnJldm9rZWRBdCxcbiAgICAgICAgICAgIHJldm9rZWRCeTogcmV2b2NhdGlvbi5yZXZva2VkQnksXG4gICAgICAgICAgICBhdHRlbXB0OiByZXZvY2F0aW9uLmF0dGVtcHQsXG4gICAgICAgIH0pKSxcbiAgICB9LCB1bmRlZmluZWQsIDQpICsgXCJcXG5cIik7XG5cbiAgICBjb25zb2xlLmxvZyhgV3JvdGUgJHtVTlJFVk9LRVNfRElSfS8ke3VucmV2b2tlSWR9Lmpzb24gY292ZXJpbmcgJHtyZXZvY2F0aW9ucy5sZW5ndGh9IHJldm9jYXRpb24ocyk6YCk7XG4gICAgZm9yIChsZXQgcmV2b2NhdGlvbiBvZiByZXZvY2F0aW9ucykge1xuICAgICAgICBjb25zb2xlLmxvZyhgICAke3Jldm9jYXRpb24uZmluZ2VycHJpbnR9IHJldm9rZWQgYnkgJHtyZXZvY2F0aW9uLnJldm9rZWRCeSB8fCBcIj9cIn0gZnJvbSAke3Jldm9jYXRpb24uYXR0ZW1wdD8uaXAgfHwgXCI/XCJ9YCk7XG4gICAgfVxuXG4gICAgLy8gU2lnbmVkIGhlcmUgcmF0aGVyIHRoYW4gbGVmdCBhcyBhIHN0ZXAgdG8gcmVtZW1iZXIuIEFuIHVucmV2b2tlIG5vYm9keSBzaWduZWQgZG9lcyBub3RoaW5nIGF0XG4gICAgLy8gYWxsLCBhbmQgdGhlIHJlcG8gd291bGQgc2l0IHRoZXJlIGxvb2tpbmcgZG9uZSB3aGlsZSBldmVyeSBtYWNoaW5lIGlnbm9yZWQgaXQuXG4gICAgYXdhaXQgc2lnblJlcG8oeyByZXBvUGF0aCB9KTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBcXG5Db21taXQgYW5kIHB1c2ggaXQsIGFuZCBlYWNoIG1hY2hpbmUgd2lsbCB3YWl0IGFuIGhvdXIgYWZ0ZXIgc2VlaW5nIGl0IGJlZm9yZWApO1xuICAgICAgICBjb25zb2xlLmxvZyhgdGhvc2Uga2V5cyB3b3JrIGFnYWluOmApO1xuICAgICAgICBjb25zb2xlLmxvZyhgXFxgXFxgXFxgXFxuZ2l0IGFkZCAtQVxcbmdpdCBjb21taXQgLW0gXCIke0NPTU1JVF9NRVNTQUdFfVwiXFxuZ2l0IHB1c2hcXG5cXGBcXGBcXGBgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgYWRkIC1BYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBjb21taXQgLW0gXCIke0NPTU1JVF9NRVNTQUdFfVwiYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBwdXNoYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGNvbnNvbGUubG9nKGBcXG5Db21taXR0ZWQgYW5kIHB1c2hlZC4gRWFjaCBtYWNoaW5lIHdhaXRzIGFuIGhvdXIgYWZ0ZXIgc2VlaW5nIGl0IGJlZm9yZSB0aG9zZWApO1xuICAgIGNvbnNvbGUubG9nKGBrZXlzIHdvcmsgYWdhaW4uYCk7XG59XG4iXX0=
167
- /* _JS_SOURCE_HASH = "0fcca51775122c0bd892f4c8b9872f06ef62cdb278ee8668702a7ce402c07867"; */
281
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5yZXZva2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1bnJldm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwyREFBNkI7QUFDN0IsNENBQW9CO0FBQ3BCLGdEQUF3QjtBQUN4QiwrREFBNEQ7QUFDNUQscURBQStGO0FBQy9GLGlEQUFnRTtBQUNoRSx1Q0FBMEM7QUFDMUMsd0RBQW9EO0FBQ3BELHFEQUFnRDtBQUVoRCw0Q0FBZ0Q7QUFDaEQsbURBQWdFO0FBQ2hFLHlDQUE2QztBQUU3QyxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUM7QUFDbEMsTUFBTSxlQUFlLEdBQUcsYUFBYSxDQUFDO0FBQ3RDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQztBQUMxQixNQUFNLGNBQWMsR0FBRyxlQUFlLENBQUM7QUFDdkMsTUFBTSxLQUFLLEdBQUcscUNBQXFDLFdBQVc7Ozs7dUJBSXZDLFdBQVc7OzswQkFHUixDQUFDO0FBcUIzQixtRUFBbUU7QUFDbkUsU0FBZ0IsWUFBWSxDQUFDLFVBQXNCOztJQUMvQyxPQUFPLFVBQVUsQ0FBQyxFQUFFLEtBQUksTUFBQSxVQUFVLENBQUMsT0FBTywwQ0FBRSxFQUFFLENBQUEsSUFBSSxFQUFFLENBQUM7QUFDekQsQ0FBQztBQUZELG9DQUVDO0FBRUQsc0ZBQXNGO0FBQ3RGLFNBQWdCLGtCQUFrQixDQUFDLFVBQXNCO0lBQ3JELE9BQU8sVUFBVSxDQUFDLFdBQVcsSUFBSSxVQUFVLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztBQUNoRSxDQUFDO0FBRkQsZ0RBRUM7QUFFRDs7OztrR0FJa0c7QUFDM0YsS0FBSyxVQUFVLHFCQUFxQixDQUFDLE1BQTZCO0lBQ3JFLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxNQUFNLENBQUM7SUFDM0IsSUFBSSxrQkFBa0IsR0FBRyxNQUFNLGtCQUFFLENBQUMsT0FBTyxDQUFDLGNBQUksQ0FBQyxJQUFJLENBQUMsWUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFF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QUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFFN0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4RUFBOEUsQ0FBQyxDQUFDO1FBQzVGLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLGNBQWMscUJBQXFCLENBQUMsQ0FBQztRQUN2RixPQUFPO0lBQ1gsQ0FBQztJQUNELE1BQU0sSUFBQSx1QkFBVSxFQUFDLFlBQVksRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELE1BQU0sSUFBQSx1QkFBVSxFQUFDLGtCQUFrQixjQUFjLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sSUFBQSx1QkFBVSxFQUFDLFVBQVUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsNEVBQTRFLENBQUMsQ0FBQztBQUM5RixDQUFDO0FBM0dELG9CQTJHQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Qcm9taXNlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvcnVuUHJvbWlzZVwiO1xuaW1wb3J0IHsgYWxsb3dBZGRyZXNzZXMsIGtleUZpbmdlcnByaW50LCBub3JtYWxpemVLZXlzLCBzdW1tYXJpemVLZXkgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgZGVyaXZlUmV2b2tlS2V5LCByZXZva2VSZXBvVVJMIH0gZnJvbSBcIi4vcmV2b2tlU291cmNlXCI7XG5pbXBvcnQgeyBmaW5kU291cmNlS2V5IH0gZnJvbSBcIi4vc291cmNlc1wiO1xuaW1wb3J0IHsgc2lnblJlcG8gfSBmcm9tIFwiLi4vc2lnbmVkRmlsZXMvc2lnbkZpbGVzXCI7XG5pbXBvcnQgeyByZWFkUmVwb0tleXMgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgZXhwYW5kSG9tZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BhdGhzXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vaGVscGVycy9zcGF3blwiO1xuaW1wb3J0IHsgZ2V0TWFjaGluZXMsIHNldE1hY2hpbmVzIH0gZnJvbSBcIi4uL21hY2hpbmVzL21hY2hpbmVzXCI7XG5pbXBvcnQgeyByZXNvbHZlS2V5c1JlcG8gfSBmcm9tIFwiLi9rZXlzUmVwb1wiO1xuXG5jb25zdCBVTlJFVk9LRVNfRElSID0gXCJ1bnJldm9rZWRcIjtcbmNvbnN0IFJFVk9DQVRJT05TX0RJUiA9IFwicmV2b2NhdGlvbnNcIjtcbmNvbnN0IEdJVF9LRVlXT1JEID0gXCJnaXRcIjtcbmNvbnN0IENPTU1JVF9NRVNTQUdFID0gXCJ1bnJldm9rZSBrZXlzXCI7XG5jb25zdCBVU0FHRSA9IGBVc2FnZTogeWFybiB1bnJldm9rZSBba2V5cy1yZXBvXSBbJHtHSVRfS0VZV09SRH1dXG5cblJ1biB0aGlzIGluIGEga2V5cyByZXBvLCBvciBuYW1lIG9uZS4gSXQgcmVhZHMgdGhhdCByZXBvJ3MgcmV2b2tlIHJlcG8gYW5kIHdyaXRlcyBvbmUgdW5yZXZva2UgZmlsZVxubmFtaW5nIGV2ZXJ5IHJldm9jYXRpb24gaW4gaXQsIHNvIHRoZSBrZXlzIGFyZSBhY2NlcHRlZCBhZ2FpbiBhcyBlYWNoIG1hY2hpbmUgcGlja3MgaXQgdXAuIEl0IHNpZ25zXG50aGUgcmVzdWx0LCBhbmQgd2l0aCAke0dJVF9LRVlXT1JEfSBpdCBjb21taXRzIGFuZCBwdXNoZXMgaXQgdG9vLlxuXG5LZXlzIHRoYXQgd2VyZSByZXZva2VkIHNob3VsZCBub3JtYWxseSBiZSBkZWxldGVkIGZyb20gdGhlIHJlcG8gaW5zdGVhZC4gVW5yZXZva2luZyBvbmx5IG1hdHRlcnNcbmZvciBhIGtleSB5b3Ugc3RpbGwgd2FudC5gO1xuXG4vKiogT25lIHJldm9jYXRpb24gZXZlbnQuIEVpdGhlciBhbiBzc2gga2V5IHVzZWQgZnJvbSBhbiBhZGRyZXNzIGl0IGlzIG5vdCBhbGxvd2VkIGZyb20sIG9yIGFcbiAgICBtYWNoaW5lIHRoYXQgdGFsa2VkIHRvIHVzIGZyb20gb25lLiBCb3RoIGFyZSB0aGUgc2FtZSBzaGFwZSAtIGFuIGlkZW50aXR5IGFuZCBhbiBhZGRyZXNzIC0gYW5kXG4gICAgYW4gdW5yZXZva2UgdW5kb2VzIGVpdGhlciBieSBhbGxvd2luZyB0aGF0IHNhbWUgcGFpci5cblxuICAgIFdoaWNoIGlzIHdoeSB1bnJldm9raW5nIG5ldmVyIG1ha2VzIGFueXRoaW5nIHVucmV2b2thYmxlOiB1c2VkIGZyb20gc29tZSBvdGhlciBhZGRyZXNzLCBpdCBpc1xuICAgIHJldm9rZWQgYWdhaW4sIHVuZGVyIGEgbmV3IGlkIG5vIGV4aXN0aW5nIHVucmV2b2tlIG5hbWVzLiAqL1xuZXhwb3J0IHR5cGUgUmV2b2NhdGlvbiA9IHtcbiAgICByZXZvY2F0aW9uSWQ6IHN0cmluZztcbiAgICAvLyBFeGFjdGx5IG9uZSBvZiB0aGVzZS4gQSBrZXkgcmV2b2NhdGlvbiBuYW1lcyBhIGZpbmdlcnByaW50LCBhIG1hY2hpbmUgcmV2b2NhdGlvbiBhIG1hY2hpbmVJZC5cbiAgICBmaW5nZXJwcmludD86IHN0cmluZztcbiAgICBtYWNoaW5lSWQ/OiBzdHJpbmc7XG4gICAgaXA/OiBzdHJpbmc7XG4gICAga2V5Pzogc3RyaW5nO1xuICAgIHJldm9rZWRBdD86IHN0cmluZztcbiAgICByZXZva2VkQnk/OiBzdHJpbmc7XG4gICAgcmVhc29uPzogc3RyaW5nO1xuICAgIGF0dGVtcHQ/OiB7IGlwPzogc3RyaW5nOyB1c2VyPzogc3RyaW5nOyByZXF1aXJlZD86IHN0cmluZyB9O1xufTtcblxuLyoqIE9sZGVyIHJldm9jYXRpb24gZmlsZXMgY2FycnkgdGhlIGFkZHJlc3MgdW5kZXIgYXR0ZW1wdCBvbmx5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9jYXRpb25JUChyZXZvY2F0aW9uOiBSZXZvY2F0aW9uKSB7XG4gICAgcmV0dXJuIHJldm9jYXRpb24uaXAgfHwgcmV2b2NhdGlvbi5hdHRlbXB0Py5pcCB8fCBcIlwiO1xufVxuXG4vKiogV2hhdCB0aGUgcmV2b2NhdGlvbiBpcyBhYm91dCwgd2hpY2ggaXMgd2hhdCBhbiB1bnJldm9rZSBoYXMgdG8gbmFtZSB0byB1bmRvIGl0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9jYXRpb25JZGVudGl0eShyZXZvY2F0aW9uOiBSZXZvY2F0aW9uKSB7XG4gICAgcmV0dXJuIHJldm9jYXRpb24uZmluZ2VycHJpbnQgfHwgcmV2b2NhdGlvbi5tYWNoaW5lSWQgfHwgXCJcIjtcbn1cblxuLyoqIEV2ZXJ5IHJldm9jYXRpb24gdGhlIHJldm9rZSByZXBvIGxpc3RzLiBDbG9uZWQgcmVhZCBvbmx5IGludG8gYSB0ZW1wIGRpcmVjdG9yeS5cblxuICAgIEEgcGVyc29uIHJ1bm5pbmcgdGhpcyBoYXMgdGhlaXIgb3duIGFjY2VzcyB0byB0aGUgcmVwbywgc28gdGhlaXIgY3JlZGVudGlhbHMgYXJlIHdoYXQgaXMgdXNlZC5cbiAgICBPbiBhIG1hY2hpbmUgdGhhdCBpcyBhbHJlYWR5IGEgcG9ydHNlY3VyZSBob3N0IHRoZXJlIG1heSBiZSBubyBzdWNoIGNyZWRlbnRpYWxzLCBidXQgdGhlIHNvdXJjZVxuICAgIGRlcGxveSBrZXkgaXMgcmlnaHQgdGhlcmUsIGFuZCB0aGUga2V5IGRlcml2ZWQgZnJvbSBpdCBpcyBvbmUgdGhhdCByZXBvIGRlZmluaXRlbHkgYWNjZXB0cy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkUmVtb3RlUmV2b2NhdGlvbnMoY29uZmlnOiB7IHNvdXJjZVVSTDogc3RyaW5nIH0pIHtcbiAgICBsZXQgeyBzb3VyY2VVUkwgfSA9IGNvbmZpZztcbiAgICBsZXQgdGVtcG9yYXJ5RGlyZWN0b3J5ID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksIFwidW5yZXZva2UtXCIpKTtcbiAgICBsZXQgcmVwb1BhdGggPSBwYXRoLmpvaW4odGVtcG9yYXJ5RGlyZWN0b3J5LCBcInJlcG9cIik7XG4gICAgbGV0IGNsb25lQXJncyA9IFtcImNsb25lXCIsIFwiLS1kZXB0aFwiLCBcIjFcIiwgcmV2b2tlUmVwb1VSTChzb3VyY2VVUkwpLCByZXBvUGF0aF07XG4gICAgbGV0IHNvdXJjZUtleSA9IGF3YWl0IGZpbmRTb3VyY2VLZXkoc291cmNlVVJMKTtcbiAgICBpZiAoc291cmNlS2V5KSB7XG4gICAgICAgIGxldCBkZXJpdmVkID0gZGVyaXZlUmV2b2tlS2V5KGF3YWl0IGZzLnJlYWRGaWxlKHNvdXJjZUtleSwgXCJ1dGY4XCIpKTtcbiAgICAgICAgbGV0IGRlcml2ZWRLZXlQYXRoID0gcGF0aC5qb2luKHRlbXBvcmFyeURpcmVjdG9yeSwgXCJrZXlcIik7XG4gICAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShkZXJpdmVkS2V5UGF0aCwgZGVyaXZlZC5wcml2YXRlS2V5RmlsZSwgeyBtb2RlOiAwbzYwMCB9KTtcbiAgICAgICAgbGV0IHNzaENvbW1hbmQgPSBgc3NoIC1pICR7ZGVyaXZlZEtleVBhdGh9IC1vIElkZW50aXRpZXNPbmx5PXllcyAtbyBCYXRjaE1vZGU9eWVzIC1vIFN0cmljdEhvc3RLZXlDaGVja2luZz1hY2NlcHQtbmV3YDtcbiAgICAgICAgY2xvbmVBcmdzID0gW1wiLWNcIiwgYGNvcmUuc3NoQ29tbWFuZD0ke3NzaENvbW1hbmR9YCwgLi4uY2xvbmVBcmdzXTtcbiAgICB9XG4gICAgbGV0IGNsb25lID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogY2xvbmVBcmdzIH0pO1xuICAgIGlmIChjbG9uZS5zdGF0dXMgIT09IDApIHtcbiAgICAgICAgYXdhaXQgZnMucm0odGVtcG9yYXJ5RGlyZWN0b3J5LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCB0byBiZSBhYmxlIHRvIHJlYWQgJHtyZXZva2VSZXBvVVJMKHNvdXJjZVVSTCl9LlxcbmBcbiAgICAgICAgICAgICsgYCR7KGNsb25lLnN0ZG91dCArIGNsb25lLnN0ZGVycikudHJpbSgpfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgbGV0IHJldm9jYXRpb25zOiBSZXZvY2F0aW9uW10gPSBbXTtcbiAgICBsZXQgZGlyZWN0b3J5ID0gcGF0aC5qb2luKHJlcG9QYXRoLCBSRVZPQ0FUSU9OU19ESVIpO1xuICAgIHRyeSB7XG4gICAgICAgIGZvciAobGV0IG5hbWUgb2YgKGF3YWl0IGZzLnJlYWRkaXIoZGlyZWN0b3J5KSkuc29ydCgpKSB7XG4gICAgICAgICAgICBpZiAobmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSB7XG4gICAgICAgICAgICAgICAgcmV2b2NhdGlvbnMucHVzaChKU09OLnBhcnNlKGF3YWl0IGZzLnJlYWRGaWxlKHBhdGguam9pbihkaXJlY3RvcnksIG5hbWUpLCBcInV0ZjhcIikpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gTm8gcmV2b2NhdGlvbnMgZGlyZWN0b3J5IGF0IGFsbCBqdXN0IG1lYW5zIG5vdGhpbmcgaGFzIGV2ZXIgYmVlbiByZXZva2VkLlxuICAgIH1cbiAgICBhd2FpdCBmcy5ybSh0ZW1wb3JhcnlEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICByZXR1cm4gcmV2b2NhdGlvbnM7XG59XG5cbi8qKiBXaGljaCBrZXlzIGluIGEgcmVwbyBhcmUgcmV2b2tlZC4gV2hhdCBzaWduZmlsZXMgYW5kIHNlY3VyZXNzaCByZWZ1c2Ugb3Zlci4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXZva2VkS2V5c0luUmVwbyhjb25maWc6IHsgcmVwb1BhdGg6IHN0cmluZzsgc291cmNlVVJMOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHJlcG9QYXRoLCBzb3VyY2VVUkwgfSA9IGNvbmZpZztcbiAgICBsZXQgcmV2b2NhdGlvbnMgPSBhd2FpdCByZWFkUmVtb3RlUmV2b2NhdGlvbnMoeyBzb3VyY2VVUkwgfSk7XG4gICAgbGV0IHJldm9rZWRGaW5nZXJwcmludHMgPSBuZXcgU2V0KHJldm9jYXRpb25zLm1hcChyZXZvY2F0aW9uID0+IHJldm9jYXRpb24uZmluZ2VycHJpbnQpKTtcbiAgICBsZXQgdW5yZXZva2VkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgdHJ5IHtcbiAgICAgICAgbGV0IGRpcmVjdG9yeSA9IHBhdGguam9pbihyZXBvUGF0aCwgVU5SRVZPS0VTX0RJUik7XG4gICAgICAgIGZvciAobGV0IG5hbWUgb2YgYXdhaXQgZnMucmVhZGRpcihkaXJlY3RvcnkpKSB7XG4gICAgICAgICAgICBpZiAoIW5hbWUuZW5kc1dpdGgoXCIuanNvblwiKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHBhcnNlZCA9IEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgbmFtZSksIFwidXRmOFwiKSk7XG4gICAgICAgICAgICBmb3IgKGxldCBhbGxvd2VkIG9mIHBhcnNlZC5hbGxvd2VkIHx8IFtdKSB7XG4gICAgICAgICAgICAgICAgdW5yZXZva2VkLmFkZChgJHthbGxvd2VkLmZpbmdlcnByaW50IHx8IGFsbG93ZWQubWFjaGluZUlkfSAke2FsbG93ZWQuaXB9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOYW1lZCBpZHMsIGZvciB0aGUgdW5yZXZva2VzIHdyaXR0ZW4gYmVmb3JlIHRoaXMgd2FzIGFib3V0IHBhaXJzLlxuICAgICAgICAgICAgZm9yIChsZXQgcmV2b2NhdGlvbklkIG9mIHBhcnNlZC5yZXZvY2F0aW9uSWRzIHx8IFtdKSB7XG4gICAgICAgICAgICAgICAgdW5yZXZva2VkLmFkZChyZXZvY2F0aW9uSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBOb3RoaW5nIGhhcyBiZWVuIHVucmV2b2tlZC5cbiAgICB9XG4gICAgbGV0IHN0aWxsUmV2b2tlZCA9IHJldm9jYXRpb25zLmZpbHRlcihyZXZvY2F0aW9uID0+ICF1bnJldm9rZWQuaGFzKHJldm9jYXRpb24ucmV2b2NhdGlvbklkKVxuICAgICAgICAmJiAhdW5yZXZva2VkLmhhcyhgJHtyZXZvY2F0aW9uLmZpbmdlcnByaW50fSAke3Jldm9jYXRpb25JUChyZXZvY2F0aW9uKX1gKSk7XG4gICAgbGV0IGtleXMgPSBub3JtYWxpemVLZXlzKGF3YWl0IGZzLnJlYWRGaWxlKHBhdGguam9pbihyZXBvUGF0aCwgXCJhdXRob3JpemVkX2tleXNcIiksIFwidXRmOFwiKS5jYXRjaCgoKSA9PiBcIlwiKSk7XG4gICAgcmV0dXJuIHN0aWxsUmV2b2tlZFxuICAgICAgICAuZmlsdGVyKHJldm9jYXRpb24gPT4ga2V5cy5zb21lKGtleSA9PiBrZXlGaW5nZXJwcmludChrZXkpID09PSByZXZvY2F0aW9uLmZpbmdlcnByaW50KSlcbiAgICAgICAgLm1hcChyZXZvY2F0aW9uID0+ICh7IHJldm9jYXRpb24sIGtleToga2V5cy5maW5kKGtleSA9PiBrZXlGaW5nZXJwcmludChrZXkpID09PSByZXZvY2F0aW9uLmZpbmdlcnByaW50KSB8fCBcIlwiIH0pKTtcbn1cblxuLyoqIFdyaXRlcyB0aGUgYWRkcmVzc2VzIGludG8gdGhlIGZyb209IGxpc3Qgb2YgZWFjaCBrZXkgaW4gdGhlIHJlcG8ncyBhdXRob3JpemVkX2tleXMsIGFuZCBzYXlzXG4gICAgd2hpY2ggb25lcyB3ZXJlIGFjdHVhbGx5IG5ldy4gT25seSB0aGUgbGluZXMgYmVpbmcgY2hhbmdlZCBhcmUgdG91Y2hlZCwgc28gY29tbWVudHMsIG9yZGVyaW5nXG4gICAgYW5kIGFueSBrZXkgbm90IGludm9sdmVkIGNvbWUgb3V0IG9mIHRoaXMgYnl0ZSBmb3IgYnl0ZSB0aGUgc2FtZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFsbG93QWRkcmVzc2VzSW5SZXBvKGNvbmZpZzoge1xuICAgIHJlcG9QYXRoOiBzdHJpbmc7XG4gICAgYWRkcmVzc2VzQnlGaW5nZXJwcmludDogTWFwPHN0cmluZywgc3RyaW5nW10+O1xufSkge1xuICAgIGxldCB7IHJlcG9QYXRoLCBhZGRyZXNzZXNCeUZpbmdlcnByaW50IH0gPSBjb25maWc7XG4gICAgbGV0IGFkZGVkID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZ1tdPigpO1xuICAgIGxldCBmaWxlUGF0aCA9IHBhdGguam9pbihyZXBvUGF0aCwgXCJhdXRob3JpemVkX2tleXNcIik7XG4gICAgbGV0IGNvbnRlbnRzO1xuICAgIHRyeSB7XG4gICAgICAgIGNvbnRlbnRzID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgsIFwidXRmOFwiKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIEEgcmVwbyBob2xkaW5nIGl0cyBrZXlzIGFzIHNlcGFyYXRlIC5wdWIgZmlsZXMuIE5vdGhpbmcgdG8gZWRpdCBpbiBvbmUgcGxhY2UsIHNvIHRoZVxuICAgICAgICAvLyBjYWxsZXIncyBsaXN0aW5nIGlzIGFsbCB3aG9ldmVyIHJhbiB0aGlzIGdldHMuXG4gICAgICAgIGNvbnNvbGUubG9nKGBObyBhdXRob3JpemVkX2tleXMgaW4gJHtyZXBvUGF0aH0sIHNvIHRoZSBhZGRyZXNzZXMgd2VyZSBub3QgYWRkZWQgdG8gYW55IGtleS5gKTtcbiAgICAgICAgcmV0dXJuIGFkZGVkO1xuICAgIH1cbiAgICBsZXQgbGluZXMgPSBjb250ZW50cy5zcGxpdChcIlxcblwiKTtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbGluZXMubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIGxldCBmaW5nZXJwcmludCA9IGtleUZpbmdlcnByaW50KGxpbmVzW2luZGV4XSk7XG4gICAgICAgIGxldCBhZGRyZXNzZXMgPSBmaW5nZXJwcmludCAmJiBhZGRyZXNzZXNCeUZpbmdlcnByaW50LmdldChmaW5nZXJwcmludCk7XG4gICAgICAgIGlmICghYWRkcmVzc2VzIHx8ICFhZGRyZXNzZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmVzdWx0ID0gYWxsb3dBZGRyZXNzZXMobGluZXNbaW5kZXhdLCBhZGRyZXNzZXMpO1xuICAgICAgICBsaW5lc1tpbmRleF0gPSByZXN1bHQua2V5TGluZTtcbiAgICAgICAgYWRkZWQuc2V0KGZpbmdlcnByaW50LCBbLi4uKGFkZGVkLmdldChmaW5nZXJwcmludCkgfHwgW10pLCAuLi5yZXN1bHQuYWRkZWRdKTtcbiAgICB9XG4gICAgaWYgKFsuLi5hZGRlZC52YWx1ZXMoKV0uc29tZShsaXN0ID0+IGxpc3QubGVuZ3RoKSkge1xuICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZVBhdGgsIGxpbmVzLmpvaW4oXCJcXG5cIikpO1xuICAgIH1cbiAgICByZXR1cm4gYWRkZWQ7XG59XG5cbi8qKiBQdXRzIGVhY2ggbWFjaGluZSdzIGFkZHJlc3NlcyBiYWNrIGludG8gaXRzIG93biBmaWxlLCB3aGljaCBpcyB0aGUgbWFjaGluZSBlcXVpdmFsZW50IG9mIGFkZGluZ1xuICAgIGFuIGFkZHJlc3MgdG8gYSBrZXkncyBmcm9tPSBsaXN0OiB3aXRob3V0IGl0IHRoZSBtYWNoaW5lIGlzIGFsbG93ZWQgYWdhaW4gaW4gcHJpbmNpcGxlIGFuZFxuICAgIHN0aWxsIHJlamVjdGVkIG9uIHNpZ2h0LCB3aGljaCByZXZva2VzIGl0IG9uY2UgbW9yZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFsbG93QWRkcmVzc2VzRm9yTWFjaGluZXMoY29uZmlnOiB7IHJlcG9QYXRoOiBzdHJpbmc7IHJldm9jYXRpb25zOiBSZXZvY2F0aW9uW10gfSkge1xuICAgIGxldCB7IHJlcG9QYXRoLCByZXZvY2F0aW9ucyB9ID0gY29uZmlnO1xuICAgIGxldCBhZGRlZCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICAvLyBSZWFkIHRoZSB3aG9sZSBsaXN0LCBjaGFuZ2Ugd2hhdCB0aGVzZSByZXZvY2F0aW9ucyBhcmUgYWJvdXQsIHdyaXRlIGl0IGJhY2suIFNldHRpbmcgaXMgYnlcbiAgICAvLyB0aGUgd2hvbGUgc2V0LCBzbyB3cml0aW5nIG9uZSBtYWNoaW5lIGF0IGEgdGltZSB3b3VsZCBkZWxldGUgZXZlcnkgb3RoZXIgbWFjaGluZS5cbiAgICBsZXQgbWFjaGluZXMgPSBhd2FpdCBnZXRNYWNoaW5lcyhyZXBvUGF0aCk7XG4gICAgZm9yIChsZXQgcmV2b2NhdGlvbiBvZiByZXZvY2F0aW9ucykge1xuICAgICAgICBsZXQgbWFjaGluZUlkID0gcmV2b2NhdGlvbi5tYWNoaW5lSWQ7XG4gICAgICAgIGxldCBpcCA9IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKTtcbiAgICAgICAgaWYgKCFtYWNoaW5lSWQgfHwgIWlwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZXhpc3RpbmcgPSBtYWNoaW5lcy5maW5kKG1hY2hpbmUgPT4gbWFjaGluZS5tYWNoaW5lSWQgPT09IG1hY2hpbmVJZCk7XG4gICAgICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZWQgZnJvbSB0aGUgcmVwbyBzaW5jZSBpdCB3YXMgcmV2b2tlZCwgc28gdGhlcmUgaXMgbm90aGluZyB0byBhbGxvdy4gRGVsZXRpbmcgYVxuICAgICAgICAgICAgLy8gbWFjaGluZSBpcyB0aGUgc3Ryb25nZXIgc3RhdGVtZW50IGFuZCBpdCBzdGFuZHMuXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgbWFjaGluZXMvJHttYWNoaW5lSWR9Lmpzb24gaXMgbm90IGluIHRoaXMgcmVwbywgc28gJHtpcH0gd2FzIG5vdCBhZGRlZCB0byBpdGApO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4aXN0aW5nLmlwcy5pbmNsdWRlcyhpcCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGV4aXN0aW5nLmlwcyA9IFsuLi5leGlzdGluZy5pcHMsIGlwXTtcbiAgICAgICAgYWRkZWQuc2V0KG1hY2hpbmVJZCwgWy4uLihhZGRlZC5nZXQobWFjaGluZUlkKSB8fCBbXSksIGlwXSk7XG4gICAgfVxuICAgIGlmIChhZGRlZC5zaXplKSB7XG4gICAgICAgIGF3YWl0IHNldE1hY2hpbmVzKHsgcmVwb1BhdGgsIG1hY2hpbmVzIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYWRkZWQ7XG59XG5cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7XG4gICAgbGV0IGFyZ3YgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMik7XG4gICAgbGV0IHB1c2hUb0dpdCA9IGFyZ3YuaW5jbHVkZXMoR0lUX0tFWVdPUkQpO1xuICAgIGxldCBwb3NpdGlvbmFsID0gYXJndi5maWx0ZXIoYXJnID0+IGFyZyAhPT0gR0lUX0tFWVdPUkQpO1xuICAgIGlmIChwb3NpdGlvbmFsLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhdCBtb3N0IGEga2V5cyByZXBvLCB3YXMgJHtwb3NpdGlvbmFsLmxlbmd0aH0gYXJndW1lbnQocylcXG4ke1VTQUdFfWApO1xuICAgIH1cbiAgICBsZXQgeyByZXBvUGF0aCwgc291cmNlVVJMOiBvcmlnaW5VUkwgfSA9IGF3YWl0IHJlc29sdmVLZXlzUmVwbyhwb3NpdGlvbmFsWzBdKTtcblxuICAgIGxldCByZXZvY2F0aW9ucyA9IGF3YWl0IHJlYWRSZW1vdGVSZXZvY2F0aW9ucyh7IHNvdXJjZVVSTDogb3JpZ2luVVJMIH0pO1xuICAgIGlmICghcmV2b2NhdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke3Jldm9rZVJlcG9VUkwob3JpZ2luVVJMKX0gbGlzdHMgbm8gcmV2b2NhdGlvbnMsIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG8gdW5kby5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBkaXJlY3RvcnkgPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFVOUkVWT0tFU19ESVIpO1xuICAgIGF3YWl0IGZzLm1rZGlyKGRpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgbGV0IHN0YW1wID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpLnJlcGxhY2UoL1s6Ll0vZywgXCItXCIpO1xuICAgIGxldCB1bnJldm9rZUlkID0gYCR7c3RhbXB9LXVucmV2b2tlYDtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgYCR7dW5yZXZva2VJZH0uanNvbmApLCBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHVucmV2b2tlSWQsXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAvLyBXaGF0IHRoaXMgZmlsZSBzYXlzOiBlYWNoIG9mIHRoZXNlIGtleXMgaXMgYWxsb3dlZCBmcm9tIHRoaXMgYWRkcmVzcy4gUGFpcnMsIG5vdCBrZXlzLFxuICAgICAgICAvLyBhbmQgbm90IGEgYmxhbmtldCBcImFsbG93IGV2ZXJ5dGhpbmcgYWdhaW5cIiAtIGEga2V5IGZvcmdpdmVuIGhlcmUgZm9yIG9uZSBhZGRyZXNzIGlzXG4gICAgICAgIC8vIHN0aWxsIHJldm9rZWQgdGhlIG1vbWVudCBpdCBpcyB1c2VkIGZyb20gYW5vdGhlci5cbiAgICAgICAgYWxsb3dlZDogcmV2b2NhdGlvbnMubWFwKHJldm9jYXRpb24gPT4gKHtcbiAgICAgICAgICAgIGZpbmdlcnByaW50OiByZXZvY2F0aW9uLmZpbmdlcnByaW50LFxuICAgICAgICAgICAgbWFjaGluZUlkOiByZXZvY2F0aW9uLm1hY2hpbmVJZCxcbiAgICAgICAgICAgIGlwOiByZXZvY2F0aW9uSVAocmV2b2NhdGlvbiksXG4gICAgICAgIH0pKSxcbiAgICAgICAgcmV2b2NhdGlvbnM6IHJldm9jYXRpb25zLm1hcChyZXZvY2F0aW9uID0+ICh7XG4gICAgICAgICAgICByZXZvY2F0aW9uSWQ6IHJldm9jYXRpb24ucmV2b2NhdGlvbklkLFxuICAgICAgICAgICAgZmluZ2VycHJpbnQ6IHJldm9jYXRpb24uZmluZ2VycHJpbnQsXG4gICAgICAgICAgICBtYWNoaW5lSWQ6IHJldm9jYXRpb24ubWFjaGluZUlkLFxuICAgICAgICAgICAgaXA6IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKSxcbiAgICAgICAgICAgIHJldm9rZWRBdDogcmV2b2NhdGlvbi5yZXZva2VkQXQsXG4gICAgICAgICAgICByZXZva2VkQnk6IHJldm9jYXRpb24ucmV2b2tlZEJ5LFxuICAgICAgICAgICAgYXR0ZW1wdDogcmV2b2NhdGlvbi5hdHRlbXB0LFxuICAgICAgICB9KSksXG4gICAgfSwgdW5kZWZpbmVkLCA0KSArIFwiXFxuXCIpO1xuXG4gICAgLy8gTmFtZWQgdGhlIHdheSB0aGUgbm90aWZpY2F0aW9ucyBuYW1lIHRoZW0uIEEgZmluZ2VycHJpbnQgaXMgbm90IGluIGF1dGhvcml6ZWRfa2V5cyBhbmRcbiAgICAvLyBjYW5ub3QgYmUgd29ya2VkIG91dCBieSBleWUsIHNvIG9uIGl0cyBvd24gaXQgdGVsbHMgd2hvZXZlciBpcyByZWFkaW5nIHRoaXMgbm90aGluZyBhYm91dFxuICAgIC8vIHdoaWNoIG9mIHRoZWlyIGtleXMgaXMgYmVpbmcgdGFsa2VkIGFib3V0LlxuICAgIGxldCBrZXlzQnlGaW5nZXJwcmludCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgZm9yIChsZXQga2V5IG9mIGF3YWl0IHJlYWRSZXBvS2V5cyhyZXBvUGF0aCkuY2F0Y2goKCkgPT4gW10gYXMgc3RyaW5nW10pKSB7XG4gICAgICAgIGtleXNCeUZpbmdlcnByaW50LnNldChrZXlGaW5nZXJwcmludChrZXkpLCBrZXkpO1xuICAgIH1cbiAgICBsZXQgZGVzY3JpYmVLZXkgPSAocmV2b2NhdGlvbjogUmV2b2NhdGlvbikgPT4ge1xuICAgICAgICBsZXQga2V5ID0ga2V5c0J5RmluZ2VycHJpbnQuZ2V0KHJldm9jYXRpb24uZmluZ2VycHJpbnQgfHwgXCJcIikgfHwgcmV2b2NhdGlvbi5rZXkgfHwgXCJcIjtcbiAgICAgICAgcmV0dXJuIGtleSAmJiBzdW1tYXJpemVLZXkoa2V5KSB8fCBgYSBrZXkgbm8gbG9uZ2VyIGluIHRoaXMgcmVwbyAoJHtyZXZvY2F0aW9uLmZpbmdlcnByaW50fSlgO1xuICAgIH07XG5cbiAgICBsZXQgYWRkcmVzc2VzQnlJZGVudGl0eSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICBmb3IgKGxldCByZXZvY2F0aW9uIG9mIHJldm9jYXRpb25zKSB7XG4gICAgICAgIGxldCBpcCA9IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKTtcbiAgICAgICAgbGV0IGlkZW50aXR5ID0gcmV2b2NhdGlvbklkZW50aXR5KHJldm9jYXRpb24pO1xuICAgICAgICBsZXQgZXhpc3RpbmcgPSBhZGRyZXNzZXNCeUlkZW50aXR5LmdldChpZGVudGl0eSkgfHwgW107XG4gICAgICAgIGlmIChpcCAmJiAhZXhpc3RpbmcuaW5jbHVkZXMoaXApKSB7XG4gICAgICAgICAgICBleGlzdGluZy5wdXNoKGlwKTtcbiAgICAgICAgfVxuICAgICAgICBhZGRyZXNzZXNCeUlkZW50aXR5LnNldChpZGVudGl0eSwgZXhpc3RpbmcpO1xuICAgIH1cblxuICAgIC8vIENhbmNlbGxpbmcgdGhlIHJldm9jYXRpb24gb24gaXRzIG93biB3b3VsZCBsZWF2ZSBzc2hkIHJlZnVzaW5nIHRoYXQgYWRkcmVzcywgYW5kIHRoZSBtYWNoaW5lc1xuICAgIC8vIHJldm9raW5nIGFsbCBvdmVyIGFnYWluLCBzbyB0aGUgYWRkcmVzc2VzIGdvIGludG8gdGhlIGtleSdzIGZyb209IGxpc3QgYW5kIGludG8gdGhlIG1hY2hpbmUnc1xuICAgIC8vIG93biBmaWxlIGhlcmUuIFdlIGFyZSBpbiB0aGUgcmVwbyB0aGF0IG93bnMgYm90aCwgc28gdGhlcmUgaXMgbm90aGluZyB0byBoYW5kIGJhY2sgdG8gd2hvZXZlclxuICAgIC8vIHJhbiB0aGlzLlxuICAgIGxldCBhZGRlZCA9IGF3YWl0IGFsbG93QWRkcmVzc2VzSW5SZXBvKHsgcmVwb1BhdGgsIGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQ6IGFkZHJlc3Nlc0J5SWRlbnRpdHkgfSk7XG4gICAgbGV0IGFkZGVkRm9yTWFjaGluZXMgPSBhd2FpdCBhbGxvd0FkZHJlc3Nlc0Zvck1hY2hpbmVzKHsgcmVwb1BhdGgsIHJldm9jYXRpb25zIH0pO1xuXG4gICAgY29uc29sZS5sb2coXCJcIik7XG4gICAgZm9yIChsZXQgW2lkZW50aXR5LCBhZGRyZXNzZXNdIG9mIGFkZHJlc3Nlc0J5SWRlbnRpdHkpIHtcbiAgICAgICAgbGV0IGVudHJpZXMgPSByZXZvY2F0aW9ucy5maWx0ZXIoZW50cnkgPT4gcmV2b2NhdGlvbklkZW50aXR5KGVudHJ5KSA9PT0gaWRlbnRpdHkpO1xuICAgICAgICBsZXQgbWFjaGluZUlkID0gZW50cmllc1swXS5tYWNoaW5lSWQ7XG4gICAgICAgIGNvbnNvbGUubG9nKGBVbmZyZWV6aW5nICR7bWFjaGluZUlkICYmIGBtYWNoaW5lICR7bWFjaGluZUlkfWAgfHwgZGVzY3JpYmVLZXkoZW50cmllc1swXSl9YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBBbGxvd2luZyBJUCAke2FkZHJlc3Nlcy5qb2luKFwiLCBcIikgfHwgXCIobm8gYWRkcmVzcyByZWNvcmRlZClcIn1gKTtcbiAgICAgICAgbGV0IGFkZGVkSGVyZSA9IG1hY2hpbmVJZCAmJiBhZGRlZEZvck1hY2hpbmVzLmdldChtYWNoaW5lSWQpIHx8IGFkZGVkLmdldChpZGVudGl0eSkgfHwgW107XG4gICAgICAgIGlmIChhZGRlZEhlcmUubGVuZ3RoKSB7XG4gICAgICAgICAgICBsZXQgd2hlcmUgPSBtYWNoaW5lSWQgJiYgYG1hY2hpbmVzLyR7bWFjaGluZUlkfS5qc29uYCB8fCBgdGhhdCBrZXkncyBmcm9tPSBsaXN0IGluIGF1dGhvcml6ZWRfa2V5c2A7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgICBhZGRlZCB0byAke3doZXJlfTogJHthZGRlZEhlcmUuam9pbihcIiwgXCIpfWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYCAgYWxyZWFkeSBhbGxvd2VkIGZyb20gJHthZGRyZXNzZXMuam9pbihcIiwgXCIpIHx8IFwiZXZlcnl3aGVyZVwifWApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgIGAgIGZyb3plbiBieSAke2VudHJ5LnJldm9rZWRCeSB8fCBcIj9cIn0gJHtlbnRyeS5yZXZva2VkQXQgfHwgXCJhdCBhbiB1bnJlY29yZGVkIHRpbWVcIn1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKFwiXCIpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgRXZlcnkgb3RoZXIgYWRkcmVzcyBzdGF5cyBmcm96ZW4sIGFuZCBhbnkgb2YgdGhlc2UgdXNlZCBmcm9tIGFueXdoZXJlIGVsc2UgaXNgKTtcbiAgICBjb25zb2xlLmxvZyhgZnJvemVuIGFnYWluLmApO1xuXG4gICAgLy8gU2lnbmVkIGhlcmUgcmF0aGVyIHRoYW4gbGVmdCBhcyBhIHN0ZXAgdG8gcmVtZW1iZXIuIEFuIHVucmV2b2tlIG5vYm9keSBzaWduZWQgZG9lcyBub3RoaW5nIGF0XG4gICAgLy8gYWxsLCBhbmQgdGhlIHJlcG8gd291bGQgc2l0IHRoZXJlIGxvb2tpbmcgZG9uZSB3aGlsZSBldmVyeSBtYWNoaW5lIGlnbm9yZWQgaXQuXG4gICAgYXdhaXQgc2lnblJlcG8oeyByZXBvUGF0aCB9KTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBcXG5Db21taXQgYW5kIHB1c2ggaXQsIGFuZCB0aG9zZSBrZXlzIHdvcmsgYWdhaW4gYXMgZWFjaCBtYWNoaW5lIHBpY2tzIGl0IHVwOmApO1xuICAgICAgICBjb25zb2xlLmxvZyhgXFxgXFxgXFxgXFxuZ2l0IGFkZCAtQVxcbmdpdCBjb21taXQgLW0gXCIke0NPTU1JVF9NRVNTQUdFfVwiXFxuZ2l0IHB1c2hcXG5cXGBcXGBcXGBgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgYWRkIC1BYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBjb21taXQgLW0gXCIke0NPTU1JVF9NRVNTQUdFfVwiYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBwdXNoYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGNvbnNvbGUubG9nKGBcXG5Db21taXR0ZWQgYW5kIHB1c2hlZC4gVGhvc2Uga2V5cyB3b3JrIGFnYWluIGFzIGVhY2ggbWFjaGluZSBwaWNrcyBpdCB1cC5gKTtcbn1cbiJdfQ==
282
+ /* _JS_SOURCE_HASH = "b373f6ddbf1cf2e062379c9bad20cb62583833a5a820a5b5e0b2db8a6f27c602"; */
@@ -0,0 +1,111 @@
1
+ import fs from "fs/promises";
2
+ import os from "os";
3
+ import path from "path";
4
+ import { CONFIG_PATH } from "./daemon/paths";
5
+ import { readRepoKeys } from "./authorizedKeys";
6
+ import { sourceRepoPath } from "./sources";
7
+ import { expandHome } from "../helpers/paths";
8
+ import { spawnPromise } from "../helpers/spawn";
9
+
10
+ // The one place that answers "which keys repo". Everything that reads or writes one comes here:
11
+ // signing, unrevoking, machine trust, and adding a machine. They were each working it out their
12
+ // own way, which is how signfiles ended up signing whatever repo you happened to be standing in.
13
+ //
14
+ // Where a Windows machine is expected to keep it, relative to the working directory. There is no
15
+ // daemon there and no /etc, so a sibling checkout is the convention.
16
+ const WINDOWS_REPO_PATH = "../authorized_keys";
17
+
18
+ async function pathExists(filePath: string) {
19
+ try {
20
+ await fs.access(filePath);
21
+ return true;
22
+ } catch (e) {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ /** A git checkout that actually holds keys. Both halves matter: a repo with no authorized_keys is
28
+ some other repo, and a directory that is not a checkout has nothing to push. */
29
+ async function isKeysRepo(repoPath: string) {
30
+ if (!await pathExists(path.join(repoPath, ".git"))) {
31
+ return false;
32
+ }
33
+ try {
34
+ await readRepoKeys(repoPath);
35
+ return true;
36
+ } catch (e) {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ /** The repo the working directory is inside, or "" when it is not inside one. */
42
+ async function repoOfCurrentDirectory() {
43
+ // Read for its value, so stdout has to be on its own. runPromise joins it with stderr, and a
44
+ // git warning glued to the front of this becomes a directory that does not exist.
45
+ let topLevel = await spawnPromise({ command: "git", args: ["rev-parse", "--show-toplevel"] });
46
+ return topLevel.status === 0 && topLevel.stdout.trim() || "";
47
+ }
48
+
49
+ /** Where this machine's own keys repo is, when the working directory is not one.
50
+
51
+ On a host that is the checkout the daemon keeps up to date. On Windows there is no daemon, so
52
+ it is the sibling directory. */
53
+ async function configuredRepo() {
54
+ if (os.platform() === "win32") {
55
+ return path.resolve(WINDOWS_REPO_PATH);
56
+ }
57
+ let config = await fs.readFile(CONFIG_PATH, "utf8").catch(() => "");
58
+ let sourceURL = config && (JSON.parse(config).repoSources || [])[0] || "";
59
+ return sourceURL && sourceRepoPath(sourceURL) || "";
60
+ }
61
+
62
+ async function originOf(repoPath: string) {
63
+ let origin = await spawnPromise({ command: "git", args: ["remote", "get-url", "origin"], cwd: repoPath });
64
+ let url = origin.stdout.trim();
65
+ if (origin.status !== 0 || !url) {
66
+ throw new Error(`Expected ${repoPath} to have an origin remote, it has none`);
67
+ }
68
+ return url;
69
+ }
70
+
71
+ /** The keys repo to act on.
72
+
73
+ A named one if there is one, otherwise the repo the command is being run in if that repo holds
74
+ keys, otherwise this machine's own. Running in some other repo therefore reaches the keys repo
75
+ rather than acting on whatever happened to be around - signing sliftutils because that is where
76
+ the terminal was is never what anybody meant. */
77
+ export async function resolveKeysRepo(named?: string): Promise<{ repoPath: string; sourceURL: string }> {
78
+ let tried: string[] = [];
79
+
80
+ let candidates: string[] = [];
81
+ if (named) {
82
+ candidates.push(expandHome(named));
83
+ } else {
84
+ let current = await repoOfCurrentDirectory();
85
+ if (current) {
86
+ candidates.push(current);
87
+ }
88
+ let configured = await configuredRepo();
89
+ if (configured && configured !== current) {
90
+ candidates.push(configured);
91
+ }
92
+ }
93
+
94
+ for (let repoPath of candidates) {
95
+ if (await isKeysRepo(repoPath)) {
96
+ return { repoPath, sourceURL: await originOf(repoPath) };
97
+ }
98
+ tried.push(repoPath);
99
+ }
100
+
101
+ throw new Error(
102
+ `Expected a git repo holding authorized_keys, found none.\n`
103
+ + `Looked in:\n ${tried.join("\n ") || "(nowhere - this is not a git repo)"}\n`
104
+ + (os.platform() === "win32"
105
+ ? `On Windows the repo is read from ${path.resolve(WINDOWS_REPO_PATH)}, so clone it there:\n`
106
+ + ` git clone <your authorized_keys repo> ${path.resolve(WINDOWS_REPO_PATH)}`
107
+ : `Set this machine up, or run this from inside a keys repo:\n`
108
+ + ` yarn setupnotify <discord-webhook-url>\n`
109
+ + ` yarn securessh add <repo-private-key> <repo-url>`)
110
+ );
111
+ }