sliftutils 1.7.136 → 1.7.138
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/printmachineid.js +5 -0
- package/examplestorage/browser.tsx +2 -2
- package/index.d.ts +10 -4
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/https/certs.d.ts +6 -1
- package/misc/https/certs.ts +11 -2
- package/misc/https/dist/certs.ts.cache +14 -5
- package/misc/https/dist/persistentLocalStorage.ts.cache +14 -4
- package/misc/https/persistentLocalStorage.d.ts +1 -0
- package/misc/https/persistentLocalStorage.ts +10 -0
- package/package.json +5 -3
- package/security/authorizedKeys/daemon/daemon.ts +4 -3
- package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
- package/security/authorizedKeys/daemon/dist/trust.ts.cache +126 -4
- package/security/authorizedKeys/daemon/revocation.d.ts +4 -7
- package/security/authorizedKeys/daemon/revocation.ts +0 -0
- package/security/authorizedKeys/daemon/trust.d.ts +12 -1
- package/security/authorizedKeys/daemon/trust.ts +124 -1
- package/security/authorizedKeys/dist/unrevoke.ts.cache +5 -186
- package/security/authorizedKeys/dist/unrevokeCli.ts.cache +195 -0
- package/security/machines/dist/machines.ts.cache +20 -68
- package/security/machines/dist/printMachineId.ts.cache +21 -0
- package/security/machines/identity2.ts +94 -6
- package/security/machines/machines.ts +27 -76
- package/security/machines/printMachineId.ts +19 -0
- package/security/signedFiles/dist/signFiles.ts.cache +16 -52
- package/storage/remoteStorage/ArchivesRemote.d.ts +1 -1
- package/storage/remoteStorage/ArchivesRemote.ts +14 -8
- package/storage/remoteStorage/accessPage.tsx +7 -123
- package/storage/remoteStorage/createArchives.d.ts +1 -1
- package/storage/remoteStorage/createArchives.ts +1 -1
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +14 -7
- package/storage/remoteStorage/dist/createArchives.ts.cache +2 -2
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +3 -3
- package/storage/remoteStorage/dist/storageController.ts.cache +8 -7
- package/storage/remoteStorage/sourceWrapper.ts +1 -1
- package/storage/remoteStorage/storageController.d.ts +1 -1
- package/storage/remoteStorage/storageController.ts +10 -10
|
@@ -3,31 +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.
|
|
6
|
+
//exports.revokedKeysInRepo = exports.readRemoteRevocations = exports.revocationIdentity = exports.revocationIP = exports.UNREVOKES_DIR = 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
|
-
const runPromise_1 = require("socket-function/src/runPromise");
|
|
11
10
|
const authorizedKeys_1 = require("./authorizedKeys");
|
|
12
11
|
const revokeSource_1 = require("./revokeSource");
|
|
13
12
|
const sources_1 = require("./sources");
|
|
14
|
-
const signFiles_1 = require("../signedFiles/signFiles");
|
|
15
|
-
const authorizedKeys_2 = require("./authorizedKeys");
|
|
16
13
|
const spawn_1 = require("../helpers/spawn");
|
|
17
|
-
|
|
18
|
-
const keysRepo_1 = require("./keysRepo");
|
|
19
|
-
const UNREVOKES_DIR = "unrevoked";
|
|
14
|
+
exports.UNREVOKES_DIR = "unrevoked";
|
|
20
15
|
const REVOCATIONS_DIR = "revocations";
|
|
21
|
-
const GIT_KEYWORD = "git";
|
|
22
|
-
const COMMIT_MESSAGE = "unrevoke keys";
|
|
23
|
-
const USAGE = `Usage: yarn unrevoke [keys-repo] [${GIT_KEYWORD}]
|
|
24
|
-
|
|
25
|
-
Run this in a keys repo, or name one. It reads that repo's revoke repo and writes one unrevoke file
|
|
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.
|
|
28
|
-
|
|
29
|
-
Keys that were revoked should normally be deleted from the repo instead. Unrevoking only matters
|
|
30
|
-
for a key you still want.`;
|
|
31
16
|
/** Older revocation files carry the address under attempt only. */
|
|
32
17
|
function revocationIP(revocation) {
|
|
33
18
|
var _a;
|
|
@@ -86,7 +71,7 @@ async function revokedKeysInRepo(config) {
|
|
|
86
71
|
let revokedFingerprints = new Set(revocations.map(revocation => revocation.fingerprint));
|
|
87
72
|
let unrevoked = new Set();
|
|
88
73
|
try {
|
|
89
|
-
let directory = path_1.default.join(repoPath, UNREVOKES_DIR);
|
|
74
|
+
let directory = path_1.default.join(repoPath, exports.UNREVOKES_DIR);
|
|
90
75
|
for (let name of await promises_1.default.readdir(directory)) {
|
|
91
76
|
if (!name.endsWith(".json")) {
|
|
92
77
|
continue;
|
|
@@ -112,171 +97,5 @@ async function revokedKeysInRepo(config) {
|
|
|
112
97
|
.map(revocation => ({ revocation, key: keys.find(key => (0, authorizedKeys_1.keyFingerprint)(key) === revocation.fingerprint) || "" }));
|
|
113
98
|
}
|
|
114
99
|
exports.revokedKeysInRepo = revokedKeysInRepo;
|
|
115
|
-
/** Writes the addresses into the from= list of each key in the repo's authorized_keys, and says
|
|
116
|
-
|
|
117
|
-
and any key not involved come out of this byte for byte the same. */
|
|
118
|
-
async function allowAddressesInRepo(config) {
|
|
119
|
-
let { repoPath, addressesByFingerprint } = config;
|
|
120
|
-
let added = new Map();
|
|
121
|
-
let filePath = path_1.default.join(repoPath, "authorized_keys");
|
|
122
|
-
let contents;
|
|
123
|
-
try {
|
|
124
|
-
contents = await promises_1.default.readFile(filePath, "utf8");
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
// A repo holding its keys as separate .pub files. Nothing to edit in one place, so the
|
|
128
|
-
// caller's listing is all whoever ran this gets.
|
|
129
|
-
console.log(`No authorized_keys in ${repoPath}, so the addresses were not added to any key.`);
|
|
130
|
-
return added;
|
|
131
|
-
}
|
|
132
|
-
let lines = contents.split("\n");
|
|
133
|
-
for (let index = 0; index < lines.length; index++) {
|
|
134
|
-
let fingerprint = (0, authorizedKeys_1.keyFingerprint)(lines[index]);
|
|
135
|
-
let addresses = fingerprint && addressesByFingerprint.get(fingerprint);
|
|
136
|
-
if (!addresses || !addresses.length) {
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
let result = (0, authorizedKeys_1.allowAddresses)(lines[index], addresses);
|
|
140
|
-
lines[index] = result.keyLine;
|
|
141
|
-
added.set(fingerprint, [...(added.get(fingerprint) || []), ...result.added]);
|
|
142
|
-
}
|
|
143
|
-
if ([...added.values()].some(list => list.length)) {
|
|
144
|
-
await promises_1.default.writeFile(filePath, lines.join("\n"));
|
|
145
|
-
}
|
|
146
|
-
return added;
|
|
147
|
-
}
|
|
148
|
-
/** Puts each machine's addresses back into its own file, which is the machine equivalent of adding
|
|
149
|
-
an address to a key's from= list: without it the machine is allowed again in principle and
|
|
150
|
-
still rejected on sight, which revokes it once more. */
|
|
151
|
-
async function allowAddressesForMachines(config) {
|
|
152
|
-
let { repoPath, revocations } = config;
|
|
153
|
-
let added = new Map();
|
|
154
|
-
// Read the whole list, change what these revocations are about, write it back. Setting is by
|
|
155
|
-
// the whole set, so writing one machine at a time would delete every other machine.
|
|
156
|
-
let machines = await (0, machines_1.getMachines)(repoPath);
|
|
157
|
-
for (let revocation of revocations) {
|
|
158
|
-
let machineId = revocation.machineId;
|
|
159
|
-
let ip = revocationIP(revocation);
|
|
160
|
-
if (!machineId || !ip) {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
let existing = machines.find(machine => machine.machineId === machineId);
|
|
164
|
-
if (!existing) {
|
|
165
|
-
// Removed from the repo since it was revoked, so there is nothing to allow. Deleting a
|
|
166
|
-
// machine is the stronger statement and it stands.
|
|
167
|
-
console.log(`machines/${machineId}.json is not in this repo, so ${ip} was not added to it`);
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
if (existing.ips.includes(ip)) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
existing.ips = [...existing.ips, ip];
|
|
174
|
-
added.set(machineId, [...(added.get(machineId) || []), ip]);
|
|
175
|
-
}
|
|
176
|
-
if (added.size) {
|
|
177
|
-
await (0, machines_1.setMachines)({ repoPath, machines });
|
|
178
|
-
}
|
|
179
|
-
return added;
|
|
180
|
-
}
|
|
181
|
-
async function main() {
|
|
182
|
-
let argv = process.argv.slice(2);
|
|
183
|
-
let pushToGit = argv.includes(GIT_KEYWORD);
|
|
184
|
-
let positional = argv.filter(arg => arg !== GIT_KEYWORD);
|
|
185
|
-
if (positional.length > 1) {
|
|
186
|
-
throw new Error(`Expected at most a keys repo, was ${positional.length} argument(s)\n${USAGE}`);
|
|
187
|
-
}
|
|
188
|
-
let { repoPath, sourceURL: originURL } = await (0, keysRepo_1.resolveKeysRepo)(positional[0]);
|
|
189
|
-
let revocations = await readRemoteRevocations({ sourceURL: originURL });
|
|
190
|
-
if (!revocations.length) {
|
|
191
|
-
console.log(`${(0, revokeSource_1.revokeRepoURL)(originURL)} lists no revocations, so there is nothing to undo.`);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
let directory = path_1.default.join(repoPath, UNREVOKES_DIR);
|
|
195
|
-
await promises_1.default.mkdir(directory, { recursive: true });
|
|
196
|
-
let stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
197
|
-
let unrevokeId = `${stamp}-unrevoke`;
|
|
198
|
-
await promises_1.default.writeFile(path_1.default.join(directory, `${unrevokeId}.json`), JSON.stringify({
|
|
199
|
-
unrevokeId,
|
|
200
|
-
createdAt: new Date().toISOString(),
|
|
201
|
-
// What this file says: each of these keys is allowed from this address. Pairs, not keys,
|
|
202
|
-
// and not a blanket "allow everything again" - a key forgiven here for one address is
|
|
203
|
-
// still revoked the moment it is used from another.
|
|
204
|
-
allowed: revocations.map(revocation => ({
|
|
205
|
-
fingerprint: revocation.fingerprint,
|
|
206
|
-
machineId: revocation.machineId,
|
|
207
|
-
ip: revocationIP(revocation),
|
|
208
|
-
})),
|
|
209
|
-
revocations: revocations.map(revocation => ({
|
|
210
|
-
revocationId: revocation.revocationId,
|
|
211
|
-
fingerprint: revocation.fingerprint,
|
|
212
|
-
machineId: revocation.machineId,
|
|
213
|
-
ip: revocationIP(revocation),
|
|
214
|
-
revokedAt: revocation.revokedAt,
|
|
215
|
-
revokedBy: revocation.revokedBy,
|
|
216
|
-
attempt: revocation.attempt,
|
|
217
|
-
})),
|
|
218
|
-
}, undefined, 4) + "\n");
|
|
219
|
-
// Named the way the notifications name them. A fingerprint is not in authorized_keys and
|
|
220
|
-
// cannot be worked out by eye, so on its own it tells whoever is reading this nothing about
|
|
221
|
-
// which of their keys is being talked about.
|
|
222
|
-
let keysByFingerprint = new Map();
|
|
223
|
-
for (let key of await (0, authorizedKeys_2.readRepoKeys)(repoPath).catch(() => [])) {
|
|
224
|
-
keysByFingerprint.set((0, authorizedKeys_1.keyFingerprint)(key), key);
|
|
225
|
-
}
|
|
226
|
-
let describeKey = (revocation) => {
|
|
227
|
-
let key = keysByFingerprint.get(revocation.fingerprint || "") || revocation.key || "";
|
|
228
|
-
return key && (0, authorizedKeys_1.summarizeKey)(key) || `a key no longer in this repo (${revocation.fingerprint})`;
|
|
229
|
-
};
|
|
230
|
-
let addressesByIdentity = new Map();
|
|
231
|
-
for (let revocation of revocations) {
|
|
232
|
-
let ip = revocationIP(revocation);
|
|
233
|
-
let identity = revocationIdentity(revocation);
|
|
234
|
-
let existing = addressesByIdentity.get(identity) || [];
|
|
235
|
-
if (ip && !existing.includes(ip)) {
|
|
236
|
-
existing.push(ip);
|
|
237
|
-
}
|
|
238
|
-
addressesByIdentity.set(identity, existing);
|
|
239
|
-
}
|
|
240
|
-
// Cancelling the revocation on its own would leave sshd refusing that address, and the machines
|
|
241
|
-
// revoking all over again, so the addresses go into the key's from= list and into the machine's
|
|
242
|
-
// own file here. We are in the repo that owns both, so there is nothing to hand back to whoever
|
|
243
|
-
// ran this.
|
|
244
|
-
let added = await allowAddressesInRepo({ repoPath, addressesByFingerprint: addressesByIdentity });
|
|
245
|
-
let addedForMachines = await allowAddressesForMachines({ repoPath, revocations });
|
|
246
|
-
console.log("");
|
|
247
|
-
for (let [identity, addresses] of addressesByIdentity) {
|
|
248
|
-
let entries = revocations.filter(entry => revocationIdentity(entry) === identity);
|
|
249
|
-
let machineId = entries[0].machineId;
|
|
250
|
-
console.log(`Unfreezing ${machineId && `machine ${machineId}` || describeKey(entries[0])}`);
|
|
251
|
-
console.log(`Allowing IP ${addresses.join(", ") || "(no address recorded)"}`);
|
|
252
|
-
let addedHere = machineId && addedForMachines.get(machineId) || added.get(identity) || [];
|
|
253
|
-
if (addedHere.length) {
|
|
254
|
-
let where = machineId && `machines/${machineId}.json` || `that key's from= list in authorized_keys`;
|
|
255
|
-
console.log(` added to ${where}: ${addedHere.join(", ")}`);
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
258
|
-
console.log(` already allowed from ${addresses.join(", ") || "everywhere"}`);
|
|
259
|
-
}
|
|
260
|
-
for (let entry of entries) {
|
|
261
|
-
console.log(` frozen by ${entry.revokedBy || "?"} ${entry.revokedAt || "at an unrecorded time"}`);
|
|
262
|
-
}
|
|
263
|
-
console.log("");
|
|
264
|
-
}
|
|
265
|
-
console.log(`Every other address stays frozen, and any of these used from anywhere else is`);
|
|
266
|
-
console.log(`frozen again.`);
|
|
267
|
-
// Signed here rather than left as a step to remember. An unrevoke nobody signed does nothing at
|
|
268
|
-
// all, and the repo would sit there looking done while every machine ignored it.
|
|
269
|
-
await (0, signFiles_1.signRepo)({ repoPath });
|
|
270
|
-
if (!pushToGit) {
|
|
271
|
-
console.log(`\nCommit and push it, and those keys work again as each machine picks it up:`);
|
|
272
|
-
console.log(`\`\`\`\ngit add -A\ngit commit -m "${COMMIT_MESSAGE}"\ngit push\n\`\`\``);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
await (0, runPromise_1.runPromise)(`git add -A`, { cwd: repoPath });
|
|
276
|
-
await (0, runPromise_1.runPromise)(`git commit -m "${COMMIT_MESSAGE}"`, { cwd: repoPath });
|
|
277
|
-
await (0, runPromise_1.runPromise)(`git push`, { cwd: repoPath });
|
|
278
|
-
console.log(`\nCommitted and pushed. Those keys work again as each machine picks it up.`);
|
|
279
|
-
}
|
|
280
|
-
exports.main = main;
|
|
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"; */
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5yZXZva2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1bnJldm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwyREFBNkI7QUFDN0IsNENBQW9CO0FBQ3BCLGdEQUF3QjtBQUN4QixxREFBaUU7QUFDakUsaURBQWdFO0FBQ2hFLHVDQUEwQztBQUMxQyw0Q0FBZ0Q7QUFFbkMsUUFBQSxhQUFhLEdBQUcsV0FBVyxDQUFDO0FBQ3pDLE1BQU0sZUFBZSxHQUFHLGFBQWEsQ0FBQztBQXFCdEMsbUVBQW1FO0FBQ25FLFNBQWdCLFlBQVksQ0FBQyxVQUFzQjs7SUFDL0MsT0FBTyxVQUFVLENBQUMsRUFBRSxLQUFJLE1BQUEsVUFBVSxDQUFDLE9BQU8sMENBQUUsRUFBRSxDQUFBLElBQUksRUFBRSxDQUFDO0FBQ3pELENBQUM7QUFGRCxvQ0FFQztBQUVELHNGQUFzRjtBQUN0RixTQUFnQixrQkFBa0IsQ0FBQyxVQUFzQjtJQUNyRCxPQUFPLFVBQVUsQ0FBQyxXQUFXLElBQUksVUFBVSxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUM7QUFDaEUsQ0FBQztBQUZELGdEQUVDO0FBRUQ7Ozs7a0dBSWtHO0FBQzNGLEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxNQUE2QjtJQUNyRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTSxDQUFDO0lBQzNCLElBQUksa0JBQWtCLEdBQUcsTUFBTSxrQkFBRSxDQUFDLE9BQU8sQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLFlBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBQy9FLElBQUksUUFBUSxHQUFHLGNBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDckQsSUFBSSxTQUFTLEdBQUcsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxJQUFBLDRCQUFhLEVBQUMsU0FBUyxDQUFDLEVBQUUsUUFBUSxDQUFDLENB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QVksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRixJQUFJLElBQUksR0FBRyxJQUFBLDhCQUFhLEVBQUMsTUFBTSxrQkFBRSxDQUFDLFFBQVEsQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzVHLE9BQU8sWUFBWTtTQUNkLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFBLCtCQUFjLEVBQUMsR0FBRyxDQUFDLEtBQUssVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1NBQ3RGLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFBLCtCQUFjLEVBQUMsR0FBRyxDQUFDLEtBQUssVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMxSCxDQUFDO0FBN0JELDhDQTZCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBvcyBmcm9tIFwib3NcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBrZXlGaW5nZXJwcmludCwgbm9ybWFsaXplS2V5cyB9IGZyb20gXCIuL2F1dGhvcml6ZWRLZXlzXCI7XG5pbXBvcnQgeyBkZXJpdmVSZXZva2VLZXksIHJldm9rZVJlcG9VUkwgfSBmcm9tIFwiLi9yZXZva2VTb3VyY2VcIjtcbmltcG9ydCB7IGZpbmRTb3VyY2VLZXkgfSBmcm9tIFwiLi9zb3VyY2VzXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vaGVscGVycy9zcGF3blwiO1xuXG5leHBvcnQgY29uc3QgVU5SRVZPS0VTX0RJUiA9IFwidW5yZXZva2VkXCI7XG5jb25zdCBSRVZPQ0FUSU9OU19ESVIgPSBcInJldm9jYXRpb25zXCI7XG5cbi8qKiBPbmUgcmV2b2NhdGlvbiBldmVudC4gRWl0aGVyIGFuIHNzaCBrZXkgdXNlZCBmcm9tIGFuIGFkZHJlc3MgaXQgaXMgbm90IGFsbG93ZWQgZnJvbSwgb3IgYVxuICAgIG1hY2hpbmUgdGhhdCB0YWxrZWQgdG8gdXMgZnJvbSBvbmUuIEJvdGggYXJlIHRoZSBzYW1lIHNoYXBlIC0gYW4gaWRlbnRpdHkgYW5kIGFuIGFkZHJlc3MgLSBhbmRcbiAgICBhbiB1bnJldm9rZSB1bmRvZXMgZWl0aGVyIGJ5IGFsbG93aW5nIHRoYXQgc2FtZSBwYWlyLlxuXG4gICAgV2hpY2ggaXMgd2h5IHVucmV2b2tpbmcgbmV2ZXIgbWFrZXMgYW55dGhpbmcgdW5yZXZva2FibGU6IHVzZWQgZnJvbSBzb21lIG90aGVyIGFkZHJlc3MsIGl0IGlzXG4gICAgcmV2b2tlZCBhZ2FpbiwgdW5kZXIgYSBuZXcgaWQgbm8gZXhpc3RpbmcgdW5yZXZva2UgbmFtZXMuICovXG5leHBvcnQgdHlwZSBSZXZvY2F0aW9uID0ge1xuICAgIHJldm9jYXRpb25JZDogc3RyaW5nO1xuICAgIC8vIEV4YWN0bHkgb25lIG9mIHRoZXNlLiBBIGtleSByZXZvY2F0aW9uIG5hbWVzIGEgZmluZ2VycHJpbnQsIGEgbWFjaGluZSByZXZvY2F0aW9uIGEgbWFjaGluZUlkLlxuICAgIGZpbmdlcnByaW50Pzogc3RyaW5nO1xuICAgIG1hY2hpbmVJZD86IHN0cmluZztcbiAgICBpcD86IHN0cmluZztcbiAgICBrZXk/OiBzdHJpbmc7XG4gICAgcmV2b2tlZEF0Pzogc3RyaW5nO1xuICAgIHJldm9rZWRCeT86IHN0cmluZztcbiAgICByZWFzb24/OiBzdHJpbmc7XG4gICAgYXR0ZW1wdD86IHsgaXA/OiBzdHJpbmc7IHVzZXI/OiBzdHJpbmc7IHJlcXVpcmVkPzogc3RyaW5nIH07XG59O1xuXG4vKiogT2xkZXIgcmV2b2NhdGlvbiBmaWxlcyBjYXJyeSB0aGUgYWRkcmVzcyB1bmRlciBhdHRlbXB0IG9ubHkuICovXG5leHBvcnQgZnVuY3Rpb24gcmV2b2NhdGlvbklQKHJldm9jYXRpb246IFJldm9jYXRpb24pIHtcbiAgICByZXR1cm4gcmV2b2NhdGlvbi5pcCB8fCByZXZvY2F0aW9uLmF0dGVtcHQ/LmlwIHx8IFwiXCI7XG59XG5cbi8qKiBXaGF0IHRoZSByZXZvY2F0aW9uIGlzIGFib3V0LCB3aGljaCBpcyB3aGF0IGFuIHVucmV2b2tlIGhhcyB0byBuYW1lIHRvIHVuZG8gaXQuICovXG5leHBvcnQgZnVuY3Rpb24gcmV2b2NhdGlvbklkZW50aXR5KHJldm9jYXRpb246IFJldm9jYXRpb24pIHtcbiAgICByZXR1cm4gcmV2b2NhdGlvbi5maW5nZXJwcmludCB8fCByZXZvY2F0aW9uLm1hY2hpbmVJZCB8fCBcIlwiO1xufVxuXG4vKiogRXZlcnkgcmV2b2NhdGlvbiB0aGUgcmV2b2tlIHJlcG8gbGlzdHMuIENsb25lZCByZWFkIG9ubHkgaW50byBhIHRlbXAgZGlyZWN0b3J5LlxuXG4gICAgQSBwZXJzb24gcnVubmluZyB0aGlzIGhhcyB0aGVpciBvd24gYWNjZXNzIHRvIHRoZSByZXBvLCBzbyB0aGVpciBjcmVkZW50aWFscyBhcmUgd2hhdCBpcyB1c2VkLlxuICAgIE9uIGEgbWFjaGluZSB0aGF0IGlzIGFscmVhZHkgYSBwb3J0c2VjdXJlIGhvc3QgdGhlcmUgbWF5IGJlIG5vIHN1Y2ggY3JlZGVudGlhbHMsIGJ1dCB0aGUgc291cmNlXG4gICAgZGVwbG95IGtleSBpcyByaWdodCB0aGVyZSwgYW5kIHRoZSBrZXkgZGVyaXZlZCBmcm9tIGl0IGlzIG9uZSB0aGF0IHJlcG8gZGVmaW5pdGVseSBhY2NlcHRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRSZW1vdGVSZXZvY2F0aW9ucyhjb25maWc6IHsgc291cmNlVVJMOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHNvdXJjZVVSTCB9ID0gY29uZmlnO1xuICAgIGxldCB0ZW1wb3JhcnlEaXJlY3RvcnkgPSBhd2FpdCBmcy5ta2R0ZW1wKHBhdGguam9pbihvcy50bXBkaXIoKSwgXCJ1bnJldm9rZS1cIikpO1xuICAgIGxldCByZXBvUGF0aCA9IHBhdGguam9pbih0ZW1wb3JhcnlEaXJlY3RvcnksIFwicmVwb1wiKTtcbiAgICBsZXQgY2xvbmVBcmdzID0gW1wiY2xvbmVcIiwgXCItLWRlcHRoXCIsIFwiMVwiLCByZXZva2VSZXBvVVJMKHNvdXJjZVVSTCksIHJlcG9QYXRoXTtcbiAgICBsZXQgc291cmNlS2V5ID0gYXdhaXQgZmluZFNvdXJjZUtleShzb3VyY2VVUkwpO1xuICAgIGlmIChzb3VyY2VLZXkpIHtcbiAgICAgICAgbGV0IGRlcml2ZWQgPSBkZXJpdmVSZXZva2VLZXkoYXdhaXQgZnMucmVhZEZpbGUoc291cmNlS2V5LCBcInV0ZjhcIikpO1xuICAgICAgICBsZXQgZGVyaXZlZEtleVBhdGggPSBwYXRoLmpvaW4odGVtcG9yYXJ5RGlyZWN0b3J5LCBcImtleVwiKTtcbiAgICAgICAgYXdhaXQgZnMud3JpdGVGaWxlKGRlcml2ZWRLZXlQYXRoLCBkZXJpdmVkLnByaXZhdGVLZXlGaWxlLCB7IG1vZGU6IDBvNjAwIH0pO1xuICAgICAgICBsZXQgc3NoQ29tbWFuZCA9IGBzc2ggLWkgJHtkZXJpdmVkS2V5UGF0aH0gLW8gSWRlbnRpdGllc09ubHk9eWVzIC1vIEJhdGNoTW9kZT15ZXMgLW8gU3RyaWN0SG9zdEtleUNoZWNraW5nPWFjY2VwdC1uZXdgO1xuICAgICAgICBjbG9uZUFyZ3MgPSBbXCItY1wiLCBgY29yZS5zc2hDb21tYW5kPSR7c3NoQ29tbWFuZH1gLCAuLi5jbG9uZUFyZ3NdO1xuICAgIH1cbiAgICBsZXQgY2xvbmUgPSBhd2FpdCBzcGF3blByb21pc2UoeyBjb21tYW5kOiBcImdpdFwiLCBhcmdzOiBjbG9uZUFyZ3MgfSk7XG4gICAgaWYgKGNsb25lLnN0YXR1cyAhPT0gMCkge1xuICAgICAgICBhd2FpdCBmcy5ybSh0ZW1wb3JhcnlEaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkIHRvIGJlIGFibGUgdG8gcmVhZCAke3Jldm9rZVJlcG9VUkwoc291cmNlVVJMKX0uXFxuYFxuICAgICAgICAgICAgKyBgJHsoY2xvbmUuc3Rkb3V0ICsgY2xvbmUuc3RkZXJyKS50cmltKCl9YFxuICAgICAgICApO1xuICAgIH1cbiAgICBsZXQgcmV2b2NhdGlvbnM6IFJldm9jYXRpb25bXSA9IFtdO1xuICAgIGxldCBkaXJlY3RvcnkgPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFJFVk9DQVRJT05TX0RJUik7XG4gICAgdHJ5IHtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBvZiAoYXdhaXQgZnMucmVhZGRpcihkaXJlY3RvcnkpKS5zb3J0KCkpIHtcbiAgICAgICAgICAgIGlmIChuYW1lLmVuZHNXaXRoKFwiLmpzb25cIikpIHtcbiAgICAgICAgICAgICAgICByZXZvY2F0aW9ucy5wdXNoKEpTT04ucGFyc2UoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKGRpcmVjdG9yeSwgbmFtZSksIFwidXRmOFwiKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBObyByZXZvY2F0aW9ucyBkaXJlY3RvcnkgYXQgYWxsIGp1c3QgbWVhbnMgbm90aGluZyBoYXMgZXZlciBiZWVuIHJldm9rZWQuXG4gICAgfVxuICAgIGF3YWl0IGZzLnJtKHRlbXBvcmFyeURpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIHJldHVybiByZXZvY2F0aW9ucztcbn1cblxuLyoqIFdoaWNoIGtleXMgaW4gYSByZXBvIGFyZSByZXZva2VkLiBXaGF0IHNpZ25maWxlcyBhbmQgc2VjdXJlc3NoIHJlZnVzZSBvdmVyLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJldm9rZWRLZXlzSW5SZXBvKGNvbmZpZzogeyByZXBvUGF0aDogc3RyaW5nOyBzb3VyY2VVUkw6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgcmVwb1BhdGgsIHNvdXJjZVVSTCB9ID0gY29uZmlnO1xuICAgIGxldCByZXZvY2F0aW9ucyA9IGF3YWl0IHJlYWRSZW1vdGVSZXZvY2F0aW9ucyh7IHNvdXJjZVVSTCB9KTtcbiAgICBsZXQgcmV2b2tlZEZpbmdlcnByaW50cyA9IG5ldyBTZXQocmV2b2NhdGlvbnMubWFwKHJldm9jYXRpb24gPT4gcmV2b2NhdGlvbi5maW5nZXJwcmludCkpO1xuICAgIGxldCB1bnJldm9rZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICB0cnkge1xuICAgICAgICBsZXQgZGlyZWN0b3J5ID0gcGF0aC5qb2luKHJlcG9QYXRoLCBVTlJFVk9LRVNfRElSKTtcbiAgICAgICAgZm9yIChsZXQgbmFtZSBvZiBhd2FpdCBmcy5yZWFkZGlyKGRpcmVjdG9yeSkpIHtcbiAgICAgICAgICAgIGlmICghbmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gSlNPTi5wYXJzZShhd2FpdCBmcy5yZWFkRmlsZShwYXRoLmpvaW4oZGlyZWN0b3J5LCBuYW1lKSwgXCJ1dGY4XCIpKTtcbiAgICAgICAgICAgIGZvciAobGV0IGFsbG93ZWQgb2YgcGFyc2VkLmFsbG93ZWQgfHwgW10pIHtcbiAgICAgICAgICAgICAgICB1bnJldm9rZWQuYWRkKGAke2FsbG93ZWQuZmluZ2VycHJpbnQgfHwgYWxsb3dlZC5tYWNoaW5lSWR9ICR7YWxsb3dlZC5pcH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5hbWVkIGlkcywgZm9yIHRoZSB1bnJldm9rZXMgd3JpdHRlbiBiZWZvcmUgdGhpcyB3YXMgYWJvdXQgcGFpcnMuXG4gICAgICAgICAgICBmb3IgKGxldCByZXZvY2F0aW9uSWQgb2YgcGFyc2VkLnJldm9jYXRpb25JZHMgfHwgW10pIHtcbiAgICAgICAgICAgICAgICB1bnJldm9rZWQuYWRkKHJldm9jYXRpb25JZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIE5vdGhpbmcgaGFzIGJlZW4gdW5yZXZva2VkLlxuICAgIH1cbiAgICBsZXQgc3RpbGxSZXZva2VkID0gcmV2b2NhdGlvbnMuZmlsdGVyKHJldm9jYXRpb24gPT4gIXVucmV2b2tlZC5oYXMocmV2b2NhdGlvbi5yZXZvY2F0aW9uSWQpXG4gICAgICAgICYmICF1bnJldm9rZWQuaGFzKGAke3Jldm9jYXRpb24uZmluZ2VycHJpbnR9ICR7cmV2b2NhdGlvbklQKHJldm9jYXRpb24pfWApKTtcbiAgICBsZXQga2V5cyA9IG5vcm1hbGl6ZUtleXMoYXdhaXQgZnMucmVhZEZpbGUocGF0aC5qb2luKHJlcG9QYXRoLCBcImF1dGhvcml6ZWRfa2V5c1wiKSwgXCJ1dGY4XCIpLmNhdGNoKCgpID0+IFwiXCIpKTtcbiAgICByZXR1cm4gc3RpbGxSZXZva2VkXG4gICAgICAgIC5maWx0ZXIocmV2b2NhdGlvbiA9PiBrZXlzLnNvbWUoa2V5ID0+IGtleUZpbmdlcnByaW50KGtleSkgPT09IHJldm9jYXRpb24uZmluZ2VycHJpbnQpKVxuICAgICAgICAubWFwKHJldm9jYXRpb24gPT4gKHsgcmV2b2NhdGlvbiwga2V5OiBrZXlzLmZpbmQoa2V5ID0+IGtleUZpbmdlcnByaW50KGtleSkgPT09IHJldm9jYXRpb24uZmluZ2VycHJpbnQpIHx8IFwiXCIgfSkpO1xufVxuIl19
|
|
101
|
+
/* _JS_SOURCE_HASH = "ca655e17af62cde1b52e49081d01fc5fc159130c52683b3523b1275b7f245c85"; */
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
6
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const runPromise_1 = require("socket-function/src/runPromise");
|
|
9
|
+
const authorizedKeys_1 = require("./authorizedKeys");
|
|
10
|
+
const revokeSource_1 = require("./revokeSource");
|
|
11
|
+
const signFiles_1 = require("../signedFiles/signFiles");
|
|
12
|
+
const machines_1 = require("../machines/machines");
|
|
13
|
+
const keysRepo_1 = require("./keysRepo");
|
|
14
|
+
const unrevoke_1 = require("./unrevoke");
|
|
15
|
+
const GIT_KEYWORD = "git";
|
|
16
|
+
const COMMIT_MESSAGE = "unrevoke keys";
|
|
17
|
+
const USAGE = `Usage: yarn unrevoke [keys-repo] [${GIT_KEYWORD}]
|
|
18
|
+
|
|
19
|
+
Run this in a keys repo, or name one. It reads that repo's revoke repo and writes one unrevoke file
|
|
20
|
+
naming every revocation in it, so the keys are accepted again as each machine picks it up. It signs
|
|
21
|
+
the result, and with ${GIT_KEYWORD} it commits and pushes it too.
|
|
22
|
+
|
|
23
|
+
Keys that were revoked should normally be deleted from the repo instead. Unrevoking only matters
|
|
24
|
+
for a key you still want.`;
|
|
25
|
+
/** Writes the addresses into the from= list of each key in the repo's authorized_keys, and says
|
|
26
|
+
which ones were actually new. Only the lines being changed are touched, so comments, ordering
|
|
27
|
+
and any key not involved come out of this byte for byte the same. */
|
|
28
|
+
async function allowAddressesInRepo(config) {
|
|
29
|
+
let { repoPath, addressesByFingerprint } = config;
|
|
30
|
+
let added = new Map();
|
|
31
|
+
let filePath = path_1.default.join(repoPath, "authorized_keys");
|
|
32
|
+
let contents;
|
|
33
|
+
try {
|
|
34
|
+
contents = await promises_1.default.readFile(filePath, "utf8");
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
// A repo holding its keys as separate .pub files. Nothing to edit in one place, so the
|
|
38
|
+
// caller's listing is all whoever ran this gets.
|
|
39
|
+
console.log(`No authorized_keys in ${repoPath}, so the addresses were not added to any key.`);
|
|
40
|
+
return added;
|
|
41
|
+
}
|
|
42
|
+
let lines = contents.split("\n");
|
|
43
|
+
for (let index = 0; index < lines.length; index++) {
|
|
44
|
+
let fingerprint = (0, authorizedKeys_1.keyFingerprint)(lines[index]);
|
|
45
|
+
let addresses = fingerprint && addressesByFingerprint.get(fingerprint);
|
|
46
|
+
if (!addresses || !addresses.length) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
let result = (0, authorizedKeys_1.allowAddresses)(lines[index], addresses);
|
|
50
|
+
lines[index] = result.keyLine;
|
|
51
|
+
added.set(fingerprint, [...(added.get(fingerprint) || []), ...result.added]);
|
|
52
|
+
}
|
|
53
|
+
if ([...added.values()].some(list => list.length)) {
|
|
54
|
+
await promises_1.default.writeFile(filePath, lines.join("\n"));
|
|
55
|
+
}
|
|
56
|
+
return added;
|
|
57
|
+
}
|
|
58
|
+
/** Puts each machine's addresses back into its own file, which is the machine equivalent of adding
|
|
59
|
+
an address to a key's from= list: without it the machine is allowed again in principle and
|
|
60
|
+
still rejected on sight, which revokes it once more. */
|
|
61
|
+
async function allowAddressesForMachines(config) {
|
|
62
|
+
let { repoPath, revocations } = config;
|
|
63
|
+
let added = new Map();
|
|
64
|
+
// Read the whole list, change what these revocations are about, write it back. Setting is by
|
|
65
|
+
// the whole set, so writing one machine at a time would delete every other machine.
|
|
66
|
+
let machines = await (0, machines_1.getMachines)(repoPath);
|
|
67
|
+
for (let revocation of revocations) {
|
|
68
|
+
let machineId = revocation.machineId;
|
|
69
|
+
let ip = (0, unrevoke_1.revocationIP)(revocation);
|
|
70
|
+
if (!machineId || !ip) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
let existing = machines.find(machine => machine.machineId === machineId);
|
|
74
|
+
if (!existing) {
|
|
75
|
+
// Removed from the repo since it was revoked, so there is nothing to allow. Deleting a
|
|
76
|
+
// machine is the stronger statement and it stands.
|
|
77
|
+
console.log(`machines/${machineId}.json is not in this repo, so ${ip} was not added to it`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (existing.ips.includes(ip)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
existing.ips = [...existing.ips, ip];
|
|
84
|
+
added.set(machineId, [...(added.get(machineId) || []), ip]);
|
|
85
|
+
}
|
|
86
|
+
if (added.size) {
|
|
87
|
+
await (0, machines_1.setMachines)({ repoPath, machines });
|
|
88
|
+
}
|
|
89
|
+
return added;
|
|
90
|
+
}
|
|
91
|
+
async function main() {
|
|
92
|
+
let argv = process.argv.slice(2);
|
|
93
|
+
let pushToGit = argv.includes(GIT_KEYWORD);
|
|
94
|
+
let positional = argv.filter(arg => arg !== GIT_KEYWORD);
|
|
95
|
+
if (positional.length > 1) {
|
|
96
|
+
throw new Error(`Expected at most a keys repo, was ${positional.length} argument(s)\n${USAGE}`);
|
|
97
|
+
}
|
|
98
|
+
let { repoPath, sourceURL: originURL } = await (0, keysRepo_1.resolveKeysRepo)(positional[0]);
|
|
99
|
+
let revocations = await (0, unrevoke_1.readRemoteRevocations)({ sourceURL: originURL });
|
|
100
|
+
if (!revocations.length) {
|
|
101
|
+
console.log(`${(0, revokeSource_1.revokeRepoURL)(originURL)} lists no revocations, so there is nothing to undo.`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
let directory = path_1.default.join(repoPath, unrevoke_1.UNREVOKES_DIR);
|
|
105
|
+
await promises_1.default.mkdir(directory, { recursive: true });
|
|
106
|
+
let stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
107
|
+
let unrevokeId = `${stamp}-unrevoke`;
|
|
108
|
+
await promises_1.default.writeFile(path_1.default.join(directory, `${unrevokeId}.json`), JSON.stringify({
|
|
109
|
+
unrevokeId,
|
|
110
|
+
createdAt: new Date().toISOString(),
|
|
111
|
+
// What this file says: each of these keys is allowed from this address. Pairs, not keys,
|
|
112
|
+
// and not a blanket "allow everything again" - a key forgiven here for one address is
|
|
113
|
+
// still revoked the moment it is used from another.
|
|
114
|
+
allowed: revocations.map(revocation => ({
|
|
115
|
+
fingerprint: revocation.fingerprint,
|
|
116
|
+
machineId: revocation.machineId,
|
|
117
|
+
ip: (0, unrevoke_1.revocationIP)(revocation),
|
|
118
|
+
})),
|
|
119
|
+
revocations: revocations.map(revocation => ({
|
|
120
|
+
revocationId: revocation.revocationId,
|
|
121
|
+
fingerprint: revocation.fingerprint,
|
|
122
|
+
machineId: revocation.machineId,
|
|
123
|
+
ip: (0, unrevoke_1.revocationIP)(revocation),
|
|
124
|
+
revokedAt: revocation.revokedAt,
|
|
125
|
+
revokedBy: revocation.revokedBy,
|
|
126
|
+
attempt: revocation.attempt,
|
|
127
|
+
})),
|
|
128
|
+
}, undefined, 4) + "\n");
|
|
129
|
+
// Named the way the notifications name them. A fingerprint is not in authorized_keys and
|
|
130
|
+
// cannot be worked out by eye, so on its own it tells whoever is reading this nothing about
|
|
131
|
+
// which of their keys is being talked about.
|
|
132
|
+
let keysByFingerprint = new Map();
|
|
133
|
+
for (let key of await (0, authorizedKeys_1.readRepoKeys)(repoPath).catch(() => [])) {
|
|
134
|
+
keysByFingerprint.set((0, authorizedKeys_1.keyFingerprint)(key), key);
|
|
135
|
+
}
|
|
136
|
+
let describeKey = (revocation) => {
|
|
137
|
+
let key = keysByFingerprint.get(revocation.fingerprint || "") || revocation.key || "";
|
|
138
|
+
return key && (0, authorizedKeys_1.summarizeKey)(key) || `a key no longer in this repo (${revocation.fingerprint})`;
|
|
139
|
+
};
|
|
140
|
+
let addressesByIdentity = new Map();
|
|
141
|
+
for (let revocation of revocations) {
|
|
142
|
+
let ip = (0, unrevoke_1.revocationIP)(revocation);
|
|
143
|
+
let identity = (0, unrevoke_1.revocationIdentity)(revocation);
|
|
144
|
+
let existing = addressesByIdentity.get(identity) || [];
|
|
145
|
+
if (ip && !existing.includes(ip)) {
|
|
146
|
+
existing.push(ip);
|
|
147
|
+
}
|
|
148
|
+
addressesByIdentity.set(identity, existing);
|
|
149
|
+
}
|
|
150
|
+
// Cancelling the revocation on its own would leave sshd refusing that address, and the machines
|
|
151
|
+
// revoking all over again, so the addresses go into the key's from= list and into the machine's
|
|
152
|
+
// own file here. We are in the repo that owns both, so there is nothing to hand back to whoever
|
|
153
|
+
// ran this.
|
|
154
|
+
let added = await allowAddressesInRepo({ repoPath, addressesByFingerprint: addressesByIdentity });
|
|
155
|
+
let addedForMachines = await allowAddressesForMachines({ repoPath, revocations });
|
|
156
|
+
console.log("");
|
|
157
|
+
for (let [identity, addresses] of addressesByIdentity) {
|
|
158
|
+
let entries = revocations.filter(entry => (0, unrevoke_1.revocationIdentity)(entry) === identity);
|
|
159
|
+
let machineId = entries[0].machineId;
|
|
160
|
+
console.log(`Unfreezing ${machineId && `machine ${machineId}` || describeKey(entries[0])}`);
|
|
161
|
+
console.log(`Allowing IP ${addresses.join(", ") || "(no address recorded)"}`);
|
|
162
|
+
let addedHere = machineId && addedForMachines.get(machineId) || added.get(identity) || [];
|
|
163
|
+
if (addedHere.length) {
|
|
164
|
+
let where = machineId && `machines/${machineId}.json` || `that key's from= list in authorized_keys`;
|
|
165
|
+
console.log(` added to ${where}: ${addedHere.join(", ")}`);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
console.log(` already allowed from ${addresses.join(", ") || "everywhere"}`);
|
|
169
|
+
}
|
|
170
|
+
for (let entry of entries) {
|
|
171
|
+
console.log(` frozen by ${entry.revokedBy || "?"} ${entry.revokedAt || "at an unrecorded time"}`);
|
|
172
|
+
}
|
|
173
|
+
console.log("");
|
|
174
|
+
}
|
|
175
|
+
console.log(`Every other address stays frozen, and any of these used from anywhere else is`);
|
|
176
|
+
console.log(`frozen again.`);
|
|
177
|
+
// Signed here rather than left as a step to remember. An unrevoke nobody signed does nothing at
|
|
178
|
+
// all, and the repo would sit there looking done while every machine ignored it.
|
|
179
|
+
await (0, signFiles_1.signRepo)({ repoPath });
|
|
180
|
+
if (!pushToGit) {
|
|
181
|
+
console.log(`\nCommit and push it, and those keys work again as each machine picks it up:`);
|
|
182
|
+
console.log(`\`\`\`\ngit add -A\ngit commit -m "${COMMIT_MESSAGE}"\ngit push\n\`\`\``);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
await (0, runPromise_1.runPromise)(`git add -A`, { cwd: repoPath });
|
|
186
|
+
await (0, runPromise_1.runPromise)(`git commit -m "${COMMIT_MESSAGE}"`, { cwd: repoPath });
|
|
187
|
+
await (0, runPromise_1.runPromise)(`git push`, { cwd: repoPath });
|
|
188
|
+
console.log(`\nCommitted and pushed. Those keys work again as each machine picks it up.`);
|
|
189
|
+
}
|
|
190
|
+
main().catch(e => {
|
|
191
|
+
console.error(`${e}`);
|
|
192
|
+
process.exitCode = 1;
|
|
193
|
+
}).finally(() => process.exit());
|
|
194
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5yZXZva2VDbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1bnJldm9rZUNsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJEQUE2QjtBQUM3QixnREFBd0I7QUFDeEIsK0RBQTREO0FBQzVELHFEQUE4RjtBQUM5RixpREFBK0M7QUFDL0Msd0RBQW9EO0FBQ3BELG1EQUFnRTtBQUNoRSx5Q0FBNkM7QUFDN0MseUNBQWdIO0FBRWhILE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQztBQUMxQixNQUFNLGNBQWMsR0FBRyxlQUFlLENBQUM7QUFDdkMsTUFBTSxLQUFLLEdBQUcscUNBQXFDLFdBQVc7Ozs7dUJBSXZDLFdBQVc7OzswQkFHUixDQUFDO0FBRTNCOzt3RUFFd0U7QUFDeEUsS0FBSyxVQUFVLG9CQUFvQixDQUFDLE1BR25DO0lBQ0csSUFBSSxFQUFFLFFBQVEsRUFBRSxzQkFBc0IsRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUNsRCxJQUFJLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBb0IsQ0FBQztJQUN4QyxJQUFJLFFBQVEsR0FBRyxjQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3RELElBQUksUUFBUSxDQUFDO0lBQ2IsSUFBSSxDQUFDO1FBQ0QsUUFBUSxHQUFHLE1BQU0sa0JBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1QsdUZBQXVGO1FBQ3ZGLGlEQUFpRDtRQUNqRCxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixRQUFRLCtDQUErQyxDQUFDLENBQUM7UUFDOUYsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUNELElBQUksS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakMsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUs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LEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyw0RUFBNEUsQ0FBQyxDQUFDO0FBQzlGLENBQUM7QUFFRCxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7SUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0QixPQUFPLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztBQUN6QixDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgcnVuUHJvbWlzZSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL3J1blByb21pc2VcIjtcbmltcG9ydCB7IGFsbG93QWRkcmVzc2VzLCBrZXlGaW5nZXJwcmludCwgcmVhZFJlcG9LZXlzLCBzdW1tYXJpemVLZXkgfSBmcm9tIFwiLi9hdXRob3JpemVkS2V5c1wiO1xuaW1wb3J0IHsgcmV2b2tlUmVwb1VSTCB9IGZyb20gXCIuL3Jldm9rZVNvdXJjZVwiO1xuaW1wb3J0IHsgc2lnblJlcG8gfSBmcm9tIFwiLi4vc2lnbmVkRmlsZXMvc2lnbkZpbGVzXCI7XG5pbXBvcnQgeyBnZXRNYWNoaW5lcywgc2V0TWFjaGluZXMgfSBmcm9tIFwiLi4vbWFjaGluZXMvbWFjaGluZXNcIjtcbmltcG9ydCB7IHJlc29sdmVLZXlzUmVwbyB9IGZyb20gXCIuL2tleXNSZXBvXCI7XG5pbXBvcnQgeyByZWFkUmVtb3RlUmV2b2NhdGlvbnMsIFJldm9jYXRpb24sIHJldm9jYXRpb25JZGVudGl0eSwgcmV2b2NhdGlvbklQLCBVTlJFVk9LRVNfRElSIH0gZnJvbSBcIi4vdW5yZXZva2VcIjtcblxuY29uc3QgR0lUX0tFWVdPUkQgPSBcImdpdFwiO1xuY29uc3QgQ09NTUlUX01FU1NBR0UgPSBcInVucmV2b2tlIGtleXNcIjtcbmNvbnN0IFVTQUdFID0gYFVzYWdlOiB5YXJuIHVucmV2b2tlIFtrZXlzLXJlcG9dIFske0dJVF9LRVlXT1JEfV1cblxuUnVuIHRoaXMgaW4gYSBrZXlzIHJlcG8sIG9yIG5hbWUgb25lLiBJdCByZWFkcyB0aGF0IHJlcG8ncyByZXZva2UgcmVwbyBhbmQgd3JpdGVzIG9uZSB1bnJldm9rZSBmaWxlXG5uYW1pbmcgZXZlcnkgcmV2b2NhdGlvbiBpbiBpdCwgc28gdGhlIGtleXMgYXJlIGFjY2VwdGVkIGFnYWluIGFzIGVhY2ggbWFjaGluZSBwaWNrcyBpdCB1cC4gSXQgc2lnbnNcbnRoZSByZXN1bHQsIGFuZCB3aXRoICR7R0lUX0tFWVdPUkR9IGl0IGNvbW1pdHMgYW5kIHB1c2hlcyBpdCB0b28uXG5cbktleXMgdGhhdCB3ZXJlIHJldm9rZWQgc2hvdWxkIG5vcm1hbGx5IGJlIGRlbGV0ZWQgZnJvbSB0aGUgcmVwbyBpbnN0ZWFkLiBVbnJldm9raW5nIG9ubHkgbWF0dGVyc1xuZm9yIGEga2V5IHlvdSBzdGlsbCB3YW50LmA7XG5cbi8qKiBXcml0ZXMgdGhlIGFkZHJlc3NlcyBpbnRvIHRoZSBmcm9tPSBsaXN0IG9mIGVhY2gga2V5IGluIHRoZSByZXBvJ3MgYXV0aG9yaXplZF9rZXlzLCBhbmQgc2F5c1xuICAgIHdoaWNoIG9uZXMgd2VyZSBhY3R1YWxseSBuZXcuIE9ubHkgdGhlIGxpbmVzIGJlaW5nIGNoYW5nZWQgYXJlIHRvdWNoZWQsIHNvIGNvbW1lbnRzLCBvcmRlcmluZ1xuICAgIGFuZCBhbnkga2V5IG5vdCBpbnZvbHZlZCBjb21lIG91dCBvZiB0aGlzIGJ5dGUgZm9yIGJ5dGUgdGhlIHNhbWUuICovXG5hc3luYyBmdW5jdGlvbiBhbGxvd0FkZHJlc3Nlc0luUmVwbyhjb25maWc6IHtcbiAgICByZXBvUGF0aDogc3RyaW5nO1xuICAgIGFkZHJlc3Nlc0J5RmluZ2VycHJpbnQ6IE1hcDxzdHJpbmcsIHN0cmluZ1tdPjtcbn0pIHtcbiAgICBsZXQgeyByZXBvUGF0aCwgYWRkcmVzc2VzQnlGaW5nZXJwcmludCB9ID0gY29uZmlnO1xuICAgIGxldCBhZGRlZCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICBsZXQgZmlsZVBhdGggPSBwYXRoLmpvaW4ocmVwb1BhdGgsIFwiYXV0aG9yaXplZF9rZXlzXCIpO1xuICAgIGxldCBjb250ZW50cztcbiAgICB0cnkge1xuICAgICAgICBjb250ZW50cyA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCBcInV0ZjhcIik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBBIHJlcG8gaG9sZGluZyBpdHMga2V5cyBhcyBzZXBhcmF0ZSAucHViIGZpbGVzLiBOb3RoaW5nIHRvIGVkaXQgaW4gb25lIHBsYWNlLCBzbyB0aGVcbiAgICAgICAgLy8gY2FsbGVyJ3MgbGlzdGluZyBpcyBhbGwgd2hvZXZlciByYW4gdGhpcyBnZXRzLlxuICAgICAgICBjb25zb2xlLmxvZyhgTm8gYXV0aG9yaXplZF9rZXlzIGluICR7cmVwb1BhdGh9LCBzbyB0aGUgYWRkcmVzc2VzIHdlcmUgbm90IGFkZGVkIHRvIGFueSBrZXkuYCk7XG4gICAgICAgIHJldHVybiBhZGRlZDtcbiAgICB9XG4gICAgbGV0IGxpbmVzID0gY29udGVudHMuc3BsaXQoXCJcXG5cIik7XG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGxpbmVzLmxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICBsZXQgZmluZ2VycHJpbnQgPSBrZXlGaW5nZXJwcmludChsaW5lc1tpbmRleF0pO1xuICAgICAgICBsZXQgYWRkcmVzc2VzID0gZmluZ2VycHJpbnQgJiYgYWRkcmVzc2VzQnlGaW5nZXJwcmludC5nZXQoZmluZ2VycHJpbnQpO1xuICAgICAgICBpZiAoIWFkZHJlc3NlcyB8fCAhYWRkcmVzc2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJlc3VsdCA9IGFsbG93QWRkcmVzc2VzKGxpbmVzW2luZGV4XSwgYWRkcmVzc2VzKTtcbiAgICAgICAgbGluZXNbaW5kZXhdID0gcmVzdWx0LmtleUxpbmU7XG4gICAgICAgIGFkZGVkLnNldChmaW5nZXJwcmludCwgWy4uLihhZGRlZC5nZXQoZmluZ2VycHJpbnQpIHx8IFtdKSwgLi4ucmVzdWx0LmFkZGVkXSk7XG4gICAgfVxuICAgIGlmIChbLi4uYWRkZWQudmFsdWVzKCldLnNvbWUobGlzdCA9PiBsaXN0Lmxlbmd0aCkpIHtcbiAgICAgICAgYXdhaXQgZnMud3JpdGVGaWxlKGZpbGVQYXRoLCBsaW5lcy5qb2luKFwiXFxuXCIpKTtcbiAgICB9XG4gICAgcmV0dXJuIGFkZGVkO1xufVxuXG4vKiogUHV0cyBlYWNoIG1hY2hpbmUncyBhZGRyZXNzZXMgYmFjayBpbnRvIGl0cyBvd24gZmlsZSwgd2hpY2ggaXMgdGhlIG1hY2hpbmUgZXF1aXZhbGVudCBvZiBhZGRpbmdcbiAgICBhbiBhZGRyZXNzIHRvIGEga2V5J3MgZnJvbT0gbGlzdDogd2l0aG91dCBpdCB0aGUgbWFjaGluZSBpcyBhbGxvd2VkIGFnYWluIGluIHByaW5jaXBsZSBhbmRcbiAgICBzdGlsbCByZWplY3RlZCBvbiBzaWdodCwgd2hpY2ggcmV2b2tlcyBpdCBvbmNlIG1vcmUuICovXG5hc3luYyBmdW5jdGlvbiBhbGxvd0FkZHJlc3Nlc0Zvck1hY2hpbmVzKGNvbmZpZzogeyByZXBvUGF0aDogc3RyaW5nOyByZXZvY2F0aW9uczogUmV2b2NhdGlvbltdIH0pIHtcbiAgICBsZXQgeyByZXBvUGF0aCwgcmV2b2NhdGlvbnMgfSA9IGNvbmZpZztcbiAgICBsZXQgYWRkZWQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG4gICAgLy8gUmVhZCB0aGUgd2hvbGUgbGlzdCwgY2hhbmdlIHdoYXQgdGhlc2UgcmV2b2NhdGlvbnMgYXJlIGFib3V0LCB3cml0ZSBpdCBiYWNrLiBTZXR0aW5nIGlzIGJ5XG4gICAgLy8gdGhlIHdob2xlIHNldCwgc28gd3JpdGluZyBvbmUgbWFjaGluZSBhdCBhIHRpbWUgd291bGQgZGVsZXRlIGV2ZXJ5IG90aGVyIG1hY2hpbmUuXG4gICAgbGV0IG1hY2hpbmVzID0gYXdhaXQgZ2V0TWFjaGluZXMocmVwb1BhdGgpO1xuICAgIGZvciAobGV0IHJldm9jYXRpb24gb2YgcmV2b2NhdGlvbnMpIHtcbiAgICAgICAgbGV0IG1hY2hpbmVJZCA9IHJldm9jYXRpb24ubWFjaGluZUlkO1xuICAgICAgICBsZXQgaXAgPSByZXZvY2F0aW9uSVAocmV2b2NhdGlvbik7XG4gICAgICAgIGlmICghbWFjaGluZUlkIHx8ICFpcCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGV4aXN0aW5nID0gbWFjaGluZXMuZmluZChtYWNoaW5lID0+IG1hY2hpbmUubWFjaGluZUlkID09PSBtYWNoaW5lSWQpO1xuICAgICAgICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmVkIGZyb20gdGhlIHJlcG8gc2luY2UgaXQgd2FzIHJldm9rZWQsIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG8gYWxsb3cuIERlbGV0aW5nIGFcbiAgICAgICAgICAgIC8vIG1hY2hpbmUgaXMgdGhlIHN0cm9uZ2VyIHN0YXRlbWVudCBhbmQgaXQgc3RhbmRzLlxuICAgICAgICAgICAgY29uc29sZS5sb2coYG1hY2hpbmVzLyR7bWFjaGluZUlkfS5qc29uIGlzIG5vdCBpbiB0aGlzIHJlcG8sIHNvICR7aXB9IHdhcyBub3QgYWRkZWQgdG8gaXRgKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChleGlzdGluZy5pcHMuaW5jbHVkZXMoaXApKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBleGlzdGluZy5pcHMgPSBbLi4uZXhpc3RpbmcuaXBzLCBpcF07XG4gICAgICAgIGFkZGVkLnNldChtYWNoaW5lSWQsIFsuLi4oYWRkZWQuZ2V0KG1hY2hpbmVJZCkgfHwgW10pLCBpcF0pO1xuICAgIH1cbiAgICBpZiAoYWRkZWQuc2l6ZSkge1xuICAgICAgICBhd2FpdCBzZXRNYWNoaW5lcyh7IHJlcG9QYXRoLCBtYWNoaW5lcyB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFkZGVkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICAgIGxldCBhcmd2ID0gcHJvY2Vzcy5hcmd2LnNsaWNlKDIpO1xuICAgIGxldCBwdXNoVG9HaXQgPSBhcmd2LmluY2x1ZGVzKEdJVF9LRVlXT1JEKTtcbiAgICBsZXQgcG9zaXRpb25hbCA9IGFyZ3YuZmlsdGVyKGFyZyA9PiBhcmcgIT09IEdJVF9LRVlXT1JEKTtcbiAgICBpZiAocG9zaXRpb25hbC5sZW5ndGggPiAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgYXQgbW9zdCBhIGtleXMgcmVwbywgd2FzICR7cG9zaXRpb25hbC5sZW5ndGh9IGFyZ3VtZW50KHMpXFxuJHtVU0FHRX1gKTtcbiAgICB9XG4gICAgbGV0IHsgcmVwb1BhdGgsIHNvdXJjZVVSTDogb3JpZ2luVVJMIH0gPSBhd2FpdCByZXNvbHZlS2V5c1JlcG8ocG9zaXRpb25hbFswXSk7XG5cbiAgICBsZXQgcmV2b2NhdGlvbnMgPSBhd2FpdCByZWFkUmVtb3RlUmV2b2NhdGlvbnMoeyBzb3VyY2VVUkw6IG9yaWdpblVSTCB9KTtcbiAgICBpZiAoIXJldm9jYXRpb25zLmxlbmd0aCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgJHtyZXZva2VSZXBvVVJMKG9yaWdpblVSTCl9IGxpc3RzIG5vIHJldm9jYXRpb25zLCBzbyB0aGVyZSBpcyBub3RoaW5nIHRvIHVuZG8uYCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZGlyZWN0b3J5ID0gcGF0aC5qb2luKHJlcG9QYXRoLCBVTlJFVk9LRVNfRElSKTtcbiAgICBhd2FpdCBmcy5ta2RpcihkaXJlY3RvcnksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGxldCBzdGFtcCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKS5yZXBsYWNlKC9bOi5dL2csIFwiLVwiKTtcbiAgICBsZXQgdW5yZXZva2VJZCA9IGAke3N0YW1wfS11bnJldm9rZWA7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHBhdGguam9pbihkaXJlY3RvcnksIGAke3VucmV2b2tlSWR9Lmpzb25gKSwgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICB1bnJldm9rZUlkLFxuICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgLy8gV2hhdCB0aGlzIGZpbGUgc2F5czogZWFjaCBvZiB0aGVzZSBrZXlzIGlzIGFsbG93ZWQgZnJvbSB0aGlzIGFkZHJlc3MuIFBhaXJzLCBub3Qga2V5cyxcbiAgICAgICAgLy8gYW5kIG5vdCBhIGJsYW5rZXQgXCJhbGxvdyBldmVyeXRoaW5nIGFnYWluXCIgLSBhIGtleSBmb3JnaXZlbiBoZXJlIGZvciBvbmUgYWRkcmVzcyBpc1xuICAgICAgICAvLyBzdGlsbCByZXZva2VkIHRoZSBtb21lbnQgaXQgaXMgdXNlZCBmcm9tIGFub3RoZXIuXG4gICAgICAgIGFsbG93ZWQ6IHJldm9jYXRpb25zLm1hcChyZXZvY2F0aW9uID0+ICh7XG4gICAgICAgICAgICBmaW5nZXJwcmludDogcmV2b2NhdGlvbi5maW5nZXJwcmludCxcbiAgICAgICAgICAgIG1hY2hpbmVJZDogcmV2b2NhdGlvbi5tYWNoaW5lSWQsXG4gICAgICAgICAgICBpcDogcmV2b2NhdGlvbklQKHJldm9jYXRpb24pLFxuICAgICAgICB9KSksXG4gICAgICAgIHJldm9jYXRpb25zOiByZXZvY2F0aW9ucy5tYXAocmV2b2NhdGlvbiA9PiAoe1xuICAgICAgICAgICAgcmV2b2NhdGlvbklkOiByZXZvY2F0aW9uLnJldm9jYXRpb25JZCxcbiAgICAgICAgICAgIGZpbmdlcnByaW50OiByZXZvY2F0aW9uLmZpbmdlcnByaW50LFxuICAgICAgICAgICAgbWFjaGluZUlkOiByZXZvY2F0aW9uLm1hY2hpbmVJZCxcbiAgICAgICAgICAgIGlwOiByZXZvY2F0aW9uSVAocmV2b2NhdGlvbiksXG4gICAgICAgICAgICByZXZva2VkQXQ6IHJldm9jYXRpb24ucmV2b2tlZEF0LFxuICAgICAgICAgICAgcmV2b2tlZEJ5OiByZXZvY2F0aW9uLnJldm9rZWRCeSxcbiAgICAgICAgICAgIGF0dGVtcHQ6IHJldm9jYXRpb24uYXR0ZW1wdCxcbiAgICAgICAgfSkpLFxuICAgIH0sIHVuZGVmaW5lZCwgNCkgKyBcIlxcblwiKTtcblxuICAgIC8vIE5hbWVkIHRoZSB3YXkgdGhlIG5vdGlmaWNhdGlvbnMgbmFtZSB0aGVtLiBBIGZpbmdlcnByaW50IGlzIG5vdCBpbiBhdXRob3JpemVkX2tleXMgYW5kXG4gICAgLy8gY2Fubm90IGJlIHdvcmtlZCBvdXQgYnkgZXllLCBzbyBvbiBpdHMgb3duIGl0IHRlbGxzIHdob2V2ZXIgaXMgcmVhZGluZyB0aGlzIG5vdGhpbmcgYWJvdXRcbiAgICAvLyB3aGljaCBvZiB0aGVpciBrZXlzIGlzIGJlaW5nIHRhbGtlZCBhYm91dC5cbiAgICBsZXQga2V5c0J5RmluZ2VycHJpbnQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgIGZvciAobGV0IGtleSBvZiBhd2FpdCByZWFkUmVwb0tleXMocmVwb1BhdGgpLmNhdGNoKCgpID0+IFtdIGFzIHN0cmluZ1tdKSkge1xuICAgICAgICBrZXlzQnlGaW5nZXJwcmludC5zZXQoa2V5RmluZ2VycHJpbnQoa2V5KSwga2V5KTtcbiAgICB9XG4gICAgbGV0IGRlc2NyaWJlS2V5ID0gKHJldm9jYXRpb246IFJldm9jYXRpb24pID0+IHtcbiAgICAgICAgbGV0IGtleSA9IGtleXNCeUZpbmdlcnByaW50LmdldChyZXZvY2F0aW9uLmZpbmdlcnByaW50IHx8IFwiXCIpIHx8IHJldm9jYXRpb24ua2V5IHx8IFwiXCI7XG4gICAgICAgIHJldHVybiBrZXkgJiYgc3VtbWFyaXplS2V5KGtleSkgfHwgYGEga2V5IG5vIGxvbmdlciBpbiB0aGlzIHJlcG8gKCR7cmV2b2NhdGlvbi5maW5nZXJwcmludH0pYDtcbiAgICB9O1xuXG4gICAgbGV0IGFkZHJlc3Nlc0J5SWRlbnRpdHkgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG4gICAgZm9yIChsZXQgcmV2b2NhdGlvbiBvZiByZXZvY2F0aW9ucykge1xuICAgICAgICBsZXQgaXAgPSByZXZvY2F0aW9uSVAocmV2b2NhdGlvbik7XG4gICAgICAgIGxldCBpZGVudGl0eSA9IHJldm9jYXRpb25JZGVudGl0eShyZXZvY2F0aW9uKTtcbiAgICAgICAgbGV0IGV4aXN0aW5nID0gYWRkcmVzc2VzQnlJZGVudGl0eS5nZXQoaWRlbnRpdHkpIHx8IFtdO1xuICAgICAgICBpZiAoaXAgJiYgIWV4aXN0aW5nLmluY2x1ZGVzKGlwKSkge1xuICAgICAgICAgICAgZXhpc3RpbmcucHVzaChpcCk7XG4gICAgICAgIH1cbiAgICAgICAgYWRkcmVzc2VzQnlJZGVudGl0eS5zZXQoaWRlbnRpdHksIGV4aXN0aW5nKTtcbiAgICB9XG5cbiAgICAvLyBDYW5jZWxsaW5nIHRoZSByZXZvY2F0aW9uIG9uIGl0cyBvd24gd291bGQgbGVhdmUgc3NoZCByZWZ1c2luZyB0aGF0IGFkZHJlc3MsIGFuZCB0aGUgbWFjaGluZXNcbiAgICAvLyByZXZva2luZyBhbGwgb3ZlciBhZ2Fpbiwgc28gdGhlIGFkZHJlc3NlcyBnbyBpbnRvIHRoZSBrZXkncyBmcm9tPSBsaXN0IGFuZCBpbnRvIHRoZSBtYWNoaW5lJ3NcbiAgICAvLyBvd24gZmlsZSBoZXJlLiBXZSBhcmUgaW4gdGhlIHJlcG8gdGhhdCBvd25zIGJvdGgsIHNvIHRoZXJlIGlzIG5vdGhpbmcgdG8gaGFuZCBiYWNrIHRvIHdob2V2ZXJcbiAgICAvLyByYW4gdGhpcy5cbiAgICBsZXQgYWRkZWQgPSBhd2FpdCBhbGxvd0FkZHJlc3Nlc0luUmVwbyh7IHJlcG9QYXRoLCBhZGRyZXNzZXNCeUZpbmdlcnByaW50OiBhZGRyZXNzZXNCeUlkZW50aXR5IH0pO1xuICAgIGxldCBhZGRlZEZvck1hY2hpbmVzID0gYXdhaXQgYWxsb3dBZGRyZXNzZXNGb3JNYWNoaW5lcyh7IHJlcG9QYXRoLCByZXZvY2F0aW9ucyB9KTtcblxuICAgIGNvbnNvbGUubG9nKFwiXCIpO1xuICAgIGZvciAobGV0IFtpZGVudGl0eSwgYWRkcmVzc2VzXSBvZiBhZGRyZXNzZXNCeUlkZW50aXR5KSB7XG4gICAgICAgIGxldCBlbnRyaWVzID0gcmV2b2NhdGlvbnMuZmlsdGVyKGVudHJ5ID0+IHJldm9jYXRpb25JZGVudGl0eShlbnRyeSkgPT09IGlkZW50aXR5KTtcbiAgICAgICAgbGV0IG1hY2hpbmVJZCA9IGVudHJpZXNbMF0ubWFjaGluZUlkO1xuICAgICAgICBjb25zb2xlLmxvZyhgVW5mcmVlemluZyAke21hY2hpbmVJZCAmJiBgbWFjaGluZSAke21hY2hpbmVJZH1gIHx8IGRlc2NyaWJlS2V5KGVudHJpZXNbMF0pfWApO1xuICAgICAgICBjb25zb2xlLmxvZyhgQWxsb3dpbmcgSVAgJHthZGRyZXNzZXMuam9pbihcIiwgXCIpIHx8IFwiKG5vIGFkZHJlc3MgcmVjb3JkZWQpXCJ9YCk7XG4gICAgICAgIGxldCBhZGRlZEhlcmUgPSBtYWNoaW5lSWQgJiYgYWRkZWRGb3JNYWNoaW5lcy5nZXQobWFjaGluZUlkKSB8fCBhZGRlZC5nZXQoaWRlbnRpdHkpIHx8IFtdO1xuICAgICAgICBpZiAoYWRkZWRIZXJlLmxlbmd0aCkge1xuICAgICAgICAgICAgbGV0IHdoZXJlID0gbWFjaGluZUlkICYmIGBtYWNoaW5lcy8ke21hY2hpbmVJZH0uanNvbmAgfHwgYHRoYXQga2V5J3MgZnJvbT0gbGlzdCBpbiBhdXRob3JpemVkX2tleXNgO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYCAgYWRkZWQgdG8gJHt3aGVyZX06ICR7YWRkZWRIZXJlLmpvaW4oXCIsIFwiKX1gKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGAgIGFscmVhZHkgYWxsb3dlZCBmcm9tICR7YWRkcmVzc2VzLmpvaW4oXCIsIFwiKSB8fCBcImV2ZXJ5d2hlcmVcIn1gKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICBgICBmcm96ZW4gYnkgJHtlbnRyeS5yZXZva2VkQnkgfHwgXCI/XCJ9ICR7ZW50cnkucmV2b2tlZEF0IHx8IFwiYXQgYW4gdW5yZWNvcmRlZCB0aW1lXCJ9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhcIlwiKTtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYEV2ZXJ5IG90aGVyIGFkZHJlc3Mgc3RheXMgZnJvemVuLCBhbmQgYW55IG9mIHRoZXNlIHVzZWQgZnJvbSBhbnl3aGVyZSBlbHNlIGlzYCk7XG4gICAgY29uc29sZS5sb2coYGZyb3plbiBhZ2Fpbi5gKTtcblxuICAgIC8vIFNpZ25lZCBoZXJlIHJhdGhlciB0aGFuIGxlZnQgYXMgYSBzdGVwIHRvIHJlbWVtYmVyLiBBbiB1bnJldm9rZSBub2JvZHkgc2lnbmVkIGRvZXMgbm90aGluZyBhdFxuICAgIC8vIGFsbCwgYW5kIHRoZSByZXBvIHdvdWxkIHNpdCB0aGVyZSBsb29raW5nIGRvbmUgd2hpbGUgZXZlcnkgbWFjaGluZSBpZ25vcmVkIGl0LlxuICAgIGF3YWl0IHNpZ25SZXBvKHsgcmVwb1BhdGggfSk7XG5cbiAgICBpZiAoIXB1c2hUb0dpdCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgXFxuQ29tbWl0IGFuZCBwdXNoIGl0LCBhbmQgdGhvc2Uga2V5cyB3b3JrIGFnYWluIGFzIGVhY2ggbWFjaGluZSBwaWNrcyBpdCB1cDpgKTtcbiAgICAgICAgY29uc29sZS5sb2coYFxcYFxcYFxcYFxcbmdpdCBhZGQgLUFcXG5naXQgY29tbWl0IC1tIFwiJHtDT01NSVRfTUVTU0FHRX1cIlxcbmdpdCBwdXNoXFxuXFxgXFxgXFxgYCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgcnVuUHJvbWlzZShgZ2l0IGFkZCAtQWAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgY29tbWl0IC1tIFwiJHtDT01NSVRfTUVTU0FHRX1cImAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBhd2FpdCBydW5Qcm9taXNlKGBnaXQgcHVzaGAsIHsgY3dkOiByZXBvUGF0aCB9KTtcbiAgICBjb25zb2xlLmxvZyhgXFxuQ29tbWl0dGVkIGFuZCBwdXNoZWQuIFRob3NlIGtleXMgd29yayBhZ2FpbiBhcyBlYWNoIG1hY2hpbmUgcGlja3MgaXQgdXAuYCk7XG59XG5cbm1haW4oKS5jYXRjaChlID0+IHtcbiAgICBjb25zb2xlLmVycm9yKGAke2V9YCk7XG4gICAgcHJvY2Vzcy5leGl0Q29kZSA9IDE7XG59KS5maW5hbGx5KCgpID0+IHByb2Nlc3MuZXhpdCgpKTtcbiJdfQ=//=
|
|
195
|
+
/* _JS_SOURCE_HASH = "f6c17d2f0173417994f5271731eccb0a6513782dab56cce076a212b049203f65"; */
|