sliftutils 1.7.129 → 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 (28) hide show
  1. package/misc/dist/ownIPs.ts.cache +30 -4
  2. package/misc/dist/strings.ts.cache +2 -2
  3. package/misc/https/dist/certs.ts.cache +2 -2
  4. package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
  5. package/misc/ownIPs.ts +29 -1
  6. package/package.json +1 -1
  7. package/security/authorizedKeys/daemon/dist/paths.ts.cache +3 -6
  8. package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
  9. package/security/authorizedKeys/daemon/dist/state.ts.cache +5 -3
  10. package/security/authorizedKeys/daemon/paths.ts +0 -3
  11. package/security/authorizedKeys/daemon/revocation.ts +0 -0
  12. package/security/authorizedKeys/daemon/state.ts +4 -8
  13. package/security/authorizedKeys/dist/keysRepo.ts.cache +111 -0
  14. package/security/authorizedKeys/dist/secureSSH.ts.cache +147 -71
  15. package/security/authorizedKeys/dist/unrevoke.ts.cache +70 -51
  16. package/security/authorizedKeys/keysRepo.ts +111 -0
  17. package/security/authorizedKeys/secureSSH.ts +28 -38
  18. package/security/authorizedKeys/unrevoke.ts +9 -36
  19. package/security/machines/addMachine.ts +4 -3
  20. package/security/machines/dist/identity.ts.cache +2 -2
  21. package/security/machines/dist/machines.ts.cache +36 -94
  22. package/security/machines/machines.ts +39 -90
  23. package/security/machines/trustServer.ts +5 -3
  24. package/security/notifications/dist/remoteWebhook.ts.cache +78 -0
  25. package/security/notifications/dist/setupNotify.ts.cache +39 -0
  26. package/security/signedFiles/dist/signFiles.ts.cache +8 -10
  27. package/security/signedFiles/signFiles.ts +6 -10
  28. package/security/machines/trustState.ts +0 -53
@@ -1,7 +1,7 @@
1
1
  import fs from "fs/promises";
2
2
  import os from "os";
3
3
  import path from "path";
4
- import { CONFIG_PATH } from "../authorizedKeys/daemon/paths";
4
+ import { resolveKeysRepo } from "../authorizedKeys/keysRepo";
5
5
  import { revokeRepo, syncRepoFiles } from "../authorizedKeys/daemon/repoFiles";
6
6
  import { listRepoDir, readRepoFile } from "../authorizedKeys/daemon/repoFiles";
7
7
  import { newRevocationId, pairKey, readRevocationFiles, readUnrevokes } from "../authorizedKeys/daemon/revocation";
@@ -9,10 +9,8 @@ import { runGit } from "../authorizedKeys/daemon/git";
9
9
  import { ensureRevokeKey } from "../authorizedKeys/daemon/repoFiles";
10
10
  import { verifyCheckout } from "../authorizedKeys/daemon/trust";
11
11
  import { revokeRepoPath, revokeRepoURL } from "../authorizedKeys/revokeSource";
12
- import { sourceRepoPath } from "../authorizedKeys/sources";
13
12
  import { notify } from "../authorizedKeys/daemon/notify";
14
13
  import { areDiscordNotificationsConfigured, configureDiscordNotifications, DEFAULT_WEBHOOK_FILE_PATH } from "../notifications/discord";
15
- import { unrevokeInEffect } from "./trustState";
16
14
  import { spawnPromise } from "../helpers/spawn";
17
15
 
18
16
  // Which machines this system talks to, kept in the same repo as the ssh keys. That repo is already
@@ -24,9 +22,6 @@ const REVOCATION_REASON = "a machine talked to us from an unapproved IP";
24
22
  // The revoke repo is pulled at most this often. A check happens per request, and a request must
25
23
  // not cost a round trip to github.
26
24
  const REVOKE_SYNC_INTERVAL = 60 * 1000;
27
- // Where a Windows machine is expected to keep the repo, relative to the working directory. There
28
- // is no daemon there to ask, and no /etc to look in.
29
- const WINDOWS_REPO_PATH = "../authorized_keys";
30
25
 
31
26
  /** One machine we are willing to talk to, and the addresses it may talk to us from. */
