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.
- package/misc/dist/ownIPs.ts.cache +30 -4
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/https/dist/certs.ts.cache +2 -2
- package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
- package/misc/ownIPs.ts +29 -1
- package/package.json +1 -1
- package/security/authorizedKeys/daemon/dist/paths.ts.cache +3 -6
- package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
- package/security/authorizedKeys/daemon/dist/state.ts.cache +5 -3
- package/security/authorizedKeys/daemon/paths.ts +0 -3
- package/security/authorizedKeys/daemon/revocation.ts +0 -0
- package/security/authorizedKeys/daemon/state.ts +4 -8
- package/security/authorizedKeys/dist/keysRepo.ts.cache +111 -0
- package/security/authorizedKeys/dist/secureSSH.ts.cache +147 -71
- package/security/authorizedKeys/dist/unrevoke.ts.cache +70 -51
- package/security/authorizedKeys/keysRepo.ts +111 -0
- package/security/authorizedKeys/secureSSH.ts +28 -38
- package/security/authorizedKeys/unrevoke.ts +9 -36
- package/security/machines/addMachine.ts +4 -3
- package/security/machines/dist/identity.ts.cache +2 -2
- package/security/machines/dist/machines.ts.cache +36 -94
- package/security/machines/machines.ts +39 -90
- package/security/machines/trustServer.ts +5 -3
- package/security/notifications/dist/remoteWebhook.ts.cache +78 -0
- package/security/notifications/dist/setupNotify.ts.cache +39 -0
- package/security/signedFiles/dist/signFiles.ts.cache +8 -10
- package/security/signedFiles/signFiles.ts +6 -10
- package/security/machines/trustState.ts +0 -53
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
6
|
-
//exports.main = exports.revokedKeysInRepo = exports.readRemoteRevocations = exports.revocationIP = void 0;
|
|
6
|
+
//exports.main = exports.revokedKeysInRepo = exports.readRemoteRevocations = exports.revocationIdentity = exports.revocationIP = void 0;
|
|
7
7
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
8
|
const os_1 = __importDefault(require("os"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
@@ -13,8 +13,9 @@ const revokeSource_1 = require("./revokeSource");
|
|
|
13
13
|
const sources_1 = require("./sources");
|
|
14
14
|
const signFiles_1 = require("../signedFiles/signFiles");
|
|
15
15
|
const authorizedKeys_2 = require("./authorizedKeys");
|
|
16
|
-
const paths_1 = require("../helpers/paths");
|
|
17
16
|
const spawn_1 = require("../helpers/spawn");
|
|
17
|
+
const machines_1 = require("../machines/machines");
|
|
18
|
+
const keysRepo_1 = require("./keysRepo");
|
|
18
19
|
const UNREVOKES_DIR = "unrevoked";
|
|
19
20
|
const REVOCATIONS_DIR = "revocations";
|
|
20
21
|
const GIT_KEYWORD = "git";
|
|
@@ -22,8 +23,8 @@ const COMMIT_MESSAGE = "unrevoke keys";
|
|
|
22
23
|
const USAGE = `Usage: yarn unrevoke [keys-repo] [${GIT_KEYWORD}]
|
|
23
24
|
|
|
24
25
|
Run this in a keys repo, or name one. It reads that repo's revoke repo and writes one unrevoke file
|
|
25
|
-
naming every revocation in it, so the keys are accepted again
|
|
26
|
-
|
|
26
|
+
naming every revocation in it, so the keys are accepted again as each machine picks it up. It signs
|
|
27
|
+
the result, and with ${GIT_KEYWORD} it commits and pushes it too.
|
|
27
28
|
|
|
28
29
|
Keys that were revoked should normally be deleted from the repo instead. Unrevoking only matters
|
|
29
30
|
for a key you still want.`;
|
|
@@ -33,6 +34,11 @@ function revocationIP(revocation) {
|
|
|
33
34
|
return revocation.ip || ((_a = revocation.attempt) === null || _a === void 0 ? void 0 : _a.ip) || "";
|
|
34
35
|
}
|
|
35
36
|
exports.revocationIP = revocationIP;
|
|
37
|
+
/** What the revocation is about, which is what an unrevoke has to name to undo it. */
|
|
38
|
+
function revocationIdentity(revocation) {
|
|
39
|
+
return revocation.fingerprint || revocation.machineId || "";
|
|
40
|
+
}
|
|
41
|
+
exports.revocationIdentity = revocationIdentity;
|
|
36
42
|
/** Every revocation the revoke repo lists. Cloned read only into a temp directory.
|
|
37
43
|
|
|
38
44
|
A person running this has their own access to the repo, so their credentials are what is used.
|
|
@@ -87,7 +93,7 @@ async function revokedKeysInRepo(config) {
|
|
|
87
93
|
}
|
|
88
94
|
let parsed = JSON.parse(await promises_1.default.readFile(path_1.default.join(directory, name), "utf8"));
|
|
89
95
|
for (let allowed of parsed.allowed || []) {
|
|
90
|
-
unrevoked.add(`${allowed.fingerprint} ${allowed.ip}`);
|
|
96
|
+
unrevoked.add(`${allowed.fingerprint || allowed.machineId} ${allowed.ip}`);
|
|
91
97
|
}
|
|
92
98
|
// Named ids, for the unrevokes written before this was about pairs.
|
|
93
99
|
for (let revocationId of parsed.revocationIds || []) {
|
|
@@ -139,30 +145,38 @@ async function allowAddressesInRepo(config) {
|
|
|
139
145
|
}
|
|
140
146
|
return added;
|
|
141
147
|
}
|
|
142
|
-
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
/** Puts each machine's addresses back into its own file, which is the machine equivalent of adding
|
|
149
|
+
an address to a key's from= list: without it the machine is allowed again in principle and
|
|
150
|
+
still rejected on sight, which revokes it once more. */
|
|
151
|
+
async function allowAddressesForMachines(config) {
|
|
152
|
+
let { repoPath, revocations } = config;
|
|
153
|
+
let added = new Map();
|
|
154
|
+
// Read the whole list, change what these revocations are about, write it back. Setting is by
|
|
155
|
+
// the whole set, so writing one machine at a time would delete every other machine.
|
|
156
|
+
let machines = await (0, machines_1.getMachines)(repoPath);
|
|
157
|
+
for (let revocation of revocations) {
|
|
158
|
+
let machineId = revocation.machineId;
|
|
159
|
+
let ip = revocationIP(revocation);
|
|
160
|
+
if (!machineId || !ip) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
let existing = machines.find(machine => machine.machineId === machineId);
|
|
164
|
+
if (!existing) {
|
|
165
|
+
// Removed from the repo since it was revoked, so there is nothing to allow. Deleting a
|
|
166
|
+
// machine is the stronger statement and it stands.
|
|
167
|
+
console.log(`machines/${machineId}.json is not in this repo, so ${ip} was not added to it`);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (existing.ips.includes(ip)) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
existing.ips = [...existing.ips, ip];
|
|
174
|
+
added.set(machineId, [...(added.get(machineId) || []), ip]);
|
|
159
175
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (origin.status !== 0 || !originURL) {
|
|
163
|
-
throw new Error(`Expected ${repoPath} to have an origin remote, it has none.\n${USAGE}`);
|
|
176
|
+
if (added.size) {
|
|
177
|
+
await (0, machines_1.setMachines)({ repoPath, machines });
|
|
164
178
|
}
|
|
165
|
-
return
|
|
179
|
+
return added;
|
|
166
180
|
}
|
|
167
181
|
async function main() {
|
|
168
182
|
let argv = process.argv.slice(2);
|
|
@@ -171,7 +185,7 @@ async function main() {
|
|
|
171
185
|
if (positional.length > 1) {
|
|
172
186
|
throw new Error(`Expected at most a keys repo, was ${positional.length} argument(s)\n${USAGE}`);
|
|
173
187
|
}
|
|
174
|
-
let { repoPath, originURL } = await resolveKeysRepo(positional[0]);
|
|
188
|
+
let { repoPath, sourceURL: originURL } = await (0, keysRepo_1.resolveKeysRepo)(positional[0]);
|
|
175
189
|
let revocations = await readRemoteRevocations({ sourceURL: originURL });
|
|
176
190
|
if (!revocations.length) {
|
|
177
191
|
console.log(`${(0, revokeSource_1.revokeRepoURL)(originURL)} lists no revocations, so there is nothing to undo.`);
|
|
@@ -189,11 +203,13 @@ async function main() {
|
|
|
189
203
|
// still revoked the moment it is used from another.
|
|
190
204
|
allowed: revocations.map(revocation => ({
|
|
191
205
|
fingerprint: revocation.fingerprint,
|
|
206
|
+
machineId: revocation.machineId,
|
|
192
207
|
ip: revocationIP(revocation),
|
|
193
208
|
})),
|
|
194
209
|
revocations: revocations.map(revocation => ({
|
|
195
210
|
revocationId: revocation.revocationId,
|
|
196
211
|
fingerprint: revocation.fingerprint,
|
|
212
|
+
machineId: revocation.machineId,
|
|
197
213
|
ip: revocationIP(revocation),
|
|
198
214
|
revokedAt: revocation.revokedAt,
|
|
199
215
|
revokedBy: revocation.revokedBy,
|
|
@@ -208,56 +224,59 @@ async function main() {
|
|
|
208
224
|
keysByFingerprint.set((0, authorizedKeys_1.keyFingerprint)(key), key);
|
|
209
225
|
}
|
|
210
226
|
let describeKey = (revocation) => {
|
|
211
|
-
let key = keysByFingerprint.get(revocation.fingerprint) || revocation.key || "";
|
|
227
|
+
let key = keysByFingerprint.get(revocation.fingerprint || "") || revocation.key || "";
|
|
212
228
|
return key && (0, authorizedKeys_1.summarizeKey)(key) || `a key no longer in this repo (${revocation.fingerprint})`;
|
|
213
229
|
};
|
|
214
|
-
let
|
|
230
|
+
let addressesByIdentity = new Map();
|
|
215
231
|
for (let revocation of revocations) {
|
|
216
232
|
let ip = revocationIP(revocation);
|
|
217
|
-
let
|
|
233
|
+
let identity = revocationIdentity(revocation);
|
|
234
|
+
let existing = addressesByIdentity.get(identity) || [];
|
|
218
235
|
if (ip && !existing.includes(ip)) {
|
|
219
236
|
existing.push(ip);
|
|
220
237
|
}
|
|
221
|
-
|
|
238
|
+
addressesByIdentity.set(identity, existing);
|
|
222
239
|
}
|
|
223
|
-
// Cancelling the revocation on its own would leave sshd refusing that address and the machines
|
|
224
|
-
// revoking
|
|
225
|
-
// the repo that owns
|
|
226
|
-
|
|
240
|
+
// Cancelling the revocation on its own would leave sshd refusing that address, and the machines
|
|
241
|
+
// revoking all over again, so the addresses go into the key's from= list and into the machine's
|
|
242
|
+
// own file here. We are in the repo that owns both, so there is nothing to hand back to whoever
|
|
243
|
+
// ran this.
|
|
244
|
+
let added = await allowAddressesInRepo({ repoPath, addressesByFingerprint: addressesByIdentity });
|
|
245
|
+
let addedForMachines = await allowAddressesForMachines({ repoPath, revocations });
|
|
227
246
|
console.log("");
|
|
228
|
-
for (let [
|
|
229
|
-
let
|
|
230
|
-
|
|
247
|
+
for (let [identity, addresses] of addressesByIdentity) {
|
|
248
|
+
let entries = revocations.filter(entry => revocationIdentity(entry) === identity);
|
|
249
|
+
let machineId = entries[0].machineId;
|
|
250
|
+
console.log(`Unfreezing ${machineId && `machine ${machineId}` || describeKey(entries[0])}`);
|
|
231
251
|
console.log(`Allowing IP ${addresses.join(", ") || "(no address recorded)"}`);
|
|
232
|
-
let addedHere = added.get(
|
|
252
|
+
let addedHere = machineId && addedForMachines.get(machineId) || added.get(identity) || [];
|
|
233
253
|
if (addedHere.length) {
|
|
234
|
-
|
|
254
|
+
let where = machineId && `machines/${machineId}.json` || `that key's from= list in authorized_keys`;
|
|
255
|
+
console.log(` added to ${where}: ${addedHere.join(", ")}`);
|
|
235
256
|
}
|
|
236
257
|
else {
|
|
237
|
-
console.log(`
|
|
258
|
+
console.log(` already allowed from ${addresses.join(", ") || "everywhere"}`);
|
|
238
259
|
}
|
|
239
|
-
for (let entry of
|
|
260
|
+
for (let entry of entries) {
|
|
240
261
|
console.log(` frozen by ${entry.revokedBy || "?"} ${entry.revokedAt || "at an unrecorded time"}`);
|
|
241
262
|
}
|
|
242
263
|
console.log("");
|
|
243
264
|
}
|
|
244
|
-
console.log(`Every other address stays frozen, and
|
|
245
|
-
console.log(`
|
|
265
|
+
console.log(`Every other address stays frozen, and any of these used from anywhere else is`);
|
|
266
|
+
console.log(`frozen again.`);
|
|
246
267
|
// Signed here rather than left as a step to remember. An unrevoke nobody signed does nothing at
|
|
247
268
|
// all, and the repo would sit there looking done while every machine ignored it.
|
|
248
269
|
await (0, signFiles_1.signRepo)({ repoPath });
|
|
249
270
|
if (!pushToGit) {
|
|
250
|
-
console.log(`\nCommit and push it, and
|
|
251
|
-
console.log(`those keys work again:`);
|
|
271
|
+
console.log(`\nCommit and push it, and those keys work again as each machine picks it up:`);
|
|
252
272
|
console.log(`\`\`\`\ngit add -A\ngit commit -m "${COMMIT_MESSAGE}"\ngit push\n\`\`\``);
|
|
253
273
|
return;
|
|
254
274
|
}
|
|
255
275
|
await (0, runPromise_1.runPromise)(`git add -A`, { cwd: repoPath });
|
|
256
276
|
await (0, runPromise_1.runPromise)(`git commit -m "${COMMIT_MESSAGE}"`, { cwd: repoPath });
|
|
257
277
|
await (0, runPromise_1.runPromise)(`git push`, { cwd: repoPath });
|
|
258
|
-
console.log(`\nCommitted and pushed.
|
|
259
|
-
console.log(`keys work again.`);
|
|
278
|
+
console.log(`\nCommitted and pushed. Those keys work again as each machine picks it up.`);
|
|
260
279
|
}
|
|
261
280
|
exports.main = main;
|
|
262
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5yZXZva2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1bnJldm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwyREFBNkI7QUFDN0IsNENBQW9CO0FBQ3BCLGdEQUF3QjtBQUN4QiwrREFBNEQ7QUFDNUQscURBQStGO0FBQy9GLGlEQUFnRTtBQUNoRSx1Q0FBMEM7QUFDMUMsd0RBQW9EO0FBQ3BELHFEQUFnRDtBQUNoRCw0Q0FBOEM7QUFDOUMsNENBQWdEO0FBRWhELE1BQU0sYUFBYSxHQUFHLFdBQVcsQ0FBQztBQUNsQyxNQUFNLGVBQWUsR0FBRyxhQUFhLENBQUM7QUFDdEMsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDO0FBQzFCLE1BQU0sY0FBYyxHQUFHLGVBQWUsQ0FBQztBQUN2QyxNQUFNLEtBQUssR0FBRyxxQ0FBcUMsV0FBVzs7Ozt3Q0FJdEIsV0FBVzs7OzBCQUd6QixDQUFDO0FBZTNCLG1FQUFtRTtBQUNuRSxTQUFnQixZQUFZLENBQUMsVUFBc0I7O0lBQy9DLE9BQU8sVUFBVSxDQUFDLEVBQUUsS0FBSSxNQUFBLFVBQVUsQ0FBQyxPQUFPLDBDQUFFLEVBQUUsQ0FBQSxJQUFJLEVBQUUsQ0FBQztBQUN6RCxDQUFDO0FBRkQsb0NBRUM7QUFFRDs7OztrR0FJa0c7QUFDM0YsS0FBSyxVQUFVLHFCQUFxQixDQUFDLE1BQTZCO0lBQ3JFLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxNQUFNLENBQUM7SUFDM0IsSUFBSSxrQkFBa0IsR0FBRyxNQUFNLGtCQUFFLENBQUMsT0FBTyxDQUFDLGNBQUksQ0FBQyxJQUFJLENBQUMsWUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDL0UsSUFBSSxRQUFRLEdBQUcsY0FBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNyRCxJQUFJLFNBQVMsR0FBRyxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FB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LENBQUMsaUZBQWlGLENBQUMsQ0FBQztJQUMvRixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFDcEMsQ0FBQztBQXRHRCxvQkFzR0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgcnVuUHJvbWlzZSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL3J1blByb21pc2VcIjtcbmltcG9ydCB7IGFsbG93QWRkcmVzc2VzLCBrZXlGaW5nZXJwcmludCwgbm9ybWFsaXplS2V5cywgc3VtbWFyaXplS2V5IH0gZnJvbSBcIi4vYXV0aG9yaXplZEtleXNcIjtcbmltcG9ydCB7IGRlcml2ZVJldm9rZUtleSwgcmV2b2tlUmVwb1VSTCB9IGZyb20gXCIuL3Jldm9rZVNvdXJjZVwiO1xuaW1wb3J0IHsgZmluZFNvdXJjZUtleSB9IGZyb20gXCIuL3NvdXJjZXNcIjtcbmltcG9ydCB7IHNpZ25SZXBvIH0gZnJvbSBcIi4uL3NpZ25lZEZpbGVzL3NpZ25GaWxlc1wiO1xuaW1wb3J0IHsgcmVhZFJlcG9LZXlzIH0gZnJvbSBcIi4vYXV0aG9yaXplZEtleXNcIjtcbmltcG9ydCB7IGV4cGFuZEhvbWUgfSBmcm9tIFwiLi4vaGVscGVycy9wYXRoc1wiO1xuaW1wb3J0IHsgc3Bhd25Qcm9taXNlIH0gZnJvbSBcIi4uL2hlbHBlcnMvc3Bhd25cIjtcblxuY29uc3QgVU5SRVZPS0VTX0RJUiA9IFwidW5yZXZva2VkXCI7XG5jb25zdCBSRVZPQ0FUSU9OU19ESVIgPSBcInJldm9jYXRpb25zXCI7XG5jb25zdCBHSVRfS0VZV09SRCA9IFwiZ2l0XCI7XG5jb25zdCBDT01NSVRfTUVTU0FHRSA9IFwidW5yZXZva2Uga2V5c1wiO1xuY29uc3QgVVNBR0UgPSBgVXNhZ2U6IHlhcm4gdW5yZXZva2UgW2tleXMtcmVwb10gWyR7R0lUX0tFWVdPUkR9XVxuXG5SdW4gdGhpcyBpbiBhIGtleXMgcmVwbywgb3IgbmFtZSBvbmUuIEl0IHJlYWRzIHRoYXQgcmVwbydzIHJldm9rZSByZXBvIGFuZCB3cml0ZXMgb25lIHVucmV2b2tlIGZpbGVcbm5hbWluZyBldmVyeSByZXZvY2F0aW9uIGluIGl0LCBzbyB0aGUga2V5cyBhcmUgYWNjZXB0ZWQgYWdhaW4gb25jZSBlYWNoIG1hY2hpbmUncyBob3VyIGxvbmcgd2FpdFxucGFzc2VzLiBJdCBzaWducyB0aGUgcmVzdWx0LCBhbmQgd2l0aCAke0dJVF9LRVlXT1JEfSBpdCBjb21taXRzIGFuZCBwdXNoZXMgaXQgdG9vLlxuXG5LZXlzIHRoYXQgd2VyZSByZXZva2VkIHNob3VsZCBub3JtYWxseSBiZSBkZWxldGVkIGZyb20gdGhlIHJlcG8gaW5zdGVhZC4gVW5yZXZva2luZyBvbmx5IG1hdHRlcnNcbmZvciBhIGtleSB5b3Ugc3RpbGwgd2FudC5gO1xuXG5leHBvcnQgdHlwZSBSZXZvY2F0aW9uID0ge1xuICAgIHJldm9jYXRpb25JZDogc3RyaW5nO1xuICAgIGZpbmdlcnByaW50OiBzdHJpbmc7XG4gICAgLy8gVGhlIGFkZHJlc3MgdGhlIGtleSB3YXMgdXNlZCBmcm9tLiBBIHJldm9jYXRpb24gaXMgYWJvdXQgdGhpcyBwYWlyLCBhbmQgYW4gdW5yZXZva2UgdW5kb2VzXG4gICAgLy8gaXQgYnkgYWxsb3dpbmcgdGhhdCBzYW1lIHBhaXIgLSB3aGljaCBpcyB3aHkgdW5yZXZva2luZyBuZXZlciBtYWtlcyBhIGtleSB1bnJldm9rYWJsZTogdXNlZFxuICAgIC8vIGZyb20gc29tZSBvdGhlciBhZGRyZXNzLCBpdCBpcyByZXZva2VkIGFnYWluLlxuICAgIGlwPzogc3RyaW5nO1xuICAgIGtleT86IHN0cmluZztcbiAgICByZXZva2VkQXQ/OiBzdHJpbmc7XG4gICAgcmV2b2tlZEJ5Pzogc3RyaW5nO1xuICAgIGF0dGVtcHQ/OiB7IGlwPzogc3RyaW5nOyB1c2VyPzogc3RyaW5nOyByZXF1aXJlZD86IHN0cmluZyB9O1xufTtcblxuLyoqIE9sZGVyIHJldm9jYXRpb24gZmlsZXMgY2FycnkgdGhlIGFkZHJlc3MgdW5kZXIgYXR0ZW1wdCBvbmx5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9jYXRpb25JUChyZXZvY2F0aW9uOiBSZXZvY2F0aW9uKSB7XG4gICAgcmV0dXJuIHJldm9jYXRpb24uaXAgfHwgcmV2b2NhdGlvbi5hdHRlbXB0Py5pcCB8fCBcIlwiO1xufVxuXG4vKiogRXZlcnkgcmV2b2NhdGlvbiB0aGUgcmV2b2tlIHJlcG8gbGlzdHMuIENsb25lZCByZWFkIG9ubHkgaW50byBhIHRlbXAgZGlyZWN0b3J5LlxuXG4gICAgQSBwZXJzb24gcnVubmluZyB0aGlzIGhhcyB0aGVpciBvd24gYWNjZXNzIHRvIHRoZSByZXBvLCBzbyB0aGVpciBjcmVkZW50aWFscyBhcmUgd2hhdCBpcyB1c2VkLlxuICAgIE9uIGEgbWFjaGluZSB0aGF0IGlzIGFscmVhZHkgYSBwb3J0c2VjdXJlIGhvc3QgdGhlcmUgbWF5IGJlIG5vIHN1Y2ggY3JlZGVudGlhbHMsIGJ1dCB0aGUgc291cmNlXG4gICAgZGVwbG95IGtleSBpcyByaWdodCB0aGVyZSwgYW5kIHRoZSBrZXkgZGVyaXZlZCBmcm9tIGl0IGlzIG9uZSB0aGF0IHJlcG8gZGVmaW5pdGVseSBhY2NlcHRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRSZW1vdGVSZXZvY2F0aW9ucyhjb25maWc6IHsgc291cmNlVVJMOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHNvdXJjZVVSTCB9ID0gY29uZmlnO1xuICAgIGxldCB0ZW1wb3JhcnlEaXJlY3RvcnkgPSBhd2FpdCBmcy5ta2R0ZW1wKHBhdGguam9pbihvcy50bXBkaXIoKSwgXCJ1bnJldm9rZS1cIikpO1xuICAgIGxldCByZXBvUGF0aCA9IHBhdGguam9pbih0ZW1wb3JhcnlEaXJlY3RvcnksIFwicmVwb1wiKTtcbiAgICBsZXQgY2xvbmVBcmdzID0gW1wiY2xvbmVcIiwgXCItLWRlcHRoXCIsIFwiMVwiLCByZXZva2VSZXBvVVJMKHNvdXJjZVVSTCksIHJlcG9QYXRoXTtcbiAgICBsZXQgc291cmNlS2V5ID0gYXdhaXQgZmluZFNvdXJjZUtleShzb3VyY2VVUkwpO1xuICAgIGlmIChzb3VyY2VLZXkpIHtcbiAgICAgICAgbGV0IGRlcml2ZWQgPSBkZXJpdmVSZXZva2VLZXkoYXdhaXQgZnMucmVhZEZpbGUoc291cmNlS2V5LCBcInV0ZjhcIikpO1xuICAgICAgICBsZXQgZGVyaXZlZEtleVBhdGggPSBwYXRoLmpvaW4odGVtcG9yYXJ5RGlyZWN0b3J5LCBcImtleVwiKTtcbiAgICAgICAgYXdhaXQgZnMud3JpdGVGaWxlKGRlcml2ZWRLZXlQYXRoLCBkZXJpdmVkLnByaXZhdGVLZXlGaWxlLCB7IG1vZGU6IDBvNjAwIH0pO1xuICAgICAgICBsZXQgc3NoQ29tbWFuZCA9IGBzc2ggLWkgJHtkZXJpdmVkS2V5UGF0aH0gLW8gSWRlbnRpdGllc09ubHk9eWVzIC1vIEJhdGNoTW9kZT15ZXMgLW8gU3RyaWN0SG9zdEtleUNoZWNraW5nPWFjY2VwdC1uZXdgO1xuICAgICAgICBjbG9uZUFyZ3MgPSBbXCItY1wiLCBgY29yZS5zc2hDb21tYW5kPSR7c3NoQ29tbWFuZH1gLCAuLi5jbG9uZUFyZ3NdO1xuICAgIH1cbiAgICBsZXQgY2xvbmUgPSBhd2FpdCBzcGF3blByb21pc2UoeyBjb21tYW5kOiBcImdpdFwiLCBhcmdzOiBjbG9uZUFyZ3MgfSk7XG4gICAgaWYgKGNsb25lLnN0YXR1cyAhPT0gMCkge1xuICAgICAgICBhd2FpdCBmcy5ybSh0ZW1wb3JhcnlEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkIHRvIGJlIGFibGUgdG8gcmVhZCAke3Jldm9rZVJlcG9VUkwoc291cmNlVVJMKX0uXFxuYFxuICAgICAgICAgICAgKyBgJHsoY2xvbmUuc3Rkb3V0ICsgY2xvbmUuc3RkZXJyKS50cmltKCl9YFxuICAgICAgICApO1xuICAgIH1cbiAgICBsZXQgcmV2b2NhdGlvbnM6IFJldm9jYXRpb25bXSA9IFtdO1xuICAgIGxldCBkaXJlY3RvcnkgPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFJFVk9DQVRJT05TX0RJUik7XG4gICAgdHJ5IHtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBvZiAoYXdhaXQgZnMucmVhZGRpcihkaXJlY3RvcnkpKS5zb3J0KCkpIHtcbiAgICAgICAgICAgIGlmIChuYW1lLmVuZHNXaXRoKFwiLmpzb25cIikpIHtcbiAgICAgICAgICAgICAgICByZXZvY2F0aW9ucy5wdXNoKEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgbmFtZSksIFwidXRmOFwiKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBObyByZXZvY2F0aW9ucyBkaXJlY3RvcnkgYXQgYWxsIGp1c3QgbWVhbnMgbm90aGluZyBoYXMgZXZlciBiZWVuIHJldm9rZWQuXG4gICAgfVxuICAgIGF3YWl0IGZzLnJtKHRlbXBvcmFyeURpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIHJldHVybiByZXZvY2F0aW9ucztcbn1cblxuLyoqIFdoaWNoIGtleXMgaW4gYSByZXBvIGFyZSByZXZva2VkLiBXaGF0IHNpZ25maWxlcyBhbmQgc2VjdXJlc3NoIHJlZnVzZSBvdmVyLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJldm9rZWRLZXlzSW5SZXBvKGNvbmZpZzogeyByZXBvUGF0aDogc3RyaW5nOyBzb3VyY2VVUkw6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgcmVwb1BhdGgsIHNvdXJjZVVSTCB9ID0gY29uZmlnO1xuICAgIGxldCByZXZvY2F0aW9ucyA9IGF3YWl0IHJlYWRSZW1vdGVSZXZvY2F0aW9ucyh7IHNvdXJjZVVSTCB9KTtcbiAgICBsZXQgcmV2b2tlZEZpbmdlcnByaW50cyA9IG5ldyBTZXQocmV2b2NhdGlvbnMubWFwKHJldm9jYXRpb24gPT4gcmV2b2NhdGlvbi5maW5nZXJwcmludCkpO1xuICAgIGxldCB1bnJldm9rZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICB0cnkge1xuICAgICAgICBsZXQgZGlyZWN0b3J5ID0gcGF0aC5qb2luKHJlcG9QYXRoLCBVTlJFVk9LRVNfRElSKTtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBvZiBhd2FpdCBmcy5yZWFkZGlyKGRpcmVjdG9yeSkpIHtcbiAgICAgICAgICAgIGlmICghbmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gSlNPTi5wYXJzZShhd2FpdCBmcy5yZWFkRmlsZShwYXRoLmpvaW4oZGlyZWN0b3J5LCBuYW1lKSwgXCJ1dGY4XCIpKTtcbiAgICAgICAgICAgIGZvciAobGV0IGFsbG93ZWQgb2YgcGFyc2VkLmFsbG93ZWQgfHwgW10pIHtcbiAgICAgICAgICAgICAgICB1bnJldm9rZWQuYWRkKGAke2FsbG93ZWQuZmluZ2VycHJpbnR9ICR7YWxsb3dlZC5pcH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5hbWVkIGlkcywgZm9yIHRoZSB1bnJldm9rZXMgd3JpdHRlbiBiZWZvcmUgdGhpcyB3YXMgYWJvdXQgcGFpcnMuXG4gICAgICAgICAgICBmb3IgKGxldCByZXZvY2F0aW9uSWQgb2YgcGFyc2VkLnJldm9jYXRpb25JZHMgfHwgW10pIHtcbiAgICAgICAgICAgICAgICB1bnJldm9rZWQuYWRkKHJldm9jYXRpb25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIE5vdGhpbmcgaGFzIGJlZW4gdW5yZXZva2VkLlxuICAgIH1cbiAgICBsZXQgc3RpbGxSZXZva2VkID0gcmV2b2NhdGlvbnMuZmlsdGVyKHJldm9jYXRpb24gPT4gIXVucmV2b2tlZC5oYXMocmV2b2NhdGlvbi5yZXZvY2F0aW9uSWQpXG4gICAgICAgICYmICF1bnJldm9rZWQuaGFzKGAke3Jldm9jYXRpb24uZmluZ2VycHJpbnR9ICR7cmV2b2NhdGlvbklQKHJldm9jYXRpb24pfWApKTtcbiAgICBsZXQga2V5cyA9IG5vcm1hbGl6ZUtleXMoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKSwgXCJ1dGY4XCIpLmNhdGNoKCgpID0+IFwiXCIpKTtcbiAgICByZXR1cm4gc3RpbGxSZXZva2VkXG4gICAgICAgIC5maWx0ZXIocmV2b2NhdGlvbiA9PiBrZXlzLnNvbWUoa2V5ID0+IGtleUZpbmdlcnByaW50KGtleSkgPT09IHJldm9jYXRpb24uZmluZ2VycHJpbnQpKVxuICAgICAgICAubWFwKHJldm9jYXRpb24gPT4gKHsgcmV2b2NhdGlvbiwga2V5OiBrZXlzLmZpbmQoa2V5ID0+IGtleUZpbmdlcnByaW50KGtleSkgPT09IHJldm9jYXRpb24uZmluZ2VycHJpbnQpIHx8IFwiXCIgfSkpO1xufVxuXG4vKiogV3JpdGVzIHRoZSBhZGRyZXNzZXMgaW50byB0aGUgZnJvbT0gbGlzdCBvZiBlYWNoIGtleSBpbiB0aGUgcmVwbydzIGF1dGhvcml6ZWRfa2V5cywgYW5kIHNheXNcbiAgICB3aGljaCBvbmVzIHdlcmUgYWN0dWFsbHkgbmV3LiBPbmx5IHRoZSBsaW5lcyBiZWluZyBjaGFuZ2VkIGFyZSB0b3VjaGVkLCBzbyBjb21tZW50cywgb3JkZXJpbmdcbiAgICBhbmQgYW55IGtleSBub3QgaW52b2x2ZWQgY29tZSBvdXQgb2YgdGhpcyBieXRlIGZvciBieXRlIHRoZSBzYW1lLiAqL1xuYXN5bmMgZnVuY3Rpb24gYWxsb3dBZGRyZXNzZXNJblJlcG8oY29uZmlnOiB7XG4gICAgcmVwb1BhdGg6IHN0cmluZztcbiAgICBhZGRyZXNzZXNCeUZpbmdlcnByaW50OiBNYXA8c3RyaW5nLCBzdHJpbmdbXT47XG59KSB7XG4gICAgbGV0IHsgcmVwb1BhdGgsIGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQgfSA9IGNvbmZpZztcbiAgICBsZXQgYWRkZWQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG4gICAgbGV0IGZpbGVQYXRoID0gcGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKTtcbiAgICBsZXQgY29udGVudHM7XG4gICAgdHJ5IHtcbiAgICAgICAgY29udGVudHMgPSBhd2FpdCBmcy5yZWFkRmlsZShmaWxlUGF0aCwgXCJ1dGY4XCIpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gQSByZXBvIGhvbGRpbmcgaXRzIGtleXMgYXMgc2VwYXJhdGUgLnB1YiBmaWxlcy4gTm90aGluZyB0byBlZGl0IGluIG9uZSBwbGFjZSwgc28gdGhlXG4gICAgICAgIC8vIGNhbGxlcidzIGxpc3RpbmcgaXMgYWxsIHdob2V2ZXIgcmFuIHRoaXMgZ2V0cy5cbiAgICAgICAgY29uc29sZS5sb2coYE5vIGF1dGhvcml6ZWRfa2V5cyBpbiAke3JlcG9QYXRofSwgc28gdGhlIGFkZHJlc3NlcyB3ZXJlIG5vdCBhZGRlZCB0byBhbnkga2V5LmApO1xuICAgICAgICByZXR1cm4gYWRkZWQ7XG4gICAgfVxuICAgIGxldCBsaW5lcyA9IGNvbnRlbnRzLnNwbGl0KFwiXFxuXCIpO1xuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBsaW5lcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgbGV0IGZpbmdlcnByaW50ID0ga2V5RmluZ2VycHJpbnQobGluZXNbaW5kZXhdKTtcbiAgICAgICAgbGV0IGFkZHJlc3NlcyA9IGZpbmdlcnByaW50ICYmIGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQuZ2V0KGZpbmdlcnByaW50KTtcbiAgICAgICAgaWYgKCFhZGRyZXNzZXMgfHwgIWFkZHJlc3Nlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGxldCByZXN1bHQgPSBhbGxvd0FkZHJlc3NlcyhsaW5lc1tpbmRleF0sIGFkZHJlc3Nlcyk7XG4gICAgICAgIGxpbmVzW2luZGV4XSA9IHJlc3VsdC5rZXlMaW5lO1xuICAgICAgICBhZGRlZC5zZXQoZmluZ2VycHJpbnQsIFsuLi4oYWRkZWQuZ2V0KGZpbmdlcnByaW50KSB8fCBbXSksIC4uLnJlc3VsdC5hZGRlZF0pO1xuICAgIH1cbiAgICBpZiAoWy4uLmFkZGVkLnZhbHVlcygpXS5zb21lKGxpc3QgPT4gbGlzdC5sZW5ndGgpKSB7XG4gICAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShmaWxlUGF0aCwgbGluZXMuam9pbihcIlxcblwiKSk7XG4gICAgfVxuICAgIHJldHVybiBhZGRlZDtcbn1cblxuLyoqIFRoZSByZXBvIG5hbWVkLCBvciB0aGUgb25lIHdlIGFyZSBzdGFuZGluZyBpbi4gQ2hlY2tlZCB0aGUgc2FtZSB3YXkgc2VjdXJlc3NoIGNoZWNrcyBpdDogYSBnaXRcbiAgICByZXBvIHRoYXQgYWN0dWFsbHkgaG9sZHMga2V5cyBhbmQgaGFzIGFuIG9yaWdpbiB0byBjbG9uZSBmcm9tLiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUtleXNSZXBvKG5hbWVkOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICBsZXQgY3dkID0gbmFtZWQgJiYgZXhwYW5kSG9tZShuYW1lZCkgfHwgdW5kZWZpbmVkO1xuICAgIC8vIHNwYXduUHJvbWlzZSByYXRoZXIgdGhhbiBydW5Qcm9taXNlLCBiZWNhdXNlIHRoZXNlIHR3byBhcmUgcmVhZCBmb3IgdGhlaXIgdmFsdWUuIHJ1blByb21pc2VcbiAgICAvLyByZXR1cm5zIHN0ZG91dCBhbmQgc3RkZXJyIGpvaW5lZCwgc28gb25lIGdpdCB3YXJuaW5nIGVuZHMgdXAgZ2x1ZWQgdG8gdGhlIGZyb250IG9mIHRoZSBwYXRoLlxuICAgIGxldCB0b3BMZXZlbCA9IGF3YWl0IHNwYXduUHJvbWlzZSh7IGNvbW1hbmQ6IFwiZ2l0XCIsIGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIi0tc2hvdy10b3BsZXZlbFwiXSwgY3dkIH0pO1xuICAgIGxldCByZXBvUGF0aCA9IHRvcExldmVsLnN0ZG91dC50cmltKCk7XG4gICAgaWYgKHRvcExldmVsLnN0YXR1cyAhPT0gMCB8fCAhcmVwb1BhdGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkICR7bmFtZWQgfHwgXCJ0aGUgY3VycmVudCBkaXJlY3RvcnlcIn0gdG8gYmUgaW5zaWRlIGEgZ2l0IHJlcG8sIGl0IGlzIG5vdC5cXG5gXG4gICAgICAgICAgICArIGAkeyh0b3BMZXZlbC5zdGRvdXQgKyB0b3BMZXZlbC5zdGRlcnIpLnRyaW0oKX1cXG4ke1VTQUdFfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcmVhZFJlcG9LZXlzKHJlcG9QYXRoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtyZXBvUGF0aH0gdG8gYmUgYSBrZXlzIHJlcG8sIGl0IGhvbGRzIG5vIGtleXMuXFxuJHtlfVxcbiR7VVNBR0V9YCk7XG4gICAgfVxuICAgIGxldCBvcmlnaW4gPSBhd2FpdCBzcGF3blByb21pc2UoeyBjb21tYW5kOiBcImdpdFwiLCBhcmdzOiBbXCJyZW1vdGVcIiwgXCJnZXQtdXJsXCIsIFwib3JpZ2luXCJdLCBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGxldCBvcmlnaW5VUkwgPSBvcmlnaW4uc3Rkb3V0LnRyaW0oKTtcbiAgICBpZiAob3JpZ2luLnN0YXR1cyAhPT0gMCB8fCAhb3JpZ2luVVJMKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHtyZXBvUGF0aH0gdG8gaGF2ZSBhbiBvcmlnaW4gcmVtb3RlLCBpdCBoYXMgbm9uZS5cXG4ke1VTQUdFfWApO1xuICAgIH1cbiAgICByZXR1cm4geyByZXBvUGF0aCwgb3JpZ2luVVJMIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICAgIGxldCBhcmd2ID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpO1xuICAgIGxldCBwdXNoVG9HaXQgPSBhcmd2LmluY2x1ZGVzKEdJVF9LRVlXT1JEKTtcbiAgICBsZXQgcG9zaXRpb25hbCA9IGFyZ3YuZmlsdGVyKGFyZyA9PiBhcmcgIT09IEdJVF9LRVlXT1JEKTtcbiAgICBpZiAocG9zaXRpb25hbC5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYXQgbW9zdCBhIGtleXMgcmVwbywgd2FzICR7cG9zaXRpb25hbC5sZW5ndGh9IGFyZ3VtZW50KHMpXFxuJHtVU0FHRX1gKTtcbiAgICB9XG4gICAgbGV0IHsgcmVwb1BhdGgsIG9yaWdpblVSTCB9ID0gYXdhaXQgcmVzb2x2ZUtleXNSZXBvKHBvc2l0aW9uYWxbMF0pO1xuXG4gICAgbGV0IHJldm9jYXRpb25zID0gYXdhaXQgcmVhZFJlbW90ZVJldm9jYXRpb25zKHsgc291cmNlVVJMOiBvcmlnaW5VUkwgfSk7XG4gICAgaWYgKCFyZXZvY2F0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgY29uc29sZS5sb2coYCR7cmV2b2tlUmVwb1VSTChvcmlnaW5VUkwpfSBsaXN0cyBubyByZXZvY2F0aW9ucywgc28gdGhlcmUgaXMgbm90aGluZyB0byB1bmRvLmApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IGRpcmVjdG9yeSA9IHBhdGguam9pbihyZXBvUGF0aCwgVU5SRVZPS0VTX0RJUik7XG4gICAgYXdhaXQgZnMubWtkaXIoZGlyZWN0b3J5LCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBsZXQgc3RhbXAgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkucmVwbGFjZSgvWzouXS9nLCBcIi1cIik7XG4gICAgbGV0IHVucmV2b2tlSWQgPSBgJHtzdGFtcH0tdW5yZXZva2VgO1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoLmpvaW4oZGlyZWN0b3J5LCBgJHt1bnJldm9rZUlkfS5qc29uYCksIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgdW5yZXZva2VJZCxcbiAgICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIC8vIFdoYXQgdGhpcyBmaWxlIHNheXM6IGVhY2ggb2YgdGhlc2Uga2V5cyBpcyBhbGxvd2VkIGZyb20gdGhpcyBhZGRyZXNzLiBQYWlycywgbm90IGtleXMsXG4gICAgICAgIC8vIGFuZCBub3QgYSBibGFua2V0IFwiYWxsb3cgZXZlcnl0aGluZyBhZ2FpblwiIC0gYSBrZXkgZm9yZ2l2ZW4gaGVyZSBmb3Igb25lIGFkZHJlc3MgaXNcbiAgICAgICAgLy8gc3RpbGwgcmV2b2tlZCB0aGUgbW9tZW50IGl0IGlzIHVzZWQgZnJvbSBhbm90aGVyLlxuICAgICAgICBhbGxvd2VkOiByZXZvY2F0aW9ucy5tYXAocmV2b2NhdGlvbiA9PiAoe1xuICAgICAgICAgICAgZmluZ2VycHJpbnQ6IHJldm9jYXRpb24uZmluZ2VycHJpbnQsXG4gICAgICAgICAgICBpcDogcmV2b2NhdGlvbklQKHJldm9jYXRpb24pLFxuICAgICAgICB9KSksXG4gICAgICAgIHJldm9jYXRpb25zOiByZXZvY2F0aW9ucy5tYXAocmV2b2NhdGlvbiA9PiAoe1xuICAgICAgICAgICAgcmV2b2NhdGlvbklkOiByZXZvY2F0aW9uLnJldm9jYXRpb25JZCxcbiAgICAgICAgICAgIGZpbmdlcnByaW50OiByZXZvY2F0aW9uLmZpbmdlcnByaW50LFxuICAgICAgICAgICAgaXA6IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKSxcbiAgICAgICAgICAgIHJldm9rZWRBdDogcmV2b2NhdGlvbi5yZXZva2VkQXQsXG4gICAgICAgICAgICByZXZva2VkQnk6IHJldm9jYXRpb24ucmV2b2tlZEJ5LFxuICAgICAgICAgICAgYXR0ZW1wdDogcmV2b2NhdGlvbi5hdHRlbXB0LFxuICAgICAgICB9KSksXG4gICAgfSwgdW5kZWZpbmVkLCA0KSArIFwiXFxuXCIpO1xuXG4gICAgLy8gTmFtZWQgdGhlIHdheSB0aGUgbm90aWZpY2F0aW9ucyBuYW1lIHRoZW0uIEEgZmluZ2VycHJpbnQgaXMgbm90IGluIGF1dGhvcml6ZWRfa2V5cyBhbmRcbiAgICAvLyBjYW5ub3QgYmUgd29ya2VkIG91dCBieSBleWUsIHNvIG9uIGl0cyBvd24gaXQgdGVsbHMgd2hvZXZlciBpcyByZWFkaW5nIHRoaXMgbm90aGluZyBhYm91dFxuICAgIC8vIHdoaWNoIG9mIHRoZWlyIGtleXMgaXMgYmVpbmcgdGFsa2VkIGFib3V0LlxuICAgIGxldCBrZXlzQnlGaW5nZXJwcmludCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgZm9yIChsZXQga2V5IG9mIGF3YWl0IHJlYWRSZXBvS2V5cyhyZXBvUGF0aCkuY2F0Y2goKCkgPT4gW10gYXMgc3RyaW5nW10pKSB7XG4gICAgICAgIGtleXNCeUZpbmdlcnByaW50LnNldChrZXlGaW5nZXJwcmludChrZXkpLCBrZXkpO1xuICAgIH1cbiAgICBsZXQgZGVzY3JpYmVLZXkgPSAocmV2b2NhdGlvbjogUmV2b2NhdGlvbikgPT4ge1xuICAgICAgICBsZXQga2V5ID0ga2V5c0J5RmluZ2VycHJpbnQuZ2V0KHJldm9jYXRpb24uZmluZ2VycHJpbnQpIHx8IHJldm9jYXRpb24ua2V5IHx8IFwiXCI7XG4gICAgICAgIHJldHVybiBrZXkgJiYgc3VtbWFyaXplS2V5KGtleSkgfHwgYGEga2V5IG5vIGxvbmdlciBpbiB0aGlzIHJlcG8gKCR7cmV2b2NhdGlvbi5maW5nZXJwcmludH0pYDtcbiAgICB9O1xuXG4gICAgbGV0IGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG4gICAgZm9yIChsZXQgcmV2b2NhdGlvbiBvZiByZXZvY2F0aW9ucykge1xuICAgICAgICBsZXQgaXAgPSByZXZvY2F0aW9uSVAocmV2b2NhdGlvbik7XG4gICAgICAgIGxldCBleGlzdGluZyA9IGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQuZ2V0KHJldm9jYXRpb24uZmluZ2VycHJpbnQpIHx8IFtdO1xuICAgICAgICBpZiAoaXAgJiYgIWV4aXN0aW5nLmluY2x1ZGVzKGlwKSkge1xuICAgICAgICAgICAgZXhpc3RpbmcucHVzaChpcCk7XG4gICAgICAgIH1cbiAgICAgICAgYWRkcmVzc2VzQnlGaW5nZXJwcmludC5zZXQocmV2b2NhdGlvbi5maW5nZXJwcmludCwgZXhpc3RpbmcpO1xuICAgIH1cblxuICAgIC8vIENhbmNlbGxpbmcgdGhlIHJldm9jYXRpb24gb24gaXRzIG93biB3b3VsZCBsZWF2ZSBzc2hkIHJlZnVzaW5nIHRoYXQgYWRkcmVzcyBhbmQgdGhlIG1hY2hpbmVzXG4gICAgLy8gcmV2b2tpbmcgdGhlIGtleSBhbGwgb3ZlciBhZ2Fpbiwgc28gdGhlIGFkZHJlc3NlcyBnbyBpbnRvIHRoZSBrZXkncyBmcm9tPSBoZXJlLiBXZSBhcmUgaW5cbiAgICAvLyB0aGUgcmVwbyB0aGF0IG93bnMgYXV0aG9yaXplZF9rZXlzLCBzbyB0aGVyZSBpcyBub3RoaW5nIHRvIGhhbmQgYmFjayB0byB3aG9ldmVyIHJhbiB0aGlzLlxuICAgIGxldCBhZGRlZCA9IGF3YWl0IGFsbG93QWRkcmVzc2VzSW5SZXBvKHsgcmVwb1BhdGgsIGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQgfSk7XG5cbiAgICBjb25zb2xlLmxvZyhcIlwiKTtcbiAgICBmb3IgKGxldCBbZmluZ2VycHJpbnQsIGFkZHJlc3Nlc10gb2YgYWRkcmVzc2VzQnlGaW5nZXJwcmludCkge1xuICAgICAgICBsZXQgcmV2b2NhdGlvbiA9IHJldm9jYXRpb25zLmZpbmQoZW50cnkgPT4gZW50cnkuZmluZ2VycHJpbnQgPT09IGZpbmdlcnByaW50KSE7XG4gICAgICAgIGNvbnNvbGUubG9nKGBVbmZyZWV6aW5nICR7ZGVzY3JpYmVLZXkocmV2b2NhdGlvbil9YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBBbGxvd2luZyBJUCAke2FkZHJlc3Nlcy5qb2luKFwiLCBcIikgfHwgXCIobm8gYWRkcmVzcyByZWNvcmRlZClcIn1gKTtcbiAgICAgICAgbGV0IGFkZGVkSGVyZSA9IGFkZGVkLmdldChmaW5nZXJwcmludCkgfHwgW107XG4gICAgICAgIGlmIChhZGRlZEhlcmUubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgICBhZGRlZCB0byB0aGF0IGtleSdzIGZyb209IGxpc3QgaW4gYXV0aG9yaXplZF9rZXlzOiAke2FkZGVkSGVyZS5qb2luKFwiLCBcIil9YCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgICB0aGF0IGtleSdzIGZyb209IGxpc3QgYWxyZWFkeSBhbGxvd2VkICR7YWRkcmVzc2VzLmpvaW4oXCIsIFwiKSA/IFwidGhlbVwiIDogXCJldmVyeXRoaW5nXCJ9YCk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgZW50cnkgb2YgcmV2b2NhdGlvbnMuZmlsdGVyKGVudHJ5ID0+IGVudHJ5LmZpbmdlcnByaW50ID09PSBmaW5nZXJwcmludCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgIGAgIGZyb3plbiBieSAke2VudHJ5LnJldm9rZWRCeSB8fCBcIj9cIn0gJHtlbnRyeS5yZXZva2VkQXQgfHwgXCJhdCBhbiB1bnJlY29yZGVkIHRpbWVcIn1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKFwiXCIpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgRXZlcnkgb3RoZXIgYWRkcmVzcyBzdGF5cyBmcm96ZW4sIGFuZCBvbmUgb2YgdGhlc2Uga2V5cyB1c2VkIGZyb20gYW55d2hlcmUgZWxzZWApO1xuICAgIGNvbnNvbGUubG9nKGBpcyBmcm96ZW4gYWdhaW4uYCk7XG5cbiAgICAvLyBTaWduZWQgaGVyZSByYXRoZXIgdGhhbiBsZWZ0IGFzIGEgc3RlcCB0byByZW1lbWJlci4gQW4gdW5yZXZva2Ugbm9ib2R5IHNpZ25lZCBkb2VzIG5vdGhpbmcgYXRcbiAgICAvLyBhbGwsIGFuZCB0aGUgcmVwbyB3b3VsZCBzaXQgdGhlcmUgbG9va2luZyBkb25lIHdoaWxlIGV2ZXJ5IG1hY2hpbmUgaWdub3JlZCBpdC5cbiAgICBhd2FpdCBzaWduUmVwbyh7IHJlcG9QYXRoIH0pO1xuXG4gICAgaWYgKCFwdXNoVG9HaXQpIHtcbiAgICAgICAgY29uc29sZS5sb2coYFxcbkNvbW1pdCBhbmQgcHVzaCBpdCwgYW5kIGVhY2ggbWFjaGluZSB3aWxsIHdhaXQgYW4gaG91ciBhZnRlciBzZWVpbmcgaXQgYmVmb3JlYCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGB0aG9zZSBrZXlzIHdvcmsgYWdhaW46YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBcXGBcXGBcXGBcXG5naXQgYWRkIC1BXFxuZ2l0IGNvbW1pdCAtbSBcIiR7Q09NTUlUX01FU1NBR0V9XCJcXG5naXQgcHVzaFxcblxcYFxcYFxcYGApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBhZGQgLUFgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgYXdhaXQgcnVuUHJvbWlzZShgZ2l0IGNvbW1pdCAtbSBcIiR7Q09NTUlUX01FU1NBR0V9XCJgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgYXdhaXQgcnVuUHJvbWlzZShgZ2l0IHB1c2hgLCB7IGN3ZDogcmVwb1BhdGggfSk7XG4gICAgY29uc29sZS5sb2coYFxcbkNvbW1pdHRlZCBhbmQgcHVzaGVkLiBFYWNoIG1hY2hpbmUgd2FpdHMgYW4gaG91ciBhZnRlciBzZWVpbmcgaXQgYmVmb3JlIHRob3NlYCk7XG4gICAgY29uc29sZS5sb2coYGtleXMgd29yayBhZ2Fpbi5gKTtcbn1cbiJdfQ==
|
|
263
|
-
/* _JS_SOURCE_HASH = "
|
|
281
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5yZXZva2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1bnJldm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwyREFBNkI7QUFDN0IsNENBQW9CO0FBQ3BCLGdEQUF3QjtBQUN4QiwrREFBNEQ7QUFDNUQscURBQStGO0FBQy9GLGlEQUFnRTtBQUNoRSx1Q0FBMEM7QUFDMUMsd0RBQW9EO0FBQ3BELHFEQUFnRDtBQUVoRCw0Q0FBZ0Q7QUFDaEQsbURBQWdFO0FBQ2hFLHlDQUE2QztBQUU3QyxNQUFNLGFBQWEsR0FBRyxXQUFXLENBQUM7QUFDbEMsTUFBTSxlQUFlLEdBQUcsYUFBYSxDQUFDO0FBQ3RDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQztBQUMxQixNQUFNLGNBQWMsR0FBRyxlQUFlLENBQUM7QUFDdkMsTUFBTSxLQUFLLEdBQUcscUNBQXFDLFdBQVc7Ozs7dUJBSXZDLFdBQVc7OzswQkFHUixDQUFDO0FBcUIzQixtRUFBbUU7QUFDbkUsU0FBZ0IsWUFBWSxDQUFDLFVBQXNCOztJQUMvQyxPQUFPLFVBQVUsQ0FBQyxFQUFFLEtBQUksTUFBQSxVQUFVLENBQUMsT0FBTywwQ0FBRSxFQUFFLENBQUEsSUFBSSxFQUFFLENBQUM7QUFDekQsQ0FBQztBQUZELG9DQUVDO0FBRUQsc0ZBQXNGO0FBQ3RGLFNBQWdCLGtCQUFrQixDQUFDLFVBQXNCO0lBQ3JELE9BQU8sVUFBVSxDQUFDLFdBQVcsSUFBSSxVQUFVLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztBQUNoRSxDQUFDO0FBRkQsZ0RBRUM7QUFFRDs7OztrR0FJa0c7QUFDM0YsS0FBSyxVQUFVLHFCQUFxQixDQUFDLE1BQTZCO0lBQ3JFLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxNQUFNLENBQUM7SUFDM0IsSUFBSSxrQkFBa0IsR0FBRyxNQUFNLGtCQUFFLENBQUMsT0FBTyxDQUFDLGNBQUksQ0FBQyxJQUFJLENBQUMsWUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFF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QUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFFN0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4RUFBOEUsQ0FBQyxDQUFDO1FBQzVGLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLGNBQWMscUJBQXFCLENBQUMsQ0FBQztRQUN2RixPQUFPO0lBQ1gsQ0FBQztJQUNELE1BQU0sSUFBQSx1QkFBVSxFQUFDLFlBQVksRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELE1BQU0sSUFBQSx1QkFBVSxFQUFDLGtCQUFrQixjQUFjLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sSUFBQSx1QkFBVSxFQUFDLFVBQVUsRUFBRSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsNEVBQTRFLENBQUMsQ0FBQztBQUM5RixDQUFDO0FBM0dELG9CQTJHQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBydW5Qcm9taXNlIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvcnVuUHJvbWlzZVwiO1xuaW1wb3J0IHsgYWxsb3dBZGRyZXNzZXMsIGtleUZpbmdlcnByaW50LCBub3JtYWxpemVLZXlzLCBzdW1tYXJpemVLZXkgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgZGVyaXZlUmV2b2tlS2V5LCByZXZva2VSZXBvVVJMIH0gZnJvbSBcIi4vcmV2b2tlU291cmNlXCI7XG5pbXBvcnQgeyBmaW5kU291cmNlS2V5IH0gZnJvbSBcIi4vc291cmNlc1wiO1xuaW1wb3J0IHsgc2lnblJlcG8gfSBmcm9tIFwiLi4vc2lnbmVkRmlsZXMvc2lnbkZpbGVzXCI7XG5pbXBvcnQgeyByZWFkUmVwb0tleXMgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgZXhwYW5kSG9tZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BhdGhzXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vaGVscGVycy9zcGF3blwiO1xuaW1wb3J0IHsgZ2V0TWFjaGluZXMsIHNldE1hY2hpbmVzIH0gZnJvbSBcIi4uL21hY2hpbmVzL21hY2hpbmVzXCI7XG5pbXBvcnQgeyByZXNvbHZlS2V5c1JlcG8gfSBmcm9tIFwiLi9rZXlzUmVwb1wiO1xuXG5jb25zdCBVTlJFVk9LRVNfRElSID0gXCJ1bnJldm9rZWRcIjtcbmNvbnN0IFJFVk9DQVRJT05TX0RJUiA9IFwicmV2b2NhdGlvbnNcIjtcbmNvbnN0IEdJVF9LRVlXT1JEID0gXCJnaXRcIjtcbmNvbnN0IENPTU1JVF9NRVNTQUdFID0gXCJ1bnJldm9rZSBrZXlzXCI7XG5jb25zdCBVU0FHRSA9IGBVc2FnZTogeWFybiB1bnJldm9rZSBba2V5cy1yZXBvXSBbJHtHSVRfS0VZV09SRH1dXG5cblJ1biB0aGlzIGluIGEga2V5cyByZXBvLCBvciBuYW1lIG9uZS4gSXQgcmVhZHMgdGhhdCByZXBvJ3MgcmV2b2tlIHJlcG8gYW5kIHdyaXRlcyBvbmUgdW5yZXZva2UgZmlsZVxubmFtaW5nIGV2ZXJ5IHJldm9jYXRpb24gaW4gaXQsIHNvIHRoZSBrZXlzIGFyZSBhY2NlcHRlZCBhZ2FpbiBhcyBlYWNoIG1hY2hpbmUgcGlja3MgaXQgdXAuIEl0IHNpZ25zXG50aGUgcmVzdWx0LCBhbmQgd2l0aCAke0dJVF9LRVlXT1JEfSBpdCBjb21taXRzIGFuZCBwdXNoZXMgaXQgdG9vLlxuXG5LZXlzIHRoYXQgd2VyZSByZXZva2VkIHNob3VsZCBub3JtYWxseSBiZSBkZWxldGVkIGZyb20gdGhlIHJlcG8gaW5zdGVhZC4gVW5yZXZva2luZyBvbmx5IG1hdHRlcnNcbmZvciBhIGtleSB5b3Ugc3RpbGwgd2FudC5gO1xuXG4vKiogT25lIHJldm9jYXRpb24gZXZlbnQuIEVpdGhlciBhbiBzc2gga2V5IHVzZWQgZnJvbSBhbiBhZGRyZXNzIGl0IGlzIG5vdCBhbGxvd2VkIGZyb20sIG9yIGFcbiAgICBtYWNoaW5lIHRoYXQgdGFsa2VkIHRvIHVzIGZyb20gb25lLiBCb3RoIGFyZSB0aGUgc2FtZSBzaGFwZSAtIGFuIGlkZW50aXR5IGFuZCBhbiBhZGRyZXNzIC0gYW5kXG4gICAgYW4gdW5yZXZva2UgdW5kb2VzIGVpdGhlciBieSBhbGxvd2luZyB0aGF0IHNhbWUgcGFpci5cblxuICAgIFdoaWNoIGlzIHdoeSB1bnJldm9raW5nIG5ldmVyIG1ha2VzIGFueXRoaW5nIHVucmV2b2thYmxlOiB1c2VkIGZyb20gc29tZSBvdGhlciBhZGRyZXNzLCBpdCBpc1xuICAgIHJldm9rZWQgYWdhaW4sIHVuZGVyIGEgbmV3IGlkIG5vIGV4aXN0aW5nIHVucmV2b2tlIG5hbWVzLiAqL1xuZXhwb3J0IHR5cGUgUmV2b2NhdGlvbiA9IHtcbiAgICByZXZvY2F0aW9uSWQ6IHN0cmluZztcbiAgICAvLyBFeGFjdGx5IG9uZSBvZiB0aGVzZS4gQSBrZXkgcmV2b2NhdGlvbiBuYW1lcyBhIGZpbmdlcnByaW50LCBhIG1hY2hpbmUgcmV2b2NhdGlvbiBhIG1hY2hpbmVJZC5cbiAgICBmaW5nZXJwcmludD86IHN0cmluZztcbiAgICBtYWNoaW5lSWQ/OiBzdHJpbmc7XG4gICAgaXA/OiBzdHJpbmc7XG4gICAga2V5Pzogc3RyaW5nO1xuICAgIHJldm9rZWRBdD86IHN0cmluZztcbiAgICByZXZva2VkQnk/OiBzdHJpbmc7XG4gICAgcmVhc29uPzogc3RyaW5nO1xuICAgIGF0dGVtcHQ/OiB7IGlwPzogc3RyaW5nOyB1c2VyPzogc3RyaW5nOyByZXF1aXJlZD86IHN0cmluZyB9O1xufTtcblxuLyoqIE9sZGVyIHJldm9jYXRpb24gZmlsZXMgY2FycnkgdGhlIGFkZHJlc3MgdW5kZXIgYXR0ZW1wdCBvbmx5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9jYXRpb25JUChyZXZvY2F0aW9uOiBSZXZvY2F0aW9uKSB7XG4gICAgcmV0dXJuIHJldm9jYXRpb24uaXAgfHwgcmV2b2NhdGlvbi5hdHRlbXB0Py5pcCB8fCBcIlwiO1xufVxuXG4vKiogV2hhdCB0aGUgcmV2b2NhdGlvbiBpcyBhYm91dCwgd2hpY2ggaXMgd2hhdCBhbiB1bnJldm9rZSBoYXMgdG8gbmFtZSB0byB1bmRvIGl0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9jYXRpb25JZGVudGl0eShyZXZvY2F0aW9uOiBSZXZvY2F0aW9uKSB7XG4gICAgcmV0dXJuIHJldm9jYXRpb24uZmluZ2VycHJpbnQgfHwgcmV2b2NhdGlvbi5tYWNoaW5lSWQgfHwgXCJcIjtcbn1cblxuLyoqIEV2ZXJ5IHJldm9jYXRpb24gdGhlIHJldm9rZSByZXBvIGxpc3RzLiBDbG9uZWQgcmVhZCBvbmx5IGludG8gYSB0ZW1wIGRpcmVjdG9yeS5cblxuICAgIEEgcGVyc29uIHJ1bm5pbmcgdGhpcyBoYXMgdGhlaXIgb3duIGFjY2VzcyB0byB0aGUgcmVwbywgc28gdGhlaXIgY3JlZGVudGlhbHMgYXJlIHdoYXQgaXMgdXNlZC5cbiAgICBPbiBhIG1hY2hpbmUgdGhhdCBpcyBhbHJlYWR5IGEgcG9ydHNlY3VyZSBob3N0IHRoZXJlIG1heSBiZSBubyBzdWNoIGNyZWRlbnRpYWxzLCBidXQgdGhlIHNvdXJjZVxuICAgIGRlcGxveSBrZXkgaXMgcmlnaHQgdGhlcmUsIGFuZCB0aGUga2V5IGRlcml2ZWQgZnJvbSBpdCBpcyBvbmUgdGhhdCByZXBvIGRlZmluaXRlbHkgYWNjZXB0cy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkUmVtb3RlUmV2b2NhdGlvbnMoY29uZmlnOiB7IHNvdXJjZVVSTDogc3RyaW5nIH0pIHtcbiAgICBsZXQgeyBzb3VyY2VVUkwgfSA9IGNvbmZpZztcbiAgICBsZXQgdGVtcG9yYXJ5RGlyZWN0b3J5ID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksIFwidW5yZXZva2UtXCIpKTtcbiAgICBsZXQgcmVwb1BhdGggPSBwYXRoLmpvaW4odGVtcG9yYXJ5RGlyZWN0b3J5LCBcInJlcG9cIik7XG4gICAgbGV0IGNsb25lQXJncyA9IFtcImNsb25lXCIsIFwiLS1kZXB0aFwiLCBcIjFcIiwgcmV2b2tlUmVwb1VSTChzb3VyY2VVUkwpLCByZXBvUGF0aF07XG4gICAgbGV0IHNvdXJjZUtleSA9IGF3YWl0IGZpbmRTb3VyY2VLZXkoc291cmNlVVJMKTtcbiAgICBpZiAoc291cmNlS2V5KSB7XG4gICAgICAgIGxldCBkZXJpdmVkID0gZGVyaXZlUmV2b2tlS2V5KGF3YWl0IGZzLnJlYWRGaWxlKHNvdXJjZUtleSwgXCJ1dGY4XCIpKTtcbiAgICAgICAgbGV0IGRlcml2ZWRLZXlQYXRoID0gcGF0aC5qb2luKHRlbXBvcmFyeURpcmVjdG9yeSwgXCJrZXlcIik7XG4gICAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShkZXJpdmVkS2V5UGF0aCwgZGVyaXZlZC5wcml2YXRlS2V5RmlsZSwgeyBtb2RlOiAwbzYwMCB9KTtcbiAgICAgICAgbGV0IHNzaENvbW1hbmQgPSBgc3NoIC1pICR7ZGVyaXZlZEtleVBhdGh9IC1vIElkZW50aXRpZXNPbmx5PXllcyAtbyBCYXRjaE1vZGU9eWVzIC1vIFN0cmljdEhvc3RLZXlDaGVja2luZz1hY2NlcHQtbmV3YDtcbiAgICAgICAgY2xvbmVBcmdzID0gW1wiLWNcIiwgYGNvcmUuc3NoQ29tbWFuZD0ke3NzaENvbW1hbmR9YCwgLi4uY2xvbmVBcmdzXTtcbiAgICB9XG4gICAgbGV0IGNsb25lID0gYXdhaXQgc3Bhd25Qcm9taXNlKHsgY29tbWFuZDogXCJnaXRcIiwgYXJnczogY2xvbmVBcmdzIH0pO1xuICAgIGlmIChjbG9uZS5zdGF0dXMgIT09IDApIHtcbiAgICAgICAgYXdhaXQgZnMucm0odGVtcG9yYXJ5RGlyZWN0b3J5LCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBFeHBlY3RlZCB0byBiZSBhYmxlIHRvIHJlYWQgJHtyZXZva2VSZXBvVVJMKHNvdXJjZVVSTCl9LlxcbmBcbiAgICAgICAgICAgICsgYCR7KGNsb25lLnN0ZG91dCArIGNsb25lLnN0ZGVycikudHJpbSgpfWBcbiAgICAgICAgKTtcbiAgICB9XG4gICAgbGV0IHJldm9jYXRpb25zOiBSZXZvY2F0aW9uW10gPSBbXTtcbiAgICBsZXQgZGlyZWN0b3J5ID0gcGF0aC5qb2luKHJlcG9QYXRoLCBSRVZPQ0FUSU9OU19ESVIpO1xuICAgIHRyeSB7XG4gICAgICAgIGZvciAobGV0IG5hbWUgb2YgKGF3YWl0IGZzLnJlYWRkaXIoZGlyZWN0b3J5KSkuc29ydCgpKSB7XG4gICAgICAgICAgICBpZiAobmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSB7XG4gICAgICAgICAgICAgICAgcmV2b2NhdGlvbnMucHVzaChKU09OLnBhcnNlKGF3YWl0IGZzLnJlYWRGaWxlKHBhdGguam9pbihkaXJlY3RvcnksIG5hbWUpLCBcInV0ZjhcIikpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gTm8gcmV2b2NhdGlvbnMgZGlyZWN0b3J5IGF0IGFsbCBqdXN0IG1lYW5zIG5vdGhpbmcgaGFzIGV2ZXIgYmVlbiByZXZva2VkLlxuICAgIH1cbiAgICBhd2FpdCBmcy5ybSh0ZW1wb3JhcnlEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICByZXR1cm4gcmV2b2NhdGlvbnM7XG59XG5cbi8qKiBXaGljaCBrZXlzIGluIGEgcmVwbyBhcmUgcmV2b2tlZC4gV2hhdCBzaWduZmlsZXMgYW5kIHNlY3VyZXNzaCByZWZ1c2Ugb3Zlci4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXZva2VkS2V5c0luUmVwbyhjb25maWc6IHsgcmVwb1BhdGg6IHN0cmluZzsgc291cmNlVVJMOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHJlcG9QYXRoLCBzb3VyY2VVUkwgfSA9IGNvbmZpZztcbiAgICBsZXQgcmV2b2NhdGlvbnMgPSBhd2FpdCByZWFkUmVtb3RlUmV2b2NhdGlvbnMoeyBzb3VyY2VVUkwgfSk7XG4gICAgbGV0IHJldm9rZWRGaW5nZXJwcmludHMgPSBuZXcgU2V0KHJldm9jYXRpb25zLm1hcChyZXZvY2F0aW9uID0+IHJldm9jYXRpb24uZmluZ2VycHJpbnQpKTtcbiAgICBsZXQgdW5yZXZva2VkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgdHJ5IHtcbiAgICAgICAgbGV0IGRpcmVjdG9yeSA9IHBhdGguam9pbihyZXBvUGF0aCwgVU5SRVZPS0VTX0RJUik7XG4gICAgICAgIGZvciAobGV0IG5hbWUgb2YgYXdhaXQgZnMucmVhZGRpcihkaXJlY3RvcnkpKSB7XG4gICAgICAgICAgICBpZiAoIW5hbWUuZW5kc1dpdGgoXCIuanNvblwiKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHBhcnNlZCA9IEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgbmFtZSksIFwidXRmOFwiKSk7XG4gICAgICAgICAgICBmb3IgKGxldCBhbGxvd2VkIG9mIHBhcnNlZC5hbGxvd2VkIHx8IFtdKSB7XG4gICAgICAgICAgICAgICAgdW5yZXZva2VkLmFkZChgJHthbGxvd2VkLmZpbmdlcnByaW50IHx8IGFsbG93ZWQubWFjaGluZUlkfSAke2FsbG93ZWQuaXB9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBOYW1lZCBpZHMsIGZvciB0aGUgdW5yZXZva2VzIHdyaXR0ZW4gYmVmb3JlIHRoaXMgd2FzIGFib3V0IHBhaXJzLlxuICAgICAgICAgICAgZm9yIChsZXQgcmV2b2NhdGlvbklkIG9mIHBhcnNlZC5yZXZvY2F0aW9uSWRzIHx8IFtdKSB7XG4gICAgICAgICAgICAgICAgdW5yZXZva2VkLmFkZChyZXZvY2F0aW9uSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBOb3RoaW5nIGhhcyBiZWVuIHVucmV2b2tlZC5cbiAgICB9XG4gICAgbGV0IHN0aWxsUmV2b2tlZCA9IHJldm9jYXRpb25zLmZpbHRlcihyZXZvY2F0aW9uID0+ICF1bnJldm9rZWQuaGFzKHJldm9jYXRpb24ucmV2b2NhdGlvbklkKVxuICAgICAgICAmJiAhdW5yZXZva2VkLmhhcyhgJHtyZXZvY2F0aW9uLmZpbmdlcnByaW50fSAke3Jldm9jYXRpb25JUChyZXZvY2F0aW9uKX1gKSk7XG4gICAgbGV0IGtleXMgPSBub3JtYWxpemVLZXlzKGF3YWl0IGZzLnJlYWRGaWxlKHBhdGguam9pbihyZXBvUGF0aCwgXCJhdXRob3JpemVkX2tleXNcIiksIFwidXRmOFwiKS5jYXRjaCgoKSA9PiBcIlwiKSk7XG4gICAgcmV0dXJuIHN0aWxsUmV2b2tlZFxuICAgICAgICAuZmlsdGVyKHJldm9jYXRpb24gPT4ga2V5cy5zb21lKGtleSA9PiBrZXlGaW5nZXJwcmludChrZXkpID09PSByZXZvY2F0aW9uLmZpbmdlcnByaW50KSlcbiAgICAgICAgLm1hcChyZXZvY2F0aW9uID0+ICh7IHJldm9jYXRpb24sIGtleToga2V5cy5maW5kKGtleSA9PiBrZXlGaW5nZXJwcmludChrZXkpID09PSByZXZvY2F0aW9uLmZpbmdlcnByaW50KSB8fCBcIlwiIH0pKTtcbn1cblxuLyoqIFdyaXRlcyB0aGUgYWRkcmVzc2VzIGludG8gdGhlIGZyb209IGxpc3Qgb2YgZWFjaCBrZXkgaW4gdGhlIHJlcG8ncyBhdXRob3JpemVkX2tleXMsIGFuZCBzYXlzXG4gICAgd2hpY2ggb25lcyB3ZXJlIGFjdHVhbGx5IG5ldy4gT25seSB0aGUgbGluZXMgYmVpbmcgY2hhbmdlZCBhcmUgdG91Y2hlZCwgc28gY29tbWVudHMsIG9yZGVyaW5nXG4gICAgYW5kIGFueSBrZXkgbm90IGludm9sdmVkIGNvbWUgb3V0IG9mIHRoaXMgYnl0ZSBmb3IgYnl0ZSB0aGUgc2FtZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFsbG93QWRkcmVzc2VzSW5SZXBvKGNvbmZpZzoge1xuICAgIHJlcG9QYXRoOiBzdHJpbmc7XG4gICAgYWRkcmVzc2VzQnlGaW5nZXJwcmludDogTWFwPHN0cmluZywgc3RyaW5nW10+O1xufSkge1xuICAgIGxldCB7IHJlcG9QYXRoLCBhZGRyZXNzZXNCeUZpbmdlcnByaW50IH0gPSBjb25maWc7XG4gICAgbGV0IGFkZGVkID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZ1tdPigpO1xuICAgIGxldCBmaWxlUGF0aCA9IHBhdGguam9pbihyZXBvUGF0aCwgXCJhdXRob3JpemVkX2tleXNcIik7XG4gICAgbGV0IGNvbnRlbnRzO1xuICAgIHRyeSB7XG4gICAgICAgIGNvbnRlbnRzID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgsIFwidXRmOFwiKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIEEgcmVwbyBob2xkaW5nIGl0cyBrZXlzIGFzIHNlcGFyYXRlIC5wdWIgZmlsZXMuIE5vdGhpbmcgdG8gZWRpdCBpbiBvbmUgcGxhY2UsIHNvIHRoZVxuICAgICAgICAvLyBjYWxsZXIncyBsaXN0aW5nIGlzIGFsbCB3aG9ldmVyIHJhbiB0aGlzIGdldHMuXG4gICAgICAgIGNvbnNvbGUubG9nKGBObyBhdXRob3JpemVkX2tleXMgaW4gJHtyZXBvUGF0aH0sIHNvIHRoZSBhZGRyZXNzZXMgd2VyZSBub3QgYWRkZWQgdG8gYW55IGtleS5gKTtcbiAgICAgICAgcmV0dXJuIGFkZGVkO1xuICAgIH1cbiAgICBsZXQgbGluZXMgPSBjb250ZW50cy5zcGxpdChcIlxcblwiKTtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbGluZXMubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIGxldCBmaW5nZXJwcmludCA9IGtleUZpbmdlcnByaW50KGxpbmVzW2luZGV4XSk7XG4gICAgICAgIGxldCBhZGRyZXNzZXMgPSBmaW5nZXJwcmludCAmJiBhZGRyZXNzZXNCeUZpbmdlcnByaW50LmdldChmaW5nZXJwcmludCk7XG4gICAgICAgIGlmICghYWRkcmVzc2VzIHx8ICFhZGRyZXNzZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmVzdWx0ID0gYWxsb3dBZGRyZXNzZXMobGluZXNbaW5kZXhdLCBhZGRyZXNzZXMpO1xuICAgICAgICBsaW5lc1tpbmRleF0gPSByZXN1bHQua2V5TGluZTtcbiAgICAgICAgYWRkZWQuc2V0KGZpbmdlcnByaW50LCBbLi4uKGFkZGVkLmdldChmaW5nZXJwcmludCkgfHwgW10pLCAuLi5yZXN1bHQuYWRkZWRdKTtcbiAgICB9XG4gICAgaWYgKFsuLi5hZGRlZC52YWx1ZXMoKV0uc29tZShsaXN0ID0+IGxpc3QubGVuZ3RoKSkge1xuICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZVBhdGgsIGxpbmVzLmpvaW4oXCJcXG5cIikpO1xuICAgIH1cbiAgICByZXR1cm4gYWRkZWQ7XG59XG5cbi8qKiBQdXRzIGVhY2ggbWFjaGluZSdzIGFkZHJlc3NlcyBiYWNrIGludG8gaXRzIG93biBmaWxlLCB3aGljaCBpcyB0aGUgbWFjaGluZSBlcXVpdmFsZW50IG9mIGFkZGluZ1xuICAgIGFuIGFkZHJlc3MgdG8gYSBrZXkncyBmcm9tPSBsaXN0OiB3aXRob3V0IGl0IHRoZSBtYWNoaW5lIGlzIGFsbG93ZWQgYWdhaW4gaW4gcHJpbmNpcGxlIGFuZFxuICAgIHN0aWxsIHJlamVjdGVkIG9uIHNpZ2h0LCB3aGljaCByZXZva2VzIGl0IG9uY2UgbW9yZS4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFsbG93QWRkcmVzc2VzRm9yTWFjaGluZXMoY29uZmlnOiB7IHJlcG9QYXRoOiBzdHJpbmc7IHJldm9jYXRpb25zOiBSZXZvY2F0aW9uW10gfSkge1xuICAgIGxldCB7IHJlcG9QYXRoLCByZXZvY2F0aW9ucyB9ID0gY29uZmlnO1xuICAgIGxldCBhZGRlZCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICAvLyBSZWFkIHRoZSB3aG9sZSBsaXN0LCBjaGFuZ2Ugd2hhdCB0aGVzZSByZXZvY2F0aW9ucyBhcmUgYWJvdXQsIHdyaXRlIGl0IGJhY2suIFNldHRpbmcgaXMgYnlcbiAgICAvLyB0aGUgd2hvbGUgc2V0LCBzbyB3cml0aW5nIG9uZSBtYWNoaW5lIGF0IGEgdGltZSB3b3VsZCBkZWxldGUgZXZlcnkgb3RoZXIgbWFjaGluZS5cbiAgICBsZXQgbWFjaGluZXMgPSBhd2FpdCBnZXRNYWNoaW5lcyhyZXBvUGF0aCk7XG4gICAgZm9yIChsZXQgcmV2b2NhdGlvbiBvZiByZXZvY2F0aW9ucykge1xuICAgICAgICBsZXQgbWFjaGluZUlkID0gcmV2b2NhdGlvbi5tYWNoaW5lSWQ7XG4gICAgICAgIGxldCBpcCA9IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKTtcbiAgICAgICAgaWYgKCFtYWNoaW5lSWQgfHwgIWlwKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZXhpc3RpbmcgPSBtYWNoaW5lcy5maW5kKG1hY2hpbmUgPT4gbWFjaGluZS5tYWNoaW5lSWQgPT09IG1hY2hpbmVJZCk7XG4gICAgICAgIGlmICghZXhpc3RpbmcpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZWQgZnJvbSB0aGUgcmVwbyBzaW5jZSBpdCB3YXMgcmV2b2tlZCwgc28gdGhlcmUgaXMgbm90aGluZyB0byBhbGxvdy4gRGVsZXRpbmcgYVxuICAgICAgICAgICAgLy8gbWFjaGluZSBpcyB0aGUgc3Ryb25nZXIgc3RhdGVtZW50IGFuZCBpdCBzdGFuZHMuXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgbWFjaGluZXMvJHttYWNoaW5lSWR9Lmpzb24gaXMgbm90IGluIHRoaXMgcmVwbywgc28gJHtpcH0gd2FzIG5vdCBhZGRlZCB0byBpdGApO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4aXN0aW5nLmlwcy5pbmNsdWRlcyhpcCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGV4aXN0aW5nLmlwcyA9IFsuLi5leGlzdGluZy5pcHMsIGlwXTtcbiAgICAgICAgYWRkZWQuc2V0KG1hY2hpbmVJZCwgWy4uLihhZGRlZC5nZXQobWFjaGluZUlkKSB8fCBbXSksIGlwXSk7XG4gICAgfVxuICAgIGlmIChhZGRlZC5zaXplKSB7XG4gICAgICAgIGF3YWl0IHNldE1hY2hpbmVzKHsgcmVwb1BhdGgsIG1hY2hpbmVzIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYWRkZWQ7XG59XG5cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1haW4oKSB7XG4gICAgbGV0IGFyZ3YgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMik7XG4gICAgbGV0IHB1c2hUb0dpdCA9IGFyZ3YuaW5jbHVkZXMoR0lUX0tFWVdPUkQpO1xuICAgIGxldCBwb3NpdGlvbmFsID0gYXJndi5maWx0ZXIoYXJnID0+IGFyZyAhPT0gR0lUX0tFWVdPUkQpO1xuICAgIGlmIChwb3NpdGlvbmFsLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhdCBtb3N0IGEga2V5cyByZXBvLCB3YXMgJHtwb3NpdGlvbmFsLmxlbmd0aH0gYXJndW1lbnQocylcXG4ke1VTQUdFfWApO1xuICAgIH1cbiAgICBsZXQgeyByZXBvUGF0aCwgc291cmNlVVJMOiBvcmlnaW5VUkwgfSA9IGF3YWl0IHJlc29sdmVLZXlzUmVwbyhwb3NpdGlvbmFsWzBdKTtcblxuICAgIGxldCByZXZvY2F0aW9ucyA9IGF3YWl0IHJlYWRSZW1vdGVSZXZvY2F0aW9ucyh7IHNvdXJjZVVSTDogb3JpZ2luVVJMIH0pO1xuICAgIGlmICghcmV2b2NhdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAke3Jldm9rZVJlcG9VUkwob3JpZ2luVVJMKX0gbGlzdHMgbm8gcmV2b2NhdGlvbnMsIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG8gdW5kby5gKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBkaXJlY3RvcnkgPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFVOUkVWT0tFU19ESVIpO1xuICAgIGF3YWl0IGZzLm1rZGlyKGRpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgbGV0IHN0YW1wID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpLnJlcGxhY2UoL1s6Ll0vZywgXCItXCIpO1xuICAgIGxldCB1bnJldm9rZUlkID0gYCR7c3RhbXB9LXVucmV2b2tlYDtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgYCR7dW5yZXZva2VJZH0uanNvbmApLCBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHVucmV2b2tlSWQsXG4gICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAvLyBXaGF0IHRoaXMgZmlsZSBzYXlzOiBlYWNoIG9mIHRoZXNlIGtleXMgaXMgYWxsb3dlZCBmcm9tIHRoaXMgYWRkcmVzcy4gUGFpcnMsIG5vdCBrZXlzLFxuICAgICAgICAvLyBhbmQgbm90IGEgYmxhbmtldCBcImFsbG93IGV2ZXJ5dGhpbmcgYWdhaW5cIiAtIGEga2V5IGZvcmdpdmVuIGhlcmUgZm9yIG9uZSBhZGRyZXNzIGlzXG4gICAgICAgIC8vIHN0aWxsIHJldm9rZWQgdGhlIG1vbWVudCBpdCBpcyB1c2VkIGZyb20gYW5vdGhlci5cbiAgICAgICAgYWxsb3dlZDogcmV2b2NhdGlvbnMubWFwKHJldm9jYXRpb24gPT4gKHtcbiAgICAgICAgICAgIGZpbmdlcnByaW50OiByZXZvY2F0aW9uLmZpbmdlcnByaW50LFxuICAgICAgICAgICAgbWFjaGluZUlkOiByZXZvY2F0aW9uLm1hY2hpbmVJZCxcbiAgICAgICAgICAgIGlwOiByZXZvY2F0aW9uSVAocmV2b2NhdGlvbiksXG4gICAgICAgIH0pKSxcbiAgICAgICAgcmV2b2NhdGlvbnM6IHJldm9jYXRpb25zLm1hcChyZXZvY2F0aW9uID0+ICh7XG4gICAgICAgICAgICByZXZvY2F0aW9uSWQ6IHJldm9jYXRpb24ucmV2b2NhdGlvbklkLFxuICAgICAgICAgICAgZmluZ2VycHJpbnQ6IHJldm9jYXRpb24uZmluZ2VycHJpbnQsXG4gICAgICAgICAgICBtYWNoaW5lSWQ6IHJldm9jYXRpb24ubWFjaGluZUlkLFxuICAgICAgICAgICAgaXA6IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKSxcbiAgICAgICAgICAgIHJldm9rZWRBdDogcmV2b2NhdGlvbi5yZXZva2VkQXQsXG4gICAgICAgICAgICByZXZva2VkQnk6IHJldm9jYXRpb24ucmV2b2tlZEJ5LFxuICAgICAgICAgICAgYXR0ZW1wdDogcmV2b2NhdGlvbi5hdHRlbXB0LFxuICAgICAgICB9KSksXG4gICAgfSwgdW5kZWZpbmVkLCA0KSArIFwiXFxuXCIpO1xuXG4gICAgLy8gTmFtZWQgdGhlIHdheSB0aGUgbm90aWZpY2F0aW9ucyBuYW1lIHRoZW0uIEEgZmluZ2VycHJpbnQgaXMgbm90IGluIGF1dGhvcml6ZWRfa2V5cyBhbmRcbiAgICAvLyBjYW5ub3QgYmUgd29ya2VkIG91dCBieSBleWUsIHNvIG9uIGl0cyBvd24gaXQgdGVsbHMgd2hvZXZlciBpcyByZWFkaW5nIHRoaXMgbm90aGluZyBhYm91dFxuICAgIC8vIHdoaWNoIG9mIHRoZWlyIGtleXMgaXMgYmVpbmcgdGFsa2VkIGFib3V0LlxuICAgIGxldCBrZXlzQnlGaW5nZXJwcmludCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgZm9yIChsZXQga2V5IG9mIGF3YWl0IHJlYWRSZXBvS2V5cyhyZXBvUGF0aCkuY2F0Y2goKCkgPT4gW10gYXMgc3RyaW5nW10pKSB7XG4gICAgICAgIGtleXNCeUZpbmdlcnByaW50LnNldChrZXlGaW5nZXJwcmludChrZXkpLCBrZXkpO1xuICAgIH1cbiAgICBsZXQgZGVzY3JpYmVLZXkgPSAocmV2b2NhdGlvbjogUmV2b2NhdGlvbikgPT4ge1xuICAgICAgICBsZXQga2V5ID0ga2V5c0J5RmluZ2VycHJpbnQuZ2V0KHJldm9jYXRpb24uZmluZ2VycHJpbnQgfHwgXCJcIikgfHwgcmV2b2NhdGlvbi5rZXkgfHwgXCJcIjtcbiAgICAgICAgcmV0dXJuIGtleSAmJiBzdW1tYXJpemVLZXkoa2V5KSB8fCBgYSBrZXkgbm8gbG9uZ2VyIGluIHRoaXMgcmVwbyAoJHtyZXZvY2F0aW9uLmZpbmdlcnByaW50fSlgO1xuICAgIH07XG5cbiAgICBsZXQgYWRkcmVzc2VzQnlJZGVudGl0eSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICBmb3IgKGxldCByZXZvY2F0aW9uIG9mIHJldm9jYXRpb25zKSB7XG4gICAgICAgIGxldCBpcCA9IHJldm9jYXRpb25JUChyZXZvY2F0aW9uKTtcbiAgICAgICAgbGV0IGlkZW50aXR5ID0gcmV2b2NhdGlvbklkZW50aXR5KHJldm9jYXRpb24pO1xuICAgICAgICBsZXQgZXhpc3RpbmcgPSBhZGRyZXNzZXNCeUlkZW50aXR5LmdldChpZGVudGl0eSkgfHwgW107XG4gICAgICAgIGlmIChpcCAmJiAhZXhpc3RpbmcuaW5jbHVkZXMoaXApKSB7XG4gICAgICAgICAgICBleGlzdGluZy5wdXNoKGlwKTtcbiAgICAgICAgfVxuICAgICAgICBhZGRyZXNzZXNCeUlkZW50aXR5LnNldChpZGVudGl0eSwgZXhpc3RpbmcpO1xuICAgIH1cblxuICAgIC8vIENhbmNlbGxpbmcgdGhlIHJldm9jYXRpb24gb24gaXRzIG93biB3b3VsZCBsZWF2ZSBzc2hkIHJlZnVzaW5nIHRoYXQgYWRkcmVzcywgYW5kIHRoZSBtYWNoaW5lc1xuICAgIC8vIHJldm9raW5nIGFsbCBvdmVyIGFnYWluLCBzbyB0aGUgYWRkcmVzc2VzIGdvIGludG8gdGhlIGtleSdzIGZyb209IGxpc3QgYW5kIGludG8gdGhlIG1hY2hpbmUnc1xuICAgIC8vIG93biBmaWxlIGhlcmUuIFdlIGFyZSBpbiB0aGUgcmVwbyB0aGF0IG93bnMgYm90aCwgc28gdGhlcmUgaXMgbm90aGluZyB0byBoYW5kIGJhY2sgdG8gd2hvZXZlclxuICAgIC8vIHJhbiB0aGlzLlxuICAgIGxldCBhZGRlZCA9IGF3YWl0IGFsbG93QWRkcmVzc2VzSW5SZXBvKHsgcmVwb1BhdGgsIGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQ6IGFkZHJlc3Nlc0J5SWRlbnRpdHkgfSk7XG4gICAgbGV0IGFkZGVkRm9yTWFjaGluZXMgPSBhd2FpdCBhbGxvd0FkZHJlc3Nlc0Zvck1hY2hpbmVzKHsgcmVwb1BhdGgsIHJldm9jYXRpb25zIH0pO1xuXG4gICAgY29uc29sZS5sb2coXCJcIik7XG4gICAgZm9yIChsZXQgW2lkZW50aXR5LCBhZGRyZXNzZXNdIG9mIGFkZHJlc3Nlc0J5SWRlbnRpdHkpIHtcbiAgICAgICAgbGV0IGVudHJpZXMgPSByZXZvY2F0aW9ucy5maWx0ZXIoZW50cnkgPT4gcmV2b2NhdGlvbklkZW50aXR5KGVudHJ5KSA9PT0gaWRlbnRpdHkpO1xuICAgICAgICBsZXQgbWFjaGluZUlkID0gZW50cmllc1swXS5tYWNoaW5lSWQ7XG4gICAgICAgIGNvbnNvbGUubG9nKGBVbmZyZWV6aW5nICR7bWFjaGluZUlkICYmIGBtYWNoaW5lICR7bWFjaGluZUlkfWAgfHwgZGVzY3JpYmVLZXkoZW50cmllc1swXSl9YCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBBbGxvd2luZyBJUCAke2FkZHJlc3Nlcy5qb2luKFwiLCBcIikgfHwgXCIobm8gYWRkcmVzcyByZWNvcmRlZClcIn1gKTtcbiAgICAgICAgbGV0IGFkZGVkSGVyZSA9IG1hY2hpbmVJZCAmJiBhZGRlZEZvck1hY2hpbmVzLmdldChtYWNoaW5lSWQpIHx8IGFkZGVkLmdldChpZGVudGl0eSkgfHwgW107XG4gICAgICAgIGlmIChhZGRlZEhlcmUubGVuZ3RoKSB7XG4gICAgICAgICAgICBsZXQgd2hlcmUgPSBtYWNoaW5lSWQgJiYgYG1hY2hpbmVzLyR7bWFjaGluZUlkfS5qc29uYCB8fCBgdGhhdCBrZXkncyBmcm9tPSBsaXN0IGluIGF1dGhvcml6ZWRfa2V5c2A7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgICBhZGRlZCB0byAke3doZXJlfTogJHthZGRlZEhlcmUuam9pbihcIiwgXCIpfWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYCAgYWxyZWFkeSBhbGxvd2VkIGZyb20gJHthZGRyZXNzZXMuam9pbihcIiwgXCIpIHx8IFwiZXZlcnl3aGVyZVwifWApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgIGAgIGZyb3plbiBieSAke2VudHJ5LnJldm9rZWRCeSB8fCBcIj9cIn0gJHtlbnRyeS5yZXZva2VkQXQgfHwgXCJhdCBhbiB1bnJlY29yZGVkIHRpbWVcIn1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKFwiXCIpO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgRXZlcnkgb3RoZXIgYWRkcmVzcyBzdGF5cyBmcm96ZW4sIGFuZCBhbnkgb2YgdGhlc2UgdXNlZCBmcm9tIGFueXdoZXJlIGVsc2UgaXNgKTtcbiAgICBjb25zb2xlLmxvZyhgZnJvemVuIGFnYWluLmApO1xuXG4gICAgLy8gU2lnbmVkIGhlcmUgcmF0aGVyIHRoYW4gbGVmdCBhcyBhIHN0ZXAgdG8gcmVtZW1iZXIuIEFuIHVucmV2b2tlIG5vYm9keSBzaWduZWQgZG9lcyBub3RoaW5nIGF0XG4gICAgLy8gYWxsLCBhbmQgdGhlIHJlcG8gd291bGQgc2l0IHRoZXJlIGxvb2tpbmcgZG9uZSB3aGlsZSBldmVyeSBtYWNoaW5lIGlnbm9yZWQgaXQuXG4gICAgYXdhaXQgc2lnblJlcG8oeyByZXBvUGF0aCB9KTtcblxuICAgIGlmICghcHVzaFRvR2l0KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBcXG5Db21taXQgYW5kIHB1c2ggaXQsIGFuZCB0aG9zZSBrZXlzIHdvcmsgYWdhaW4gYXMgZWFjaCBtYWNoaW5lIHBpY2tzIGl0IHVwOmApO1xuICAgICAgICBjb25zb2xlLmxvZyhgXFxgXFxgXFxgXFxuZ2l0IGFkZCAtQVxcbmdpdCBjb21taXQgLW0gXCIke0NPTU1JVF9NRVNTQUdFfVwiXFxuZ2l0IHB1c2hcXG5cXGBcXGBcXGBgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgYWRkIC1BYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBjb21taXQgLW0gXCIke0NPTU1JVF9NRVNTQUdFfVwiYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGF3YWl0IHJ1blByb21pc2UoYGdpdCBwdXNoYCwgeyBjd2Q6IHJlcG9QYXRoIH0pO1xuICAgIGNvbnNvbGUubG9nKGBcXG5Db21taXR0ZWQgYW5kIHB1c2hlZC4gVGhvc2Uga2V5cyB3b3JrIGFnYWluIGFzIGVhY2ggbWFjaGluZSBwaWNrcyBpdCB1cC5gKTtcbn1cbiJdfQ==
|
|
282
|
+
/* _JS_SOURCE_HASH = "b373f6ddbf1cf2e062379c9bad20cb62583833a5a820a5b5e0b2db8a6f27c602"; */
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { CONFIG_PATH } from "./daemon/paths";
|
|
5
|
+
import { readRepoKeys } from "./authorizedKeys";
|
|
6
|
+
import { sourceRepoPath } from "./sources";
|
|
7
|
+
import { expandHome } from "../helpers/paths";
|
|
8
|
+
import { spawnPromise } from "../helpers/spawn";
|
|
9
|
+
|
|
10
|
+
// The one place that answers "which keys repo". Everything that reads or writes one comes here:
|
|
11
|
+
// signing, unrevoking, machine trust, and adding a machine. They were each working it out their
|
|
12
|
+
// own way, which is how signfiles ended up signing whatever repo you happened to be standing in.
|
|
13
|
+
//
|
|
14
|
+
// Where a Windows machine is expected to keep it, relative to the working directory. There is no
|
|
15
|
+
// daemon there and no /etc, so a sibling checkout is the convention.
|
|
16
|
+
const WINDOWS_REPO_PATH = "../authorized_keys";
|
|
17
|
+
|
|
18
|
+
async function pathExists(filePath: string) {
|
|
19
|
+
try {
|
|
20
|
+
await fs.access(filePath);
|
|
21
|
+
return true;
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** A git checkout that actually holds keys. Both halves matter: a repo with no authorized_keys is
|
|
28
|
+
some other repo, and a directory that is not a checkout has nothing to push. */
|
|
29
|
+
async function isKeysRepo(repoPath: string) {
|
|
30
|
+
if (!await pathExists(path.join(repoPath, ".git"))) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await readRepoKeys(repoPath);
|
|
35
|
+
return true;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The repo the working directory is inside, or "" when it is not inside one. */
|
|
42
|
+
async function repoOfCurrentDirectory() {
|
|
43
|
+
// Read for its value, so stdout has to be on its own. runPromise joins it with stderr, and a
|
|
44
|
+
// git warning glued to the front of this becomes a directory that does not exist.
|
|
45
|
+
let topLevel = await spawnPromise({ command: "git", args: ["rev-parse", "--show-toplevel"] });
|
|
46
|
+
return topLevel.status === 0 && topLevel.stdout.trim() || "";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Where this machine's own keys repo is, when the working directory is not one.
|
|
50
|
+
|
|
51
|
+
On a host that is the checkout the daemon keeps up to date. On Windows there is no daemon, so
|
|
52
|
+
it is the sibling directory. */
|
|
53
|
+
async function configuredRepo() {
|
|
54
|
+
if (os.platform() === "win32") {
|
|
55
|
+
return path.resolve(WINDOWS_REPO_PATH);
|
|
56
|
+
}
|
|
57
|
+
let config = await fs.readFile(CONFIG_PATH, "utf8").catch(() => "");
|
|
58
|
+
let sourceURL = config && (JSON.parse(config).repoSources || [])[0] || "";
|
|
59
|
+
return sourceURL && sourceRepoPath(sourceURL) || "";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function originOf(repoPath: string) {
|
|
63
|
+
let origin = await spawnPromise({ command: "git", args: ["remote", "get-url", "origin"], cwd: repoPath });
|
|
64
|
+
let url = origin.stdout.trim();
|
|
65
|
+
if (origin.status !== 0 || !url) {
|
|
66
|
+
throw new Error(`Expected ${repoPath} to have an origin remote, it has none`);
|
|
67
|
+
}
|
|
68
|
+
return url;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The keys repo to act on.
|
|
72
|
+
|
|
73
|
+
A named one if there is one, otherwise the repo the command is being run in if that repo holds
|
|
74
|
+
keys, otherwise this machine's own. Running in some other repo therefore reaches the keys repo
|
|
75
|
+
rather than acting on whatever happened to be around - signing sliftutils because that is where
|
|
76
|
+
the terminal was is never what anybody meant. */
|
|
77
|
+
export async function resolveKeysRepo(named?: string): Promise<{ repoPath: string; sourceURL: string }> {
|
|
78
|
+
let tried: string[] = [];
|
|
79
|
+
|
|
80
|
+
let candidates: string[] = [];
|
|
81
|
+
if (named) {
|
|
82
|
+
candidates.push(expandHome(named));
|
|
83
|
+
} else {
|
|
84
|
+
let current = await repoOfCurrentDirectory();
|
|
85
|
+
if (current) {
|
|
86
|
+
candidates.push(current);
|
|
87
|
+
}
|
|
88
|
+
let configured = await configuredRepo();
|
|
89
|
+
if (configured && configured !== current) {
|
|
90
|
+
candidates.push(configured);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (let repoPath of candidates) {
|
|
95
|
+
if (await isKeysRepo(repoPath)) {
|
|
96
|
+
return { repoPath, sourceURL: await originOf(repoPath) };
|
|
97
|
+
}
|
|
98
|
+
tried.push(repoPath);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Expected a git repo holding authorized_keys, found none.\n`
|
|
103
|
+
+ `Looked in:\n ${tried.join("\n ") || "(nowhere - this is not a git repo)"}\n`
|
|
104
|
+
+ (os.platform() === "win32"
|
|
105
|
+
? `On Windows the repo is read from ${path.resolve(WINDOWS_REPO_PATH)}, so clone it there:\n`
|
|
106
|
+
+ ` git clone <your authorized_keys repo> ${path.resolve(WINDOWS_REPO_PATH)}`
|
|
107
|
+
: `Set this machine up, or run this from inside a keys repo:\n`
|
|
108
|
+
+ ` yarn setupnotify <discord-webhook-url>\n`
|
|
109
|
+
+ ` yarn securessh add <repo-private-key> <repo-url>`)
|
|
110
|
+
);
|
|
111
|
+
}
|
|
@@ -7,6 +7,7 @@ import { findSourceKey, KEYS_DIR_NAME, sourceKeyPath, sourceName, sourceRepoPath
|
|
|
7
7
|
import { deriveRevokeKey, REVOKE_KEY_LABEL, revokeRepoURL } from "./revokeSource";
|
|
8
8
|
import { legacySourceKeyPath } from "./sources";
|
|
9
9
|
import { revokedKeysInRepo } from "./unrevoke";
|
|
10
|
+
import { resolveKeysRepo } from "./keysRepo";
|
|
10
11
|
import { expandHome } from "../helpers/paths";
|
|
11
12
|
import { spawnPromise } from "../helpers/spawn";
|
|
12
13
|
import { describeHost, readRemoteFile, remoteCommandExists, runOverSSH, SUDO_PREAMBLE, THIS_MACHINE, writeRemoteFile } from "../helpers/remoteSSH";
|
|
@@ -155,38 +156,15 @@ async function cloneRepoForInspection(config: { repoURL: string; keyPath: string
|
|
|
155
156
|
return repoPath;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
/** With no repo url given, the repo
|
|
159
|
-
|
|
159
|
+
/** With no repo url given, the keys repo this machine resolves to is used - the one we are
|
|
160
|
+
standing in when that holds keys, and this machine's own otherwise. */
|
|
160
161
|
async function resolveRepoURL(passedURL: string | undefined) {
|
|
161
162
|
if (passedURL) {
|
|
162
163
|
return normalizeRepoURL(passedURL);
|
|
163
164
|
}
|
|
164
|
-
let
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
let repoPath = topLevel.stdout.trim();
|
|
169
|
-
try {
|
|
170
|
-
await readRepoKeys(repoPath);
|
|
171
|
-
} catch (e) {
|
|
172
|
-
throw new Error(
|
|
173
|
-
`Expected a repo url, or the current repo (${repoPath}) to hold keys, it does not.\n${e}\n${USAGE}`
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
let origin = await runLocal({
|
|
177
|
-
command: "git",
|
|
178
|
-
args: ["remote", "get-url", "origin"],
|
|
179
|
-
cwd: repoPath,
|
|
180
|
-
allowFailure: true,
|
|
181
|
-
});
|
|
182
|
-
if (origin.status !== 0 || !origin.stdout.trim()) {
|
|
183
|
-
throw new Error(
|
|
184
|
-
`Expected the current repo (${repoPath}) to have an origin remote, it has none.`
|
|
185
|
-
+ ` The host clones the source itself, so a local path is no use to it.`
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
let repoURL = normalizeRepoURL(origin.stdout.trim());
|
|
189
|
-
console.log(`No repo url given, using the current repo: ${repoURL}`);
|
|
165
|
+
let { repoPath, sourceURL } = await resolveKeysRepo();
|
|
166
|
+
let repoURL = normalizeRepoURL(sourceURL);
|
|
167
|
+
console.log(`No repo url given, using ${repoPath}: ${repoURL}`);
|
|
190
168
|
return repoURL;
|
|
191
169
|
}
|
|
192
170
|
|
|
@@ -638,6 +616,21 @@ function parseArgs(argv: string[]) {
|
|
|
638
616
|
host = positional[0];
|
|
639
617
|
positional = positional.slice(1);
|
|
640
618
|
}
|
|
619
|
+
|
|
620
|
+
// How many arguments each verb takes, checked here rather than where the verb is acted on, so
|
|
621
|
+
// that a command which was typed wrong says so before anything else is complained about.
|
|
622
|
+
if (verb === "list" && positional.length) {
|
|
623
|
+
throw new Error(`Expected nothing after list, was ${positional.length} argument(s)\n${USAGE}`);
|
|
624
|
+
}
|
|
625
|
+
if (verb === "update" && positional.length) {
|
|
626
|
+
throw new Error(`Expected nothing after update, was ${positional.length} argument(s)\n${USAGE}`);
|
|
627
|
+
}
|
|
628
|
+
if (verb === "add" && (!positional.length || positional.length > 2)) {
|
|
629
|
+
throw new Error(`Expected a private key and optionally a repo url, was ${positional.length} argument(s)\n${USAGE}`);
|
|
630
|
+
}
|
|
631
|
+
if (verb === "remove" && positional.length > 1) {
|
|
632
|
+
throw new Error(`Expected at most a repo url to remove, was ${positional.length} argument(s)\n${USAGE}`);
|
|
633
|
+
}
|
|
641
634
|
return { verb, host, rest: positional };
|
|
642
635
|
}
|
|
643
636
|
|
|
@@ -655,29 +648,26 @@ function requireRoot() {
|
|
|
655
648
|
}
|
|
656
649
|
|
|
657
650
|
export async function main() {
|
|
658
|
-
|
|
651
|
+
// What was typed is checked before anything about this machine is. A command that does not
|
|
652
|
+
// make sense is worth saying so about whoever is running it, and being told to find sudo only
|
|
653
|
+
// to then be told the arguments were wrong is two trips for one mistake.
|
|
659
654
|
let { verb, host, rest } = parseArgs(process.argv.slice(2));
|
|
655
|
+
// With a host, everything root-owned happens on that host through $SUDO over ssh, so being root here proves nothing and would block running this from a workstation.
|
|
656
|
+
if (host === THIS_MACHINE) {
|
|
657
|
+
requireRoot();
|
|
658
|
+
}
|
|
660
659
|
|
|
661
660
|
if (verb === "list") {
|
|
662
661
|
await listSources(host);
|
|
663
662
|
return;
|
|
664
663
|
}
|
|
665
664
|
if (verb === "update") {
|
|
666
|
-
if (rest.length) {
|
|
667
|
-
throw new Error(`Expected nothing after update, was ${rest.length} argument(s)\n${USAGE}`);
|
|
668
|
-
}
|
|
669
665
|
await updateDaemon(host);
|
|
670
666
|
return;
|
|
671
667
|
}
|
|
672
668
|
if (verb === "add") {
|
|
673
|
-
if (!rest.length || rest.length > 2) {
|
|
674
|
-
throw new Error(`Expected a private key and optionally a repo url, was ${rest.length} argument(s)\n${USAGE}`);
|
|
675
|
-
}
|
|
676
669
|
await addSource({ host, keyPath: expandHome(rest[0]), repoURL: await resolveRepoURL(rest[1]) });
|
|
677
670
|
return;
|
|
678
671
|
}
|
|
679
|
-
if (rest.length > 1) {
|
|
680
|
-
throw new Error(`Expected at most a repo url to remove, was ${rest.length} argument(s)\n${USAGE}`);
|
|
681
|
-
}
|
|
682
672
|
await removeSource({ host, repoURL: await resolveRepoURL(rest[0]) });
|
|
683
673
|
}
|