sliftutils 1.7.126 → 1.7.127
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/testnotify.js +9 -0
- package/package.json +5 -3
- package/security/authorizedKeys/authorizedKeys.ts +49 -9
- package/security/authorizedKeys/daemon/authLog.ts +74 -5
- package/security/authorizedKeys/daemon/changes.ts +26 -0
- package/security/authorizedKeys/daemon/daemon.ts +51 -24
- package/security/authorizedKeys/daemon/revocation.ts +46 -23
- package/security/authorizedKeys/daemon/rootKeys.ts +88 -25
- package/security/authorizedKeys/daemon/sessions.ts +139 -0
- package/security/authorizedKeys/daemon/state.ts +16 -2
- package/security/authorizedKeys/dist/authorizedKeys.ts.cache +49 -11
- package/security/authorizedKeys/dist/secureSSH.ts.cache +18 -31
- package/security/authorizedKeys/dist/unrevoke.ts.cache +36 -14
- package/security/authorizedKeys/secureSSH.ts +77 -61
- package/security/authorizedKeys/unrevoke.ts +38 -12
- package/security/helpers/remoteSSH.ts +17 -6
- package/security/notifications/discord.ts +18 -1
- package/security/notifications/dist/discord.ts.cache +21 -4
- package/security/notifications/setupNotify.ts +17 -8
- package/security/notifications/testNotify.ts +48 -0
- package/security/signedFiles/dist/manifest.ts.cache +21 -4
- package/security/signedFiles/dist/signFiles.ts.cache +48 -13
- package/security/signedFiles/manifest.ts +19 -2
- package/security/signedFiles/signFiles.ts +51 -12
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import { DEFAULT_WEBHOOK_FILE_PATH, parseWebhookFile, sendToWebhookURL } from "./discord";
|
|
4
|
+
import { readRemoteFile } from "../helpers/remoteSSH";
|
|
5
|
+
|
|
6
|
+
const USAGE = `Usage: yarn testnotify [host]
|
|
7
|
+
|
|
8
|
+
Sends one message to a webhook, to prove it works. With no host it uses this machine's webhook at
|
|
9
|
+
${DEFAULT_WEBHOOK_FILE_PATH}. With a host it reads that host's webhook and sends to that instead,
|
|
10
|
+
which is how you check a machine you have just set up.`;
|
|
11
|
+
|
|
12
|
+
export async function main() {
|
|
13
|
+
let argv = process.argv.slice(2);
|
|
14
|
+
if (argv.length > 1) {
|
|
15
|
+
throw new Error(`Expected at most a host, was ${argv.length} argument(s)\n${USAGE}`);
|
|
16
|
+
}
|
|
17
|
+
let host = argv[0];
|
|
18
|
+
|
|
19
|
+
let contents: string | undefined;
|
|
20
|
+
if (host) {
|
|
21
|
+
contents = await readRemoteFile({ host, filePath: DEFAULT_WEBHOOK_FILE_PATH });
|
|
22
|
+
if (!contents) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
`Expected a webhook at ${DEFAULT_WEBHOOK_FILE_PATH} on ${host}, no such file exists.\n`
|
|
25
|
+
+ `Set it up with:\n yarn setupnotify ${host} <discord-webhook-url>`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
try {
|
|
30
|
+
contents = await fs.readFile(DEFAULT_WEBHOOK_FILE_PATH, "utf8");
|
|
31
|
+
} catch (e) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Expected a webhook at ${DEFAULT_WEBHOOK_FILE_PATH} on this machine, ${e}\n`
|
|
34
|
+
+ `Name a host to use that host's webhook instead.\n${USAGE}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let source = host || os.hostname();
|
|
40
|
+
let webhookURL = parseWebhookFile({ contents, sourceName: `${source}:${DEFAULT_WEBHOOK_FILE_PATH}` });
|
|
41
|
+
// Said plainly, so nobody reading the channel later has to work out whether it was real.
|
|
42
|
+
await sendToWebhookURL({
|
|
43
|
+
webhookURL,
|
|
44
|
+
message: `**portsecure test**: this is a test message, nothing has happened.`
|
|
45
|
+
+ ` Sent with \`yarn testnotify\` for the webhook \`${source}\` uses.`,
|
|
46
|
+
});
|
|
47
|
+
console.log(`Sent a test message to the webhook ${source} uses.`);
|
|
48
|
+
}
|
|
@@ -17,7 +17,13 @@ exports.SIGNATURE_NAME = "signedfiles.json.sig";
|
|
|
17
17
|
// ssh signatures are namespaced, so a signature made for one purpose cannot be replayed as another.
|
|
18
18
|
exports.SIGN_NAMESPACE = "signfiles";
|
|
19
19
|
exports.MANIFEST_VERSION = 1;
|
|
20
|
-
/** Everything in the repo that is not ignored
|
|
20
|
+
/** Everything in the repo that is not ignored: what is in the index, plus what is not staged yet.
|
|
21
|
+
Git is asked because git is what knows how to apply the ignore rules.
|
|
22
|
+
|
|
23
|
+
What comes back is a hint that a file might be there, not that it is. A file deleted from the
|
|
24
|
+
working tree stays in the index until that deletion is staged, so git names it and there is
|
|
25
|
+
nothing to read, which is why each one is checked before it goes in.
|
|
26
|
+
|
|
21
27
|
The manifest and its signature are left out, since they cannot describe themselves. */
|
|
22
28
|
async function listRepoFiles(repoPath) {
|
|
23
29
|
let result = await (0, spawn_1.spawnPromise)({
|
|
@@ -29,10 +35,21 @@ async function listRepoFiles(repoPath) {
|
|
|
29
35
|
throw new Error(`Expected to list the files in ${repoPath}, git ls-files exited ${result.status}. `
|
|
30
36
|
+ `${(result.stdout + result.stderr).trim()}`);
|
|
31
37
|
}
|
|
32
|
-
|
|
38
|
+
let listed = result.stdout.split("\n")
|
|
33
39
|
.map(line => line.trim())
|
|
34
40
|
.filter(line => line && line !== exports.MANIFEST_NAME && line !== exports.SIGNATURE_NAME)
|
|
35
41
|
.sort();
|
|
42
|
+
let present = [];
|
|
43
|
+
for (let relativePath of listed) {
|
|
44
|
+
try {
|
|
45
|
+
await promises_1.default.access(path_1.default.join(repoPath, relativePath));
|
|
46
|
+
present.push(relativePath);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.log(`Leaving ${relativePath} out of the manifest, it is gone from the working tree`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return present;
|
|
36
53
|
}
|
|
37
54
|
exports.listRepoFiles = listRepoFiles;
|
|
38
55
|
/** A Windows checkout turns LF into CRLF, so the same commit hashes differently there than it
|
|
@@ -64,5 +81,5 @@ function formatManifest(manifest) {
|
|
|
64
81
|
return JSON.stringify(manifest, undefined, 4) + "\n";
|
|
65
82
|
}
|
|
66
83
|
exports.formatManifest = formatManifest;
|
|
67
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
68
|
-
/* _JS_SOURCE_HASH = "
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuaWZlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtYW5pZmVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsMkRBQTZCO0FBQzdCLGdEQUF3QjtBQUN4Qiw0Q0FBZ0Q7QUFFaEQsa0dBQWtHO0FBQ2xHLGlHQUFpRztBQUNqRyxrR0FBa0c7QUFDbEcsdUJBQXVCO0FBRVYsUUFBQSxhQUFhLEdBQUcsa0JBQWtCLENBQUM7QUFDbkMsUUFBQSxjQUFjLEdBQUcsc0JBQXNCLENBQUM7QUFDckQsb0dBQW9HO0FBQ3ZGLFFBQUEsY0FBYyxHQUFHLFdBQVcsQ0FBQztBQUM3QixRQUFBLGdCQUFnQixHQUFHLENBQUMsQ0FBQztBQU9sQzs7Ozs7OzswRkFPMEY7QUFDbkYsS0FBSyxVQUFVLGFBQWEsQ0FBQyxRQUFnQjtJQUNoRCxJQUFJLE1BQU0sR0FBRyxNQUFNLElBQUEsb0JBQVksRUFBQztRQUM1QixPQUFPLEVBQUUsS0FBSztRQUNkLElBQUksRUFBRSxDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLG9CQUFvQixDQUFDO1FBQ2hFLEdBQUcsRUFBRSxRQUFRO0tBQ2hCLENBQUMsQ0FBQztJQUNILElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN0QixNQUFNLElBQUksS0FBSyxDQUNYLGlDQUFpQyxRQUFRLHlCQUF5QixNQUFNLENBQUMsTUFBTSxJQUFJO2NBQ2pGLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNoRCxDQUFDO0lBQ04sQ0FBQztJQUNELElBQUksTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQztTQUNqQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxJQUFJLElBQUksS0FBSyxxQkFBYSxJQUFJLElBQUksS0FBSyxzQkFBYyxDQUFDO1NBQ3pFLElBQUksRUFBRSxDQUFDO0lBRVosSUFBSSxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQzNCLEtBQUssSUFBSSxZQUFZLElBQUksTUFBTSxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDO1lBQ0QsTUFBTSxrQkFBRSxDQUFDLE1BQU0sQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQ25ELE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDL0IsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDVCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsWUFBWSx3REFBd0QsQ0FBQyxDQUFDO1FBQ2pHLENBQUM7SUFDTCxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDbkIsQ0FBQztBQTNCRCxzQ0EyQkM7QUFFRDs7OytCQUcrQjtBQUMvQixTQUFnQixnQkFBZ0IsQ0FBQyxRQUFnQjtJQUM3QyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ3JGLENBQUM7QUFGRCw0Q0FFQztBQUVEOytGQUMrRjtBQUN4RixLQUFLLFVBQVUsVUFBVSxDQUFDLFFBQWdCO0lBQzdDLElBQUksUUFBUSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sa0JBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUM3RCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLGdCQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztBQUN6RyxDQUFDO0FBSEQsZ0NBR0M7QUFFTSxLQUFLLFVBQVUsYUFBYSxDQUFDLFFBQWdCO0lBQ2hELElBQUksS0FBSyxHQUFzQixFQUFFLENBQUM7SUFDbEMsS0FBSyxJQUFJLFlBQVksSUFBSSxNQUFNLGFBQWEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQ3JELElBQUksTUFBTSxHQUFHLE1BQU0sVUFBVSxDQUFDLGNBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDakUsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ2pGLENBQUM7SUFDRCxPQUFPLEVBQUUsT0FBTyxFQUFFLHdCQUFnQixFQUFFLEtBQUssRUFBRSxDQUFDO0FBQ2hELENBQUM7QUFQRCxzQ0FPQztBQUVELG1HQUFtRztBQUNuRyxTQUFnQixjQUFjLENBQUMsUUFBa0I7SUFDN0MsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO0FBQ3pELENBQUM7QUFGRCx3Q0FFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcnlwdG8gZnJvbSBcImNyeXB0b1wiO1xuaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHNwYXduUHJvbWlzZSB9IGZyb20gXCIuLi9oZWxwZXJzL3NwYXduXCI7XG5cbi8vIFBPUlRFRCBDT0RFOiBzZWN1cml0eS9hdXRob3JpemVkS2V5cy9kYWVtb24vcG9ydHNlY3VyZURhZW1vbi5qcyBjb250YWlucyBhIHBsYWluIEpTIHBvcnQgb2YgdGhlXG4vLyB2ZXJpZnlpbmcgaGFsZiBvZiB0aGlzIGZpbGUsIHNvIGl0IGNhbiBjaGVjayBhIHNpZ25hdHVyZSB3aXRoIG5vIGRlcGVuZGVuY2llcy4gQm90aCBzaWRlcyBtdXN0XG4vLyBhZ3JlZSBvbiB0aGUgbWFuaWZlc3Qgc2hhcGUgYW5kIG9uIHdoaWNoIGZpbGVzIGl0IGNvdmVycyAtIGlmIHlvdSBjaGFuZ2Ugb25lLCBtYWtlIHRoZSBtYXRjaGluZ1xuLy8gY2hhbmdlIGluIHRoZSBvdGhlci5cblxuZXhwb3J0IGNvbnN0IE1BTklGRVNUX05BTUUgPSBcInNpZ25lZGZpbGVzLmpzb25cIjtcbmV4cG9ydCBjb25zdCBTSUdOQVRVUkVfTkFNRSA9IFwic2lnbmVkZmlsZXMuanNvbi5zaWdcIjtcbi8vIHNzaCBzaWduYXR1cmVzIGFyZSBuYW1lc3BhY2VkLCBzbyBhIHNpZ25hdHVyZSBtYWRlIGZvciBvbmUgcHVycG9zZSBjYW5ub3QgYmUgcmVwbGF5ZWQgYXMgYW5vdGhlci5cbmV4cG9ydCBjb25zdCBTSUdOX05BTUVTUEFDRSA9IFwic2lnbmZpbGVzXCI7XG5leHBvcnQgY29uc3QgTUFOSUZFU1RfVkVSU0lPTiA9IDE7XG5cbmV4cG9ydCB0eXBlIE1hbmlmZXN0ID0ge1xuICAgIHZlcnNpb246IG51bWJlcjtcbiAgICBmaWxlczogeyBwYXRoOiBzdHJpbmc7IHNpemU6IG51bWJlcjsgc2hhMjU2OiBzdHJpbmcgfVtdO1xufTtcblxuLyoqIEV2ZXJ5dGhpbmcgaW4gdGhlIHJlcG8gdGhhdCBpcyBub3QgaWdub3JlZDogd2hhdCBpcyBpbiB0aGUgaW5kZXgsIHBsdXMgd2hhdCBpcyBub3Qgc3RhZ2VkIHlldC5cbiAgICBHaXQgaXMgYXNrZWQgYmVjYXVzZSBnaXQgaXMgd2hhdCBrbm93cyBob3cgdG8gYXBwbHkgdGhlIGlnbm9yZSBydWxlcy5cblxuICAgIFdoYXQgY29tZXMgYmFjayBpcyBhIGhpbnQgdGhhdCBhIGZpbGUgbWlnaHQgYmUgdGhlcmUsIG5vdCB0aGF0IGl0IGlzLiBBIGZpbGUgZGVsZXRlZCBmcm9tIHRoZVxuICAgIHdvcmtpbmcgdHJlZSBzdGF5cyBpbiB0aGUgaW5kZXggdW50aWwgdGhhdCBkZWxldGlvbiBpcyBzdGFnZWQsIHNvIGdpdCBuYW1lcyBpdCBhbmQgdGhlcmUgaXNcbiAgICBub3RoaW5nIHRvIHJlYWQsIHdoaWNoIGlzIHdoeSBlYWNoIG9uZSBpcyBjaGVja2VkIGJlZm9yZSBpdCBnb2VzIGluLlxuXG4gICAgVGhlIG1hbmlmZXN0IGFuZCBpdHMgc2lnbmF0dXJlIGFyZSBsZWZ0IG91dCwgc2luY2UgdGhleSBjYW5ub3QgZGVzY3JpYmUgdGhlbXNlbHZlcy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0UmVwb0ZpbGVzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgcmVzdWx0ID0gYXdhaXQgc3Bhd25Qcm9taXNlKHtcbiAgICAgICAgY29tbWFuZDogXCJnaXRcIixcbiAgICAgICAgYXJnczogW1wibHMtZmlsZXNcIiwgXCItLWNhY2hlZFwiLCBcIi0tb3RoZXJzXCIsIFwiLS1leGNsdWRlLXN0YW5kYXJkXCJdLFxuICAgICAgICBjd2Q6IHJlcG9QYXRoLFxuICAgIH0pO1xuICAgIGlmIChyZXN1bHQuc3RhdHVzICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCB0byBsaXN0IHRoZSBmaWxlcyBpbiAke3JlcG9QYXRofSwgZ2l0IGxzLWZpbGVzIGV4aXRlZCAke3Jlc3VsdC5zdGF0dXN9LiBgXG4gICAgICAgICAgICArIGAkeyhyZXN1bHQuc3Rkb3V0ICsgcmVzdWx0LnN0ZGVycikudHJpbSgpfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgbGV0IGxpc3RlZCA9IHJlc3VsdC5zdGRvdXQuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgLm1hcChsaW5lID0+IGxpbmUudHJpbSgpKVxuICAgICAgICAuZmlsdGVyKGxpbmUgPT4gbGluZSAmJiBsaW5lICE9PSBNQU5JRkVTVF9OQU1FICYmIGxpbmUgIT09IFNJR05BVFVSRV9OQU1FKVxuICAgICAgICAuc29ydCgpO1xuXG4gICAgbGV0IHByZXNlbnQ6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChsZXQgcmVsYXRpdmVQYXRoIG9mIGxpc3RlZCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZnMuYWNjZXNzKHBhdGguam9pbihyZXBvUGF0aCwgcmVsYXRpdmVQYXRoKSk7XG4gICAgICAgICAgICBwcmVzZW50LnB1c2gocmVsYXRpdmVQYXRoKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYExlYXZpbmcgJHtyZWxhdGl2ZVBhdGh9IG91dCBvZiB0aGUgbWFuaWZlc3QsIGl0IGlzIGdvbmUgZnJvbSB0aGUgd29ya2luZyB0cmVlYCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHByZXNlbnQ7XG59XG5cbi8qKiBBIFdpbmRvd3MgY2hlY2tvdXQgdHVybnMgTEYgaW50byBDUkxGLCBzbyB0aGUgc2FtZSBjb21taXQgaGFzaGVzIGRpZmZlcmVudGx5IHRoZXJlIHRoYW4gaXRcbiAgICBkb2VzIG9uIHRoZSBtYWNoaW5lIHRoYXQgcHVsbHMgaXQuIE5vcm1hbGlzaW5nIGZpcnN0IG1ha2VzIHRoZSBkaWdlc3QgZGVzY3JpYmUgdGhlIGNvbnRlbnRcbiAgICByYXRoZXIgdGhhbiB3aGljaGV2ZXIgY2hlY2tvdXQgcHJvZHVjZWQgaXQuIGxhdGluMSByb3VuZCB0cmlwcyBldmVyeSBieXRlLCBzbyB0aGlzIGlzIHNhZmUgb25cbiAgICBmaWxlcyB0aGF0IGFyZSBub3QgdGV4dC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVDb250ZW50KGNvbnRlbnRzOiBCdWZmZXIpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oY29udGVudHMudG9TdHJpbmcoXCJsYXRpbjFcIikucmVwbGFjZSgvXFxyXFxuL2csIFwiXFxuXCIpLCBcImxhdGluMVwiKTtcbn1cblxuLyoqIFRoZSBzaXplIGFuZCBoYXNoIG9mIGEgZmlsZSdzIG5vcm1hbGlzZWQgY29udGVudC4gVGhlIHNpemUgaXMgdGhlIG5vcm1hbGlzZWQgb25lIG9uIHB1cnBvc2UsXG4gICAgc28gaXQgYWdyZWVzIHdpdGggdGhlIGhhc2ggcmF0aGVyIHRoYW4gd2l0aCB3aGF0ZXZlciB0aGUgbG9jYWwgY2hlY2tvdXQgaGFwcGVucyB0byBob2xkLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRpZ2VzdEZpbGUoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIGxldCBjb250ZW50cyA9IG5vcm1hbGl6ZUNvbnRlbnQoYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgpKTtcbiAgICByZXR1cm4geyBzaXplOiBjb250ZW50cy5sZW5ndGgsIHNoYTI1NjogY3J5cHRvLmNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKGNvbnRlbnRzKS5kaWdlc3QoXCJoZXhcIikgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1aWxkTWFuaWZlc3QocmVwb1BhdGg6IHN0cmluZykge1xuICAgIGxldCBmaWxlczogTWFuaWZlc3RbXCJmaWxlc1wiXSA9IFtdO1xuICAgIGZvciAobGV0IHJlbGF0aXZlUGF0aCBvZiBhd2FpdCBsaXN0UmVwb0ZpbGVzKHJlcG9QYXRoKSkge1xuICAgICAgICBsZXQgZGlnZXN0ID0gYXdhaXQgZGlnZXN0RmlsZShwYXRoLmpvaW4ocmVwb1BhdGgsIHJlbGF0aXZlUGF0aCkpO1xuICAgICAgICBmaWxlcy5wdXNoKHsgcGF0aDogcmVsYXRpdmVQYXRoLCBzaXplOiBkaWdlc3Quc2l6ZSwgc2hhMjU2OiBkaWdlc3Quc2hhMjU2IH0pO1xuICAgIH1cbiAgICByZXR1cm4geyB2ZXJzaW9uOiBNQU5JRkVTVF9WRVJTSU9OLCBmaWxlcyB9O1xufVxuXG4vKiogU29ydGVkIGtleXMgYW5kIGEgdHJhaWxpbmcgbmV3bGluZSwgc28gdGhlIHNhbWUgdHJlZSBhbHdheXMgcHJvZHVjZXMgdGhlIHNhbWUgYnl0ZXMgdG8gc2lnbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRNYW5pZmVzdChtYW5pZmVzdDogTWFuaWZlc3QpIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobWFuaWZlc3QsIHVuZGVmaW5lZCwgNCkgKyBcIlxcblwiO1xufVxuIl19
|
|
85
|
+
/* _JS_SOURCE_HASH = "e58787cb53d84ba9647f11c90c737f7303e120b8e02ca37cc9f38202fce1929d"; */
|
|
@@ -3,14 +3,16 @@ 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 = void 0;
|
|
6
|
+
//exports.main = exports.signRepo = 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 paths_1 = require("../helpers/paths");
|
|
12
|
+
const spawn_1 = require("../helpers/spawn");
|
|
12
13
|
const manifest_1 = require("./manifest");
|
|
13
14
|
const unrevoke_1 = require("../authorizedKeys/unrevoke");
|
|
15
|
+
const authorizedKeys_1 = require("../authorizedKeys/authorizedKeys");
|
|
14
16
|
// A hardware backed key is the entire point. A key sitting on disk is compromised the moment the
|
|
15
17
|
// machine is, and then the signature proves nothing, so this is what we make when asked to make one.
|
|
16
18
|
const DEFAULT_KEY_TYPE = "ed25519-sk";
|
|
@@ -59,6 +61,24 @@ async function publicKeyOf(keyPath) {
|
|
|
59
61
|
}
|
|
60
62
|
return `${keyType} ${keyBody}`;
|
|
61
63
|
}
|
|
64
|
+
/** A keys repo has rules the rest of this cannot enforce afterwards, so they are enforced before it
|
|
65
|
+
is signed. Signing anything that is not a keys repo is none of this function's business. */
|
|
66
|
+
async function refuseUnusableKeys(repoPath) {
|
|
67
|
+
let authorizedPath = path_1.default.join(repoPath, "authorized_keys");
|
|
68
|
+
if (!await pathExists(authorizedPath)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
let problems = (0, authorizedKeys_1.findKeyProblems)((0, authorizedKeys_1.normalizeKeys)(await promises_1.default.readFile(authorizedPath, "utf8")));
|
|
72
|
+
if (!problems.length) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Expected every key in ${authorizedPath} to be restricted and to belong to one person,`
|
|
76
|
+
+ ` found ${problems.length} problem(s):\n`
|
|
77
|
+
+ problems.map(problem => ` - ${problem}`).join("\n")
|
|
78
|
+
+ `\n\nEvery key needs a from= naming the addresses it may be used from, and no two keys may`
|
|
79
|
+
+ `\nname the same ones. Revoking a key that shares its addresses with another leaves that`
|
|
80
|
+
+ `\nother key working, which defeats the point of revoking it.`);
|
|
81
|
+
}
|
|
62
82
|
/** Signing a keys repo that still holds a revoked key would publish it back to every machine that
|
|
63
83
|
took it out. Only applies to a repo that holds keys and has a revoke repo to check - signing
|
|
64
84
|
anything else is none of this function's business. */
|
|
@@ -66,8 +86,10 @@ async function refuseRevokedKeys(repoPath) {
|
|
|
66
86
|
if (!await pathExists(path_1.default.join(repoPath, "authorized_keys"))) {
|
|
67
87
|
return;
|
|
68
88
|
}
|
|
69
|
-
|
|
70
|
-
|
|
89
|
+
// Read for its value, so stdout has to be on its own. runPromise joins it with stderr.
|
|
90
|
+
let origin = await (0, spawn_1.spawnPromise)({ command: "git", args: ["remote", "get-url", "origin"], cwd: repoPath });
|
|
91
|
+
let originURL = origin.stdout.trim();
|
|
92
|
+
if (origin.status !== 0 || !originURL) {
|
|
71
93
|
return;
|
|
72
94
|
}
|
|
73
95
|
let revoked;
|
|
@@ -97,16 +119,15 @@ function parseArgs(argv) {
|
|
|
97
119
|
}
|
|
98
120
|
return { keyPath: positional[0], pushToGit };
|
|
99
121
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
let signingKey = keyPath && (0, paths_1.expandHome)(keyPath) || await ensureDefaultKey();
|
|
122
|
+
/** Writes the manifest and its signature into a repo. Separate from the command so anything that
|
|
123
|
+
changes a keys repo can leave it signed, rather than telling someone to go and do it. */
|
|
124
|
+
async function signRepo(config) {
|
|
125
|
+
let { repoPath } = config;
|
|
126
|
+
let signingKey = config.keyPath && (0, paths_1.expandHome)(config.keyPath) || await ensureDefaultKey();
|
|
107
127
|
if (!await pathExists(signingKey)) {
|
|
108
128
|
throw new Error(`Expected a signing key at ${signingKey}, no such file exists`);
|
|
109
129
|
}
|
|
130
|
+
await refuseUnusableKeys(repoPath);
|
|
110
131
|
await refuseRevokedKeys(repoPath);
|
|
111
132
|
let manifest = await (0, manifest_1.buildManifest)(repoPath);
|
|
112
133
|
console.log(`${manifest_1.MANIFEST_NAME} covers ${manifest.files.length} file(s) in ${repoPath}`);
|
|
@@ -125,6 +146,19 @@ async function main() {
|
|
|
125
146
|
await promises_1.default.copyFile(stagedSignature, path_1.default.join(repoPath, manifest_1.SIGNATURE_NAME));
|
|
126
147
|
await promises_1.default.rm(stagingDirectory, { recursive: true, force: true });
|
|
127
148
|
console.log(`Signed with ${await publicKeyOf(signingKey)}`);
|
|
149
|
+
}
|
|
150
|
+
exports.signRepo = signRepo;
|
|
151
|
+
async function main() {
|
|
152
|
+
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
|
+
}
|
|
161
|
+
await signRepo({ repoPath, keyPath });
|
|
128
162
|
if (!pushToGit) {
|
|
129
163
|
console.log(`Commit and push ${manifest_1.MANIFEST_NAME} and ${manifest_1.SIGNATURE_NAME} for anything to see them.`);
|
|
130
164
|
return;
|
|
@@ -132,7 +166,8 @@ async function main() {
|
|
|
132
166
|
await (0, runPromise_1.runPromise)(`git add -A`, { cwd: repoPath });
|
|
133
167
|
// Nothing staged is not worth stopping on. git commit calls that a failure, but it only means
|
|
134
168
|
// the signature matches the one already committed, so there is nothing to deploy.
|
|
135
|
-
let
|
|
169
|
+
let status = await (0, spawn_1.spawnPromise)({ command: "git", args: ["status", "--porcelain"], cwd: repoPath });
|
|
170
|
+
let staged = status.stdout;
|
|
136
171
|
if (!staged.trim()) {
|
|
137
172
|
console.log(`Nothing changed, ${manifest_1.MANIFEST_NAME} and ${manifest_1.SIGNATURE_NAME} are already committed.`);
|
|
138
173
|
return;
|
|
@@ -142,5 +177,5 @@ async function main() {
|
|
|
142
177
|
console.log(`Committed and pushed.`);
|
|
143
178
|
}
|
|
144
179
|
exports.main = main;
|
|
145
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbkZpbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2lnbkZpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJEQUE2QjtBQUM3Qiw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLCtEQUE0RDtBQUM1RCw0Q0FBOEM7QUFDOUMseUNBQTBHO0FBQzFHLHlEQUErRDtBQUUvRCxpR0FBaUc7QUFDakcscUdBQXFHO0FBQ3JHLE1BQU0sZ0JBQWdCLEdBQUcsWUFBWSxDQUFDO0FBQ3RDLE1BQU0sZ0JBQWdCLEdBQUcsNkJBQTZCLENBQUM7QUFDdkQsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDO0FBQzFCLE1BQU0sY0FBYyxHQUFHLHdCQUF3QixDQUFDO0FBQ2hELE1BQU0scUJBQXFCLEdBQUcsR0FBRyxDQUFDO0FBQ2xDLE1BQU0sS0FBSyxHQUFHLHdDQUF3QyxXQUFXOzs7RUFHL0QsZ0JBQWdCLFdBQVcsZ0JBQWdCO09BQ3RDLFdBQVcsc0NBQXNDLENBQUM7QUFFekQ7MEVBQzBFO0FBQzFFLFNBQVMsS0FBSyxDQUFDLEtBQWE7SUFDeEIsT0FBTyxJQUFJLEtBQUssR0FBRyxDQUFDO0FBQ3hCLENBQUM7QUFFRCxLQUFLLFVBQVUsVUFBVSxDQUFDLFFBQWdCO0lBQ3RDLElBQUksQ0FBQztRQUNELE1BQU0sa0JBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDMUIsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0FBQ0wsQ0FBQztBQUVELG9FQUFvRTtBQUNwRSxLQUFLLFVBQVUsZ0JBQWdCO0lBQzNCLElBQUksT0FBTyxHQUFHLElBQUEsa0JBQVUsRUFBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzNDLElBQUksTUFBTSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM1QixPQUFPLE9BQU8sQ0FBQztJ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cG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Qcm9taXNlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvcnVuUHJvbWlzZVwiO1xuaW1wb3J0IHsgZXhwYW5kSG9tZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BhdGhzXCI7XG5pbXBvcnQgeyBidWlsZE1hbmlmZXN0LCBmb3JtYXRNYW5pZmVzdCwgTUFOSUZFU1RfTkFNRSwgU0lHTkFUVVJFX05BTUUsIFNJR05fTkFNRVNQQUNFIH0gZnJvbSBcIi4vbWFuaWZlc3RcIjtcbmltcG9ydCB7IHJldm9rZWRLZXlzSW5SZXBvIH0gZnJvbSBcIi4uL2F1dGhvcml6ZWRLZXlzL3VucmV2b2tlXCI7XG5cbi8vIEEgaGFyZHdhcmUgYmFja2VkIGtleSBpcyB0aGUgZW50aXJlIHBvaW50LiBBIGtleSBzaXR0aW5nIG9uIGRpc2sgaXMgY29tcHJvbWlzZWQgdGhlIG1vbWVudCB0aGVcbi8vIG1hY2hpbmUgaXMsIGFuZCB0aGVuIHRoZSBzaWduYXR1cmUgcHJvdmVzIG5vdGhpbmcsIHNvIHRoaXMgaXMgd2hhdCB3ZSBtYWtlIHdoZW4gYXNrZWQgdG8gbWFrZSBvbmUuXG5jb25zdCBERUZBVUxUX0tFWV9UWVBFID0gXCJlZDI1NTE5LXNrXCI7XG5jb25zdCBERUZBVUxUX0tFWV9QQVRIID0gXCJ+Ly5zc2gvc2lnbmZpbGVzX2VkMjU1MTlfc2tcIjtcbmNvbnN0IEdJVF9LRVlXT1JEID0gXCJnaXRcIjtcbmNvbnN0IENPTU1JVF9NRVNTQUdFID0gXCJkZXBsb3lpbmcgc2lnbmVkIGZpbGVzXCI7XG5jb25zdCBNQVhfRVJST1JfQk9EWV9MRU5HVEggPSA1MDA7XG5jb25zdCBVU0FHRSA9IGBVc2FnZTogeWFybiBzaWduZmlsZXMgW3NpZ25pbmcta2V5XSBbJHtHSVRfS0VZV09SRH1dXG5cblNpZ25zIHRoZSBmaWxlcyBvZiB0aGUgcmVwbyBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkuIFdpdGggbm8ga2V5LCBhIGhhcmR3YXJlIGJhY2tlZFxuJHtERUZBVUxUX0tFWV9UWVBFfSBrZXkgYXQgJHtERUZBVUxUX0tFWV9QQVRIfSBpcyB1c2VkLCBhbmQgY3JlYXRlZCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cblBhc3MgJHtHSVRfS0VZV09SRH0gdG8gYWxzbyBjb21taXQgYW5kIHB1c2ggdGhlIHJlc3VsdC5gO1xuXG4vKiogcnVuUHJvbWlzZSB0YWtlcyBhIGNvbW1hbmQgbGluZSByYXRoZXIgdGhhbiBhbiBhcmd1bWVudCBsaXN0LCBzbyBhbnl0aGluZyBob2xkaW5nIGEgcGF0aCBoYXMgdG9cbiAgICBzdXJ2aXZlIHRoZSBzaGVsbC4gRG91YmxlIHF1b3RlcyB3b3JrIG9uIGJvdGggY21kIGFuZCBwb3NpeCBzaGVsbHMuICovXG5mdW5jdGlvbiBxdW90ZSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGBcIiR7dmFsdWV9XCJgO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXRoRXhpc3RzKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBmcy5hY2Nlc3MoZmlsZVBhdGgpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5cbi8qKiBDcmVhdGluZyB0aGlzIG5lZWRzIHRoZSBzZWN1cml0eSBrZXkgcGx1Z2dlZCBpbiwgYW5kIGEgdG91Y2guICovXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVEZWZhdWx0S2V5KCkge1xuICAgIGxldCBrZXlQYXRoID0gZXhwYW5kSG9tZShERUZBVUxUX0tFWV9QQVRIKTtcbiAgICBpZiAoYXdhaXQgcGF0aEV4aXN0cyhrZXlQYXRoKSkge1xuICAgICAgICByZXR1cm4ga2V5UGF0aDtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYE5vIHNpZ25pbmcga2V5IGF0ICR7a2V5UGF0aH0sIGNyZWF0aW5nIGFuICR7REVGQVVMVF9LRVlfVFlQRX0gb25lLmApO1xuICAgIGNvbnNvbGUubG9nKGBQbHVnIHlvdXIgc2VjdXJpdHkga2V5IGluIC0geW91IHdpbGwgYmUgYXNrZWQgdG8gdG91Y2ggaXQuYCk7XG4gICAgYXdhaXQgZnMubWtkaXIocGF0aC5kaXJuYW1lKGtleVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgbW9kZTogMG83MDAgfSk7XG4gICAgYXdhaXQgcnVuUHJvbWlzZShgc3NoLWtleWdlbiAtdCAke0RFRkFVTFRfS0VZX1RZUEV9IC1mICR7cXVvdGUoa2V5UGF0aCl9IC1OIFwiXCIgLUMgc2lnbmZpbGVzYCk7XG4gICAgcmV0dXJuIGtleVBhdGg7XG59XG5cbi8qKiBUaGUgcHVibGljIGtleSBpbiB0aGUgZm9ybSB0aGUgZGFlbW9uIHJlcG9ydHMgaXQsIHNvIHdoYXQgaXMgcHJpbnRlZCBoZXJlIGNhbiBiZSBjb21wYXJlZFxuICAgIGFnYWluc3Qgd2hhdCBhcnJpdmVzIG9uIERpc2NvcmQuICovXG5hc3luYyBmdW5jdGlvbiBwdWJsaWNLZXlPZihrZXlQYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgY29udGVudHMgPSBhd2FpdCBmcy5yZWFkRmlsZShgJHtrZXlQYXRofS5wdWJgLCBcInV0ZjhcIik7XG4gICAgbGV0IFtrZXlUeXBlLCBrZXlCb2R5XSA9IGNvbnRlbnRzLnRyaW0oKS5zcGxpdCgvXFxzKy8pO1xuICAgIGlmICgha2V5VHlwZSB8fCAha2V5Qm9keSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgcHVibGljIGtleSBpbiAke2tleVBhdGh9LnB1Yiwgd2FzICR7Y29udGVudHMuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGAke2tleVR5cGV9ICR7a2V5Qm9keX1gO1xufVxuXG4vKiogU2lnbmluZyBhIGtleXMgcmVwbyB0aGF0IHN0aWxsIGhvbGRzIGEgcmV2b2tlZCBrZXkgd291bGQgcHVibGlzaCBpdCBiYWNrIHRvIGV2ZXJ5IG1hY2hpbmUgdGhhdFxuICAgIHRvb2sgaXQgb3V0LiBPbmx5IGFwcGxpZXMgdG8gYSByZXBvIHRoYXQgaG9sZHMga2V5cyBhbmQgaGFzIGEgcmV2b2tlIHJlcG8gdG8gY2hlY2sgLSBzaWduaW5nXG4gICAgYW55dGhpbmcgZWxzZSBpcyBub25lIG9mIHRoaXMgZnVuY3Rpb24ncyBidXNpbmVzcy4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlZnVzZVJldm9rZWRLZXlzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBpZiAoIWF3YWl0IHBhdGhFeGlzdHMocGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgb3JpZ2luVVJMID0gKGF3YWl0IHJ1blByb21pc2UoXCJnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luXCIsIHsgY3dkOiByZXBvUGF0aCwgcXVpZXQ6IHRydWUsIG5vdGhyb3c6IHRydWUgfSkpLnRyaW0oKTtcbiAgICBpZiAoIW9yaWdpblVSTCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCByZXZva2VkO1xuICAgIHRyeSB7XG4gICAgICAgIHJldm9rZWQgPSBhd2FpdCByZXZva2VkS2V5c0luUmVwbyh7IHJlcG9QYXRoLCBzb3VyY2VVUkw6IG9yaWdpblVSTCB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIE5vIHJldm9rZSByZXBvLCBvciBubyBhY2Nlc3MgdG8gaXQuIE5vdGhpbmcgaGFzIGJlZW4gcmV2b2tlZCB0aGF0IHdlIGNhbiBzZWUuXG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCFyZXZva2VkLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkICR7cmVwb1BhdGh9IHRvIGhvbGQgbm8gcmV2b2tlZCBrZXlzLCBpdCBob2xkcyAke3Jldm9rZWQubGVuZ3RofTpcXG5gXG4gICAgICAgICsgcmV2b2tlZC5tYXAoZW50cnkgPT4gYCAgJHtlbnRyeS5yZXZvY2F0aW9uLmZpbmdlcnByaW50fSByZXZva2VkIGJ5ICR7ZW50cnkucmV2b2NhdGlvbi5yZXZva2VkQnkgfHwgXCI/XCJ9YFxuICAgICAgICAgICAgKyBgIGFmdGVyIHVzZSBmcm9tICR7ZW50cnkucmV2b2NhdGlvbi5hdHRlbXB0Py5pcCB8fCBcIj9cIn1gKS5qb2luKFwiXFxuXCIpXG4gICAgICAgICsgYFxcbkRlbGV0ZSB0aGVtIGZyb20gYXV0aG9yaXplZF9rZXlzLCBvciBydW4gXCJ5YXJuIHVucmV2b2tlXCIgaGVyZSB0byBhbGxvdyB0aGVtIGFnYWluLmBcbiAgICApO1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MoYXJndjogc3RyaW5nW10pIHtcbiAgICBsZXQgcHVzaFRvR2l0ID0gYXJndi5pbmNsdWRlcyhHSVRfS0VZV09SRCk7XG4gICAgbGV0IHBvc2l0aW9uYWwgPSBhcmd2LmZpbHRlcihhcmcgPT4gYXJnICE9PSBHSVRfS0VZV09SRCk7XG4gICAgaWYgKHBvc2l0aW9uYWwubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGF0IG1vc3QgYSBzaWduaW5nIGtleSwgd2FzICR7cG9zaXRpb25hbC5sZW5ndGh9IGFyZ3VtZW50KHMpOiAke3Bvc2l0aW9uYWwuam9pbihcIiBcIil9XFxuJHtVU0FHRX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHsga2V5UGF0aDogcG9zaXRpb25hbFswXSwgcHVzaFRvR2l0IH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICAgIGxldCB7IGtleVBhdGgsIHB1c2hUb0dpdCB9ID0gcGFyc2VBcmdzKHByb2Nlc3MuYXJndi5zbGljZSgyKSk7XG5cbiAgICBsZXQgcmVwb1BhdGggPSAoYXdhaXQgcnVuUHJvbWlzZShcImdpdCByZXYtcGFyc2UgLS1zaG93LXRvcGxldmVsXCIsIHsgcXVpZXQ6IHRydWUgfSkpLnRyaW0oKTtcbiAgICBpZiAoIXJlcG9QYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgdGhlIGN1cnJlbnQgZGlyZWN0b3J5IHRvIGJlIGluc2lkZSBhIGdpdCByZXBvLCBpdCBpcyBub3QuXFxuJHtVU0FHRX1gKTtcbiAgICB9XG5cbiAgICBsZXQgc2lnbmluZ0tleSA9IGtleVBhdGggJiYgZXhwYW5kSG9tZShrZXlQYXRoKSB8fCBhd2FpdCBlbnN1cmVEZWZhdWx0S2V5KCk7XG4gICAgaWYgKCFhd2FpdCBwYXRoRXhpc3RzKHNpZ25pbmdLZXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYSBzaWduaW5nIGtleSBhdCAke3NpZ25pbmdLZXl9LCBubyBzdWNoIGZpbGUgZXhpc3RzYCk7XG4gICAgfVxuXG4gICAgYXdhaXQgcmVmdXNlUmV2b2tlZEtleXMocmVwb1BhdGgpO1xuXG4gICAgbGV0IG1hbmlmZXN0ID0gYXdhaXQgYnVpbGRNYW5pZmVzdChyZXBvUGF0aCk7XG4gICAgY29uc29sZS5sb2coYCR7TUFOSUZFU1RfTkFNRX0gY292ZXJzICR7bWFuaWZlc3QuZmlsZXMubGVuZ3RofSBmaWxlKHMpIGluICR7cmVwb1BhdGh9YCk7XG5cbiAgICAvLyBUaGUgbWFuaWZlc3QgaXMgYnVpbHQgYW5kIHNpZ25lZCBhd2F5IGZyb20gdGhlIHJlcG8sIGFuZCBvbmx5IG1vdmVkIGluIG9uY2UgYm90aCBleGlzdC5cbiAgICAvLyBMYW5kaW5nIGEgbmV3IG1hbmlmZXN0IG5leHQgdG8gYW4gb2xkIHNpZ25hdHVyZSBwcm9kdWNlcyBhIHBhaXIgdGhhdCBjYW4gbmV2ZXIgdmVyaWZ5LCBhbmRcbiAgICAvLyB0aGUgZGFlbW9uIHJlYWRpbmcgaXQgY2FuIG9ubHkgdHJlYXQgdGhhdCBhcyB0YW1wZXJpbmcuXG4gICAgbGV0IHN0YWdpbmdEaXJlY3RvcnkgPSBhd2FpdCBmcy5ta2R0ZW1wKHBhdGguam9pbihvcy50bXBkaXIoKSwgXCJzaWduZmlsZXMtXCIpKTtcbiAgICBsZXQgc3RhZ2VkTWFuaWZlc3QgPSBwYXRoLmpvaW4oc3RhZ2luZ0RpcmVjdG9yeSwgTUFOSUZFU1RfTkFNRSk7XG4gICAgbGV0IHN0YWdlZFNpZ25hdHVyZSA9IGAke3N0YWdlZE1hbmlmZXN0fS5zaWdgO1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZShzdGFnZWRNYW5pZmVzdCwgZm9ybWF0TWFuaWZlc3QobWFuaWZlc3QpKTtcblxuICAgIC8vIFNpZ25pbmcgaGFwcGVucyBiZWZvcmUgYW55IGdpdCB3b3JrLCBzbyBhIGZhaWxlZCBwdXNoIG5ldmVyIGNvc3RzIGEgc2Vjb25kIHRvdWNoIG9mIHRoZSBrZXkuXG4gICAgYXdhaXQgcnVuUHJvbWlzZShgc3NoLWtleWdlbiAtWSBzaWduIC1mICR7cXVvdGUoc2lnbmluZ0tleSl9IC1uICR7U0lHTl9OQU1FU1BBQ0V9ICR7cXVvdGUoc3RhZ2VkTWFuaWZlc3QpfWApO1xuICAgIC8vIENoZWNrZWQgaGVyZSByYXRoZXIgdGhhbiBsZWZ0IGZvciBhIG1hY2hpbmUgdGhhdCBoYXMgYWxyZWFkeSBwdWxsZWQgaXQgdG8gZGlzY292ZXIuXG4gICAgYXdhaXQgcnVuUHJvbWlzZShcbiAgICAgICAgYHNzaC1rZXlnZW4gLVkgY2hlY2stbm92YWxpZGF0ZSAtbiAke1NJR05fTkFNRVNQQUNFfSAtcyAke3F1b3RlKHN0YWdlZFNpZ25hdHVyZSl9IDwgJHtxdW90ZShzdGFnZWRNYW5pZmVzdCl9YFxuICAgICk7XG4gICAgYXdhaXQgZnMuY29weUZpbGUoc3RhZ2VkTWFuaWZlc3QsIHBhdGguam9pbihyZXBvUGF0aCwgTUFOSUZFU1RfTkFNRSkpO1xuICAgIGF3YWl0IGZzLmNvcHlGaWxlKHN0YWdlZFNpZ25hdHVyZSwgcGF0aC5qb2luKHJlcG9QYXRoLCBTSUdOQVRVUkVfTkFNRSkpO1xuICAgIGF3YWl0IGZzLnJtKHN0YWdpbmdEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICBjb25zb2xlLmxvZyhgU2lnbmVkIHdpdGggJHthd2FpdCBwdWJsaWNLZXlPZihzaWduaW5nS2V5KX1gKTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBDb21taXQgYW5kIHB1c2ggJHtNQU5JRkVTVF9OQU1FfSBhbmQgJHtTSUdOQVRVUkVfTkFNRX0gZm9yIGFueXRoaW5nIHRvIHNlZSB0aGVtLmApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBhZGQgLUFgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgLy8gTm90aGluZyBzdGFnZWQgaXMgbm90IHdvcnRoIHN0b3BwaW5nIG9uLiBnaXQgY29tbWl0IGNhbGxzIHRoYXQgYSBmYWlsdXJlLCBidXQgaXQgb25seSBtZWFuc1xuICAgIC8vIHRoZSBzaWduYXR1cmUgbWF0Y2hlcyB0aGUgb25lIGFscmVhZHkgY29tbWl0dGVkLCBzbyB0aGVyZSBpcyBub3RoaW5nIHRvIGRlcGxveS5cbiAgICBsZXQgc3RhZ2VkID0gYXdhaXQgcnVuUHJvbWlzZShgZ2l0IHN0YXR1cyAtLXBvcmNlbGFpbmAsIHsgY3dkOiByZXBvUGF0aCwgcXVpZXQ6IHRydWUgfSk7XG4gICAgaWYgKCFzdGFnZWQudHJpbSgpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBOb3RoaW5nIGNoYW5nZWQsICR7TUFOSUZFU1RfTkFNRX0gYW5kICR7U0lHTkFUVVJFX05BTUV9IGFyZSBhbHJlYWR5IGNvbW1pdHRlZC5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgY29tbWl0IC1tICR7cXVvdGUoQ09NTUlUX01FU1NBR0UpfWAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgcHVzaGAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBjb25zb2xlLmxvZyhgQ29tbWl0dGVkIGFuZCBwdXNoZWQuYCk7XG59XG4iXX0=
|
|
146
|
-
/* _JS_SOURCE_HASH = "
|
|
180
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbkZpbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2lnbkZpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJEQUE2QjtBQUM3Qiw0Q0FBb0I7QUFDcEIsZ0RBQXdCO0FBQ3hCLCtEQUE0RDtBQUM1RCw0Q0FBOEM7QUFDOUMsNENBQWdEO0FBQ2hELHlDQUEwRztBQUMxRyx5REFBK0Q7QUFDL0QscUVBQWtGO0FBRWxGLGlHQUFpRztBQUNqRyxxR0FBcUc7QUFDckcsTUFBTSxnQkFBZ0IsR0FBRyxZQUFZLENBQUM7QUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyw2QkFBNkIsQ0FBQztBQUN2RCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUM7QUFDMUIsTUFBTSxjQUFjLEdBQUcsd0JBQXdCLENBQUM7QUFDaEQsTUFBTSxxQkFBcUIsR0FBRyxHQUFHLENBQUM7QUFDbEMsTUFBTSxLQUFLLEdBQUcsd0NBQXdDLFdBQVc7OztFQUcvRCxnQkFBZ0IsV0FBVyxnQkFBZ0I7T0FDdEMsV0FBVyxzQ0FBc0MsQ0FBQztBQUV6RDswRUFDMEU7QUFDMUUsU0FBUyxLQUFLLENBQUMsS0FBYTtJQUN4QixPQUFPLElBQUksS0FBSyxHQUFHLENBQUM7QUFDeEIsQ0FBQztBQUVELEtBQUssVUFBVSxVQUFVLENBQUMsUUFBZ0I7SUFDdEMsSUFBSSxDQUFDO1FBQ0QsTUFBTSxrQkFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxQixPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7QUFDTCxDQUFDO0FBRUQsb0VBQW9FO0FBQ3BFLEtBQUssVUFBVSxnQkFBZ0I7SUFDM0IsSUFBSSxPQUFPLEdBQUcsSUFBQSxrQkFBVSxFQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDM0MsSUFBSSxNQUFNLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxD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QXlCLENBQUMsQ0FBQztRQUM5RixPQUFPO0lBQ1gsQ0FBQztJQUNELE1BQU0sSUFBQSx1QkFBVSxFQUFDLGlCQUFpQixLQUFLLENBQUMsY0FBYyxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQzlFLE1BQU0sSUFBQSx1QkFBVSxFQUFDLFVBQVUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBL0JELG9CQStCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Qcm9taXNlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvcnVuUHJvbWlzZVwiO1xuaW1wb3J0IHsgZXhwYW5kSG9tZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BhdGhzXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vaGVscGVycy9zcGF3blwiO1xuaW1wb3J0IHsgYnVpbGRNYW5pZmVzdCwgZm9ybWF0TWFuaWZlc3QsIE1BTklGRVNUX05BTUUsIFNJR05BVFVSRV9OQU1FLCBTSUdOX05BTUVTUEFDRSB9IGZyb20gXCIuL21hbmlmZXN0XCI7XG5pbXBvcnQgeyByZXZva2VkS2V5c0luUmVwbyB9IGZyb20gXCIuLi9hdXRob3JpemVkS2V5cy91bnJldm9rZVwiO1xuaW1wb3J0IHsgZmluZEtleVByb2JsZW1zLCBub3JtYWxpemVLZXlzIH0gZnJvbSBcIi4uL2F1dGhvcml6ZWRLZXlzL2F1dGhvcml6ZWRLZXlzXCI7XG5cbi8vIEEgaGFyZHdhcmUgYmFja2VkIGtleSBpcyB0aGUgZW50aXJlIHBvaW50LiBBIGtleSBzaXR0aW5nIG9uIGRpc2sgaXMgY29tcHJvbWlzZWQgdGhlIG1vbWVudCB0aGVcbi8vIG1hY2hpbmUgaXMsIGFuZCB0aGVuIHRoZSBzaWduYXR1cmUgcHJvdmVzIG5vdGhpbmcsIHNvIHRoaXMgaXMgd2hhdCB3ZSBtYWtlIHdoZW4gYXNrZWQgdG8gbWFrZSBvbmUuXG5jb25zdCBERUZBVUxUX0tFWV9UWVBFID0gXCJlZDI1NTE5LXNrXCI7XG5jb25zdCBERUZBVUxUX0tFWV9QQVRIID0gXCJ+Ly5zc2gvc2lnbmZpbGVzX2VkMjU1MTlfc2tcIjtcbmNvbnN0IEdJVF9LRVlXT1JEID0gXCJnaXRcIjtcbmNvbnN0IENPTU1JVF9NRVNTQUdFID0gXCJkZXBsb3lpbmcgc2lnbmVkIGZpbGVzXCI7XG5jb25zdCBNQVhfRVJST1JfQk9EWV9MRU5HVEggPSA1MDA7XG5jb25zdCBVU0FHRSA9IGBVc2FnZTogeWFybiBzaWduZmlsZXMgW3NpZ25pbmcta2V5XSBbJHtHSVRfS0VZV09SRH1dXG5cblNpZ25zIHRoZSBmaWxlcyBvZiB0aGUgcmVwbyBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkuIFdpdGggbm8ga2V5LCBhIGhhcmR3YXJlIGJhY2tlZFxuJHtERUZBVUxUX0tFWV9UWVBFfSBrZXkgYXQgJHtERUZBVUxUX0tFWV9QQVRIfSBpcyB1c2VkLCBhbmQgY3JlYXRlZCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cblBhc3MgJHtHSVRfS0VZV09SRH0gdG8gYWxzbyBjb21taXQgYW5kIHB1c2ggdGhlIHJlc3VsdC5gO1xuXG4vKiogcnVuUHJvbWlzZSB0YWtlcyBhIGNvbW1hbmQgbGluZSByYXRoZXIgdGhhbiBhbiBhcmd1bWVudCBsaXN0LCBzbyBhbnl0aGluZyBob2xkaW5nIGEgcGF0aCBoYXMgdG9cbiAgICBzdXJ2aXZlIHRoZSBzaGVsbC4gRG91YmxlIHF1b3RlcyB3b3JrIG9uIGJvdGggY21kIGFuZCBwb3NpeCBzaGVsbHMuICovXG5mdW5jdGlvbiBxdW90ZSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGBcIiR7dmFsdWV9XCJgO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXRoRXhpc3RzKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBmcy5hY2Nlc3MoZmlsZVBhdGgpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5cbi8qKiBDcmVhdGluZyB0aGlzIG5lZWRzIHRoZSBzZWN1cml0eSBrZXkgcGx1Z2dlZCBpbiwgYW5kIGEgdG91Y2guICovXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVEZWZhdWx0S2V5KCkge1xuICAgIGxldCBrZXlQYXRoID0gZXhwYW5kSG9tZShERUZBVUxUX0tFWV9QQVRIKTtcbiAgICBpZiAoYXdhaXQgcGF0aEV4aXN0cyhrZXlQYXRoKSkge1xuICAgICAgICByZXR1cm4ga2V5UGF0aDtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYE5vIHNpZ25pbmcga2V5IGF0ICR7a2V5UGF0aH0sIGNyZWF0aW5nIGFuICR7REVGQVVMVF9LRVlfVFlQRX0gb25lLmApO1xuICAgIGNvbnNvbGUubG9nKGBQbHVnIHlvdXIgc2VjdXJpdHkga2V5IGluIC0geW91IHdpbGwgYmUgYXNrZWQgdG8gdG91Y2ggaXQuYCk7XG4gICAgYXdhaXQgZnMubWtkaXIocGF0aC5kaXJuYW1lKGtleVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgbW9kZTogMG83MDAgfSk7XG4gICAgYXdhaXQgcnVuUHJvbWlzZShgc3NoLWtleWdlbiAtdCAke0RFRkFVTFRfS0VZX1RZUEV9IC1mICR7cXVvdGUoa2V5UGF0aCl9IC1OIFwiXCIgLUMgc2lnbmZpbGVzYCk7XG4gICAgcmV0dXJuIGtleVBhdGg7XG59XG5cbi8qKiBUaGUgcHVibGljIGtleSBpbiB0aGUgZm9ybSB0aGUgZGFlbW9uIHJlcG9ydHMgaXQsIHNvIHdoYXQgaXMgcHJpbnRlZCBoZXJlIGNhbiBiZSBjb21wYXJlZFxuICAgIGFnYWluc3Qgd2hhdCBhcnJpdmVzIG9uIERpc2NvcmQuICovXG5hc3luYyBmdW5jdGlvbiBwdWJsaWNLZXlPZihrZXlQYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgY29udGVudHMgPSBhd2FpdCBmcy5yZWFkRmlsZShgJHtrZXlQYXRofS5wdWJgLCBcInV0ZjhcIik7XG4gICAgbGV0IFtrZXlUeXBlLCBrZXlCb2R5XSA9IGNvbnRlbnRzLnRyaW0oKS5zcGxpdCgvXFxzKy8pO1xuICAgIGlmICgha2V5VHlwZSB8fCAha2V5Qm9keSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEgcHVibGljIGtleSBpbiAke2tleVBhdGh9LnB1Yiwgd2FzICR7Y29udGVudHMuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIGAke2tleVR5cGV9ICR7a2V5Qm9keX1gO1xufVxuXG4vKiogQSBrZXlzIHJlcG8gaGFzIHJ1bGVzIHRoZSByZXN0IG9mIHRoaXMgY2Fubm90IGVuZm9yY2UgYWZ0ZXJ3YXJkcywgc28gdGhleSBhcmUgZW5mb3JjZWQgYmVmb3JlIGl0XG4gICAgaXMgc2lnbmVkLiBTaWduaW5nIGFueXRoaW5nIHRoYXQgaXMgbm90IGEga2V5cyByZXBvIGlzIG5vbmUgb2YgdGhpcyBmdW5jdGlvbidzIGJ1c2luZXNzLiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVmdXNlVW51c2FibGVLZXlzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBsZXQgYXV0aG9yaXplZFBhdGggPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFwiYXV0aG9yaXplZF9rZXlzXCIpO1xuICAgIGlmICghYXdhaXQgcGF0aEV4aXN0cyhhdXRob3JpemVkUGF0aCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcHJvYmxlbXMgPSBmaW5kS2V5UHJvYmxlbXMobm9ybWFsaXplS2V5cyhhd2FpdCBmcy5yZWFkRmlsZShhdXRob3JpemVkUGF0aCwgXCJ1dGY4XCIpKSk7XG4gICAgaWYgKCFwcm9ibGVtcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBFeHBlY3RlZCBldmVyeSBrZXkgaW4gJHthdXRob3JpemVkUGF0aH0gdG8gYmUgcmVzdHJpY3RlZCBhbmQgdG8gYmVsb25nIHRvIG9uZSBwZXJzb24sYFxuICAgICAgICArIGAgZm91bmQgJHtwcm9ibGVtcy5sZW5ndGh9IHByb2JsZW0ocyk6XFxuYFxuICAgICAgICArIHByb2JsZW1zLm1hcChwcm9ibGVtID0+IGAgIC0gJHtwcm9ibGVtfWApLmpvaW4oXCJcXG5cIilcbiAgICAgICAgKyBgXFxuXFxuRXZlcnkga2V5IG5lZWRzIGEgZnJvbT0gbmFtaW5nIHRoZSBhZGRyZXNzZXMgaXQgbWF5IGJlIHVzZWQgZnJvbSwgYW5kIG5vIHR3byBrZXlzIG1heWBcbiAgICAgICAgKyBgXFxubmFtZSB0aGUgc2FtZSBvbmVzLiBSZXZva2luZyBhIGtleSB0aGF0IHNoYXJlcyBpdHMgYWRkcmVzc2VzIHdpdGggYW5vdGhlciBsZWF2ZXMgdGhhdGBcbiAgICAgICAgKyBgXFxub3RoZXIga2V5IHdvcmtpbmcsIHdoaWNoIGRlZmVhdHMgdGhlIHBvaW50IG9mIHJldm9raW5nIGl0LmBcbiAgICApO1xufVxuXG4vKiogU2lnbmluZyBhIGtleXMgcmVwbyB0aGF0IHN0aWxsIGhvbGRzIGEgcmV2b2tlZCBrZXkgd291bGQgcHVibGlzaCBpdCBiYWNrIHRvIGV2ZXJ5IG1hY2hpbmUgdGhhdFxuICAgIHRvb2sgaXQgb3V0LiBPbmx5IGFwcGxpZXMgdG8gYSByZXBvIHRoYXQgaG9sZHMga2V5cyBhbmQgaGFzIGEgcmV2b2tlIHJlcG8gdG8gY2hlY2sgLSBzaWduaW5nXG4gICAgYW55dGhpbmcgZWxzZSBpcyBub25lIG9mIHRoaXMgZnVuY3Rpb24ncyBidXNpbmVzcy4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlZnVzZVJldm9rZWRLZXlzKHJlcG9QYXRoOiBzdHJpbmcpIHtcbiAgICBpZiAoIWF3YWl0IHBhdGhFeGlzdHMocGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBSZWFkIGZvciBpdHMgdmFsdWUsIHNvIHN0ZG91dCBoYXMgdG8gYmUgb24gaXRzIG93bi4gcnVuUHJvbWlzZSBqb2lucyBpdCB3aXRoIHN0ZGVyci5cbiAgICBsZXQgb3JpZ2luID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogW1wicmVtb3RlXCIsIFwiZ2V0LXVybFwiLCBcIm9yaWdpblwiXSwgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBsZXQgb3JpZ2luVVJMID0gb3JpZ2luLnN0ZG91dC50cmltKCk7XG4gICAgaWYgKG9yaWdpbi5zdGF0dXMgIT09IDAgfHwgIW9yaWdpblVSTCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCByZXZva2VkO1xuICAgIHRyeSB7XG4gICAgICAgIHJldm9rZWQgPSBhd2FpdCByZXZva2VkS2V5c0luUmVwbyh7IHJlcG9QYXRoLCBzb3VyY2VVUkw6IG9yaWdpblVSTCB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIE5vIHJldm9rZSByZXBvLCBvciBubyBhY2Nlc3MgdG8gaXQuIE5vdGhpbmcgaGFzIGJlZW4gcmV2b2tlZCB0aGF0IHdlIGNhbiBzZWUuXG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCFyZXZva2VkLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkICR7cmVwb1BhdGh9IHRvIGhvbGQgbm8gcmV2b2tlZCBrZXlzLCBpdCBob2xkcyAke3Jldm9rZWQubGVuZ3RofTpcXG5gXG4gICAgICAgICsgcmV2b2tlZC5tYXAoZW50cnkgPT4gYCAgJHtlbnRyeS5yZXZvY2F0aW9uLmZpbmdlcnByaW50fSByZXZva2VkIGJ5ICR7ZW50cnkucmV2b2NhdGlvbi5yZXZva2VkQnkgfHwgXCI/XCJ9YFxuICAgICAgICAgICAgKyBgIGFmdGVyIHVzZSBmcm9tICR7ZW50cnkucmV2b2NhdGlvbi5hdHRlbXB0Py5pcCB8fCBcIj9cIn1gKS5qb2luKFwiXFxuXCIpXG4gICAgICAgICsgYFxcbkRlbGV0ZSB0aGVtIGZyb20gYXV0aG9yaXplZF9rZXlzLCBvciBydW4gXCJ5YXJuIHVucmV2b2tlXCIgaGVyZSB0byBhbGxvdyB0aGVtIGFnYWluLmBcbiAgICApO1xufVxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MoYXJndjogc3RyaW5nW10pIHtcbiAgICBsZXQgcHVzaFRvR2l0ID0gYXJndi5pbmNsdWRlcyhHSVRfS0VZV09SRCk7XG4gICAgbGV0IHBvc2l0aW9uYWwgPSBhcmd2LmZpbHRlcihhcmcgPT4gYXJnICE9PSBHSVRfS0VZV09SRCk7XG4gICAgaWYgKHBvc2l0aW9uYWwubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGF0IG1vc3QgYSBzaWduaW5nIGtleSwgd2FzICR7cG9zaXRpb25hbC5sZW5ndGh9IGFyZ3VtZW50KHMpOiAke3Bvc2l0aW9uYWwuam9pbihcIiBcIil9XFxuJHtVU0FHRX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHsga2V5UGF0aDogcG9zaXRpb25hbFswXSwgcHVzaFRvR2l0IH07XG59XG5cbi8qKiBXcml0ZXMgdGhlIG1hbmlmZXN0IGFuZCBpdHMgc2lnbmF0dXJlIGludG8gYSByZXBvLiBTZXBhcmF0ZSBmcm9tIHRoZSBjb21tYW5kIHNvIGFueXRoaW5nIHRoYXRcbiAgICBjaGFuZ2VzIGEga2V5cyByZXBvIGNhbiBsZWF2ZSBpdCBzaWduZWQsIHJhdGhlciB0aGFuIHRlbGxpbmcgc29tZW9uZSB0byBnbyBhbmQgZG8gaXQuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnblJlcG8oY29uZmlnOiB7IHJlcG9QYXRoOiBzdHJpbmc7IGtleVBhdGg/OiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHJlcG9QYXRoIH0gPSBjb25maWc7XG4gICAgbGV0IHNpZ25pbmdLZXkgPSBjb25maWcua2V5UGF0aCAmJiBleHBhbmRIb21lKGNvbmZpZy5rZXlQYXRoKSB8fCBhd2FpdCBlbnN1cmVEZWZhdWx0S2V5KCk7XG4gICAgaWYgKCFhd2FpdCBwYXRoRXhpc3RzKHNpZ25pbmdLZXkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYSBzaWduaW5nIGtleSBhdCAke3NpZ25pbmdLZXl9LCBubyBzdWNoIGZpbGUgZXhpc3RzYCk7XG4gICAgfVxuXG4gICAgYXdhaXQgcmVmdXNlVW51c2FibGVLZXlzKHJlcG9QYXRoKTtcbiAgICBhd2FpdCByZWZ1c2VSZXZva2VkS2V5cyhyZXBvUGF0aCk7XG5cbiAgICBsZXQgbWFuaWZlc3QgPSBhd2FpdCBidWlsZE1hbmlmZXN0KHJlcG9QYXRoKTtcbiAgICBjb25zb2xlLmxvZyhgJHtNQU5JRkVTVF9OQU1FfSBjb3ZlcnMgJHttYW5pZmVzdC5maWxlcy5sZW5ndGh9IGZpbGUocykgaW4gJHtyZXBvUGF0aH1gKTtcblxuICAgIC8vIFRoZSBtYW5pZmVzdCBpcyBidWlsdCBhbmQgc2lnbmVkIGF3YXkgZnJvbSB0aGUgcmVwbywgYW5kIG9ubHkgbW92ZWQgaW4gb25jZSBib3RoIGV4aXN0LlxuICAgIC8vIExhbmRpbmcgYSBuZXcgbWFuaWZlc3QgbmV4dCB0byBhbiBvbGQgc2lnbmF0dXJlIHByb2R1Y2VzIGEgcGFpciB0aGF0IGNhbiBuZXZlciB2ZXJpZnksIGFuZFxuICAgIC8vIHRoZSBkYWVtb24gcmVhZGluZyBpdCBjYW4gb25seSB0cmVhdCB0aGF0IGFzIHRhbXBlcmluZy5cbiAgICBsZXQgc3RhZ2luZ0RpcmVjdG9yeSA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCBcInNpZ25maWxlcy1cIikpO1xuICAgIGxldCBzdGFnZWRNYW5pZmVzdCA9IHBhdGguam9pbihzdGFnaW5nRGlyZWN0b3J5LCBNQU5JRkVTVF9OQU1FKTtcbiAgICBsZXQgc3RhZ2VkU2lnbmF0dXJlID0gYCR7c3RhZ2VkTWFuaWZlc3R9LnNpZ2A7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHN0YWdlZE1hbmlmZXN0LCBmb3JtYXRNYW5pZmVzdChtYW5pZmVzdCkpO1xuXG4gICAgLy8gU2lnbmluZyBoYXBwZW5zIGJlZm9yZSBhbnkgZ2l0IHdvcmssIHNvIGEgZmFpbGVkIHB1c2ggbmV2ZXIgY29zdHMgYSBzZWNvbmQgdG91Y2ggb2YgdGhlIGtleS5cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBzc2gta2V5Z2VuIC1ZIHNpZ24gLWYgJHtxdW90ZShzaWduaW5nS2V5KX0gLW4gJHtTSUdOX05BTUVTUEFDRX0gJHtxdW90ZShzdGFnZWRNYW5pZmVzdCl9YCk7XG4gICAgLy8gQ2hlY2tlZCBoZXJlIHJhdGhlciB0aGFuIGxlZnQgZm9yIGEgbWFjaGluZSB0aGF0IGhhcyBhbHJlYWR5IHB1bGxlZCBpdCB0byBkaXNjb3Zlci5cbiAgICBhd2FpdCBydW5Qcm9taXNlKFxuICAgICAgICBgc3NoLWtleWdlbiAtWSBjaGVjay1ub3ZhbGlkYXRlIC1uICR7U0lHTl9OQU1FU1BBQ0V9IC1zICR7cXVvdGUoc3RhZ2VkU2lnbmF0dXJlKX0gPCAke3F1b3RlKHN0YWdlZE1hbmlmZXN0KX1gXG4gICAgKTtcbiAgICBhd2FpdCBmcy5jb3B5RmlsZShzdGFnZWRNYW5pZmVzdCwgcGF0aC5qb2luKHJlcG9QYXRoLCBNQU5JRkVTVF9OQU1FKSk7XG4gICAgYXdhaXQgZnMuY29weUZpbGUoc3RhZ2VkU2lnbmF0dXJlLCBwYXRoLmpvaW4ocmVwb1BhdGgsIFNJR05BVFVSRV9OQU1FKSk7XG4gICAgYXdhaXQgZnMucm0oc3RhZ2luZ0RpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIGNvbnNvbGUubG9nKGBTaWduZWQgd2l0aCAke2F3YWl0IHB1YmxpY0tleU9mKHNpZ25pbmdLZXkpfWApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgICBsZXQgeyBrZXlQYXRoLCBwdXNoVG9HaXQgfSA9IHBhcnNlQXJncyhwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpO1xuXG4gICAgLy8gUmVhZCBmb3IgaXRzIHZhbHVlLCBzbyBzdGRvdXQgaGFzIHRvIGJlIG9uIGl0cyBvd24uIHJ1blByb21pc2Ugam9pbnMgaXQgd2l0aCBzdGRlcnIsIGFuZCBhXG4gICAgLy8gZ2l0IHdhcm5pbmcgZ2x1ZWQgdG8gdGhlIGZyb250IG9mIHRoaXMgYmVjb21lcyBhIGRpcmVjdG9yeSB0aGF0IGRvZXMgbm90IGV4aXN0LlxuICAgIGxldCB0b3BMZXZlbCA9IGF3YWl0IHNwYXduUHJvbWlzZSh7IGNvbW1hbmQ6IFwiZ2l0XCIsIGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIi0tc2hvdy10b3BsZXZlbFwiXSB9KTtcbiAgICBsZXQgcmVwb1BhdGggPSB0b3BMZXZlbC5zdGRvdXQudHJpbSgpO1xuICAgIGlmICh0b3BMZXZlbC5zdGF0dXMgIT09IDAgfHwgIXJlcG9QYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCB0aGUgY3VycmVudCBkaXJlY3RvcnkgdG8gYmUgaW5zaWRlIGEgZ2l0IHJlcG8sIGl0IGlzIG5vdC5cXG5gXG4gICAgICAgICAgICArIGAkeyh0b3BMZXZlbC5zdGRvdXQgKyB0b3BMZXZlbC5zdGRlcnIpLnRyaW0oKX1cXG4ke1VTQUdFfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgYXdhaXQgc2lnblJlcG8oeyByZXBvUGF0aCwga2V5UGF0aCB9KTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBDb21taXQgYW5kIHB1c2ggJHtNQU5JRkVTVF9OQU1FfSBhbmQgJHtTSUdOQVRVUkVfTkFNRX0gZm9yIGFueXRoaW5nIHRvIHNlZSB0aGVtLmApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBhZGQgLUFgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgLy8gTm90aGluZyBzdGFnZWQgaXMgbm90IHdvcnRoIHN0b3BwaW5nIG9uLiBnaXQgY29tbWl0IGNhbGxzIHRoYXQgYSBmYWlsdXJlLCBidXQgaXQgb25seSBtZWFuc1xuICAgIC8vIHRoZSBzaWduYXR1cmUgbWF0Y2hlcyB0aGUgb25lIGFscmVhZHkgY29tbWl0dGVkLCBzbyB0aGVyZSBpcyBub3RoaW5nIHRvIGRlcGxveS5cbiAgICBsZXQgc3RhdHVzID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogW1wic3RhdHVzXCIsIFwiLS1wb3JjZWxhaW5cIl0sIGN3ZDogcmVwb1BhdGggfSk7XG4gICAgbGV0IHN0YWdlZCA9IHN0YXR1cy5zdGRvdXQ7XG4gICAgaWYgKCFzdGFnZWQudHJpbSgpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBOb3RoaW5nIGNoYW5nZWQsICR7TUFOSUZFU1RfTkFNRX0gYW5kICR7U0lHTkFUVVJFX05BTUV9IGFyZSBhbHJlYWR5IGNvbW1pdHRlZC5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgY29tbWl0IC1tICR7cXVvdGUoQ09NTUlUX01FU1NBR0UpfWAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgcHVzaGAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBjb25zb2xlLmxvZyhgQ29tbWl0dGVkIGFuZCBwdXNoZWQuYCk7XG59XG4iXX0=
|
|
181
|
+
/* _JS_SOURCE_HASH = "5656bac7a766bdb1101df9294951fc82d227c63f880590d3dd4eb51bd67c88d1"; */
|
|
@@ -19,7 +19,13 @@ export type Manifest = {
|
|
|
19
19
|
files: { path: string; size: number; sha256: string }[];
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
/** Everything in the repo that is not ignored
|
|
22
|
+
/** Everything in the repo that is not ignored: what is in the index, plus what is not staged yet.
|
|
23
|
+
Git is asked because git is what knows how to apply the ignore rules.
|
|
24
|
+
|
|
25
|
+
What comes back is a hint that a file might be there, not that it is. A file deleted from the
|
|
26
|
+
working tree stays in the index until that deletion is staged, so git names it and there is
|
|
27
|
+
nothing to read, which is why each one is checked before it goes in.
|
|
28
|
+
|
|
23
29
|
The manifest and its signature are left out, since they cannot describe themselves. */
|
|
24
30
|
export async function listRepoFiles(repoPath: string) {
|
|
25
31
|
let result = await spawnPromise({
|
|
@@ -33,10 +39,21 @@ export async function listRepoFiles(repoPath: string) {
|
|
|
33
39
|
+ `${(result.stdout + result.stderr).trim()}`
|
|
34
40
|
);
|
|
35
41
|
}
|
|
36
|
-
|
|
42
|
+
let listed = result.stdout.split("\n")
|
|
37
43
|
.map(line => line.trim())
|
|
38
44
|
.filter(line => line && line !== MANIFEST_NAME && line !== SIGNATURE_NAME)
|
|
39
45
|
.sort();
|
|
46
|
+
|
|
47
|
+
let present: string[] = [];
|
|
48
|
+
for (let relativePath of listed) {
|
|
49
|
+
try {
|
|
50
|
+
await fs.access(path.join(repoPath, relativePath));
|
|
51
|
+
present.push(relativePath);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.log(`Leaving ${relativePath} out of the manifest, it is gone from the working tree`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return present;
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
/** A Windows checkout turns LF into CRLF, so the same commit hashes differently there than it
|
|
@@ -3,8 +3,10 @@ import os from "os";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { runPromise } from "socket-function/src/runPromise";
|
|
5
5
|
import { expandHome } from "../helpers/paths";
|
|
6
|
+
import { spawnPromise } from "../helpers/spawn";
|
|
6
7
|
import { buildManifest, formatManifest, MANIFEST_NAME, SIGNATURE_NAME, SIGN_NAMESPACE } from "./manifest";
|
|
7
8
|
import { revokedKeysInRepo } from "../authorizedKeys/unrevoke";
|
|
9
|
+
import { findKeyProblems, normalizeKeys } from "../authorizedKeys/authorizedKeys";
|
|
8
10
|
|
|
9
11
|
// A hardware backed key is the entire point. A key sitting on disk is compromised the moment the
|
|
10
12
|
// machine is, and then the signature proves nothing, so this is what we make when asked to make one.
|
|
@@ -58,6 +60,27 @@ async function publicKeyOf(keyPath: string) {
|
|
|
58
60
|
return `${keyType} ${keyBody}`;
|
|
59
61
|
}
|
|
60
62
|
|
|
63
|
+
/** A keys repo has rules the rest of this cannot enforce afterwards, so they are enforced before it
|
|
64
|
+
is signed. Signing anything that is not a keys repo is none of this function's business. */
|
|
65
|
+
async function refuseUnusableKeys(repoPath: string) {
|
|
66
|
+
let authorizedPath = path.join(repoPath, "authorized_keys");
|
|
67
|
+
if (!await pathExists(authorizedPath)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
let problems = findKeyProblems(normalizeKeys(await fs.readFile(authorizedPath, "utf8")));
|
|
71
|
+
if (!problems.length) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Expected every key in ${authorizedPath} to be restricted and to belong to one person,`
|
|
76
|
+
+ ` found ${problems.length} problem(s):\n`
|
|
77
|
+
+ problems.map(problem => ` - ${problem}`).join("\n")
|
|
78
|
+
+ `\n\nEvery key needs a from= naming the addresses it may be used from, and no two keys may`
|
|
79
|
+
+ `\nname the same ones. Revoking a key that shares its addresses with another leaves that`
|
|
80
|
+
+ `\nother key working, which defeats the point of revoking it.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
61
84
|
/** Signing a keys repo that still holds a revoked key would publish it back to every machine that
|
|
62
85
|
took it out. Only applies to a repo that holds keys and has a revoke repo to check - signing
|
|
63
86
|
anything else is none of this function's business. */
|
|
@@ -65,8 +88,10 @@ async function refuseRevokedKeys(repoPath: string) {
|
|
|
65
88
|
if (!await pathExists(path.join(repoPath, "authorized_keys"))) {
|
|
66
89
|
return;
|
|
67
90
|
}
|
|
68
|
-
|
|
69
|
-
|
|
91
|
+
// Read for its value, so stdout has to be on its own. runPromise joins it with stderr.
|
|
92
|
+
let origin = await spawnPromise({ command: "git", args: ["remote", "get-url", "origin"], cwd: repoPath });
|
|
93
|
+
let originURL = origin.stdout.trim();
|
|
94
|
+
if (origin.status !== 0 || !originURL) {
|
|
70
95
|
return;
|
|
71
96
|
}
|
|
72
97
|
let revoked;
|
|
@@ -96,19 +121,16 @@ function parseArgs(argv: string[]) {
|
|
|
96
121
|
return { keyPath: positional[0], pushToGit };
|
|
97
122
|
}
|
|
98
123
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
let repoPath =
|
|
103
|
-
|
|
104
|
-
throw new Error(`Expected the current directory to be inside a git repo, it is not.\n${USAGE}`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
let signingKey = keyPath && expandHome(keyPath) || await ensureDefaultKey();
|
|
124
|
+
/** Writes the manifest and its signature into a repo. Separate from the command so anything that
|
|
125
|
+
changes a keys repo can leave it signed, rather than telling someone to go and do it. */
|
|
126
|
+
export async function signRepo(config: { repoPath: string; keyPath?: string }) {
|
|
127
|
+
let { repoPath } = config;
|
|
128
|
+
let signingKey = config.keyPath && expandHome(config.keyPath) || await ensureDefaultKey();
|
|
108
129
|
if (!await pathExists(signingKey)) {
|
|
109
130
|
throw new Error(`Expected a signing key at ${signingKey}, no such file exists`);
|
|
110
131
|
}
|
|
111
132
|
|
|
133
|
+
await refuseUnusableKeys(repoPath);
|
|
112
134
|
await refuseRevokedKeys(repoPath);
|
|
113
135
|
|
|
114
136
|
let manifest = await buildManifest(repoPath);
|
|
@@ -132,6 +154,22 @@ export async function main() {
|
|
|
132
154
|
await fs.copyFile(stagedSignature, path.join(repoPath, SIGNATURE_NAME));
|
|
133
155
|
await fs.rm(stagingDirectory, { recursive: true, force: true });
|
|
134
156
|
console.log(`Signed with ${await publicKeyOf(signingKey)}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export async function main() {
|
|
160
|
+
let { keyPath, pushToGit } = parseArgs(process.argv.slice(2));
|
|
161
|
+
|
|
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
|
+
}
|
|
172
|
+
await signRepo({ repoPath, keyPath });
|
|
135
173
|
|
|
136
174
|
if (!pushToGit) {
|
|
137
175
|
console.log(`Commit and push ${MANIFEST_NAME} and ${SIGNATURE_NAME} for anything to see them.`);
|
|
@@ -140,7 +178,8 @@ export async function main() {
|
|
|
140
178
|
await runPromise(`git add -A`, { cwd: repoPath });
|
|
141
179
|
// Nothing staged is not worth stopping on. git commit calls that a failure, but it only means
|
|
142
180
|
// the signature matches the one already committed, so there is nothing to deploy.
|
|
143
|
-
let
|
|
181
|
+
let status = await spawnPromise({ command: "git", args: ["status", "--porcelain"], cwd: repoPath });
|
|
182
|
+
let staged = status.stdout;
|
|
144
183
|
if (!staged.trim()) {
|
|
145
184
|
console.log(`Nothing changed, ${MANIFEST_NAME} and ${SIGNATURE_NAME} are already committed.`);
|
|
146
185
|
return;
|