32
27
  export type MachineState = {
@@ -48,27 +43,27 @@ function machineFilePath(repoPath: string, machineId: string) {
48
43
  return path.join(repoPath, MACHINES_DIR, `${machineId}.json`);
49
44
  }
50
45
 
51
- /** Reads every machine a checkout lists, or sets them.
46
+ /** Every machine a checkout lists. */
47
+ export async function getMachines(repoPath: string): Promise<MachineState[]> {
48
+ return [...(await readMachines(repoPath)).values()];
49
+ }
50
+
51
+ /** Makes a checkout list exactly these machines: those named are written with the addresses given,
52
+ and anything not named is removed. So read them, change what you want, and write the result.
52
53
 
53
- Passing `machines` makes the repo match it exactly: machines named are written with the
54
- addresses given, and machines not named are removed. That is why the addresses are part of
55
- setting rather than a separate step - a machine with no address it may talk from is not a
56
- machine we would accept anyway, so there is no state where naming one without them means
57
- anything. Read first, change what you want, write the result.
54
+ The addresses are part of setting rather than a separate step, because a machine with no
55
+ address it may talk from is not a machine that would ever be accepted - there is no state where
56
+ naming one without them means anything.
58
57
 
59
- Nothing here signs or commits anything. The signature is what every other machine checks before
58
+ Nothing here signs or commits. The signature is what every other machine checks before
60
59
  believing any of this, and it takes the hardware key, so `yarn signfiles git` is still yours to
61
60
  run afterwards. */
62
- export async function machineState(config: {
61
+ export async function setMachines(config: {
63
62
  repoPath: string;
64
- machines?: { machineId: string; ips: string[] }[];
63
+ machines: { machineId: string; ips: string[] }[];
65
64
  }): Promise<MachineState[]> {
66
65
  let { repoPath, machines } = config;
67
66
  let existing = await readMachines(repoPath);
68
- if (!machines) {
69
- return [...existing.values()];
70
- }
71
-
72
67
  let directory = path.join(repoPath, MACHINES_DIR);
73
68
  let written: MachineState[] = [];
74
69
  for (let machine of machines) {
@@ -122,61 +117,6 @@ async function readMachines(repoPath: string) {
122
117
  return machines;
123
118
  }
124
119
 
125
- async function isKeysRepo(repoPath: string) {
126
- return await pathExists(path.join(repoPath, ".git"))
127
- && await pathExists(path.join(repoPath, "authorized_keys"));
128
- }
129
-
130
- async function originOf(repoPath: string) {
131
- let origin = await spawnPromise({ command: "git", args: ["remote", "get-url", "origin"], cwd: repoPath });
132
- let url = origin.stdout.trim();
133
- if (origin.status !== 0 || !url) {
134
- throw new Error(`Expected ${repoPath} to have an origin remote, it has none`);
135
- }
136
- return url;
137
- }
138
-
139
- /** The keys repo this machine answers from, and the one anything editing the machine list edits.
140
-
141
- On a host, that is the checkout the daemon already keeps up to date. On Windows there is no
142
- daemon and no /etc, so the repo is expected beside the working directory, which is where a
143
- developer working on both would have it.
144
-
145
- Never the directory the command happens to be run from. Which repo this machine trusts is a
146
- property of the machine, not of where somebody was standing when they typed something. */
147
- export async function resolveKeysRepo() {
148
- if (os.platform() === "win32") {
149
- let repoPath = path.resolve(WINDOWS_REPO_PATH);
150
- if (!await isKeysRepo(repoPath)) {
151
- throw new Error(
152
- `Expected ${repoPath} to be an authorized_keys repo, it is not.\n`
153
- + `On Windows the repo is read from there, so clone it beside this one:\n`
154
- + ` git clone <your authorized_keys repo> ${repoPath}`
155
- );
156
- }
157
- return { repoPath, sourceURL: await originOf(repoPath) };
158
- }
159
-
160
- let config = await fs.readFile(CONFIG_PATH, "utf8").catch(() => "");
161
- let sourceURL = config && (JSON.parse(config).repoSources || [])[0] || "";
162
- if (!sourceURL) {
163
- throw new Error(
164
- `Expected this machine to be set up with an authorized_keys repo, ${CONFIG_PATH} names none.\n`
165
- + `Set it up first:\n`
166
- + ` yarn setupnotify <discord-webhook-url>\n`
167
- + ` yarn securessh add <repo-private-key> <repo-url>`
168
- );
169
- }
170
- let repoPath = sourceRepoPath(sourceURL);
171
- if (!await isKeysRepo(repoPath)) {
172
- throw new Error(
173
- `Expected a checkout of ${sourceURL} at ${repoPath}, there is none.\n`
174
- + `Run \`yarn securessh update\` to put it back.`
175
- );
176
- }
177
- return { repoPath, sourceURL };
178
- }
179
-
180
120
  let lastRevokeSync = 0;
181
121
 
182
122
  /** Pulled at most once a REVOKE_SYNC_INTERVAL, because this is asked per request. A sync that
@@ -285,7 +225,7 @@ async function recordMachineRevocation(config: {
285
225
  + `\n\nIt is frozen everywhere now, and nothing accepts it.`
286
226
  + `\n\nIf this was an attack, remove \`machines/${machineId}.json\` from \`${sourceURL}\` now.`
287
227
  + `\nIf it was legitimate, run \`yarn unrevoke git\` in that repo. It allows ${ip} for that`
288
- + ` machine, and takes an hour to reach every machine.`
228
+ + ` machine, and takes effect as each machine picks it up.`
289
229
  + `\n\nmachine: \`${machineId}\``
290
230
  + `\nfrozen by: \`${hostLabel}\``
291
231
  );
@@ -299,9 +239,15 @@ async function recordMachineRevocation(config: {
299
239
  have, is treated as the same kind of event as a stolen ssh key - it is revoked everywhere, and
300
240
  stays revoked until an unrevoke allows that machine from that address.
301
241
 
242
+ Says why when the answer is no, because the three ways to be refused are entirely different
243
+ things to a person reading it: never trusted at all, trusted but frozen, or trusted and talking
244
+ from somewhere it should not be.
245
+
302
246
  Throws when the repo itself cannot be read or is not signed, rather than answering false: that
303
247
  is a broken installation, not a rejected machine, and the two deserve different handling. */
304
- export async function isMachineAccepted(config: { machineId: string; ip: string }): Promise<boolean> {
248
+ export type MachineVerdict = { accepted: boolean; reason: string };
249
+
250
+ export async function isMachineAccepted(config: { machineId: string; ip: string }): Promise<MachineVerdict> {
305
251
  let { machineId, ip } = config;
306
252
  if (!machineId || !ip) {
307
253
  throw new Error(`Expected a machineId and an ip, was ${JSON.stringify(machineId)} and ${JSON.stringify(ip)}`);
@@ -313,34 +259,36 @@ export async function isMachineAccepted(config: { machineId: string; ip: string
313
259
 
314
260
  let machine = (await readMachines(repoPath)).get(machineId);
315
261
  if (!machine) {
316
- return false;
262
+ return { accepted: false, reason: "that machine is not trusted" };
317
263
  }
318
264
 
319
265
  await syncRevocations(sourceURL);
320
266
  let unrevokes = await readUnrevokes(sourceURL).catch(() => ({ pairs: new Map(), legacyIds: new Map() }));
321
- // An unrevoke is only honoured once it has waited out its hour, exactly as an ssh key's is.
322
- let allowedAgain = async (pair: string) => {
323
- let unrevokeId = unrevokes.pairs.get(pair);
324
- return !!unrevokeId && await unrevokeInEffect(unrevokeId);
325
- };
267
+ // An unrevoke counts as soon as it is seen. It is signed, so writing one already takes the
268
+ // hardware key, and anyone holding that can sign anything at all - a wait before honouring it
269
+ // guards against an attacker who has no need of it.
270
+ let allowedAgain = (pair: string) => !!unrevokes.pairs.get(pair)?.length;
326
271
  let revocations = await readMachineRevocations(sourceURL);
327
272
  // Any revocation nothing has undone keeps the machine out, from everywhere, the way a revoked
328
273
  // ssh key is out everywhere rather than only from the address it was misused from.
329
- let revoked = false;
274
+ let frozenFrom = "";
330
275
  for (let revocation of revocations) {
331
276
  if (revocation.machineId !== machineId) {
332
277
  continue;
333
278
  }
334
- if (!await allowedAgain(pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }))) {
335
- revoked = true;
279
+ if (!allowedAgain(pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }))) {
280
+ frozenFrom = revocation.ip;
336
281
  }
337
282
  }
338
- if (revoked) {
339
- return false;
283
+ if (frozenFrom) {
284
+ return {
285
+ accepted: false,
286
+ reason: `that machine is frozen, it was used from ${frozenFrom} which it is not allowed from`,
287
+ };
340
288
  }
341
289
 
342
290
  if (machine.ips.includes(ip)) {
343
- return true;
291
+ return { accepted: true, reason: "" };
344
292
  }
345
293
 
346
294
  // Listed, but talking to us from somewhere it should not be. Recorded once for this machine
@@ -348,8 +296,9 @@ export async function isMachineAccepted(config: { machineId: string; ip: string
348
296
  let pair = pairKey({ fingerprint: machineId, ip });
349
297
  let alreadyRecorded = revocations.some(revocation =>
350
298
  pairKey({ fingerprint: revocation.machineId, ip: revocation.ip }) === pair);
351
- if (!alreadyRecorded && !await allowedAgain(pair)) {
299
+ if (!alreadyRecorded && !allowedAgain(pair)) {
352
300
  await recordMachineRevocation({ sourceURL, machineId, ip, hostLabel: os.hostname() });
301
+ return { accepted: false, reason: `that machine is not allowed from ${ip}, so it is now frozen everywhere` };
353
302
  }
354
- return false;
303
+ return { accepted: false, reason: `that machine is not allowed from ${ip}` };
355
304
  }
@@ -47,14 +47,16 @@ export function startTrustServer(config: { port: number }) {
47
47
  // Not a rejection of the machine, a packet that does not prove anything about one.
48
48
  return { status: 400, body: { trusted: false, ip, reason: verified.problem } };
49
49
  }
50
- let trusted = await isMachineAccepted({ machineId: packet.machineId, ip });
50
+ let verdict = await isMachineAccepted({ machineId: packet.machineId, ip });
51
51
  return {
52
52
  status: 200,
53
53
  body: {
54
- trusted,
54
+ trusted: verdict.accepted,
55
55
  machineId: packet.machineId,
56
56
  ip,
57
- reason: trusted && "" || "that machine is not trusted from that address",
57
+ // Whatever the check itself said. It is the only thing that knows which of the
58
+ // ways to be refused this was.
59
+ reason: verdict.reason,
58
60
  },
59
61
  };
60
62
  };
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.ensureRemoteWebhook = exports.REPLACE_KEYWORD = void 0;
4
+ const discord_1 = require("./discord");
5
+ const remoteSSH_1 = require("../helpers/remoteSSH");
6
+ exports.REPLACE_KEYWORD = "replace";
7
+ const UNPARSEABLE_LABEL = "(unparseable)";
8
+ /** Puts a webhook on a remote host, refusing to clobber a different existing one unless asked.
9
+ Returns what happened, so callers can decide whether to keep going. */
10
+ async function ensureRemoteWebhook(config) {
11
+ let { host, webhookURL, replace } = config;
12
+ let filePath = config.filePath || discord_1.DEFAULT_WEBHOOK_FILE_PATH;
13
+ let replacedURL = "";
14
+ let existingContents = await (0, remoteSSH_1.readRemoteFile)({ host, filePath });
15
+ if (existingContents) {
16
+ // A corrupt existing file still counts as a conflict, so "replace" can repair it instead
17
+ // of the setup dead ending on a parse error.
18
+ let existingURL = UNPARSEABLE_LABEL;
19
+ try {
20
+ existingURL = (0, discord_1.parseWebhookFile)({ contents: existingContents, sourceName: `${host}:${filePath}` });
21
+ }
22
+ catch (e) {
23
+ console.error(`${host}:${filePath} exists but could not be parsed. ${e}`);
24
+ }
25
+ if (existingURL === webhookURL) {
26
+ return { outcome: "unchanged", filePath };
27
+ }
28
+ if (!replace) {
29
+ throw new Error(`Expected no conflicting webhook on ${host}, but ${filePath} already holds a different one.\n`
30
+ + `Existing: ${existingURL}\n`
31
+ + `New: ${webhookURL}\n`
32
+ + `Pass "${exports.REPLACE_KEYWORD}" to overwrite it.`);
33
+ }
34
+ replacedURL = existingURL;
35
+ }
36
+ await (0, remoteSSH_1.writeRemoteFile)({
37
+ host,
38
+ filePath,
39
+ contents: (0, discord_1.formatWebhookFile)(webhookURL),
40
+ fileMode: "600",
41
+ directoryMode: "700",
42
+ });
43
+ let writtenContents = await (0, remoteSSH_1.readRemoteFile)({ host, filePath });
44
+ if (!writtenContents) {
45
+ throw new Error(`Expected ${filePath} to exist on ${host} after writing, no such file exists`);
46
+ }
47
+ let writtenURL = (0, discord_1.parseWebhookFile)({ contents: writtenContents, sourceName: `${host}:${filePath}` });
48
+ if (writtenURL !== webhookURL) {
49
+ throw new Error(`Expected ${host}:${filePath} to hold the new webhook, was ${writtenURL}`);
50
+ }
51
+ if (replacedURL && replacedURL !== UNPARSEABLE_LABEL) {
52
+ // The new webhook is redacted, so this channel can identify the replacement without
53
+ // receiving a webhook it could post to.
54
+ try {
55
+ await (0, discord_1.sendToWebhookURL)({
56
+ webhookURL: replacedURL,
57
+ message: `**portsecure**: the Discord webhook for \`${host}\` was replaced with`
58
+ + ` \`${(0, discord_1.redactWebhookURL)(webhookURL)}\`.`
59
+ + ` This channel will stop receiving notifications for that host.`,
60
+ });
61
+ }
62
+ catch (e) {
63
+ // The replacement already happened, so a dead old webhook must not fail the setup.
64
+ console.error(`Could not notify the old webhook that it was replaced. ${e}`);
65
+ }
66
+ }
67
+ // Failing here means the file is in place but the webhook itself does not work, which is
68
+ // exactly what the operator needs to hear about.
69
+ await (0, discord_1.sendToWebhookURL)({
70
+ webhookURL,
71
+ message: `**portsecure**: notifications are now configured for \`${host}\`.`
72
+ + ` This channel will receive its security notifications.`,
73
+ });
74
+ return { outcome: replacedURL && "replaced" || "created", filePath };
75
+ }
76
+ exports.ensureRemoteWebhook = ensureRemoteWebhook;
77
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlV2ViaG9vay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlbW90ZVdlYmhvb2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdUNBQStIO0FBQy9ILG9EQUF1RTtBQUUxRCxRQUFBLGVBQWUsR0FBRyxTQUFTLENBQUM7QUFDekMsTUFBTSxpQkFBaUIsR0FBRyxlQUFlLENBQUM7QUFFMUM7MEVBQzBFO0FBQ25FLEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxNQUt6QztJQUNHLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUMzQyxJQUFJLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxJQUFJLG1DQUF5QixDQUFDO0lBRTVELElBQUksV0FBVyxHQUFHLEVBQUUsQ0FBQztJQUNyQixJQUFJLGdCQUFnQixHQUFHLE1BQU0sSUFBQSwwQkFBYyxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDaEUsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ25CLHlGQUF5RjtRQUN6Riw2Q0FBNkM7UUFDN0MsSUFBSSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7UUFDcEMsSUFBSSxDQUFDO1lBQ0QsV0FBVyxHQUFHLElBQUEsMEJBQWdCLEVBQUMsRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBSSxJQUFJLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0RyxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNULE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLElBQUksUUFBUSxvQ0FBb0MsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM5RSxDQUFDO1FBQ0QsSUFBSSxXQUFXLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDN0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxXQUFvQixFQUFFLFFBQVEsRUFBRSxDQUFDO1FBQ3ZELENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUNYLHNDQUFzQyxJQUFJLFNBQVMsUUFBUSxtQ0FBbUM7a0JBQzVGLGFBQWEsV0FBVyxJQUFJO2tCQUM1QixhQUFhLFVBQVUsSUFBSTtrQkFDM0IsU0FBUyx1QkFBZSxvQkFBb0IsQ0FDakQsQ0FBQztRQUNOLENBQUM7UUFDRCxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQzlCLENBQUM7SUFFRCxNQUFNLElBQUEsMkJBQWUsRUFBQztRQUNsQixJQUFJO1FBQ0osUUFBUTtRQUNSLFFBQVEsRUFBRSxJQUFBLDJCQUFpQixFQUFDLFVBQVUsQ0FBQztRQUN2QyxRQUFRLEVBQUUsS0FBSztRQUNmLGFBQWEsRUFBRSxLQUFLO0tBQ3ZCLENBQUMsQ0FBQztJQUVILElBQUksZUFBZSxHQUFHLE1BQU0sSUFBQSwwQkFBYyxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDL0QsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ25CLE1BQU0sSUFBSSxLQUFLLENBQUMsWUFBWSxRQUFRLGdCQUFnQixJQUFJLHFDQUFxQyxDQUFDLENBQUM7SUFDbkcsQ0FBQztJQUNELElBQUksVUFBVSxHQUFHLElBQUEsMEJBQWdCLEVBQUMsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksSUFBSSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEcsSUFBSSxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxZQUFZLElBQUksSUFBSSxRQUFRLGlDQUFpQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQy9GLENBQUM7SUFFRCxJQUFJLFdBQVcsSUFBSSxXQUFXLEtBQUssaUJBQWlCLEVBQUUsQ0FBQztRQUNuRCxvRkFBb0Y7UUFDcEYsd0NBQXdDO1FBQ3hDLElBQUksQ0FBQztZQUNELE1BQU0sSUFBQSwwQkFBZ0IsRUFBQztnQkFDbkIsVUFBVSxFQUFFLFdBQVc7Z0JBQ3ZCLE9BQU8sRUFBRSw2Q0FBNkMsSUFBSSxzQkFBc0I7c0JBQzFFLE1BQU0sSUFBQSwwQkFBZ0IsRUFBQyxVQUFVLENBQUMsS0FBSztzQkFDdkMsZ0VBQWdFO2FBQ3pFLENBQUMsQ0FBQztRQUNQLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1QsbUZBQW1GO1lBQ25GLE9BQU8sQ0FBQyxLQUFLLENBQUMsMERBQTBELENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakYsQ0FBQztJQUNMLENBQUM7SUFFRCx5RkFBeUY7SUFDekYsaURBQWlEO0lBQ2pELE1BQU0sSUFBQSwwQkFBZ0IsRUFBQztRQUNuQixVQUFVO1FBQ1YsT0FBTyxFQUFFLDBEQUEwRCxJQUFJLEtBQUs7Y0FDdEUsd0RBQXdEO0tBQ2pFLENBQUMsQ0FBQztJQUVILE9BQU8sRUFBRSxPQUFPLEVBQUUsV0FBVyxJQUFJLFVBQW1CLElBQUksU0FBa0IsRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUMzRixDQUFDO0FBNUVELGtEQTRFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERFRkFVTFRfV0VCSE9PS19GSUxFX1BBVEgsIGZvcm1hdFdlYmhvb2tGaWxlLCBwYXJzZVdlYmhvb2tGaWxlLCByZWRhY3RXZWJob29rVVJMLCBzZW5kVG9XZWJob29rVVJMIH0gZnJvbSBcIi4vZGlzY29yZFwiO1xuaW1wb3J0IHsgcmVhZFJlbW90ZUZpbGUsIHdyaXRlUmVtb3RlRmlsZSB9IGZyb20gXCIuLi9oZWxwZXJzL3JlbW90ZVNTSFwiO1xuXG5leHBvcnQgY29uc3QgUkVQTEFDRV9LRVlXT1JEID0gXCJyZXBsYWNlXCI7XG5jb25zdCBVTlBBUlNFQUJMRV9MQUJFTCA9IFwiKHVucGFyc2VhYmxlKVwiO1xuXG4vKiogUHV0cyBhIHdlYmhvb2sgb24gYSByZW1vdGUgaG9zdCwgcmVmdXNpbmcgdG8gY2xvYmJlciBhIGRpZmZlcmVudCBleGlzdGluZyBvbmUgdW5sZXNzIGFza2VkLlxuICAgIFJldHVybnMgd2hhdCBoYXBwZW5lZCwgc28gY2FsbGVycyBjYW4gZGVjaWRlIHdoZXRoZXIgdG8ga2VlcCBnb2luZy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmVSZW1vdGVXZWJob29rKGNvbmZpZzoge1xuICAgIGhvc3Q6IHN0cmluZztcbiAgICB3ZWJob29rVVJMOiBzdHJpbmc7XG4gICAgcmVwbGFjZTogYm9vbGVhbjtcbiAgICBmaWxlUGF0aD86IHN0cmluZztcbn0pIHtcbiAgICBsZXQgeyBob3N0LCB3ZWJob29rVVJMLCByZXBsYWNlIH0gPSBjb25maWc7XG4gICAgbGV0IGZpbGVQYXRoID0gY29uZmlnLmZpbGVQYXRoIHx8IERFRkFVTFRfV0VCSE9PS19GSUxFX1BBVEg7XG5cbiAgICBsZXQgcmVwbGFjZWRVUkwgPSBcIlwiO1xuICAgIGxldCBleGlzdGluZ0NvbnRlbnRzID0gYXdhaXQgcmVhZFJlbW90ZUZpbGUoeyBob3N0LCBmaWxlUGF0aCB9KTtcbiAgICBpZiAoZXhpc3RpbmdDb250ZW50cykge1xuICAgICAgICAvLyBBIGNvcnJ1cHQgZXhpc3RpbmcgZmlsZSBzdGlsbCBjb3VudHMgYXMgYSBjb25mbGljdCwgc28gXCJyZXBsYWNlXCIgY2FuIHJlcGFpciBpdCBpbnN0ZWFkXG4gICAgICAgIC8vIG9mIHRoZSBzZXR1cCBkZWFkIGVuZGluZyBvbiBhIHBhcnNlIGVycm9yLlxuICAgICAgICBsZXQgZXhpc3RpbmdVUkwgPSBVTlBBUlNFQUJMRV9MQUJFTDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGV4aXN0aW5nVVJMID0gcGFyc2VXZWJob29rRmlsZSh7IGNvbnRlbnRzOiBleGlzdGluZ0NvbnRlbnRzLCBzb3VyY2VOYW1lOiBgJHtob3N0fToke2ZpbGVQYXRofWAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7aG9zdH06JHtmaWxlUGF0aH0gZXhpc3RzIGJ1dCBjb3VsZCBub3QgYmUgcGFyc2VkLiAke2V9YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4aXN0aW5nVVJMID09PSB3ZWJob29rVVJMKSB7XG4gICAgICAgICAgICByZXR1cm4geyBvdXRjb21lOiBcInVuY2hhbmdlZFwiIGFzIGNvbnN0LCBmaWxlUGF0aCB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghcmVwbGFjZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBFeHBlY3RlZCBubyBjb25mbGljdGluZyB3ZWJob29rIG9uICR7aG9zdH0sIGJ1dCAke2ZpbGVQYXRofSBhbHJlYWR5IGhvbGRzIGEgZGlmZmVyZW50IG9uZS5cXG5gXG4gICAgICAgICAgICAgICAgKyBgRXhpc3Rpbmc6ICR7ZXhpc3RpbmdVUkx9XFxuYFxuICAgICAgICAgICAgICAgICsgYE5ldzogICAgICAke3dlYmhvb2tVUkx9XFxuYFxuICAgICAgICAgICAgICAgICsgYFBhc3MgXCIke1JFUExBQ0VfS0VZV09SRH1cIiB0byBvdmVyd3JpdGUgaXQuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICByZXBsYWNlZFVSTCA9IGV4aXN0aW5nVVJMO1xuICAgIH1cblxuICAgIGF3YWl0IHdyaXRlUmVtb3RlRmlsZSh7XG4gICAgICAgIGhvc3QsXG4gICAgICAgIGZpbGVQYXRoLFxuICAgICAgICBjb250ZW50czogZm9ybWF0V2ViaG9va0ZpbGUod2ViaG9va1VSTCksXG4gICAgICAgIGZpbGVNb2RlOiBcIjYwMFwiLFxuICAgICAgICBkaXJlY3RvcnlNb2RlOiBcIjcwMFwiLFxuICAgIH0pO1xuXG4gICAgbGV0IHdyaXR0ZW5Db250ZW50cyA9IGF3YWl0IHJlYWRSZW1vdGVGaWxlKHsgaG9zdCwgZmlsZVBhdGggfSk7XG4gICAgaWYgKCF3cml0dGVuQ29udGVudHMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAke2ZpbGVQYXRofSB0byBleGlzdCBvbiAke2hvc3R9IGFmdGVyIHdyaXRpbmcsIG5vIHN1Y2ggZmlsZSBleGlzdHNgKTtcbiAgICB9XG4gICAgbGV0IHdyaXR0ZW5VUkwgPSBwYXJzZVdlYmhvb2tGaWxlKHsgY29udGVudHM6IHdyaXR0ZW5Db250ZW50cywgc291cmNlTmFtZTogYCR7aG9zdH06JHtmaWxlUGF0aH1gIH0pO1xuICAgIGlmICh3cml0dGVuVVJMICE9PSB3ZWJob29rVVJMKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtob3N0fToke2ZpbGVQYXRofSB0byBob2xkIHRoZSBuZXcgd2ViaG9vaywgd2FzICR7d3JpdHRlblVSTH1gKTtcbiAgICB9XG5cbiAgICBpZiAocmVwbGFjZWRVUkwgJiYgcmVwbGFjZWRVUkwgIT09IFVOUEFSU0VBQkxFX0xBQkVMKSB7XG4gICAgICAgIC8vIFRoZSBuZXcgd2ViaG9vayBpcyByZWRhY3RlZCwgc28gdGhpcyBjaGFubmVsIGNhbiBpZGVudGlmeSB0aGUgcmVwbGFjZW1lbnQgd2l0aG91dFxuICAgICAgICAvLyByZWNlaXZpbmcgYSB3ZWJob29rIGl0IGNvdWxkIHBvc3QgdG8uXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBzZW5kVG9XZWJob29rVVJMKHtcbiAgICAgICAgICAgICAgICB3ZWJob29rVVJMOiByZXBsYWNlZFVSTCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBgKipwb3J0c2VjdXJlKio6IHRoZSBEaXNjb3JkIHdlYmhvb2sgZm9yIFxcYCR7aG9zdH1cXGAgd2FzIHJlcGxhY2VkIHdpdGhgXG4gICAgICAgICAgICAgICAgICAgICsgYCBcXGAke3JlZGFjdFdlYmhvb2tVUkwod2ViaG9va1VSTCl9XFxgLmBcbiAgICAgICAgICAgICAgICAgICAgKyBgIFRoaXMgY2hhbm5lbCB3aWxsIHN0b3AgcmVjZWl2aW5nIG5vdGlmaWNhdGlvbnMgZm9yIHRoYXQgaG9zdC5gLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIFRoZSByZXBsYWNlbWVudCBhbHJlYWR5IGhhcHBlbmVkLCBzbyBhIGRlYWQgb2xkIHdlYmhvb2sgbXVzdCBub3QgZmFpbCB0aGUgc2V0dXAuXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBDb3VsZCBub3Qgbm90aWZ5IHRoZSBvbGQgd2ViaG9vayB0aGF0IGl0IHdhcyByZXBsYWNlZC4gJHtlfWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmFpbGluZyBoZXJlIG1lYW5zIHRoZSBmaWxlIGlzIGluIHBsYWNlIGJ1dCB0aGUgd2ViaG9vayBpdHNlbGYgZG9lcyBub3Qgd29yaywgd2hpY2ggaXNcbiAgICAvLyBleGFjdGx5IHdoYXQgdGhlIG9wZXJhdG9yIG5lZWRzIHRvIGhlYXIgYWJvdXQuXG4gICAgYXdhaXQgc2VuZFRvV2ViaG9va1VSTCh7XG4gICAgICAgIHdlYmhvb2tVUkwsXG4gICAgICAgIG1lc3NhZ2U6IGAqKnBvcnRzZWN1cmUqKjogbm90aWZpY2F0aW9ucyBhcmUgbm93IGNvbmZpZ3VyZWQgZm9yIFxcYCR7aG9zdH1cXGAuYFxuICAgICAgICAgICAgKyBgIFRoaXMgY2hhbm5lbCB3aWxsIHJlY2VpdmUgaXRzIHNlY3VyaXR5IG5vdGlmaWNhdGlvbnMuYCxcbiAgICB9KTtcblxuICAgIHJldHVybiB7IG91dGNvbWU6IHJlcGxhY2VkVVJMICYmIFwicmVwbGFjZWRcIiBhcyBjb25zdCB8fCBcImNyZWF0ZWRcIiBhcyBjb25zdCwgZmlsZVBhdGggfTtcbn1cbiJdfQ==
78
+ /* _JS_SOURCE_HASH = "7383d5b5b9fee5c3deb4ea3e75d9c556e64aef84ab8d71e7683a02bc87c5070a"; */
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.main = void 0;
4
+ const discord_1 = require("./discord");
5
+ const remoteWebhook_1 = require("./remoteWebhook");
6
+ const remoteSSH_1 = require("../helpers/remoteSSH");
7
+ const USAGE = `Usage: yarn setupnotify [host] <discord-webhook-url> [${remoteWebhook_1.REPLACE_KEYWORD}]
8
+
9
+ With no host it sets the webhook up on this machine.`;
10
+ function parseArgs(argv) {
11
+ let replace = argv.includes(remoteWebhook_1.REPLACE_KEYWORD);
12
+ let positional = argv.filter(arg => arg !== remoteWebhook_1.REPLACE_KEYWORD);
13
+ if (!positional.length || positional.length > 2) {
14
+ throw new Error(`Expected a webhook URL, and optionally a host before it, was ${positional.length}`
15
+ + ` argument(s): ${positional.join(" ") || "(none)"}\n${USAGE}`);
16
+ }
17
+ // The webhook url is the last one, so whatever comes before it is the host. Without one this
18
+ // machine is the target.
19
+ let webhookURL = positional[positional.length - 1];
20
+ let host = positional.length > 1 && positional[0] || remoteSSH_1.THIS_MACHINE;
21
+ // Validates the URL shape up front, so we never go anywhere with a bad webhook.
22
+ (0, discord_1.parseWebhookFile)({ contents: webhookURL, sourceName: "the command line" });
23
+ return { host, webhookURL, replace };
24
+ }
25
+ async function main() {
26
+ let { host, webhookURL, replace } = parseArgs(process.argv.slice(2));
27
+ let { outcome, filePath } = await (0, remoteWebhook_1.ensureRemoteWebhook)({ host, webhookURL, replace });
28
+ if (outcome === "unchanged") {
29
+ console.log(`${(0, remoteSSH_1.describeHost)(host)} already has this exact webhook in ${filePath}, nothing to do.`);
30
+ return;
31
+ }
32
+ if (outcome === "replaced") {
33
+ console.log(`Replaced the webhook on ${(0, remoteSSH_1.describeHost)(host)} and notified the old one.`);
34
+ }
35
+ console.log(`Wrote ${filePath} on ${(0, remoteSSH_1.describeHost)(host)} (mode 600), and confirmed on the new webhook.`);
36
+ }
37
+ exports.main = main;
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dXBOb3RpZnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZXR1cE5vdGlmeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx1Q0FBNkM7QUFDN0MsbURBQXVFO0FBQ3ZFLG9EQUFrRTtBQUVsRSxNQUFNLEtBQUssR0FBRyx5REFBeUQsK0JBQWU7O3FEQUVqQyxDQUFDO0FBRXRELFNBQVMsU0FBUyxDQUFDLElBQWM7SUFDN0IsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQywrQkFBZSxDQUFDLENBQUM7SUFDN0MsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSywrQkFBZSxDQUFDLENBQUM7SUFDN0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLElBQUksVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM5QyxNQUFNLElBQUksS0FBSyxDQUNYLGdFQUFnRSxVQUFVLENBQUMsTUFBTSxFQUFFO2NBQ2pGLGlCQUFpQixVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLFFBQVEsS0FBSyxLQUFLLEVBQUUsQ0FDbEUsQ0FBQztJQUNOLENBQUM7SUFDRCw2RkFBNkY7SUFDN0YseUJBQXlCO0lBQ3pCLElBQUksVUFBVSxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ25ELElBQUksSUFBSSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSx3QkFBWSxDQUFDO0lBQ2xFLGdGQUFnRjtJQUNoRixJQUFBLDBCQUFnQixFQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO0lBQzNFLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBQ3pDLENBQUM7QUFFTSxLQUFLLFVBQVUsSUFBSTtJQUN0QixJQUFJLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sSUFBQSxtQ0FBbUIsRUFBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRixJQUFJLE9BQU8sS0FBSyxXQUFXLEVBQUUsQ0FBQztRQUMxQixPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBQSx3QkFBWSxFQUFDLElBQUksQ0FBQyxzQ0FBc0MsUUFBUSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ25HLE9BQU87SUFDWCxDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsSUFBQSx3QkFBWSxFQUFDLElBQUksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsUUFBUSxPQUFPLElBQUEsd0JBQVksRUFBQyxJQUFJLENBQUMsZ0RBQWdELENBQUMsQ0FBQztBQUM1RyxDQUFDO0FBWEQsb0JBV0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwYXJzZVdlYmhvb2tGaWxlIH0gZnJvbSBcIi4vZGlzY29yZFwiO1xuaW1wb3J0IHsgZW5zdXJlUmVtb3RlV2ViaG9vaywgUkVQTEFDRV9LRVlXT1JEIH0gZnJvbSBcIi4vcmVtb3RlV2ViaG9va1wiO1xuaW1wb3J0IHsgZGVzY3JpYmVIb3N0LCBUSElTX01BQ0hJTkUgfSBmcm9tIFwiLi4vaGVscGVycy9yZW1vdGVTU0hcIjtcblxuY29uc3QgVVNBR0UgPSBgVXNhZ2U6IHlhcm4gc2V0dXBub3RpZnkgW2hvc3RdIDxkaXNjb3JkLXdlYmhvb2stdXJsPiBbJHtSRVBMQUNFX0tFWVdPUkR9XVxuXG5XaXRoIG5vIGhvc3QgaXQgc2V0cyB0aGUgd2ViaG9vayB1cCBvbiB0aGlzIG1hY2hpbmUuYDtcblxuZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3Y6IHN0cmluZ1tdKSB7XG4gICAgbGV0IHJlcGxhY2UgPSBhcmd2LmluY2x1ZGVzKFJFUExBQ0VfS0VZV09SRCk7XG4gICAgbGV0IHBvc2l0aW9uYWwgPSBhcmd2LmZpbHRlcihhcmcgPT4gYXJnICE9PSBSRVBMQUNFX0tFWVdPUkQpO1xuICAgIGlmICghcG9zaXRpb25hbC5sZW5ndGggfHwgcG9zaXRpb25hbC5sZW5ndGggPiAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCBhIHdlYmhvb2sgVVJMLCBhbmQgb3B0aW9uYWxseSBhIGhvc3QgYmVmb3JlIGl0LCB3YXMgJHtwb3NpdGlvbmFsLmxlbmd0aH1gXG4gICAgICAgICAgICArIGAgYXJndW1lbnQocyk6ICR7cG9zaXRpb25hbC5qb2luKFwiIFwiKSB8fCBcIihub25lKVwifVxcbiR7VVNBR0V9YFxuICAgICAgICApO1xuICAgIH1cbiAgICAvLyBUaGUgd2ViaG9vayB1cmwgaXMgdGhlIGxhc3Qgb25lLCBzbyB3aGF0ZXZlciBjb21lcyBiZWZvcmUgaXQgaXMgdGhlIGhvc3QuIFdpdGhvdXQgb25lIHRoaXNcbiAgICAvLyBtYWNoaW5lIGlzIHRoZSB0YXJnZXQuXG4gICAgbGV0IHdlYmhvb2tVUkwgPSBwb3NpdGlvbmFsW3Bvc2l0aW9uYWwubGVuZ3RoIC0gMV07XG4gICAgbGV0IGhvc3QgPSBwb3NpdGlvbmFsLmxlbmd0aCA+IDEgJiYgcG9zaXRpb25hbFswXSB8fCBUSElTX01BQ0hJTkU7XG4gICAgLy8gVmFsaWRhdGVzIHRoZSBVUkwgc2hhcGUgdXAgZnJvbnQsIHNvIHdlIG5ldmVyIGdvIGFueXdoZXJlIHdpdGggYSBiYWQgd2ViaG9vay5cbiAgICBwYXJzZVdlYmhvb2tGaWxlKHsgY29udGVudHM6IHdlYmhvb2tVUkwsIHNvdXJjZU5hbWU6IFwidGhlIGNvbW1hbmQgbGluZVwiIH0pO1xuICAgIHJldHVybiB7IGhvc3QsIHdlYmhvb2tVUkwsIHJlcGxhY2UgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7XG4gICAgbGV0IHsgaG9zdCwgd2ViaG9va1VSTCwgcmVwbGFjZSB9ID0gcGFyc2VBcmdzKHByb2Nlc3MuYXJndi5zbGljZSgyKSk7XG4gICAgbGV0IHsgb3V0Y29tZSwgZmlsZVBhdGggfSA9IGF3YWl0IGVuc3VyZVJlbW90ZVdlYmhvb2soeyBob3N0LCB3ZWJob29rVVJMLCByZXBsYWNlIH0pO1xuICAgIGlmIChvdXRjb21lID09PSBcInVuY2hhbmdlZFwiKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke2Rlc2NyaWJlSG9zdChob3N0KX0gYWxyZWFkeSBoYXMgdGhpcyBleGFjdCB3ZWJob29rIGluICR7ZmlsZVBhdGh9LCBub3RoaW5nIHRvIGRvLmApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChvdXRjb21lID09PSBcInJlcGxhY2VkXCIpIHtcbiAgICAgICAgY29uc29sZS5sb2coYFJlcGxhY2VkIHRoZSB3ZWJob29rIG9uICR7ZGVzY3JpYmVIb3N0KGhvc3QpfSBhbmQgbm90aWZpZWQgdGhlIG9sZCBvbmUuYCk7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBXcm90ZSAke2ZpbGVQYXRofSBvbiAke2Rlc2NyaWJlSG9zdChob3N0KX0gKG1vZGUgNjAwKSwgYW5kIGNvbmZpcm1lZCBvbiB0aGUgbmV3IHdlYmhvb2suYCk7XG59XG4iXX0=
39
+ /* _JS_SOURCE_HASH = "75262294c247703aec2fc4b9dcf81c245e79b0b1566401ca4654e019705f6a40"; */
@@ -12,6 +12,7 @@ const paths_1 = require("../helpers/paths");
12
12
  const spawn_1 = require("../helpers/spawn");
13
13
  const manifest_1 = require("./manifest");
14
14
  const unrevoke_1 = require("../authorizedKeys/unrevoke");
15
+ const keysRepo_1 = require("../authorizedKeys/keysRepo");
15
16
  const authorizedKeys_1 = require("../authorizedKeys/authorizedKeys");
16
17
  // A hardware backed key is the entire point. A key sitting on disk is compromised the moment the
17
18
  // machine is, and then the signature proves nothing, so this is what we make when asked to make one.
@@ -150,14 +151,11 @@ async function signRepo(config) {
150
151
  exports.signRepo = signRepo;
151
152
  async function main() {
152
153
  let { keyPath, pushToGit } = parseArgs(process.argv.slice(2));
153
- // Read for its value, so stdout has to be on its own. runPromise joins it with stderr, and a
154
- // git warning glued to the front of this becomes a directory that does not exist.
155
- let topLevel = await (0, spawn_1.spawnPromise)({ command: "git", args: ["rev-parse", "--show-toplevel"] });
156
- let repoPath = topLevel.stdout.trim();
157
- if (topLevel.status !== 0 || !repoPath) {
158
- throw new Error(`Expected the current directory to be inside a git repo, it is not.\n`
159
- + `${(topLevel.stdout + topLevel.stderr).trim()}\n${USAGE}`);
160
- }
154
+ // The keys repo, which is this one when it holds keys and this machine's otherwise. Signing
155
+ // whatever repo the terminal happened to be in is how you end up signing something that is not
156
+ // a keys repo at all.
157
+ let { repoPath } = await (0, keysRepo_1.resolveKeysRepo)();
158
+ console.log(`Signing ${repoPath}`);
161
159
  await signRepo({ repoPath, keyPath });
162
160
  if (!pushToGit) {
163
161
  console.log(`Commit and push ${manifest_1.MANIFEST_NAME} and ${manifest_1.SIGNATURE_NAME} for anything to see them.`);
@@ -177,5 +175,5 @@ async function main() {
177
175
  console.log(`Committed and pushed.`);
178
176
  }
179
177
  exports.main = main;
180
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbkZpbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2lnbkZpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJEQUE2QjtBQUM3Qiw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLCtEQUE0RDtBQUM1RCw0Q0FBOEM7QUFDOUMsNENBQWdEO0FBQ2hELHlDQUEwRztBQUMxRyx5REFBK0Q7QUFDL0QscUVBQWtGO0FBRWxGLGlHQUFpRztBQUNqRyxxR0FBcUc7QUFDckcsTUFBTSxnQkFBZ0IsR0FBRyxZQUFZLENBQUM7QUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyw2QkFBNkIsQ0FBQztBQUN2RCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUM7QUFDMUIsTUFBTSxjQUFjLEdBQUcsd0JBQXdCLENBQUM7QUFDaEQsTUFBTSxxQkFBcUIsR0FBRyxHQUFHLENBQUM7QUFDbEMsTUFBTSxLQUFLLEdBQUcsd0NBQXdDLFdBQVc7OztFQUcvRCxnQkFBZ0IsV0FBVyxnQkFBZ0I7T0FDdEMsV0FBVyxzQ0FBc0MsQ0FBQztBQUV6RDswRUFDMEU7QUFDMUUsU0FBUyxLQUFLLENBQUMsS0FBYTtJQUN4QixPQUFPLElBQUksS0FBSyxHQUFHLENBQUM7QUFDeEIsQ0FBQztBQUVELEtBQUssVUFBVSxVQUFVLENBQUMsUUFBZ0I7SUFDdEMsSUFBSSxDQUFDO1FBQ0QsTUFBTSxrQkFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxQixPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7QUFDTCxDQUFDO0FBRUQsb0VBQW9FO0FBQ3BFLEtBQUssVUFBVSxnQkFBZ0I7SUFDM0IsSUFBSSxPQUFPLEdBQUcsSUFBQSxrQkFBVSxFQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDM0MsSUFBSSxNQUFNLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxD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QXlCLENBQUMsQ0FBQztRQUM5RixPQUFPO0lBQ1gsQ0FBQztJQUNELE1BQU0sSUFBQSx1QkFBVSxFQUFDLGlCQUFpQixLQUFLLENBQUMsY0FBYyxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQzlFLE1BQU0sSUFBQSx1QkFBVSxFQUFDLFVBQVUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBL0JELG9CQStCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Qcm9taXNlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvcnVuUHJvbWlzZVwiO1xuaW1wb3J0IHsgZXhwYW5kSG9tZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BhdGhzXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vaGVscGVycy9zcGF3blwiO1xuaW1wb3J0IHsgYnVpbGRNYW5pZmVzdCwgZm9ybWF0TWFuaWZlc3QsIE1BTklGRVNUX05BTUUsIFNJR05BVFVSRV9OQU1FLCBTSUdOX05BTUVTUEFDRSB9IGZyb20gXCIuL21hbmlmZXN0XCI7XG5pbXBvcnQgeyByZXZva2VkS2V5c0luUmVwbyB9IGZyb20gXCIuLi9hdXRob3JpemVkS2V5cy91bnJldm9rZVwiO1xuaW1wb3J0IHsgZmluZEtleVByb2JsZW1zLCBub3JtYWxpemVLZXlzIH0gZnJvbSBcIi4uL2F1dGhvcml6ZWRLZXlzL2F1dGhvcml6ZWRLZXlzXCI7XG5cbi8vIEEgaGFyZHdhcmUgYmFja2VkIGtleSBpcyB0aGUgZW50aXJlIHBvaW50LiBBIGtleSBzaXR0aW5nIG9uIGRpc2sgaXMgY29tcHJvbWlzZWQgdGhlIG1vbWVudCB0aGVcbi8vIG1hY2hpbmUgaXMsIGFuZCB0aGVuIHRoZSBzaWduYXR1cmUgcHJvdmVzIG5vdGhpbmcsIHNvIHRoaXMgaXMgd2hhdCB3ZSBtYWtlIHdoZW4gYXNrZWQgdG8gbWFrZSBvbmUuXG5jb25zdCBERUZBVUxUX0tFWV9UWVBFID0gXCJlZDI1NTE5LXNrXCI7XG5jb25zdCBERUZBVUxUX0tFWV9QQVRIID0gXCJ+Ly5zc2gvc2lnbmZpbGVzX2VkMjU1MTlfc2tcIjtcbmNvbnN0IEdJVF9LRVlXT1JEID0gXCJnaXRcIjtcbmNvbnN0IENPTU1JVF9NRVNTQUdFID0gXCJkZXBsb3lpbmcgc2lnbmVkIGZpbGVzXCI7XG5jb25zdCBNQVhfRVJST1JfQk9EWV9MRU5HVEggPSA1MDA7XG5jb25zdCBVU0FHRSA9IGBVc2FnZTogeWFybiBzaWduZmlsZXMgW3NpZ25pbmcta2V5XSBbJHtHSVRfS0VZV09SRH1dXG5cblNpZ25zIHRoZSBmaWxlcyBvZiB0aGUgcmVwbyBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkuIFdpdGggbm8ga2V5LCBhIGhhcmR3YXJlIGJhY2tlZFxuJHtERUZBVUxUX0tFWV9UWVBFfSBrZXkgYXQgJHtERUZBVUxUX0tFWV9QQVRIfSBpcyB1c2VkLCBhbmQgY3JlYXRlZCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cblBhc3MgJHtHSVRfS0VZV09SRH0gdG8gYWxzbyBjb21taXQgYW5kIHB1c2ggdGhlIHJlc3VsdC5gO1xuXG4vKiogcnVuUHJvbWlzZSB0YWtlcyBhIGNvbW1hbmQgbGluZSByYXRoZXIgdGhhbiBhbiBhcmd1bWVudCBsaXN0LCBzbyBhbnl0aGluZyBob2xkaW5nIGEgcGF0aCBoYXMgdG9cbiAgICBzdXJ2aXZlIHRoZSBzaGVsbC4gRG91YmxlIHF1b3RlcyB3b3JrIG9uIGJvdGggY21kIGFuZCBwb3NpeCBzaGVsbHMuICovXG5mdW5jdGlvbiBxdW90ZSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGBcIiR7dmFsdWV9XCJgO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXRoRXhpc3RzKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBmcy5hY2Nlc3MoZmlsZVBhdGgpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5cbi8qKiBDcmVhdGluZyB0aGlzIG5lZWRzIHRoZSBzZWN1cml0eSBrZXkgcGx1Z2dlZCBpbiwgYW5kIGEgdG91Y2guICovXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVEZWZhdWx0S2V5KCkge1xuICAgIGxldCBrZXlQYXRoID0gZXhwYW5kSG9tZShERUZBVUxUX0tFWV9QQVRIKTtcbiAgICBpZiAoYXdhaXQgcGF0aEV4aXN0cyhrZXlQYXRoKSkge1xuICAgICAgICByZXR1cm4ga2V5UGF0aDtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYE5vIHNpZ25pbmcga2V5IGF0ICR7a2V5UGF0aH0sIGNyZWF0aW5nIGFuICR7REVGQVVMVF9LRVlfVFlQRX0gb25lLmApO1xuICAgIGNvbnNvbGUubG9nKGBQbHVnIHlvdXIgc2VjdXJpdHkga2V5IGluIC0geW91IHdpbGwgYmUgYXNrZWQgdG8gdG91Y2ggaXQuYCk7XG4gICAgYXdhaXQgZnMubWtkaXIocGF0aC5kaXJuYW1lKGtleVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgbW9kZTogMG83MDAgfSk7XG4gICAgYXdhaXQgcnVuUHJvbWlzZShgc3NoLWtleWdlbiAtdCAke0RFRkFVTFRfS0VZX1RZUEV9IC1mICR7cXVvdGUoa2V5UGF0aCl9IC1OIFwiXCIgLUMgc2lnbmZpbGVzYCk7XG4gICAgcmV0dXJuIGtleVBhdGg7XG59XG5cbi8qKiBUaGUgcHVibGljIGtleSBpbiB0aGUgZm9ybSB0aGUgZGFlbW9uIHJlcG9ydHMgaXQsIHNvIHdoYXQgaXMgcHJpbnRlZCBoZXJlIGNhbiBiZSBjb21wYXJlZFxuICAgIGFnYWluc3Qgd2hhdCBhcnJpdmVzIG9uIERpc2NvcmQuICovXG5hc3luYyBmdW5jdGlvbiBwdWJsaWNLZXlPZihrZXlQYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgY29udGVudHMgPSBhd2FpdCBmcy5yZWFkRmlsZShgJHtrZXlQYXRofS5wdWJgLCBcInV0ZjhcIik7XG4gICAgbGV0IFtrZXlUeXBlLCBrZXlCb2R5XSA9IGNvbnRlbnRzLnRyaW0oKS5zcGxpdCgvXFxzKy8pO1xuICAgIGlmICgha2V5VHlwZSB8fCAha2V5Qm9keSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgcHVibGljIGtleSBpbiAke2tleVBhdGh9LnB1Yiwgd2FzICR7Y29udGVudHMuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGAke2tleVR5cGV9ICR7a2V5Qm9keX1gO1xufVxuXG4vKiogQSBrZXlzIHJlcG8gaGFzIHJ1bGVzIHRoZSByZXN0IG9mIHRoaXMgY2Fubm90IGVuZm9yY2UgYWZ0ZXJ3YXJkcywgc28gdGhleSBhcmUgZW5mb3JjZWQgYmVmb3JlIGl0XG4gICAgaXMgc2lnbmVkLiBTaWduaW5nIGFueXRoaW5nIHRoYXQgaXMgbm90IGEga2V5cyByZXBvIGlzIG5vbmUgb2YgdGhpcyBmdW5jdGlvbidzIGJ1c2luZXNzLiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVmdXNlVW51c2FibGVLZXlzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgYXV0aG9yaXplZFBhdGggPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFwiYXV0aG9yaXplZF9rZXlzXCIpO1xuICAgIGlmICghYXdhaXQgcGF0aEV4aXN0cyhhdXRob3JpemVkUGF0aCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcHJvYmxlbXMgPSBmaW5kS2V5UHJvYmxlbXMobm9ybWFsaXplS2V5cyhhd2FpdCBmcy5yZWFkRmlsZShhdXRob3JpemVkUGF0aCwgXCJ1dGY4XCIpKSk7XG4gICAgaWYgKCFwcm9ibGVtcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBFeHBlY3RlZCBldmVyeSBrZXkgaW4gJHthdXRob3JpemVkUGF0aH0gdG8gYmUgcmVzdHJpY3RlZCBhbmQgdG8gYmVsb25nIHRvIG9uZSBwZXJzb24sYFxuICAgICAgICArIGAgZm91bmQgJHtwcm9ibGVtcy5sZW5ndGh9IHByb2JsZW0ocyk6XFxuYFxuICAgICAgICArIHByb2JsZW1zLm1hcChwcm9ibGVtID0+IGAgIC0gJHtwcm9ibGVtfWApLmpvaW4oXCJcXG5cIilcbiAgICAgICAgKyBgXFxuXFxuRXZlcnkga2V5IG5lZWRzIGEgZnJvbT0gbmFtaW5nIHRoZSBhZGRyZXNzZXMgaXQgbWF5IGJlIHVzZWQgZnJvbSwgYW5kIG5vIHR3byBrZXlzIG1heWBcbiAgICAgICAgKyBgXFxubmFtZSB0aGUgc2FtZSBvbmVzLiBSZXZva2luZyBhIGtleSB0aGF0IHNoYXJlcyBpdHMgYWRkcmVzc2VzIHdpdGggYW5vdGhlciBsZWF2ZXMgdGhhdGBcbiAgICAgICAgKyBgXFxub3RoZXIga2V5IHdvcmtpbmcsIHdoaWNoIGRlZmVhdHMgdGhlIHBvaW50IG9mIHJldm9raW5nIGl0LmBcbiAgICApO1xufVxuXG4vKiogU2lnbmluZyBhIGtleXMgcmVwbyB0aGF0IHN0aWxsIGhvbGRzIGEgcmV2b2tlZCBrZXkgd291bGQgcHVibGlzaCBpdCBiYWNrIHRvIGV2ZXJ5IG1hY2hpbmUgdGhhdFxuICAgIHRvb2sgaXQgb3V0LiBPbmx5IGFwcGxpZXMgdG8gYSByZXBvIHRoYXQgaG9sZHMga2V5cyBhbmQgaGFzIGEgcmV2b2tlIHJlcG8gdG8gY2hlY2sgLSBzaWduaW5nXG4gICAgYW55dGhpbmcgZWxzZSBpcyBub25lIG9mIHRoaXMgZnVuY3Rpb24ncyBidXNpbmVzcy4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlZnVzZVJldm9rZWRLZXlzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBpZiAoIWF3YWl0IHBhdGhFeGlzdHMocGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBSZWFkIGZvciBpdHMgdmFsdWUsIHNvIHN0ZG91dCBoYXMgdG8gYmUgb24gaXRzIG93bi4gcnVuUHJvbWlzZSBqb2lucyBpdCB3aXRoIHN0ZGVyci5cbiAgICBsZXQgb3JpZ2luID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogW1wicmVtb3RlXCIsIFwiZ2V0LXVybFwiLCBcIm9yaWdpblwiXSwgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBsZXQgb3JpZ2luVVJMID0gb3JpZ2luLnN0ZG91dC50cmltKCk7XG4gICAgaWYgKG9yaWdpbi5zdGF0dXMgIT09IDAgfHwgIW9yaWdpblVSTCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCByZXZva2VkO1xuICAgIHRyeSB7XG4gICAgICAgIHJldm9rZWQgPSBhd2FpdCByZXZva2VkS2V5c0luUmVwbyh7IHJlcG9QYXRoLCBzb3VyY2VVUkw6IG9yaWdpblVSTCB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIE5vIHJldm9rZSByZXBvLCBvciBubyBhY2Nlc3MgdG8gaXQuIE5vdGhpbmcgaGFzIGJlZW4gcmV2b2tlZCB0aGF0IHdlIGNhbiBzZWUuXG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCFyZXZva2VkLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkICR7cmVwb1BhdGh9IHRvIGhvbGQgbm8gcmV2b2tlZCBrZXlzLCBpdCBob2xkcyAke3Jldm9rZWQubGVuZ3RofTpcXG5gXG4gICAgICAgICsgcmV2b2tlZC5tYXAoZW50cnkgPT4gYCAgJHtlbnRyeS5yZXZvY2F0aW9uLmZpbmdlcnByaW50fSByZXZva2VkIGJ5ICR7ZW50cnkucmV2b2NhdGlvbi5yZXZva2VkQnkgfHwgXCI/XCJ9YFxuICAgICAgICAgICAgKyBgIGFmdGVyIHVzZSBmcm9tICR7ZW50cnkucmV2b2NhdGlvbi5hdHRlbXB0Py5pcCB8fCBcIj9cIn1gKS5qb2luKFwiXFxuXCIpXG4gICAgICAgICsgYFxcbkRlbGV0ZSB0aGVtIGZyb20gYXV0aG9yaXplZF9rZXlzLCBvciBydW4gXCJ5YXJuIHVucmV2b2tlXCIgaGVyZSB0byBhbGxvdyB0aGVtIGFnYWluLmBcbiAgICApO1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MoYXJndjogc3RyaW5nW10pIHtcbiAgICBsZXQgcHVzaFRvR2l0ID0gYXJndi5pbmNsdWRlcyhHSVRfS0VZV09SRCk7XG4gICAgbGV0IHBvc2l0aW9uYWwgPSBhcmd2LmZpbHRlcihhcmcgPT4gYXJnICE9PSBHSVRfS0VZV09SRCk7XG4gICAgaWYgKHBvc2l0aW9uYWwubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGF0IG1vc3QgYSBzaWduaW5nIGtleSwgd2FzICR7cG9zaXRpb25hbC5sZW5ndGh9IGFyZ3VtZW50KHMpOiAke3Bvc2l0aW9uYWwuam9pbihcIiBcIil9XFxuJHtVU0FHRX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHsga2V5UGF0aDogcG9zaXRpb25hbFswXSwgcHVzaFRvR2l0IH07XG59XG5cbi8qKiBXcml0ZXMgdGhlIG1hbmlmZXN0IGFuZCBpdHMgc2lnbmF0dXJlIGludG8gYSByZXBvLiBTZXBhcmF0ZSBmcm9tIHRoZSBjb21tYW5kIHNvIGFueXRoaW5nIHRoYXRcbiAgICBjaGFuZ2VzIGEga2V5cyByZXBvIGNhbiBsZWF2ZSBpdCBzaWduZWQsIHJhdGhlciB0aGFuIHRlbGxpbmcgc29tZW9uZSB0byBnbyBhbmQgZG8gaXQuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnblJlcG8oY29uZmlnOiB7IHJlcG9QYXRoOiBzdHJpbmc7IGtleVBhdGg/OiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHJlcG9QYXRoIH0gPSBjb25maWc7XG4gICAgbGV0IHNpZ25pbmdLZXkgPSBjb25maWcua2V5UGF0aCAmJiBleHBhbmRIb21lKGNvbmZpZy5rZXlQYXRoKSB8fCBhd2FpdCBlbnN1cmVEZWZhdWx0S2V5KCk7XG4gICAgaWYgKCFhd2FpdCBwYXRoRXhpc3RzKHNpZ25pbmdLZXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYSBzaWduaW5nIGtleSBhdCAke3NpZ25pbmdLZXl9LCBubyBzdWNoIGZpbGUgZXhpc3RzYCk7XG4gICAgfVxuXG4gICAgYXdhaXQgcmVmdXNlVW51c2FibGVLZXlzKHJlcG9QYXRoKTtcbiAgICBhd2FpdCByZWZ1c2VSZXZva2VkS2V5cyhyZXBvUGF0aCk7XG5cbiAgICBsZXQgbWFuaWZlc3QgPSBhd2FpdCBidWlsZE1hbmlmZXN0KHJlcG9QYXRoKTtcbiAgICBjb25zb2xlLmxvZyhgJHtNQU5JRkVTVF9OQU1FfSBjb3ZlcnMgJHttYW5pZmVzdC5maWxlcy5sZW5ndGh9IGZpbGUocykgaW4gJHtyZXBvUGF0aH1gKTtcblxuICAgIC8vIFRoZSBtYW5pZmVzdCBpcyBidWlsdCBhbmQgc2lnbmVkIGF3YXkgZnJvbSB0aGUgcmVwbywgYW5kIG9ubHkgbW92ZWQgaW4gb25jZSBib3RoIGV4aXN0LlxuICAgIC8vIExhbmRpbmcgYSBuZXcgbWFuaWZlc3QgbmV4dCB0byBhbiBvbGQgc2lnbmF0dXJlIHByb2R1Y2VzIGEgcGFpciB0aGF0IGNhbiBuZXZlciB2ZXJpZnksIGFuZFxuICAgIC8vIHRoZSBkYWVtb24gcmVhZGluZyBpdCBjYW4gb25seSB0cmVhdCB0aGF0IGFzIHRhbXBlcmluZy5cbiAgICBsZXQgc3RhZ2luZ0RpcmVjdG9yeSA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCBcInNpZ25maWxlcy1cIikpO1xuICAgIGxldCBzdGFnZWRNYW5pZmVzdCA9IHBhdGguam9pbihzdGFnaW5nRGlyZWN0b3J5LCBNQU5JRkVTVF9OQU1FKTtcbiAgICBsZXQgc3RhZ2VkU2lnbmF0dXJlID0gYCR7c3RhZ2VkTWFuaWZlc3R9LnNpZ2A7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHN0YWdlZE1hbmlmZXN0LCBmb3JtYXRNYW5pZmVzdChtYW5pZmVzdCkpO1xuXG4gICAgLy8gU2lnbmluZyBoYXBwZW5zIGJlZm9yZSBhbnkgZ2l0IHdvcmssIHNvIGEgZmFpbGVkIHB1c2ggbmV2ZXIgY29zdHMgYSBzZWNvbmQgdG91Y2ggb2YgdGhlIGtleS5cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBzc2gta2V5Z2VuIC1ZIHNpZ24gLWYgJHtxdW90ZShzaWduaW5nS2V5KX0gLW4gJHtTSUdOX05BTUVTUEFDRX0gJHtxdW90ZShzdGFnZWRNYW5pZmVzdCl9YCk7XG4gICAgLy8gQ2hlY2tlZCBoZXJlIHJhdGhlciB0aGFuIGxlZnQgZm9yIGEgbWFjaGluZSB0aGF0IGhhcyBhbHJlYWR5IHB1bGxlZCBpdCB0byBkaXNjb3Zlci5cbiAgICBhd2FpdCBydW5Qcm9taXNlKFxuICAgICAgICBgc3NoLWtleWdlbiAtWSBjaGVjay1ub3ZhbGlkYXRlIC1uICR7U0lHTl9OQU1FU1BBQ0V9IC1zICR7cXVvdGUoc3RhZ2VkU2lnbmF0dXJlKX0gPCAke3F1b3RlKHN0YWdlZE1hbmlmZXN0KX1gXG4gICAgKTtcbiAgICBhd2FpdCBmcy5jb3B5RmlsZShzdGFnZWRNYW5pZmVzdCwgcGF0aC5qb2luKHJlcG9QYXRoLCBNQU5JRkVTVF9OQU1FKSk7XG4gICAgYXdhaXQgZnMuY29weUZpbGUoc3RhZ2VkU2lnbmF0dXJlLCBwYXRoLmpvaW4ocmVwb1BhdGgsIFNJR05BVFVSRV9OQU1FKSk7XG4gICAgYXdhaXQgZnMucm0oc3RhZ2luZ0RpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIGNvbnNvbGUubG9nKGBTaWduZWQgd2l0aCAke2F3YWl0IHB1YmxpY0tleU9mKHNpZ25pbmdLZXkpfWApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgICBsZXQgeyBrZXlQYXRoLCBwdXNoVG9HaXQgfSA9IHBhcnNlQXJncyhwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuXG4gICAgLy8gUmVhZCBmb3IgaXRzIHZhbHVlLCBzbyBzdGRvdXQgaGFzIHRvIGJlIG9uIGl0cyBvd24uIHJ1blByb21pc2Ugam9pbnMgaXQgd2l0aCBzdGRlcnIsIGFuZCBhXG4gICAgLy8gZ2l0IHdhcm5pbmcgZ2x1ZWQgdG8gdGhlIGZyb250IG9mIHRoaXMgYmVjb21lcyBhIGRpcmVjdG9yeSB0aGF0IGRvZXMgbm90IGV4aXN0LlxuICAgIGxldCB0b3BMZXZlbCA9IGF3YWl0IHNwYXduUHJvbWlzZSh7IGNvbW1hbmQ6IFwiZ2l0XCIsIGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIi0tc2hvdy10b3BsZXZlbFwiXSB9KTtcbiAgICBsZXQgcmVwb1BhdGggPSB0b3BMZXZlbC5zdGRvdXQudHJpbSgpO1xuICAgIGlmICh0b3BMZXZlbC5zdGF0dXMgIT09IDAgfHwgIXJlcG9QYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCB0aGUgY3VycmVudCBkaXJlY3RvcnkgdG8gYmUgaW5zaWRlIGEgZ2l0IHJlcG8sIGl0IGlzIG5vdC5cXG5gXG4gICAgICAgICAgICArIGAkeyh0b3BMZXZlbC5zdGRvdXQgKyB0b3BMZXZlbC5zdGRlcnIpLnRyaW0oKX1cXG4ke1VTQUdFfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgYXdhaXQgc2lnblJlcG8oeyByZXBvUGF0aCwga2V5UGF0aCB9KTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBDb21taXQgYW5kIHB1c2ggJHtNQU5JRkVTVF9OQU1FfSBhbmQgJHtTSUdOQVRVUkVfTkFNRX0gZm9yIGFueXRoaW5nIHRvIHNlZSB0aGVtLmApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBhZGQgLUFgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgLy8gTm90aGluZyBzdGFnZWQgaXMgbm90IHdvcnRoIHN0b3BwaW5nIG9uLiBnaXQgY29tbWl0IGNhbGxzIHRoYXQgYSBmYWlsdXJlLCBidXQgaXQgb25seSBtZWFuc1xuICAgIC8vIHRoZSBzaWduYXR1cmUgbWF0Y2hlcyB0aGUgb25lIGFscmVhZHkgY29tbWl0dGVkLCBzbyB0aGVyZSBpcyBub3RoaW5nIHRvIGRlcGxveS5cbiAgICBsZXQgc3RhdHVzID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogW1wic3RhdHVzXCIsIFwiLS1wb3JjZWxhaW5cIl0sIGN3ZDogcmVwb1BhdGggfSk7XG4gICAgbGV0IHN0YWdlZCA9IHN0YXR1cy5zdGRvdXQ7XG4gICAgaWYgKCFzdGFnZWQudHJpbSgpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBOb3RoaW5nIGNoYW5nZWQsICR7TUFOSUZFU1RfTkFNRX0gYW5kICR7U0lHTkFUVVJFX05BTUV9IGFyZSBhbHJlYWR5IGNvbW1pdHRlZC5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgY29tbWl0IC1tICR7cXVvdGUoQ09NTUlUX01FU1NBR0UpfWAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgcHVzaGAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBjb25zb2xlLmxvZyhgQ29tbWl0dGVkIGFuZCBwdXNoZWQuYCk7XG59XG4iXX0=
181
- /* _JS_SOURCE_HASH = "5656bac7a766bdb1101df9294951fc82d227c63f880590d3dd4eb51bd67c88d1"; */
178
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbkZpbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2lnbkZpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJEQUE2QjtBQUM3Qiw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLCtEQUE0RDtBQUM1RCw0Q0FBOEM7QUFDOUMsNENBQWdEO0FBQ2hELHlDQUEwRztBQUMxRyx5REFBK0Q7QUFDL0QseURBQTZEO0FBQzdELHFFQUFrRjtBQUVsRixpR0FBaUc7QUFDakcscUdBQXFHO0FBQ3JHLE1BQU0sZ0JBQWdCLEdBQUcsWUFBWSxDQUFDO0FBQ3RDLE1BQU0sZ0JBQWdCLEdBQUcsNkJBQTZCLENBQUM7QUFDdkQsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDO0FBQzFCLE1BQU0sY0FBYyxHQUFHLHdCQUF3QixDQUFDO0FBQ2hELE1BQU0scUJBQXFCLEdBQUcsR0FBRyxDQUFDO0FBQ2xDLE1BQU0sS0FBSyxHQUFHLHdDQUF3QyxXQUFXOzs7RUFHL0QsZ0JBQWdCLFdBQVcsZ0JBQWdCO09BQ3RDLFdBQVcsc0NBQXNDLENBQUM7QUFFekQ7MEVBQzBFO0FBQzFFLFNBQVMsS0FBSyxDQUFDLEtBQWE7SUFDeEIsT0FBTyxJQUFJLEtBQUssR0FBRyxDQUFDO0FBQ3hCLENBQUM7QUFFRCxLQUFLLFVBQVUsVUFBVSxDQUFDLFFBQWdCO0lBQ3RDLElBQUksQ0FBQztRQUNELE1BQU0sa0JBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDMUIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0FBQ0wsQ0FBQztBQUVELG9FQUFvRTtBQUNwRSxLQUFLLFVBQVUsZ0JBQWdCO0lBQzNCLElBQUksT0FBTyxHQUFHLElBQUEsa0JBQVUsRUFBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzNDLElBQUksTUFBTSxVQUFVLENBQUMsT0FB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QyxDQUFDO0FBQ3pDLENBQUM7QUExQkQsb0JBMEJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IG9zIGZyb20gXCJvc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHJ1blByb21pc2UgfSBmcm9tIFwic29ja2V0LWZ1bmN0aW9uL3NyYy9ydW5Qcm9taXNlXCI7XG5pbXBvcnQgeyBleHBhbmRIb21lIH0gZnJvbSBcIi4uL2hlbHBlcnMvcGF0aHNcIjtcbmltcG9ydCB7IHNwYXduUHJvbWlzZSB9IGZyb20gXCIuLi9oZWxwZXJzL3NwYXduXCI7XG5pbXBvcnQgeyBidWlsZE1hbmlmZXN0LCBmb3JtYXRNYW5pZmVzdCwgTUFOSUZFU1RfTkFNRSwgU0lHTkFUVVJFX05BTUUsIFNJR05fTkFNRVNQQUNFIH0gZnJvbSBcIi4vbWFuaWZlc3RcIjtcbmltcG9ydCB7IHJldm9rZWRLZXlzSW5SZXBvIH0gZnJvbSBcIi4uL2F1dGhvcml6ZWRLZXlzL3VucmV2b2tlXCI7XG5pbXBvcnQgeyByZXNvbHZlS2V5c1JlcG8gfSBmcm9tIFwiLi4vYXV0aG9yaXplZEtleXMva2V5c1JlcG9cIjtcbmltcG9ydCB7IGZpbmRLZXlQcm9ibGVtcywgbm9ybWFsaXplS2V5cyB9IGZyb20gXCIuLi9hdXRob3JpemVkS2V5cy9hdXRob3JpemVkS2V5c1wiO1xuXG4vLyBBIGhhcmR3YXJlIGJhY2tlZCBrZXkgaXMgdGhlIGVudGlyZSBwb2ludC4gQSBrZXkgc2l0dGluZyBvbiBkaXNrIGlzIGNvbXByb21pc2VkIHRoZSBtb21lbnQgdGhlXG4vLyBtYWNoaW5lIGlzLCBhbmQgdGhlbiB0aGUgc2lnbmF0dXJlIHByb3ZlcyBub3RoaW5nLCBzbyB0aGlzIGlzIHdoYXQgd2UgbWFrZSB3aGVuIGFza2VkIHRvIG1ha2Ugb25lLlxuY29uc3QgREVGQVVMVF9LRVlfVFlQRSA9IFwiZWQyNTUxOS1za1wiO1xuY29uc3QgREVGQVVMVF9LRVlfUEFUSCA9IFwifi8uc3NoL3NpZ25maWxlc19lZDI1NTE5X3NrXCI7XG5jb25zdCBHSVRfS0VZV09SRCA9IFwiZ2l0XCI7XG5jb25zdCBDT01NSVRfTUVTU0FHRSA9IFwiZGVwbG95aW5nIHNpZ25lZCBmaWxlc1wiO1xuY29uc3QgTUFYX0VSUk9SX0JPRFlfTEVOR1RIID0gNTAwO1xuY29uc3QgVVNBR0UgPSBgVXNhZ2U6IHlhcm4gc2lnbmZpbGVzIFtzaWduaW5nLWtleV0gWyR7R0lUX0tFWVdPUkR9XVxuXG5TaWducyB0aGUgZmlsZXMgb2YgdGhlIHJlcG8gaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5LiBXaXRoIG5vIGtleSwgYSBoYXJkd2FyZSBiYWNrZWRcbiR7REVGQVVMVF9LRVlfVFlQRX0ga2V5IGF0ICR7REVGQVVMVF9LRVlfUEFUSH0gaXMgdXNlZCwgYW5kIGNyZWF0ZWQgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5QYXNzICR7R0lUX0tFWVdPUkR9IHRvIGFsc28gY29tbWl0IGFuZCBwdXNoIHRoZSByZXN1bHQuYDtcblxuLyoqIHJ1blByb21pc2UgdGFrZXMgYSBjb21tYW5kIGxpbmUgcmF0aGVyIHRoYW4gYW4gYXJndW1lbnQgbGlzdCwgc28gYW55dGhpbmcgaG9sZGluZyBhIHBhdGggaGFzIHRvXG4gICAgc3Vydml2ZSB0aGUgc2hlbGwuIERvdWJsZSBxdW90ZXMgd29yayBvbiBib3RoIGNtZCBhbmQgcG9zaXggc2hlbGxzLiAqL1xuZnVuY3Rpb24gcXVvdGUodmFsdWU6IHN0cmluZykge1xuICAgIHJldHVybiBgXCIke3ZhbHVlfVwiYDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcGF0aEV4aXN0cyhmaWxlUGF0aDogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZnMuYWNjZXNzKGZpbGVQYXRoKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG4vKiogQ3JlYXRpbmcgdGhpcyBuZWVkcyB0aGUgc2VjdXJpdHkga2V5IHBsdWdnZWQgaW4sIGFuZCBhIHRvdWNoLiAqL1xuYXN5bmMgZnVuY3Rpb24gZW5zdXJlRGVmYXVsdEtleSgpIHtcbiAgICBsZXQga2V5UGF0aCA9IGV4cGFuZEhvbWUoREVGQVVMVF9LRVlfUEFUSCk7XG4gICAgaWYgKGF3YWl0IHBhdGhFeGlzdHMoa2V5UGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIGtleVBhdGg7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBObyBzaWduaW5nIGtleSBhdCAke2tleVBhdGh9LCBjcmVhdGluZyBhbiAke0RFRkFVTFRfS0VZX1RZUEV9IG9uZS5gKTtcbiAgICBjb25zb2xlLmxvZyhgUGx1ZyB5b3VyIHNlY3VyaXR5IGtleSBpbiAtIHlvdSB3aWxsIGJlIGFza2VkIHRvIHRvdWNoIGl0LmApO1xuICAgIGF3YWl0IGZzLm1rZGlyKHBhdGguZGlybmFtZShrZXlQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUsIG1vZGU6IDBvNzAwIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYHNzaC1rZXlnZW4gLXQgJHtERUZBVUxUX0tFWV9UWVBFfSAtZiAke3F1b3RlKGtleVBhdGgpfSAtTiBcIlwiIC1DIHNpZ25maWxlc2ApO1xuICAgIHJldHVybiBrZXlQYXRoO1xufVxuXG4vKiogVGhlIHB1YmxpYyBrZXkgaW4gdGhlIGZvcm0gdGhlIGRhZW1vbiByZXBvcnRzIGl0LCBzbyB3aGF0IGlzIHByaW50ZWQgaGVyZSBjYW4gYmUgY29tcGFyZWRcbiAgICBhZ2FpbnN0IHdoYXQgYXJyaXZlcyBvbiBEaXNjb3JkLiAqL1xuYXN5bmMgZnVuY3Rpb24gcHVibGljS2V5T2Yoa2V5UGF0aDogc3RyaW5nKSB7XG4gICAgbGV0IGNvbnRlbnRzID0gYXdhaXQgZnMucmVhZEZpbGUoYCR7a2V5UGF0aH0ucHViYCwgXCJ1dGY4XCIpO1xuICAgIGxldCBba2V5VHlwZSwga2V5Qm9keV0gPSBjb250ZW50cy50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgICBpZiAoIWtleVR5cGUgfHwgIWtleUJvZHkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIHB1YmxpYyBrZXkgaW4gJHtrZXlQYXRofS5wdWIsIHdhcyAke2NvbnRlbnRzLnNsaWNlKDAsIE1BWF9FUlJPUl9CT0RZX0xFTkdUSCl9YCk7XG4gICAgfVxuICAgIHJldHVybiBgJHtrZXlUeXBlfSAke2tleUJvZHl9YDtcbn1cblxuLyoqIEEga2V5cyByZXBvIGhhcyBydWxlcyB0aGUgcmVzdCBvZiB0aGlzIGNhbm5vdCBlbmZvcmNlIGFmdGVyd2FyZHMsIHNvIHRoZXkgYXJlIGVuZm9yY2VkIGJlZm9yZSBpdFxuICAgIGlzIHNpZ25lZC4gU2lnbmluZyBhbnl0aGluZyB0aGF0IGlzIG5vdCBhIGtleXMgcmVwbyBpcyBub25lIG9mIHRoaXMgZnVuY3Rpb24ncyBidXNpbmVzcy4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlZnVzZVVudXNhYmxlS2V5cyhyZXBvUGF0aDogc3RyaW5nKSB7XG4gICAgbGV0IGF1dGhvcml6ZWRQYXRoID0gcGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKTtcbiAgICBpZiAoIWF3YWl0IHBhdGhFeGlzdHMoYXV0aG9yaXplZFBhdGgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IHByb2JsZW1zID0gZmluZEtleVByb2JsZW1zKG5vcm1hbGl6ZUtleXMoYXdhaXQgZnMucmVhZEZpbGUoYXV0aG9yaXplZFBhdGgsIFwidXRmOFwiKSkpO1xuICAgIGlmICghcHJvYmxlbXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRXhwZWN0ZWQgZXZlcnkga2V5IGluICR7YXV0aG9yaXplZFBhdGh9IHRvIGJlIHJlc3RyaWN0ZWQgYW5kIHRvIGJlbG9uZyB0byBvbmUgcGVyc29uLGBcbiAgICAgICAgKyBgIGZvdW5kICR7cHJvYmxlbXMubGVuZ3RofSBwcm9ibGVtKHMpOlxcbmBcbiAgICAgICAgKyBwcm9ibGVtcy5tYXAocHJvYmxlbSA9PiBgICAtICR7cHJvYmxlbX1gKS5qb2luKFwiXFxuXCIpXG4gICAgICAgICsgYFxcblxcbkV2ZXJ5IGtleSBuZWVkcyBhIGZyb209IG5hbWluZyB0aGUgYWRkcmVzc2VzIGl0IG1heSBiZSB1c2VkIGZyb20sIGFuZCBubyB0d28ga2V5cyBtYXlgXG4gICAgICAgICsgYFxcbm5hbWUgdGhlIHNhbWUgb25lcy4gUmV2b2tpbmcgYSBrZXkgdGhhdCBzaGFyZXMgaXRzIGFkZHJlc3NlcyB3aXRoIGFub3RoZXIgbGVhdmVzIHRoYXRgXG4gICAgICAgICsgYFxcbm90aGVyIGtleSB3b3JraW5nLCB3aGljaCBkZWZlYXRzIHRoZSBwb2ludCBvZiByZXZva2luZyBpdC5gXG4gICAgKTtcbn1cblxuLyoqIFNpZ25pbmcgYSBrZXlzIHJlcG8gdGhhdCBzdGlsbCBob2xkcyBhIHJldm9rZWQga2V5IHdvdWxkIHB1Ymxpc2ggaXQgYmFjayB0byBldmVyeSBtYWNoaW5lIHRoYXRcbiAgICB0b29rIGl0IG91dC4gT25seSBhcHBsaWVzIHRvIGEgcmVwbyB0aGF0IGhvbGRzIGtleXMgYW5kIGhhcyBhIHJldm9rZSByZXBvIHRvIGNoZWNrIC0gc2lnbmluZ1xuICAgIGFueXRoaW5nIGVsc2UgaXMgbm9uZSBvZiB0aGlzIGZ1bmN0aW9uJ3MgYnVzaW5lc3MuICovXG5hc3luYyBmdW5jdGlvbiByZWZ1c2VSZXZva2VkS2V5cyhyZXBvUGF0aDogc3RyaW5nKSB7XG4gICAgaWYgKCFhd2FpdCBwYXRoRXhpc3RzKHBhdGguam9pbihyZXBvUGF0aCwgXCJhdXRob3JpemVkX2tleXNcIikpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gUmVhZCBmb3IgaXRzIHZhbHVlLCBzbyBzdGRvdXQgaGFzIHRvIGJlIG9uIGl0cyBvd24uIHJ1blByb21pc2Ugam9pbnMgaXQgd2l0aCBzdGRlcnIuXG4gICAgbGV0IG9yaWdpbiA9IGF3YWl0IHNwYXduUHJvbWlzZSh7IGNvbW1hbmQ6IFwiZ2l0XCIsIGFyZ3M6IFtcInJlbW90ZVwiLCBcImdldC11cmxcIiwgXCJvcmlnaW5cIl0sIGN3ZDogcmVwb1BhdGggfSk7XG4gICAgbGV0IG9yaWdpblVSTCA9IG9yaWdpbi5zdGRvdXQudHJpbSgpO1xuICAgIGlmIChvcmlnaW4uc3RhdHVzICE9PSAwIHx8ICFvcmlnaW5VUkwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcmV2b2tlZDtcbiAgICB0cnkge1xuICAgICAgICByZXZva2VkID0gYXdhaXQgcmV2b2tlZEtleXNJblJlcG8oeyByZXBvUGF0aCwgc291cmNlVVJMOiBvcmlnaW5VUkwgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBObyByZXZva2UgcmVwbywgb3Igbm8gYWNjZXNzIHRvIGl0LiBOb3RoaW5nIGhhcyBiZWVuIHJldm9rZWQgdGhhdCB3ZSBjYW4gc2VlLlxuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghcmV2b2tlZC5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBFeHBlY3RlZCAke3JlcG9QYXRofSB0byBob2xkIG5vIHJldm9rZWQga2V5cywgaXQgaG9sZHMgJHtyZXZva2VkLmxlbmd0aH06XFxuYFxuICAgICAgICArIHJldm9rZWQubWFwKGVudHJ5ID0+IGAgICR7ZW50cnkucmV2b2NhdGlvbi5maW5nZXJwcmludH0gcmV2b2tlZCBieSAke2VudHJ5LnJldm9jYXRpb24ucmV2b2tlZEJ5IHx8IFwiP1wifWBcbiAgICAgICAgICAgICsgYCBhZnRlciB1c2UgZnJvbSAke2VudHJ5LnJldm9jYXRpb24uYXR0ZW1wdD8uaXAgfHwgXCI/XCJ9YCkuam9pbihcIlxcblwiKVxuICAgICAgICArIGBcXG5EZWxldGUgdGhlbSBmcm9tIGF1dGhvcml6ZWRfa2V5cywgb3IgcnVuIFwieWFybiB1bnJldm9rZVwiIGhlcmUgdG8gYWxsb3cgdGhlbSBhZ2Fpbi5gXG4gICAgKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3Y6IHN0cmluZ1tdKSB7XG4gICAgbGV0IHB1c2hUb0dpdCA9IGFyZ3YuaW5jbHVkZXMoR0lUX0tFWVdPUkQpO1xuICAgIGxldCBwb3NpdGlvbmFsID0gYXJndi5maWx0ZXIoYXJnID0+IGFyZyAhPT0gR0lUX0tFWVdPUkQpO1xuICAgIGlmIChwb3NpdGlvbmFsLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhdCBtb3N0IGEgc2lnbmluZyBrZXksIHdhcyAke3Bvc2l0aW9uYWwubGVuZ3RofSBhcmd1bWVudChzKTogJHtwb3NpdGlvbmFsLmpvaW4oXCIgXCIpfVxcbiR7VVNBR0V9YCk7XG4gICAgfVxuICAgIHJldHVybiB7IGtleVBhdGg6IHBvc2l0aW9uYWxbMF0sIHB1c2hUb0dpdCB9O1xufVxuXG4vKiogV3JpdGVzIHRoZSBtYW5pZmVzdCBhbmQgaXRzIHNpZ25hdHVyZSBpbnRvIGEgcmVwby4gU2VwYXJhdGUgZnJvbSB0aGUgY29tbWFuZCBzbyBhbnl0aGluZyB0aGF0XG4gICAgY2hhbmdlcyBhIGtleXMgcmVwbyBjYW4gbGVhdmUgaXQgc2lnbmVkLCByYXRoZXIgdGhhbiB0ZWxsaW5nIHNvbWVvbmUgdG8gZ28gYW5kIGRvIGl0LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25SZXBvKGNvbmZpZzogeyByZXBvUGF0aDogc3RyaW5nOyBrZXlQYXRoPzogc3RyaW5nIH0pIHtcbiAgICBsZXQgeyByZXBvUGF0aCB9ID0gY29uZmlnO1xuICAgIGxldCBzaWduaW5nS2V5ID0gY29uZmlnLmtleVBhdGggJiYgZXhwYW5kSG9tZShjb25maWcua2V5UGF0aCkgfHwgYXdhaXQgZW5zdXJlRGVmYXVsdEtleSgpO1xuICAgIGlmICghYXdhaXQgcGF0aEV4aXN0cyhzaWduaW5nS2V5KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgc2lnbmluZyBrZXkgYXQgJHtzaWduaW5nS2V5fSwgbm8gc3VjaCBmaWxlIGV4aXN0c2ApO1xuICAgIH1cblxuICAgIGF3YWl0IHJlZnVzZVVudXNhYmxlS2V5cyhyZXBvUGF0aCk7XG4gICAgYXdhaXQgcmVmdXNlUmV2b2tlZEtleXMocmVwb1BhdGgpO1xuXG4gICAgbGV0IG1hbmlmZXN0ID0gYXdhaXQgYnVpbGRNYW5pZmVzdChyZXBvUGF0aCk7XG4gICAgY29uc29sZS5sb2coYCR7TUFOSUZFU1RfTkFNRX0gY292ZXJzICR7bWFuaWZlc3QuZmlsZXMubGVuZ3RofSBmaWxlKHMpIGluICR7cmVwb1BhdGh9YCk7XG5cbiAgICAvLyBUaGUgbWFuaWZlc3QgaXMgYnVpbHQgYW5kIHNpZ25lZCBhd2F5IGZyb20gdGhlIHJlcG8sIGFuZCBvbmx5IG1vdmVkIGluIG9uY2UgYm90aCBleGlzdC5cbiAgICAvLyBMYW5kaW5nIGEgbmV3IG1hbmlmZXN0IG5leHQgdG8gYW4gb2xkIHNpZ25hdHVyZSBwcm9kdWNlcyBhIHBhaXIgdGhhdCBjYW4gbmV2ZXIgdmVyaWZ5LCBhbmRcbiAgICAvLyB0aGUgZGFlbW9uIHJlYWRpbmcgaXQgY2FuIG9ubHkgdHJlYXQgdGhhdCBhcyB0YW1wZXJpbmcuXG4gICAgbGV0IHN0YWdpbmdEaXJlY3RvcnkgPSBhd2FpdCBmcy5ta2R0ZW1wKHBhdGguam9pbihvcy50bXBkaXIoKSwgXCJzaWduZmlsZXMtXCIpKTtcbiAgICBsZXQgc3RhZ2VkTWFuaWZlc3QgPSBwYXRoLmpvaW4oc3RhZ2luZ0RpcmVjdG9yeSwgTUFOSUZFU1RfTkFNRSk7XG4gICAgbGV0IHN0YWdlZFNpZ25hdHVyZSA9IGAke3N0YWdlZE1hbmlmZXN0fS5zaWdgO1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZShzdGFnZWRNYW5pZmVzdCwgZm9ybWF0TWFuaWZlc3QobWFuaWZlc3QpKTtcblxuICAgIC8vIFNpZ25pbmcgaGFwcGVucyBiZWZvcmUgYW55IGdpdCB3b3JrLCBzbyBhIGZhaWxlZCBwdXNoIG5ldmVyIGNvc3RzIGEgc2Vjb25kIHRvdWNoIG9mIHRoZSBrZXkuXG4gICAgYXdhaXQgcnVuUHJvbWlzZShgc3NoLWtleWdlbiAtWSBzaWduIC1mICR7cXVvdGUoc2lnbmluZ0tleSl9IC1uICR7U0lHTl9OQU1FU1BBQ0V9ICR7cXVvdGUoc3RhZ2VkTWFuaWZlc3QpfWApO1xuICAgIC8vIENoZWNrZWQgaGVyZSByYXRoZXIgdGhhbiBsZWZ0IGZvciBhIG1hY2hpbmUgdGhhdCBoYXMgYWxyZWFkeSBwdWxsZWQgaXQgdG8gZGlzY292ZXIuXG4gICAgYXdhaXQgcnVuUHJvbWlzZShcbiAgICAgICAgYHNzaC1rZXlnZW4gLVkgY2hlY2stbm92YWxpZGF0ZSAtbiAke1NJR05fTkFNRVNQQUNFfSAtcyAke3F1b3RlKHN0YWdlZFNpZ25hdHVyZSl9IDwgJHtxdW90ZShzdGFnZWRNYW5pZmVzdCl9YFxuICAgICk7XG4gICAgYXdhaXQgZnMuY29weUZpbGUoc3RhZ2VkTWFuaWZlc3QsIHBhdGguam9pbihyZXBvUGF0aCwgTUFOSUZFU1RfTkFNRSkpO1xuICAgIGF3YWl0IGZzLmNvcHlGaWxlKHN0YWdlZFNpZ25hdHVyZSwgcGF0aC5qb2luKHJlcG9QYXRoLCBTSUdOQVRVUkVfTkFNRSkpO1xuICAgIGF3YWl0IGZzLnJtKHN0YWdpbmdEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICBjb25zb2xlLmxvZyhgU2lnbmVkIHdpdGggJHthd2FpdCBwdWJsaWNLZXlPZihzaWduaW5nS2V5KX1gKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7XG4gICAgbGV0IHsga2V5UGF0aCwgcHVzaFRvR2l0IH0gPSBwYXJzZUFyZ3MocHJvY2Vzcy5hcmd2LnNsaWNlKDIpKTtcblxuICAgIC8vIFRoZSBrZXlzIHJlcG8sIHdoaWNoIGlzIHRoaXMgb25lIHdoZW4gaXQgaG9sZHMga2V5cyBhbmQgdGhpcyBtYWNoaW5lJ3Mgb3RoZXJ3aXNlLiBTaWduaW5nXG4gICAgLy8gd2hhdGV2ZXIgcmVwbyB0aGUgdGVybWluYWwgaGFwcGVuZWQgdG8gYmUgaW4gaXMgaG93IHlvdSBlbmQgdXAgc2lnbmluZyBzb21ldGhpbmcgdGhhdCBpcyBub3RcbiAgICAvLyBhIGtleXMgcmVwbyBhdCBhbGwuXG4gICAgbGV0IHsgcmVwb1BhdGggfSA9IGF3YWl0IHJlc29sdmVLZXlzUmVwbygpO1xuICAgIGNvbnNvbGUubG9nKGBTaWduaW5nICR7cmVwb1BhdGh9YCk7XG4gICAgYXdhaXQgc2lnblJlcG8oeyByZXBvUGF0aCwga2V5UGF0aCB9KTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBDb21taXQgYW5kIHB1c2ggJHtNQU5JRkVTVF9OQU1FfSBhbmQgJHtTSUdOQVRVUkVfTkFNRX0gZm9yIGFueXRoaW5nIHRvIHNlZSB0aGVtLmApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBhZGQgLUFgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgLy8gTm90aGluZyBzdGFnZWQgaXMgbm90IHdvcnRoIHN0b3BwaW5nIG9uLiBnaXQgY29tbWl0IGNhbGxzIHRoYXQgYSBmYWlsdXJlLCBidXQgaXQgb25seSBtZWFuc1xuICAgIC8vIHRoZSBzaWduYXR1cmUgbWF0Y2hlcyB0aGUgb25lIGFscmVhZHkgY29tbWl0dGVkLCBzbyB0aGVyZSBpcyBub3RoaW5nIHRvIGRlcGxveS5cbiAgICBsZXQgc3RhdHVzID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogW1wic3RhdHVzXCIsIFwiLS1wb3JjZWxhaW5cIl0sIGN3ZDogcmVwb1BhdGggfSk7XG4gICAgbGV0IHN0YWdlZCA9IHN0YXR1cy5zdGRvdXQ7XG4gICAgaWYgKCFzdGFnZWQudHJpbSgpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBOb3RoaW5nIGNoYW5nZWQsICR7TUFOSUZFU1RfTkFNRX0gYW5kICR7U0lHTkFUVVJFX05BTUV9IGFyZSBhbHJlYWR5IGNvbW1pdHRlZC5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgY29tbWl0IC1tICR7cXVvdGUoQ09NTUlUX01FU1NBR0UpfWAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgcHVzaGAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBjb25zb2xlLmxvZyhgQ29tbWl0dGVkIGFuZCBwdXNoZWQuYCk7XG59XG4iXX0=
179
+ /* _JS_SOURCE_HASH = "e62739f311ed1c2d2b818032186647cfb19cc96beec3178194cb15bda564b243"; */
@@ -6,6 +6,7 @@ import { expandHome } from "../helpers/paths";
6
6
  import { spawnPromise } from "../helpers/spawn";
7
7
  import { buildManifest, formatManifest, MANIFEST_NAME, SIGNATURE_NAME, SIGN_NAMESPACE } from "./manifest";
8
8
  import { revokedKeysInRepo } from "../authorizedKeys/unrevoke";
9
+ import { resolveKeysRepo } from "../authorizedKeys/keysRepo";
9
10
  import { findKeyProblems, normalizeKeys } from "../authorizedKeys/authorizedKeys";
10
11
 
11
12
  // A hardware backed key is the entire point. A key sitting on disk is compromised the moment the
@@ -159,16 +160,11 @@ export async function signRepo(config: { repoPath: string; keyPath?: string }) {
159
160
  export async function main() {
160
161
  let { keyPath, pushToGit } = parseArgs(process.argv.slice(2));
161
162
 
162
- // Read for its value, so stdout has to be on its own. runPromise joins it with stderr, and a
163
- // git warning glued to the front of this becomes a directory that does not exist.
164
- let topLevel = await spawnPromise({ command: "git", args: ["rev-parse", "--show-toplevel"] });
165
- let repoPath = topLevel.stdout.trim();
166
- if (topLevel.status !== 0 || !repoPath) {
167
- throw new Error(
168
- `Expected the current directory to be inside a git repo, it is not.\n`
169
- + `${(topLevel.stdout + topLevel.stderr).trim()}\n${USAGE}`
170
- );
171
- }
163
+ // The keys repo, which is this one when it holds keys and this machine's otherwise. Signing
164
+ // whatever repo the terminal happened to be in is how you end up signing something that is not
165
+ // a keys repo at all.
166
+ let { repoPath } = await resolveKeysRepo();
167
+ console.log(`Signing ${repoPath}`);
172
168
  await signRepo({ repoPath, keyPath });
173
169
 
174
170
  if (!pushToGit) {
@@ -1,53 +0,0 @@
1
- import fs from "fs/promises";
2
- import path from "path";
3
- import { UNREVOKE_DELAY } from "../authorizedKeys/daemon/paths";
4
- import { keysDir } from "../authorizedKeys/sources";
5
- import { messageTimestamp } from "../notifications/discord";
6
-
7
- // When this machine first saw each unrevoke, by unrevoke id.
8
- //
9
- // The same rule the ssh keys get, for the same reason: an unrevoke waits an hour before it counts,
10
- // so a signing key that was itself stolen cannot instantly undo the revocation that shut it out.
11
- // Counted from when we first saw it, never from a time the file states - whoever wrote the file
12
- // chooses that, and would choose an hour ago.
13
- //
14
- // On disk, because a check runs in whatever process happens to be asking. Measuring from process
15
- // start would restart the hour on every request and the unrevoke would never arrive. Kept beside
16
- // the repo keys rather than in the daemon's state, because this has to work on a machine with no
17
- // daemon, which is most of them.
18
- const FIRST_SEEN_FILE = "machine-unrevokes.json";
19
-
20
- function firstSeenPath() {
21
- return path.join(keysDir(), FIRST_SEEN_FILE);
22
- }
23
-
24
- async function readFirstSeen(): Promise<{ [unrevokeId: string]: number }> {
25
- try {
26
- return JSON.parse(await fs.readFile(firstSeenPath(), "utf8"));
27
- } catch (e) {
28
- // Never written, or unreadable. Either way nothing has been seen before now.
29
- return {};
30
- }
31
- }
32
-
33
- /** Whether an unrevoke has waited out its hour, recording the first sighting if this is one.
34
-
35
- Returns false the first time, which is the point: seeing an unrevoke is not the same as
36
- honouring it. */
37
- export async function unrevokeInEffect(unrevokeId: string) {
38
- let firstSeen = await readFirstSeen();
39
- let seenAt = firstSeen[unrevokeId];
40
- if (!seenAt) {
41
- seenAt = Date.now();
42
- firstSeen[unrevokeId] = seenAt;
43
- await fs.mkdir(path.dirname(firstSeenPath()), { recursive: true, mode: 0o700 });
44
- await fs.writeFile(firstSeenPath(), JSON.stringify(firstSeen, undefined, 4) + "\n");
45
- }
46
- if (Date.now() - seenAt < UNREVOKE_DELAY) {
47
- console.log(
48
- `Holding the unrevoke ${unrevokeId} until ${messageTimestamp(new Date(seenAt + UNREVOKE_DELAY))}`
49
- );
50
- return false;
51
- }
52
- return true;
53
- }