sliftutils 1.7.127 → 1.7.129
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/addmachine.js +9 -0
- package/bin/machineclient.js +9 -0
- package/bin/machineserver.js +10 -0
- package/index.d.ts +15 -0
- package/misc/dist/ownIPs.ts.cache +43 -0
- 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.d.ts +11 -0
- package/misc/ownIPs.ts +34 -0
- package/package.json +9 -3
- package/security/authorizedKeys/authorizedKeys.ts +34 -0
- package/security/authorizedKeys/daemon/authLog.ts +12 -5
- package/security/authorizedKeys/daemon/changes.ts +16 -1
- package/security/authorizedKeys/daemon/daemon.ts +50 -40
- package/security/authorizedKeys/daemon/dist/changes.ts.cache +40 -0
- package/security/authorizedKeys/daemon/dist/git.ts.cache +121 -0
- package/security/authorizedKeys/daemon/dist/notify.ts.cache +39 -0
- package/security/authorizedKeys/daemon/dist/paths.ts.cache +29 -0
- package/security/authorizedKeys/daemon/dist/repoFiles.ts.cache +114 -0
- package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
- package/security/authorizedKeys/daemon/dist/sessions.ts.cache +147 -0
- package/security/authorizedKeys/daemon/dist/state.ts.cache +74 -0
- package/security/authorizedKeys/daemon/dist/trust.ts.cache +295 -0
- package/security/authorizedKeys/daemon/git.ts +3 -3
- package/security/authorizedKeys/daemon/notify.ts +8 -2
- package/security/authorizedKeys/daemon/repoFiles.ts +118 -0
- package/security/authorizedKeys/daemon/revocation.ts +0 -0
- package/security/authorizedKeys/daemon/rootKeys.ts +77 -10
- package/security/authorizedKeys/daemon/state.ts +25 -7
- package/security/authorizedKeys/daemon/trust.ts +37 -16
- package/security/authorizedKeys/daemon/userKeys.ts +5 -4
- package/security/authorizedKeys/dist/authorizedKeys.ts.cache +37 -3
- package/security/authorizedKeys/dist/revokeSource.ts.cache +17 -4
- package/security/authorizedKeys/dist/sources.ts.cache +52 -8
- package/security/authorizedKeys/dist/unrevoke.ts.cache +113 -17
- package/security/authorizedKeys/revokeSource.ts +12 -2
- package/security/authorizedKeys/secureSSH.ts +66 -12
- package/security/authorizedKeys/sources.ts +47 -5
- package/security/authorizedKeys/unrevoke.ts +176 -16
- package/security/helpers/dist/remoteSSH.ts.cache +19 -9
- package/security/machines/addMachine.ts +83 -0
- package/security/machines/dist/addMachine.ts.cache +88 -0
- package/security/machines/dist/identity.ts.cache +176 -0
- package/security/machines/dist/machines.ts.cache +322 -0
- package/security/machines/dist/trustClient.ts.cache +48 -0
- package/security/machines/dist/trustState.ts.cache +57 -0
- package/security/machines/identity.ts +199 -0
- package/security/machines/machines.ts +355 -0
- package/security/machines/trustClient.ts +51 -0
- package/security/machines/trustServer.ts +85 -0
- package/security/machines/trustState.ts +53 -0
- package/security/notifications/discord.ts +14 -5
- package/security/notifications/dist/discord.ts.cache +17 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import os from "os";
|
|
3
3
|
import { configureDiscordNotifications, DEFAULT_WEBHOOK_FILE_PATH } from "../../notifications/discord";
|
|
4
|
-
import { sourceKeyPath, sourceRepoPath } from "../sources";
|
|
4
|
+
import { findSourceKey, legacySourceKeyPath, sourceKeyPath, sourceRepoPath } from "../sources";
|
|
5
5
|
import { cloneRepo, syncRepo } from "./git";
|
|
6
6
|
import {
|
|
7
7
|
CHECK_INTERVAL,
|
|
@@ -15,7 +15,9 @@ import { enforceSSHDConfig } from "./sshdConfig";
|
|
|
15
15
|
import { getState, loadState, saveState, sourceState } from "./state";
|
|
16
16
|
import { resolveSourceKeys } from "./trust";
|
|
17
17
|
import { parseAuthLog, readNewAuthLog, watchAuthLog } from "./authLog";
|
|
18
|
-
import { absorbRevocations, applyUnrevokes, recordRevocation, removeRevokedKeys
|
|
18
|
+
import { absorbRevocations, applyUnrevokes, pairKey, recordRevocation, removeRevokedKeys } from "./revocation";
|
|
19
|
+
import { revokeRepo, syncRepoFiles } from "./repoFiles";
|
|
20
|
+
import { revokeRepoURL } from "../revokeSource";
|
|
19
21
|
import { keyFingerprint } from "../authorizedKeys";
|
|
20
22
|
import { addChangeReason } from "./changes";
|
|
21
23
|
import { checkOtherUserKeys, seedUserKeys } from "./userKeys";
|
|
@@ -42,6 +44,8 @@ import { checkOtherUserKeys, seedUserKeys } from "./userKeys";
|
|
|
42
44
|
// 7. A source changed without its signature being updated, so the change is ignored.
|
|
43
45
|
// 8. A source has a corrupted signature, so its contents are ignored.
|
|
44
46
|
// 9. The webhook file itself changed, reported to the webhook being replaced.
|
|
47
|
+
// 10. A trusted machine talked to us from an address it is not allowed from, so it was frozen
|
|
48
|
+
// everywhere. Sent by whichever machine wrote that revocation, from machines.ts.
|
|
45
49
|
|
|
46
50
|
export type DaemonConfig = {
|
|
47
51
|
repoSources: string[];
|
|
@@ -74,10 +78,11 @@ async function loadConfig(): Promise<DaemonConfig> {
|
|
|
74
78
|
process.exit(1);
|
|
75
79
|
}
|
|
76
80
|
for (let repoURL of parsed.repoSources) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
if (!await findSourceKey(repoURL)) {
|
|
82
|
+
console.error(
|
|
83
|
+
`portsecure: expected the private key for ${repoURL} at ${sourceKeyPath(repoURL)}`
|
|
84
|
+
+ ` or ${legacySourceKeyPath(repoURL)}, neither exists`
|
|
85
|
+
);
|
|
81
86
|
process.exit(1);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
@@ -137,11 +142,13 @@ async function queueRefusedKeys(allowedKeys: string[]) {
|
|
|
137
142
|
}
|
|
138
143
|
let state = getState();
|
|
139
144
|
for (let found of parseAuthLog(contents)) {
|
|
140
|
-
//
|
|
141
|
-
|
|
145
|
+
// A key and the address it was used from. The same pair twice is one revocation, but the
|
|
146
|
+
// same key from somewhere else is a new event, whatever was forgiven before.
|
|
147
|
+
let pair = pairKey({ fingerprint: found.fingerprint, ip: found.attempt.ip });
|
|
148
|
+
if (Object.values(state.revocations).some(revocation => pairKey(revocation) === pair)) {
|
|
142
149
|
continue;
|
|
143
150
|
}
|
|
144
|
-
if (state.pendingRevocations.some(pending => pending.fingerprint
|
|
151
|
+
if (state.pendingRevocations.some(pending => pairKey({ fingerprint: pending.fingerprint, ip: pending.attempt.ip }) === pair)) {
|
|
145
152
|
continue;
|
|
146
153
|
}
|
|
147
154
|
let sourceURL = sourceOfFingerprint(found.fingerprint);
|
|
@@ -174,11 +181,13 @@ async function writeQueuedRevocations() {
|
|
|
174
181
|
try {
|
|
175
182
|
let remaining = [];
|
|
176
183
|
for (let pending of state.pendingRevocations) {
|
|
177
|
-
|
|
184
|
+
let known = () => Object.values(state.revocations)
|
|
185
|
+
.some(revocation => pairKey(revocation) === pairKey({ fingerprint: pending.fingerprint, ip: pending.attempt.ip }));
|
|
186
|
+
if (known()) {
|
|
178
187
|
continue;
|
|
179
188
|
}
|
|
180
189
|
let recorded = await recordRevocation({ ...pending, hostLabel: config.hostLabel });
|
|
181
|
-
if (!recorded && !
|
|
190
|
+
if (!recorded && !known()) {
|
|
182
191
|
remaining.push(pending);
|
|
183
192
|
}
|
|
184
193
|
}
|
|
@@ -213,7 +222,7 @@ async function pollSource(repoURL: string) {
|
|
|
213
222
|
// Availability over tidiness: throw the working copy away and start again.
|
|
214
223
|
console.log(`Discarding the checkout of ${repoURL} and cloning from scratch`);
|
|
215
224
|
try {
|
|
216
|
-
await cloneRepo({ repoURL, repoPath: sourceRepoPath(repoURL), keyPath: sourceKeyPath(repoURL) });
|
|
225
|
+
await cloneRepo({ repoURL, repoPath: sourceRepoPath(repoURL), keyPath: await findSourceKey(repoURL) || sourceKeyPath(repoURL) });
|
|
217
226
|
repoFailureCounts[repoURL] = 0;
|
|
218
227
|
return true;
|
|
219
228
|
} catch (cloneError) {
|
|
@@ -223,10 +232,11 @@ async function pollSource(repoURL: string) {
|
|
|
223
232
|
}
|
|
224
233
|
|
|
225
234
|
if (result.historyRewritten) {
|
|
226
|
-
await notify(
|
|
227
|
-
`
|
|
228
|
-
+ `
|
|
229
|
-
+
|
|
235
|
+
await notify(`KEY REPO HISTORY REWRITTEN`,
|
|
236
|
+
`Commits that used to be in \`${repoURL}\` are gone, so somebody force pushed over it`
|
|
237
|
+
+ ` or tampered with it. Whatever it says now has been applied.`
|
|
238
|
+
+ `\n\nwas at: \`${result.previousSha.slice(0, 12)}\``
|
|
239
|
+
+ `\nnow at: \`${result.remoteSha.slice(0, 12)}\``
|
|
230
240
|
);
|
|
231
241
|
}
|
|
232
242
|
if (!result.changed) {
|
|
@@ -234,11 +244,18 @@ async function pollSource(repoURL: string) {
|
|
|
234
244
|
}
|
|
235
245
|
// Said when the file is written, and only if it came out different. A commit that does not
|
|
236
246
|
// touch the keys is not worth telling anyone about.
|
|
237
|
-
addChangeReason(
|
|
247
|
+
addChangeReason(`The key repo \`${repoURL}\` moved to \`${result.remoteSha.slice(0, 12)}\`.`);
|
|
238
248
|
sourceState(repoURL).lastSha = result.remoteSha;
|
|
239
249
|
return true;
|
|
240
250
|
}
|
|
241
251
|
|
|
252
|
+
/** The one loop. Every repo this machine reads is brought up to date here: each source, and the
|
|
253
|
+
revoke repo beside it that says which of its keys are no longer accepted.
|
|
254
|
+
|
|
255
|
+
A repo that cannot be read is reported and skipped, and nothing downstream may read that as an
|
|
256
|
+
answer. An unreachable source keeps the keys it last gave us, and an unreachable revoke repo
|
|
257
|
+
keeps the revocations we already know - the alternative is one network failure emptying
|
|
258
|
+
authorized_keys, or handing a revoked key back to every machine. */
|
|
242
259
|
async function everyCheck() {
|
|
243
260
|
let anyChanged = false;
|
|
244
261
|
for (let repoURL of config.repoSources) {
|
|
@@ -246,17 +263,20 @@ async function everyCheck() {
|
|
|
246
263
|
try {
|
|
247
264
|
anyChanged = await pollSource(repoURL) || anyChanged;
|
|
248
265
|
} catch (e) {
|
|
249
|
-
console.
|
|
266
|
+
console.error(`Polling ${repoURL} failed, its last known keys stay in place. ${e && (e as Error).stack || e}`);
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
await syncRepoFiles(revokeRepo(repoURL));
|
|
270
|
+
} catch (e) {
|
|
271
|
+
console.error(
|
|
272
|
+
`Could not read ${revokeRepoURL(repoURL)}, the revocations already known stay in place. ${e}`
|
|
273
|
+
);
|
|
250
274
|
}
|
|
251
275
|
}
|
|
252
276
|
if (anyChanged) {
|
|
253
277
|
await saveState();
|
|
254
278
|
}
|
|
255
279
|
|
|
256
|
-
// What other machines have revoked, and anything published to undo a revocation.
|
|
257
|
-
for (let repoURL of config.repoSources) {
|
|
258
|
-
await syncRevokeRepo(repoURL);
|
|
259
|
-
}
|
|
260
280
|
await absorbRevocations(config.repoSources);
|
|
261
281
|
await applyUnrevokes(config.repoSources);
|
|
262
282
|
|
|
@@ -298,28 +318,18 @@ export async function main() {
|
|
|
298
318
|
|
|
299
319
|
console.log(`Starting, ${config.repoSources.length} source(s), keys applied to ${ROOT_AUTHORIZED_KEYS}`);
|
|
300
320
|
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
for (let repoURL of config.repoSources) {
|
|
304
|
-
try {
|
|
305
|
-
sourceState(repoURL).lastSha = (await syncRepo(repoURL)).remoteSha;
|
|
306
|
-
} catch (e) {
|
|
307
|
-
console.log(`Initial sync of ${repoURL} failed, continuing with whatever is on disk. ${e}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
await saveState();
|
|
321
|
+
// Whatever other users already have, before the first check, so what is there at startup is
|
|
322
|
+
// not reported as somebody having just changed it.
|
|
311
323
|
await seedUserKeys();
|
|
312
324
|
|
|
313
|
-
for (let repoURL of config.repoSources) {
|
|
314
|
-
await syncRevokeRepo(repoURL);
|
|
315
|
-
}
|
|
316
|
-
await absorbRevocations(config.repoSources);
|
|
317
|
-
await enforceRootKeys(await removeRevokedKeys(await readAllowedKeys()));
|
|
318
|
-
await enforceSSHDConfig();
|
|
319
|
-
|
|
320
325
|
// configureDiscordNotifications watches the webhook file on its own, so there is nothing to
|
|
321
326
|
// schedule for it here.
|
|
322
|
-
startInterval({ name: "check", intervalTime: CHECK_INTERVAL, run: everyCheck });
|
|
327
|
+
let runCheck = startInterval({ name: "check", intervalTime: CHECK_INTERVAL, run: everyCheck });
|
|
328
|
+
// The same check as every other, run once now rather than a minute from now: a machine has to
|
|
329
|
+
// be correct immediately after boot. Running the one function, rather than a startup copy of
|
|
330
|
+
// it, is what keeps a step from being left out of one of them - the copy here had no
|
|
331
|
+
// applyUnrevokes, so every restart re-applied a revocation that had already been undone.
|
|
332
|
+
await runCheck();
|
|
323
333
|
|
|
324
334
|
// A refused login is acted on when sshd writes it. The one pass here covers anything written
|
|
325
335
|
// while the daemon was not running.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Why root's authorized_keys is about to change, collected as it happens.
|
|
3
|
+
//
|
|
4
|
+
// Nothing announces itself at the moment it decides something. A revocation arriving, a key being
|
|
5
|
+
// revoked here, an unrevoke taking effect, a repo moving on: each of those says what it is and
|
|
6
|
+
// leaves it here. The file is then written, and only if it actually came out different does any of
|
|
7
|
+
// it get reported, in one message.
|
|
8
|
+
//
|
|
9
|
+
// Doing it the other way round is what produced several messages for one event, and messages about
|
|
10
|
+
// removing a key that had already gone.
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
12
|
+
//exports.takeChangeReasons = exports.addLeadingChangeReason = exports.addChangeReason = void 0;
|
|
13
|
+
let reasons = [];
|
|
14
|
+
let leadingReasons = [];
|
|
15
|
+
function addChangeReason(reason) {
|
|
16
|
+
// The same reason twice in one pass says nothing the once did not.
|
|
17
|
+
if (!reasons.includes(reason)) {
|
|
18
|
+
reasons.push(reason);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.addChangeReason = addChangeReason;
|
|
22
|
+
/** For the one thing worth reading before anything else: somebody using a key from an address it
|
|
23
|
+
is not allowed from. */
|
|
24
|
+
function addLeadingChangeReason(reason) {
|
|
25
|
+
if (!leadingReasons.some(existing => existing.headline === reason.headline)) {
|
|
26
|
+
leadingReasons.push(reason);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.addLeadingChangeReason = addLeadingChangeReason;
|
|
30
|
+
/** The reasons gathered since the last write, and clears them. Called whether or not anything
|
|
31
|
+
changed, so reasons that came to nothing cannot show up against some later change. */
|
|
32
|
+
function takeChangeReasons() {
|
|
33
|
+
let taken = { leading: leadingReasons, reasons };
|
|
34
|
+
leadingReasons = [];
|
|
35
|
+
reasons = [];
|
|
36
|
+
return taken;
|
|
37
|
+
}
|
|
38
|
+
exports.takeChangeReasons = takeChangeReasons;
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhbmdlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNoYW5nZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDBFQUEwRTtBQUMxRSxFQUFFO0FBQ0Ysa0dBQWtHO0FBQ2xHLCtGQUErRjtBQUMvRixtR0FBbUc7QUFDbkcsbUNBQW1DO0FBQ25DLEVBQUU7QUFDRixtR0FBbUc7QUFDbkcsd0NBQXdDOzs7QUFPeEMsSUFBSSxPQUFPLEdBQWEsRUFBRSxDQUFDO0FBQzNCLElBQUksY0FBYyxHQUFvQixFQUFFLENBQUM7QUFFekMsU0FBZ0IsZUFBZSxDQUFDLE1BQWM7SUFDMUMsbUVBQW1FO0lBQ25FLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDNUIsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QixDQUFDO0FBQ0wsQ0FBQztBQUxELDBDQUtDO0FBRUQ7MkJBQzJCO0FBQzNCLFNBQWdCLHNCQUFzQixDQUFDLE1BQXFCO0lBQ3hELElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsS0FBSyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUMxRSxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2hDLENBQUM7QUFDTCxDQUFDO0FBSkQsd0RBSUM7QUFFRDt5RkFDeUY7QUFDekYsU0FBZ0IsaUJBQWlCO0lBQzdCLElBQUksS0FBSyxHQUFHLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNqRCxjQUFjLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLE9BQU8sR0FBRyxFQUFFLENBQUM7SUFDYixPQUFPLEtBQUssQ0FBQztBQUNqQixDQUFDO0FBTEQsOENBS0MiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBXaHkgcm9vdCdzIGF1dGhvcml6ZWRfa2V5cyBpcyBhYm91dCB0byBjaGFuZ2UsIGNvbGxlY3RlZCBhcyBpdCBoYXBwZW5zLlxuLy9cbi8vIE5vdGhpbmcgYW5ub3VuY2VzIGl0c2VsZiBhdCB0aGUgbW9tZW50IGl0IGRlY2lkZXMgc29tZXRoaW5nLiBBIHJldm9jYXRpb24gYXJyaXZpbmcsIGEga2V5IGJlaW5nXG4vLyByZXZva2VkIGhlcmUsIGFuIHVucmV2b2tlIHRha2luZyBlZmZlY3QsIGEgcmVwbyBtb3Zpbmcgb246IGVhY2ggb2YgdGhvc2Ugc2F5cyB3aGF0IGl0IGlzIGFuZFxuLy8gbGVhdmVzIGl0IGhlcmUuIFRoZSBmaWxlIGlzIHRoZW4gd3JpdHRlbiwgYW5kIG9ubHkgaWYgaXQgYWN0dWFsbHkgY2FtZSBvdXQgZGlmZmVyZW50IGRvZXMgYW55IG9mXG4vLyBpdCBnZXQgcmVwb3J0ZWQsIGluIG9uZSBtZXNzYWdlLlxuLy9cbi8vIERvaW5nIGl0IHRoZSBvdGhlciB3YXkgcm91bmQgaXMgd2hhdCBwcm9kdWNlZCBzZXZlcmFsIG1lc3NhZ2VzIGZvciBvbmUgZXZlbnQsIGFuZCBtZXNzYWdlcyBhYm91dFxuLy8gcmVtb3ZpbmcgYSBrZXkgdGhhdCBoYWQgYWxyZWFkeSBnb25lLlxuXG4vKiogQSByZWFzb24gaW1wb3J0YW50IGVub3VnaCB0byBuYW1lIHRoZSB3aG9sZSBtZXNzYWdlLiBJdHMgaGVhZGxpbmUgcmVwbGFjZXMgdGhlIG9uZSB0aGUgY2hhbmdlXG4gICAgaXRzZWxmIHdvdWxkIGhhdmUgZ290LCBiZWNhdXNlIFwic29tZWJvZHkgaXMgdXNpbmcgYSBrZXkgdGhleSBzaG91bGQgbm90XCIgb3V0cmFua3MgXCJ0aGUga2V5c1xuICAgIGNoYW5nZWRcIiBpbiB0aGUgb25lIGxpbmUgYSBwaG9uZSBzaG93cy4gKi9cbmV4cG9ydCB0eXBlIExlYWRpbmdSZWFzb24gPSB7IGhlYWRsaW5lOiBzdHJpbmc7IGJvZHk6IHN0cmluZyB9O1xuXG5sZXQgcmVhc29uczogc3RyaW5nW10gPSBbXTtcbmxldCBsZWFkaW5nUmVhc29uczogTGVhZGluZ1JlYXNvbltdID0gW107XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRDaGFuZ2VSZWFzb24ocmVhc29uOiBzdHJpbmcpIHtcbiAgICAvLyBUaGUgc2FtZSByZWFzb24gdHdpY2UgaW4gb25lIHBhc3Mgc2F5cyBub3RoaW5nIHRoZSBvbmNlIGRpZCBub3QuXG4gICAgaWYgKCFyZWFzb25zLmluY2x1ZGVzKHJlYXNvbikpIHtcbiAgICAgICAgcmVhc29ucy5wdXNoKHJlYXNvbik7XG4gICAgfVxufVxuXG4vKiogRm9yIHRoZSBvbmUgdGhpbmcgd29ydGggcmVhZGluZyBiZWZvcmUgYW55dGhpbmcgZWxzZTogc29tZWJvZHkgdXNpbmcgYSBrZXkgZnJvbSBhbiBhZGRyZXNzIGl0XG4gICAgaXMgbm90IGFsbG93ZWQgZnJvbS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRMZWFkaW5nQ2hhbmdlUmVhc29uKHJlYXNvbjogTGVhZGluZ1JlYXNvbikge1xuICAgIGlmICghbGVhZGluZ1JlYXNvbnMuc29tZShleGlzdGluZyA9PiBleGlzdGluZy5oZWFkbGluZSA9PT0gcmVhc29uLmhlYWRsaW5lKSkge1xuICAgICAgICBsZWFkaW5nUmVhc29ucy5wdXNoKHJlYXNvbik7XG4gICAgfVxufVxuXG4vKiogVGhlIHJlYXNvbnMgZ2F0aGVyZWQgc2luY2UgdGhlIGxhc3Qgd3JpdGUsIGFuZCBjbGVhcnMgdGhlbS4gQ2FsbGVkIHdoZXRoZXIgb3Igbm90IGFueXRoaW5nXG4gICAgY2hhbmdlZCwgc28gcmVhc29ucyB0aGF0IGNhbWUgdG8gbm90aGluZyBjYW5ub3Qgc2hvdyB1cCBhZ2FpbnN0IHNvbWUgbGF0ZXIgY2hhbmdlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRha2VDaGFuZ2VSZWFzb25zKCkge1xuICAgIGxldCB0YWtlbiA9IHsgbGVhZGluZzogbGVhZGluZ1JlYXNvbnMsIHJlYXNvbnMgfTtcbiAgICBsZWFkaW5nUmVhc29ucyA9IFtdO1xuICAgIHJlYXNvbnMgPSBbXTtcbiAgICByZXR1cm4gdGFrZW47XG59XG4iXX0=
|
|
40
|
+
/* _JS_SOURCE_HASH = "6d0282fa2244057d7a106dc14b6b13dd37ddc1ba1ecc4a44b33dfd51c3e409a5"; */
|
|
@@ -0,0 +1,121 @@
|
|
|
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
|
+
//exports.syncRepo = exports.currentBranch = exports.cloneRepo = exports.repoIsUsable = exports.runGit = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const spawn_1 = require("../../helpers/spawn");
|
|
10
|
+
const sources_1 = require("../sources");
|
|
11
|
+
const paths_1 = require("./paths");
|
|
12
|
+
const state_1 = require("./state");
|
|
13
|
+
async function pathExists(filePath) {
|
|
14
|
+
try {
|
|
15
|
+
await promises_1.default.access(filePath);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** core.sshCommand keeps the key selection with the command instead of in the environment. */
|
|
23
|
+
async function runGit(config) {
|
|
24
|
+
let { args, cwd, keyPath, allowFailure } = config;
|
|
25
|
+
let sshCommand = `ssh -i ${keyPath} -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=accept-new`;
|
|
26
|
+
let result = await (0, spawn_1.spawnPromise)({
|
|
27
|
+
command: "git",
|
|
28
|
+
args: ["-c", `core.sshCommand=${sshCommand}`, ...args],
|
|
29
|
+
cwd,
|
|
30
|
+
timeoutTime: paths_1.GIT_TIMEOUT,
|
|
31
|
+
});
|
|
32
|
+
if (result.error) {
|
|
33
|
+
throw new Error(`Expected git ${args.join(" ")} to run, failed with ${result.error.message}`);
|
|
34
|
+
}
|
|
35
|
+
if (result.status !== 0 && !allowFailure) {
|
|
36
|
+
throw new Error(`Expected git ${args.join(" ")} to exit 0, was ${result.status}. `
|
|
37
|
+
+ `${(result.stdout + result.stderr).trim().slice(0, paths_1.MAX_ERROR_BODY_LENGTH)}`);
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
exports.runGit = runGit;
|
|
42
|
+
async function repoIsUsable(config) {
|
|
43
|
+
let { repoPath, keyPath } = config;
|
|
44
|
+
if (!await pathExists(path_1.default.join(repoPath, ".git"))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
let result = await runGit({ args: ["rev-parse", "--git-dir"], cwd: repoPath, keyPath, allowFailure: true });
|
|
48
|
+
if (result.status !== 0) {
|
|
49
|
+
console.log(`Repo at ${repoPath} is not usable. ${(result.stdout + result.stderr).trim()}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
exports.repoIsUsable = repoIsUsable;
|
|
55
|
+
/** Cloned beside the old checkout and swapped in, so a clone that fails leaves the copy we are
|
|
56
|
+
already using untouched rather than deleting the only keys we have. */
|
|
57
|
+
async function cloneRepo(config) {
|
|
58
|
+
let { repoURL, repoPath, keyPath } = config;
|
|
59
|
+
let incomingPath = `${repoPath}.incoming`;
|
|
60
|
+
await promises_1.default.rm(incomingPath, { recursive: true, force: true });
|
|
61
|
+
await promises_1.default.mkdir(path_1.default.dirname(repoPath), { recursive: true });
|
|
62
|
+
await runGit({ args: ["clone", repoURL, incomingPath], keyPath });
|
|
63
|
+
await promises_1.default.rm(repoPath, { recursive: true, force: true });
|
|
64
|
+
await promises_1.default.rename(incomingPath, repoPath);
|
|
65
|
+
console.log(`Cloned ${repoURL} into ${repoPath}`);
|
|
66
|
+
}
|
|
67
|
+
exports.cloneRepo = cloneRepo;
|
|
68
|
+
async function currentBranch(config) {
|
|
69
|
+
return (await runGit({ args: ["rev-parse", "--abbrev-ref", "HEAD"], ...config })).stdout.trim();
|
|
70
|
+
}
|
|
71
|
+
exports.currentBranch = currentBranch;
|
|
72
|
+
async function ensureSourceRepo(repoURL) {
|
|
73
|
+
let repoPath = (0, sources_1.sourceRepoPath)(repoURL);
|
|
74
|
+
let keyPath = await (0, sources_1.findSourceKey)(repoURL) || (0, sources_1.sourceKeyPath)(repoURL);
|
|
75
|
+
if (!await repoIsUsable({ repoPath, keyPath })) {
|
|
76
|
+
await cloneRepo({ repoURL, repoPath, keyPath });
|
|
77
|
+
}
|
|
78
|
+
if (!(0, state_1.sourceState)(repoURL).branch) {
|
|
79
|
+
(0, state_1.sourceState)(repoURL).branch = await currentBranch({ repoPath, keyPath });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Returns what changed, so the caller can report it. A rewritten history is called out
|
|
83
|
+
separately - it means the remote no longer contains the commits we already had. */
|
|
84
|
+
async function syncRepo(repoURL) {
|
|
85
|
+
await ensureSourceRepo(repoURL);
|
|
86
|
+
let repoPath = (0, sources_1.sourceRepoPath)(repoURL);
|
|
87
|
+
let keyPath = await (0, sources_1.findSourceKey)(repoURL) || (0, sources_1.sourceKeyPath)(repoURL);
|
|
88
|
+
let branch = (0, state_1.sourceState)(repoURL).branch;
|
|
89
|
+
let localSha = (await runGit({ args: ["rev-parse", "HEAD"], cwd: repoPath, keyPath })).stdout.trim();
|
|
90
|
+
// A ref listing is a few hundred bytes and no objects, so the usual case of nothing having
|
|
91
|
+
// changed costs almost nothing and we only fetch when there is something to fetch.
|
|
92
|
+
let listing = (await runGit({ args: ["ls-remote", "origin", branch], cwd: repoPath, keyPath })).stdout;
|
|
93
|
+
let remoteSha = (listing.split(/\s+/)[0] || "").trim();
|
|
94
|
+
if (!remoteSha) {
|
|
95
|
+
throw new Error(`Expected origin to report a sha for ${branch}, listed ${listing.slice(0, paths_1.MAX_ERROR_BODY_LENGTH)}`);
|
|
96
|
+
}
|
|
97
|
+
if (remoteSha === localSha && remoteSha === (0, state_1.sourceState)(repoURL).lastSha) {
|
|
98
|
+
return { changed: false, historyRewritten: false, remoteSha, previousSha: localSha };
|
|
99
|
+
}
|
|
100
|
+
await runGit({ args: ["fetch", "--prune", "origin", branch], cwd: repoPath, keyPath });
|
|
101
|
+
remoteSha = (await runGit({ args: ["rev-parse", `origin/${branch}`], cwd: repoPath, keyPath })).stdout.trim();
|
|
102
|
+
let previousSha = (0, state_1.sourceState)(repoURL).lastSha || localSha;
|
|
103
|
+
let historyRewritten = false;
|
|
104
|
+
if (previousSha && previousSha !== remoteSha) {
|
|
105
|
+
// If what we already had is no longer an ancestor of the remote tip, commits were removed
|
|
106
|
+
// or rewritten rather than added.
|
|
107
|
+
let ancestry = await runGit({
|
|
108
|
+
args: ["merge-base", "--is-ancestor", previousSha, remoteSha],
|
|
109
|
+
cwd: repoPath,
|
|
110
|
+
keyPath,
|
|
111
|
+
allowFailure: true,
|
|
112
|
+
});
|
|
113
|
+
historyRewritten = ancestry.status !== 0;
|
|
114
|
+
}
|
|
115
|
+
await runGit({ args: ["reset", "--hard", `origin/${branch}`], cwd: repoPath, keyPath });
|
|
116
|
+
await runGit({ args: ["clean", "-fdx"], cwd: repoPath, keyPath });
|
|
117
|
+
return { changed: true, historyRewritten, remoteSha, previousSha };
|
|
118
|
+
}
|
|
119
|
+
exports.syncRepo = syncRepo;
|
|
120
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZ2l0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJEQUE2QjtBQUM3QixnREFBd0I7QUFDeEIsK0NBQW1EO0FBQ25ELHdDQUEwRTtBQUMxRSxtQ0FBNkQ7QUFDN0QsbUNBQXNDO0FBRXRDLEtBQUssVUFBVSxVQUFVLENBQUMsUUFBZ0I7SUFDdEMsSUFBSSxDQUFDO1FBQ0QsTUFBTSxrQkFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxQixPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7QUFDTCxDQUFDO0FBRUQsOEZBQThGO0FBQ3ZGLEtBQUssVUFBVSxNQUFNLENBQUMsTUFBaUY7SUFDMUcsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sQ0FBQztJQUNsRCxJQUFJLFVBQVUsR0FBRyxVQUFVLE9BQU8sNkVBQTZFLENBQUM7SUFDaEgsSUFBSSxNQUFNLEdBQUcsTUFBTSxJQUFBLG9CQUFZLEVBQUM7UUFDNUIsT0FBTyxFQUFFLEtBQUs7UUFDZCxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsbUJBQW1CLFVBQVUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBQ3RELEdBQUc7UUFDSCxXQUFXLEVBQUUsbUJBQVc7S0FDM0IsQ0FBQyxDQUFDO0lBQ0gsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLElBQUksS0FBSyxDQUFDLGdCQUFnQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ2xHLENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMs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QVcsRUFBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLElBQUksUUFBUSxDQUFDO0lBQzNELElBQUksZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0lBQzdCLElBQUksV0FBVyxJQUFJLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMzQywwRkFBMEY7UUFDMUYsa0NBQWtDO1FBQ2xDLElBQUksUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDO1lBQ3hCLElBQUksRUFBRSxDQUFDLFlBQVksRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQztZQUM3RCxHQUFHLEVBQUUsUUFBUTtZQUNiLE9BQU87WUFDUCxZQUFZLEVBQUUsSUFBSTtTQUNyQixDQUFDLENBQUM7UUFDSCxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBQ0QsTUFBTSxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLFVBQVUsTUFBTSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDeEYsTUFBTSxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ2xFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUN2RSxDQUFDO0FBckNELDRCQXFDQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBzcGF3blByb21pc2UgfSBmcm9tIFwiLi4vLi4vaGVscGVycy9zcGF3blwiO1xuaW1wb3J0IHsgZmluZFNvdXJjZUtleSwgc291cmNlS2V5UGF0aCwgc291cmNlUmVwb1BhdGggfSBmcm9tIFwiLi4vc291cmNlc1wiO1xuaW1wb3J0IHsgR0lUX1RJTUVPVVQsIE1BWF9FUlJPUl9CT0RZX0xFTkdUSCB9IGZyb20gXCIuL3BhdGhzXCI7XG5pbXBvcnQgeyBzb3VyY2VTdGF0ZSB9IGZyb20gXCIuL3N0YXRlXCI7XG5cbmFzeW5jIGZ1bmN0aW9uIHBhdGhFeGlzdHMoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZzLmFjY2VzcyhmaWxlUGF0aCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLyoqIGNvcmUuc3NoQ29tbWFuZCBrZWVwcyB0aGUga2V5IHNlbGVjdGlvbiB3aXRoIHRoZSBjb21tYW5kIGluc3RlYWQgb2YgaW4gdGhlIGVudmlyb25tZW50LiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bkdpdChjb25maWc6IHsgYXJnczogc3RyaW5nW107IGN3ZD86IHN0cmluZzsga2V5UGF0aDogc3RyaW5nOyBhbGxvd0ZhaWx1cmU/OiBib29sZWFuIH0pIHtcbiAgICBsZXQgeyBhcmdzLCBjd2QsIGtleVBhdGgsIGFsbG93RmFpbHVyZSB9ID0gY29uZmlnO1xuICAgIGxldCBzc2hDb21tYW5kID0gYHNzaCAtaSAke2tleVBhdGh9IC1vIElkZW50aXRpZXNPbmx5PXllcyAtbyBCYXRjaE1vZGU9eWVzIC1vIFN0cmljdEhvc3RLZXlDaGVja2luZz1hY2NlcHQtbmV3YDtcbiAgICBsZXQgcmVzdWx0ID0gYXdhaXQgc3Bhd25Qcm9taXNlKHtcbiAgICAgICAgY29tbWFuZDogXCJnaXRcIixcbiAgICAgICAgYXJnczogW1wiLWNcIiwgYGNvcmUuc3NoQ29tbWFuZD0ke3NzaENvbW1hbmR9YCwgLi4uYXJnc10sXG4gICAgICAgIGN3ZCxcbiAgICAgICAgdGltZW91dFRpbWU6IEdJVF9USU1FT1VULFxuICAgIH0pO1xuICAgIGlmIChyZXN1bHQuZXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBnaXQgJHthcmdzLmpvaW4oXCIgXCIpfSB0byBydW4sIGZhaWxlZCB3aXRoICR7cmVzdWx0LmVycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICAgIGlmIChyZXN1bHQuc3RhdHVzICE9PSAwICYmICFhbGxvd0ZhaWx1cmUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkIGdpdCAke2FyZ3Muam9pbihcIiBcIil9IHRvIGV4aXQgMCwgd2FzICR7cmVzdWx0LnN0YXR1c30uIGBcbiAgICAgICAgICAgICsgYCR7KHJlc3VsdC5zdGRvdXQgKyByZXN1bHQuc3RkZXJyKS50cmltKCkuc2xpY2UoMCwgTUFYX0VSUk9SX0JPRFlfTEVOR1RIKX1gXG4gICAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXBvSXNVc2FibGUoY29uZmlnOiB7IHJlcG9QYXRoOiBzdHJpbmc7IGtleVBhdGg6IHN0cmluZyB9KSB7XG4gICAgbGV0IHsgcmVwb1BhdGgsIGtleVBhdGggfSA9IGNvbmZpZztcbiAgICBpZiAoIWF3YWl0IHBhdGhFeGlzdHMocGF0aC5qb2luKHJlcG9QYXRoLCBcIi5naXRcIikpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgbGV0IHJlc3VsdCA9IGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIi0tZ2l0LWRpclwiXSwgY3dkOiByZXBvUGF0aCwga2V5UGF0aCwgYWxsb3dGYWlsdXJlOiB0cnVlIH0pO1xuICAgIGlmIChyZXN1bHQuc3RhdHVzICE9PSAwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBSZXBvIGF0ICR7cmVwb1BhdGh9IGlzIG5vdCB1c2FibGUuICR7KHJlc3VsdC5zdGRvdXQgKyByZXN1bHQuc3RkZXJyKS50cmltKCl9YCk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbi8qKiBDbG9uZWQgYmVzaWRlIHRoZSBvbGQgY2hlY2tvdXQgYW5kIHN3YXBwZWQgaW4sIHNvIGEgY2xvbmUgdGhhdCBmYWlscyBsZWF2ZXMgdGhlIGNvcHkgd2UgYXJlXG4gICAgYWxyZWFkeSB1c2luZyB1bnRvdWNoZWQgcmF0aGVyIHRoYW4gZGVsZXRpbmcgdGhlIG9ubHkga2V5cyB3ZSBoYXZlLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsb25lUmVwbyhjb25maWc6IHsgcmVwb1VSTDogc3RyaW5nOyByZXBvUGF0aDogc3RyaW5nOyBrZXlQYXRoOiBzdHJpbmcgfSkge1xuICAgIGxldCB7IHJlcG9VUkwsIHJlcG9QYXRoLCBrZXlQYXRoIH0gPSBjb25maWc7XG4gICAgbGV0IGluY29taW5nUGF0aCA9IGAke3JlcG9QYXRofS5pbmNvbWluZ2A7XG4gICAgYXdhaXQgZnMucm0oaW5jb21pbmdQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gICAgYXdhaXQgZnMubWtkaXIocGF0aC5kaXJuYW1lKHJlcG9QYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgYXdhaXQgcnVuR2l0KHsgYXJnczogW1wiY2xvbmVcIiwgcmVwb1VSTCwgaW5jb21pbmdQYXRoXSwga2V5UGF0aCB9KTtcbiAgICBhd2FpdCBmcy5ybShyZXBvUGF0aCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuICAgIGF3YWl0IGZzLnJlbmFtZShpbmNvbWluZ1BhdGgsIHJlcG9QYXRoKTtcbiAgICBjb25zb2xlLmxvZyhgQ2xvbmVkICR7cmVwb1VSTH0gaW50byAke3JlcG9QYXRofWApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3VycmVudEJyYW5jaChjb25maWc6IHsgcmVwb1BhdGg6IHN0cmluZzsga2V5UGF0aDogc3RyaW5nIH0pIHtcbiAgICByZXR1cm4gKGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIi0tYWJicmV2LXJlZlwiLCBcIkhFQURcIl0sIC4uLmNvbmZpZyB9KSkuc3Rkb3V0LnRyaW0oKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZW5zdXJlU291cmNlUmVwbyhyZXBvVVJMOiBzdHJpbmcpIHtcbiAgICBsZXQgcmVwb1BhdGggPSBzb3VyY2VSZXBvUGF0aChyZXBvVVJMKTtcbiAgICBsZXQga2V5UGF0aCA9IGF3YWl0IGZpbmRTb3VyY2VLZXkocmVwb1VSTCkgfHwgc291cmNlS2V5UGF0aChyZXBvVVJMKTtcbiAgICBpZiAoIWF3YWl0IHJlcG9Jc1VzYWJsZSh7IHJlcG9QYXRoLCBrZXlQYXRoIH0pKSB7XG4gICAgICAgIGF3YWl0IGNsb25lUmVwbyh7IHJlcG9VUkwsIHJlcG9QYXRoLCBrZXlQYXRoIH0pO1xuICAgIH1cbiAgICBpZiAoIXNvdXJjZVN0YXRlKHJlcG9VUkwpLmJyYW5jaCkge1xuICAgICAgICBzb3VyY2VTdGF0ZShyZXBvVVJMKS5icmFuY2ggPSBhd2FpdCBjdXJyZW50QnJhbmNoKHsgcmVwb1BhdGgsIGtleVBhdGggfSk7XG4gICAgfVxufVxuXG4vKiogUmV0dXJucyB3aGF0IGNoYW5nZWQsIHNvIHRoZSBjYWxsZXIgY2FuIHJlcG9ydCBpdC4gQSByZXdyaXR0ZW4gaGlzdG9yeSBpcyBjYWxsZWQgb3V0XG4gICAgc2VwYXJhdGVseSAtIGl0IG1lYW5zIHRoZSByZW1vdGUgbm8gbG9uZ2VyIGNvbnRhaW5zIHRoZSBjb21taXRzIHdlIGFscmVhZHkgaGFkLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN5bmNSZXBvKHJlcG9VUkw6IHN0cmluZykge1xuICAgIGF3YWl0IGVuc3VyZVNvdXJjZVJlcG8ocmVwb1VSTCk7XG4gICAgbGV0IHJlcG9QYXRoID0gc291cmNlUmVwb1BhdGgocmVwb1VSTCk7XG4gICAgbGV0IGtleVBhdGggPSBhd2FpdCBmaW5kU291cmNlS2V5KHJlcG9VUkwpIHx8IHNvdXJjZUtleVBhdGgocmVwb1VSTCk7XG4gICAgbGV0IGJyYW5jaCA9IHNvdXJjZVN0YXRlKHJlcG9VUkwpLmJyYW5jaDtcbiAgICBsZXQgbG9jYWxTaGEgPSAoYXdhaXQgcnVuR2l0KHsgYXJnczogW1wicmV2LXBhcnNlXCIsIFwiSEVBRFwiXSwgY3dkOiByZXBvUGF0aCwga2V5UGF0aCB9KSkuc3Rkb3V0LnRyaW0oKTtcblxuICAgIC8vIEEgcmVmIGxpc3RpbmcgaXMgYSBmZXcgaHVuZHJlZCBieXRlcyBhbmQgbm8gb2JqZWN0cywgc28gdGhlIHVzdWFsIGNhc2Ugb2Ygbm90aGluZyBoYXZpbmdcbiAgICAvLyBjaGFuZ2VkIGNvc3RzIGFsbW9zdCBub3RoaW5nIGFuZCB3ZSBvbmx5IGZldGNoIHdoZW4gdGhlcmUgaXMgc29tZXRoaW5nIHRvIGZldGNoLlxuICAgIGxldCBsaXN0aW5nID0gKGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcImxzLXJlbW90ZVwiLCBcIm9yaWdpblwiLCBicmFuY2hdLCBjd2Q6IHJlcG9QYXRoLCBrZXlQYXRoIH0pKS5zdGRvdXQ7XG4gICAgbGV0IHJlbW90ZVNoYSA9IChsaXN0aW5nLnNwbGl0KC9cXHMrLylbMF0gfHwgXCJcIikudHJpbSgpO1xuICAgIGlmICghcmVtb3RlU2hhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgb3JpZ2luIHRvIHJlcG9ydCBhIHNoYSBmb3IgJHticmFuY2h9LCBsaXN0ZWQgJHtsaXN0aW5nLnNsaWNlKDAsIE1BWF9FUlJPUl9CT0RZX0xFTkdUSCl9YCk7XG4gICAgfVxuICAgIGlmIChyZW1vdGVTaGEgPT09IGxvY2FsU2hhICYmIHJlbW90ZVNoYSA9PT0gc291cmNlU3RhdGUocmVwb1VSTCkubGFzdFNoYSkge1xuICAgICAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSwgaGlzdG9yeVJld3JpdHRlbjogZmFsc2UsIHJlbW90ZVNoYSwgcHJldmlvdXNTaGE6IGxvY2FsU2hhIH07XG4gICAgfVxuXG4gICAgYXdhaXQgcnVuR2l0KHsgYXJnczogW1wiZmV0Y2hcIiwgXCItLXBydW5lXCIsIFwib3JpZ2luXCIsIGJyYW5jaF0sIGN3ZDogcmVwb1BhdGgsIGtleVBhdGggfSk7XG4gICAgcmVtb3RlU2hhID0gKGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcInJldi1wYXJzZVwiLCBgb3JpZ2luLyR7YnJhbmNofWBdLCBjd2Q6IHJlcG9QYXRoLCBrZXlQYXRoIH0pKS5zdGRvdXQudHJpbSgpO1xuXG4gICAgbGV0IHByZXZpb3VzU2hhID0gc291cmNlU3RhdGUocmVwb1VSTCkubGFzdFNoYSB8fCBsb2NhbFNoYTtcbiAgICBsZXQgaGlzdG9yeVJld3JpdHRlbiA9IGZhbHNlO1xuICAgIGlmIChwcmV2aW91c1NoYSAmJiBwcmV2aW91c1NoYSAhPT0gcmVtb3RlU2hhKSB7XG4gICAgICAgIC8vIElmIHdoYXQgd2UgYWxyZWFkeSBoYWQgaXMgbm8gbG9uZ2VyIGFuIGFuY2VzdG9yIG9mIHRoZSByZW1vdGUgdGlwLCBjb21taXRzIHdlcmUgcmVtb3ZlZFxuICAgICAgICAvLyBvciByZXdyaXR0ZW4gcmF0aGVyIHRoYW4gYWRkZWQuXG4gICAgICAgIGxldCBhbmNlc3RyeSA9IGF3YWl0IHJ1bkdpdCh7XG4gICAgICAgICAgICBhcmdzOiBbXCJtZXJnZS1iYXNlXCIsIFwiLS1pcy1hbmNlc3RvclwiLCBwcmV2aW91c1NoYSwgcmVtb3RlU2hhXSxcbiAgICAgICAgICAgIGN3ZDogcmVwb1BhdGgsXG4gICAgICAgICAgICBrZXlQYXRoLFxuICAgICAgICAgICAgYWxsb3dGYWlsdXJlOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgaGlzdG9yeVJld3JpdHRlbiA9IGFuY2VzdHJ5LnN0YXR1cyAhPT0gMDtcbiAgICB9XG4gICAgYXdhaXQgcnVuR2l0KHsgYXJnczogW1wicmVzZXRcIiwgXCItLWhhcmRcIiwgYG9yaWdpbi8ke2JyYW5jaH1gXSwgY3dkOiByZXBvUGF0aCwga2V5UGF0aCB9KTtcbiAgICBhd2FpdCBydW5HaXQoeyBhcmdzOiBbXCJjbGVhblwiLCBcIi1mZHhcIl0sIGN3ZDogcmVwb1BhdGgsIGtleVBhdGggfSk7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgaGlzdG9yeVJld3JpdHRlbiwgcmVtb3RlU2hhLCBwcmV2aW91c1NoYSB9O1xufVxuIl19
|
|
121
|
+
/* _JS_SOURCE_HASH = "da70130786edfd6c82adec69297c753d740fb3477e29daf0f2670052fa21b0fd"; */
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
//exports.notify = exports.setHostLabel = void 0;
|
|
7
|
+
const os_1 = __importDefault(require("os"));
|
|
8
|
+
const discord_1 = require("../../notifications/discord");
|
|
9
|
+
let hostLabelValue = "";
|
|
10
|
+
function setHostLabel(value) {
|
|
11
|
+
hostLabelValue = value;
|
|
12
|
+
}
|
|
13
|
+
exports.setHostLabel = setHostLabel;
|
|
14
|
+
// DO NOT add new calls to this. Every message goes to a real Discord server someone reads, so a
|
|
15
|
+
// notification is only ever added when the user explicitly asks for that specific case. Startup,
|
|
16
|
+
// success, errors, retries and recoveries all belong in console.log instead. The complete list of
|
|
17
|
+
// cases that are allowed to notify is at the top of daemon.ts.
|
|
18
|
+
/** A headline and the rest.
|
|
19
|
+
|
|
20
|
+
The headline is all a phone shows. It gets the whole preview to itself: no product name, no
|
|
21
|
+
host, no timestamp in front of it, because a person glancing at their lock screen needs to read
|
|
22
|
+
what happened, not which machine said it or when. Those go at the end, where they are there for
|
|
23
|
+
whoever opens the message and out of the way of whoever does not. */
|
|
24
|
+
async function notify(headline, body) {
|
|
25
|
+
let full = `**${headline}**\n\n${body}\n\n${hostLabelValue || os_1.default.hostname()}`;
|
|
26
|
+
// Logged before it is sent, and whether or not it arrives, so the journal is a complete record
|
|
27
|
+
// of what this machine had to say even when Discord is unreachable or the webhook is wrong.
|
|
28
|
+
console.log(`Discord: ${full}`);
|
|
29
|
+
try {
|
|
30
|
+
await (0, discord_1.sendDiscordNotification)(full);
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
// A failed notification must never take the daemon down, the local log is the fallback.
|
|
34
|
+
console.log(`Failed to send the Discord notification above. ${e}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.notify = notify;
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibm90aWZ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDRDQUFvQjtBQUNwQix5REFBc0U7QUFFdEUsSUFBSSxjQUFjLEdBQUcsRUFBRSxDQUFDO0FBRXhCLFNBQWdCLFlBQVksQ0FBQyxLQUFhO0lBQ3RDLGNBQWMsR0FBRyxLQUFLLENBQUM7QUFDM0IsQ0FBQztBQUZELG9DQUVDO0FBRUQsZ0dBQWdHO0FBQ2hHLGlHQUFpRztBQUNqRyxrR0FBa0c7QUFDbEcsK0RBQStEO0FBQy9EOzs7Ozt3RUFLd0U7QUFDakUsS0FBSyxVQUFVLE1BQU0sQ0FBQyxRQUFnQixFQUFFLElBQVk7SUFDdkQsSUFBSSxJQUFJLEdBQUcsS0FBSyxRQUFRLFNBQVMsSUFBSSxPQUFPLGNBQWMsSUFBSSxZQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztJQUM5RSwrRkFBK0Y7SUFDL0YsNEZBQTRGO0lBQzVGLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2hDLElBQUksQ0FBQztRQUNELE1BQU0sSUFBQSxpQ0FBdUIsRUFBQyxJQUFJLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULHdGQUF3RjtRQUN4RixPQUFPLENBQUMsR0FBRyxDQUFDLGtEQUFrRCxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7QUFDTCxDQUFDO0FBWEQsd0JBV0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgb3MgZnJvbSBcIm9zXCI7XG5pbXBvcnQgeyBzZW5kRGlzY29yZE5vdGlmaWNhdGlvbiB9IGZyb20gXCIuLi8uLi9ub3RpZmljYXRpb25zL2Rpc2NvcmRcIjtcblxubGV0IGhvc3RMYWJlbFZhbHVlID0gXCJcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldEhvc3RMYWJlbCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgaG9zdExhYmVsVmFsdWUgPSB2YWx1ZTtcbn1cblxuLy8gRE8gTk9UIGFkZCBuZXcgY2FsbHMgdG8gdGhpcy4gRXZlcnkgbWVzc2FnZSBnb2VzIHRvIGEgcmVhbCBEaXNjb3JkIHNlcnZlciBzb21lb25lIHJlYWRzLCBzbyBhXG4vLyBub3RpZmljYXRpb24gaXMgb25seSBldmVyIGFkZGVkIHdoZW4gdGhlIHVzZXIgZXhwbGljaXRseSBhc2tzIGZvciB0aGF0IHNwZWNpZmljIGNhc2UuIFN0YXJ0dXAsXG4vLyBzdWNjZXNzLCBlcnJvcnMsIHJldHJpZXMgYW5kIHJlY292ZXJpZXMgYWxsIGJlbG9uZyBpbiBjb25zb2xlLmxvZyBpbnN0ZWFkLiBUaGUgY29tcGxldGUgbGlzdCBvZlxuLy8gY2FzZXMgdGhhdCBhcmUgYWxsb3dlZCB0byBub3RpZnkgaXMgYXQgdGhlIHRvcCBvZiBkYWVtb24udHMuXG4vKiogQSBoZWFkbGluZSBhbmQgdGhlIHJlc3QuXG5cbiAgICBUaGUgaGVhZGxpbmUgaXMgYWxsIGEgcGhvbmUgc2hvd3MuIEl0IGdldHMgdGhlIHdob2xlIHByZXZpZXcgdG8gaXRzZWxmOiBubyBwcm9kdWN0IG5hbWUsIG5vXG4gICAgaG9zdCwgbm8gdGltZXN0YW1wIGluIGZyb250IG9mIGl0LCBiZWNhdXNlIGEgcGVyc29uIGdsYW5jaW5nIGF0IHRoZWlyIGxvY2sgc2NyZWVuIG5lZWRzIHRvIHJlYWRcbiAgICB3aGF0IGhhcHBlbmVkLCBub3Qgd2hpY2ggbWFjaGluZSBzYWlkIGl0IG9yIHdoZW4uIFRob3NlIGdvIGF0IHRoZSBlbmQsIHdoZXJlIHRoZXkgYXJlIHRoZXJlIGZvclxuICAgIHdob2V2ZXIgb3BlbnMgdGhlIG1lc3NhZ2UgYW5kIG91dCBvZiB0aGUgd2F5IG9mIHdob2V2ZXIgZG9lcyBub3QuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbm90aWZ5KGhlYWRsaW5lOiBzdHJpbmcsIGJvZHk6IHN0cmluZykge1xuICAgIGxldCBmdWxsID0gYCoqJHtoZWFkbGluZX0qKlxcblxcbiR7Ym9keX1cXG5cXG4ke2hvc3RMYWJlbFZhbHVlIHx8IG9zLmhvc3RuYW1lKCl9YDtcbiAgICAvLyBMb2dnZWQgYmVmb3JlIGl0IGlzIHNlbnQsIGFuZCB3aGV0aGVyIG9yIG5vdCBpdCBhcnJpdmVzLCBzbyB0aGUgam91cm5hbCBpcyBhIGNvbXBsZXRlIHJlY29yZFxuICAgIC8vIG9mIHdoYXQgdGhpcyBtYWNoaW5lIGhhZCB0byBzYXkgZXZlbiB3aGVuIERpc2NvcmQgaXMgdW5yZWFjaGFibGUgb3IgdGhlIHdlYmhvb2sgaXMgd3JvbmcuXG4gICAgY29uc29sZS5sb2coYERpc2NvcmQ6ICR7ZnVsbH1gKTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBzZW5kRGlzY29yZE5vdGlmaWNhdGlvbihmdWxsKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIEEgZmFpbGVkIG5vdGlmaWNhdGlvbiBtdXN0IG5ldmVyIHRha2UgdGhlIGRhZW1vbiBkb3duLCB0aGUgbG9jYWwgbG9nIGlzIHRoZSBmYWxsYmFjay5cbiAgICAgICAgY29uc29sZS5sb2coYEZhaWxlZCB0byBzZW5kIHRoZSBEaXNjb3JkIG5vdGlmaWNhdGlvbiBhYm92ZS4gJHtlfWApO1xuICAgIH1cbn1cbiJdfQ==
|
|
39
|
+
/* _JS_SOURCE_HASH = "9fe72e2c338fa1d2d53a34b85265b997cc47def23f019ca77b8a3735088305e5"; */
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Locations the daemon owns. Fixed rather than configurable, so every machine looks the same and
|
|
3
|
+
// the config file only carries what genuinely differs between them.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
5
|
+
//exports.MAX_REPO_FAILURES_BEFORE_RECLONE = exports.UNREVOKE_DELAY = exports.SIGNER_CHANGE_DELAY = exports.MAX_ERROR_BODY_LENGTH = exports.GIT_TIMEOUT = exports.WEBHOOK_CHECK_INTERVAL = exports.CHECK_INTERVAL = exports.AUTH_LOG_PATH = exports.PASSWD_PATH = exports.SSHD_DROPIN_PATH = exports.SSHD_DROPIN_DIR = exports.SSHD_CONFIG_PATH = exports.ROOT_AUTHORIZED_KEYS = exports.KEYS_HISTORY_PATH = exports.STATE_PATH = exports.CONFIG_PATH = void 0;
|
|
6
|
+
exports.CONFIG_PATH = "/etc/portsecure/daemon.json";
|
|
7
|
+
exports.STATE_PATH = "/var/lib/portsecure/state.json";
|
|
8
|
+
exports.KEYS_HISTORY_PATH = "/var/lib/portsecure/authorized-keys-history";
|
|
9
|
+
exports.ROOT_AUTHORIZED_KEYS = "/root/.ssh/authorized_keys";
|
|
10
|
+
exports.SSHD_CONFIG_PATH = "/etc/ssh/sshd_config";
|
|
11
|
+
exports.SSHD_DROPIN_DIR = "/etc/ssh/sshd_config.d";
|
|
12
|
+
exports.SSHD_DROPIN_PATH = "/etc/ssh/sshd_config.d/00-portsecure.conf";
|
|
13
|
+
exports.PASSWD_PATH = "/etc/passwd";
|
|
14
|
+
exports.AUTH_LOG_PATH = "/var/log/auth.log";
|
|
15
|
+
exports.CHECK_INTERVAL = 60 * 1000;
|
|
16
|
+
exports.WEBHOOK_CHECK_INTERVAL = 5 * 60 * 1000;
|
|
17
|
+
exports.GIT_TIMEOUT = 120 * 1000;
|
|
18
|
+
exports.MAX_ERROR_BODY_LENGTH = 500;
|
|
19
|
+
// A source that starts being signed by someone new is held at arm's length for this long, so a
|
|
20
|
+
// stolen signing key cannot push keys onto a machine before anyone notices the warning.
|
|
21
|
+
exports.SIGNER_CHANGE_DELAY = 24 * 60 * 60 * 1000;
|
|
22
|
+
// An unrevoke waits this long before taking effect, so a compromised signing key cannot instantly
|
|
23
|
+
// undo the revocation that locked it out.
|
|
24
|
+
exports.UNREVOKE_DELAY = 60 * 60 * 1000;
|
|
25
|
+
// After this many consecutive failures a repo is thrown away and cloned from scratch, which
|
|
26
|
+
// recovers from corruption and interrupted fetches. Counted in checks, so about a quarter hour.
|
|
27
|
+
exports.MAX_REPO_FAILURES_BEFORE_RECLONE = 15;
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwYXRocy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsaUdBQWlHO0FBQ2pHLG9FQUFvRTs7O0FBRXZELFFBQUEsV0FBVyxHQUFHLDZCQUE2QixDQUFDO0FBQzVDLFFBQUEsVUFBVSxHQUFHLGdDQUFnQyxDQUFDO0FBQzlDLFFBQUEsaUJBQWlCLEdBQUcsNkNBQTZDLENBQUM7QUFDbEUsUUFBQSxvQkFBb0IsR0FBRyw0QkFBNEIsQ0FBQztBQUNwRCxRQUFBLGdCQUFnQixHQUFHLHNCQUFzQixDQUFDO0FBQzFDLFFBQUEsZUFBZSxHQUFHLHdCQUF3QixDQUFDO0FBQzNDLFFBQUEsZ0JBQWdCLEdBQUcsMkNBQTJDLENBQUM7QUFDL0QsUUFBQSxXQUFXLEdBQUcsYUFBYSxDQUFDO0FBQzVCLFFBQUEsYUFBYSxHQUFHLG1CQUFtQixDQUFDO0FBRXBDLFFBQUEsY0FBYyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDM0IsUUFBQSxzQkFBc0IsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUN2QyxRQUFBLFdBQVcsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDO0FBQ3pCLFFBQUEscUJBQXFCLEdBQUcsR0FBRyxDQUFDO0FBQ3pDLCtGQUErRjtBQUMvRix3RkFBd0Y7QUFDM0UsUUFBQSxtQkFBbUIsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDdkQsa0dBQWtHO0FBQ2xHLDBDQUEwQztBQUM3QixRQUFBLGNBQWMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUM3Qyw0RkFBNEY7QUFDNUYsZ0dBQWdHO0FBQ25GLFFBQUEsZ0NBQWdDLEdBQUcsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTG9jYXRpb25zIHRoZSBkYWVtb24gb3ducy4gRml4ZWQgcmF0aGVyIHRoYW4gY29uZmlndXJhYmxlLCBzbyBldmVyeSBtYWNoaW5lIGxvb2tzIHRoZSBzYW1lIGFuZFxuLy8gdGhlIGNvbmZpZyBmaWxlIG9ubHkgY2FycmllcyB3aGF0IGdlbnVpbmVseSBkaWZmZXJzIGJldHdlZW4gdGhlbS5cblxuZXhwb3J0IGNvbnN0IENPTkZJR19QQVRIID0gXCIvZXRjL3BvcnRzZWN1cmUvZGFlbW9uLmpzb25cIjtcbmV4cG9ydCBjb25zdCBTVEFURV9QQVRIID0gXCIvdmFyL2xpYi9wb3J0c2VjdXJlL3N0YXRlLmpzb25cIjtcbmV4cG9ydCBjb25zdCBLRVlTX0hJU1RPUllfUEFUSCA9IFwiL3Zhci9saWIvcG9ydHNlY3VyZS9hdXRob3JpemVkLWtleXMtaGlzdG9yeVwiO1xuZXhwb3J0IGNvbnN0IFJPT1RfQVVUSE9SSVpFRF9LRVlTID0gXCIvcm9vdC8uc3NoL2F1dGhvcml6ZWRfa2V5c1wiO1xuZXhwb3J0IGNvbnN0IFNTSERfQ09ORklHX1BBVEggPSBcIi9ldGMvc3NoL3NzaGRfY29uZmlnXCI7XG5leHBvcnQgY29uc3QgU1NIRF9EUk9QSU5fRElSID0gXCIvZXRjL3NzaC9zc2hkX2NvbmZpZy5kXCI7XG5leHBvcnQgY29uc3QgU1NIRF9EUk9QSU5fUEFUSCA9IFwiL2V0Yy9zc2gvc3NoZF9jb25maWcuZC8wMC1wb3J0c2VjdXJlLmNvbmZcIjtcbmV4cG9ydCBjb25zdCBQQVNTV0RfUEFUSCA9IFwiL2V0Yy9wYXNzd2RcIjtcbmV4cG9ydCBjb25zdCBBVVRIX0xPR19QQVRIID0gXCIvdmFyL2xvZy9hdXRoLmxvZ1wiO1xuXG5leHBvcnQgY29uc3QgQ0hFQ0tfSU5URVJWQUwgPSA2MCAqIDEwMDA7XG5leHBvcnQgY29uc3QgV0VCSE9PS19DSEVDS19JTlRFUlZBTCA9IDUgKiA2MCAqIDEwMDA7XG5leHBvcnQgY29uc3QgR0lUX1RJTUVPVVQgPSAxMjAgKiAxMDAwO1xuZXhwb3J0IGNvbnN0IE1BWF9FUlJPUl9CT0RZX0xFTkdUSCA9IDUwMDtcbi8vIEEgc291cmNlIHRoYXQgc3RhcnRzIGJlaW5nIHNpZ25lZCBieSBzb21lb25lIG5ldyBpcyBoZWxkIGF0IGFybSdzIGxlbmd0aCBmb3IgdGhpcyBsb25nLCBzbyBhXG4vLyBzdG9sZW4gc2lnbmluZyBrZXkgY2Fubm90IHB1c2gga2V5cyBvbnRvIGEgbWFjaGluZSBiZWZvcmUgYW55b25lIG5vdGljZXMgdGhlIHdhcm5pbmcuXG5leHBvcnQgY29uc3QgU0lHTkVSX0NIQU5HRV9ERUxBWSA9IDI0ICogNjAgKiA2MCAqIDEwMDA7XG4vLyBBbiB1bnJldm9rZSB3YWl0cyB0aGlzIGxvbmcgYmVmb3JlIHRha2luZyBlZmZlY3QsIHNvIGEgY29tcHJvbWlzZWQgc2lnbmluZyBrZXkgY2Fubm90IGluc3RhbnRseVxuLy8gdW5kbyB0aGUgcmV2b2NhdGlvbiB0aGF0IGxvY2tlZCBpdCBvdXQuXG5leHBvcnQgY29uc3QgVU5SRVZPS0VfREVMQVkgPSA2MCAqIDYwICogMTAwMDtcbi8vIEFmdGVyIHRoaXMgbWFueSBjb25zZWN1dGl2ZSBmYWlsdXJlcyBhIHJlcG8gaXMgdGhyb3duIGF3YXkgYW5kIGNsb25lZCBmcm9tIHNjcmF0Y2gsIHdoaWNoXG4vLyByZWNvdmVycyBmcm9tIGNvcnJ1cHRpb24gYW5kIGludGVycnVwdGVkIGZldGNoZXMuIENvdW50ZWQgaW4gY2hlY2tzLCBzbyBhYm91dCBhIHF1YXJ0ZXIgaG91ci5cbmV4cG9ydCBjb25zdCBNQVhfUkVQT19GQUlMVVJFU19CRUZPUkVfUkVDTE9ORSA9IDE1O1xuIl19
|
|
29
|
+
/* _JS_SOURCE_HASH = "04c95747c8ff6d5611015502a598fe430e5fddd148541921318ff8e5ec0cbf25"; */
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
//exports.listRepoDir = exports.readRepoFile = exports.syncRepoFiles = exports.ensureRevokeKey = exports.revokeRepo = exports.sourceRepo = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const revokeSource_1 = require("../revokeSource");
|
|
10
|
+
const sources_1 = require("../sources");
|
|
11
|
+
const git_1 = require("./git");
|
|
12
|
+
function sourceRepo(sourceURL) {
|
|
13
|
+
return {
|
|
14
|
+
repoURL: sourceURL,
|
|
15
|
+
repoPath: (0, sources_1.sourceRepoPath)(sourceURL),
|
|
16
|
+
keyPath: async () => await (0, sources_1.findSourceKey)(sourceURL) || (0, sources_1.sourceKeyPath)(sourceURL),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
exports.sourceRepo = sourceRepo;
|
|
20
|
+
function revokeRepo(sourceURL) {
|
|
21
|
+
return {
|
|
22
|
+
repoURL: (0, revokeSource_1.revokeRepoURL)(sourceURL),
|
|
23
|
+
repoPath: (0, revokeSource_1.revokeRepoPath)(sourceURL),
|
|
24
|
+
keyPath: () => ensureRevokeKey(sourceURL),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
exports.revokeRepo = revokeRepo;
|
|
28
|
+
/** The revoke repo's key is worked out from the source's, so nothing extra had to be uploaded and
|
|
29
|
+
nothing extra is stored anywhere it could be taken from. */
|
|
30
|
+
async function ensureRevokeKey(sourceURL) {
|
|
31
|
+
let existing = await (0, revokeSource_1.findRevokeKey)(sourceURL);
|
|
32
|
+
if (existing) {
|
|
33
|
+
return existing;
|
|
34
|
+
}
|
|
35
|
+
let sourceKey = await (0, sources_1.findSourceKey)(sourceURL);
|
|
36
|
+
if (!sourceKey) {
|
|
37
|
+
throw new Error(`Expected a key for ${sourceURL} at ${(0, sources_1.sourceKeyPath)(sourceURL)}, no such file exists`);
|
|
38
|
+
}
|
|
39
|
+
let derived = (0, revokeSource_1.deriveRevokeKey)(await promises_1.default.readFile(sourceKey, "utf8"));
|
|
40
|
+
let keyPath = (0, revokeSource_1.revokeKeyPath)(sourceURL);
|
|
41
|
+
await promises_1.default.mkdir(path_1.default.dirname(keyPath), { recursive: true, mode: 0o700 });
|
|
42
|
+
await promises_1.default.writeFile(keyPath, derived.privateKeyFile, { mode: 0o600 });
|
|
43
|
+
await promises_1.default.writeFile(`${keyPath}.pub`, `${derived.publicKey} ${revokeSource_1.REVOKE_KEY_LABEL}\n`, { mode: 0o644 });
|
|
44
|
+
console.log(`Derived the revoke key for ${sourceURL} into ${keyPath}`);
|
|
45
|
+
return keyPath;
|
|
46
|
+
}
|
|
47
|
+
exports.ensureRevokeKey = ensureRevokeKey;
|
|
48
|
+
async function pathExists(filePath) {
|
|
49
|
+
try {
|
|
50
|
+
await promises_1.default.access(filePath);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Brings the checkout in line with the remote. Cloned the first time, pulled after that, and the
|
|
58
|
+
usual case of nothing having changed costs one ref listing and no objects. Throws if the repo
|
|
59
|
+
cannot be read, so a caller cannot mistake that for an empty repo. */
|
|
60
|
+
async function syncRepoFiles(repo) {
|
|
61
|
+
let { repoURL, repoPath } = repo;
|
|
62
|
+
let keyPath = await repo.keyPath();
|
|
63
|
+
if (!await (0, git_1.repoIsUsable)({ repoPath, keyPath })) {
|
|
64
|
+
await (0, git_1.cloneRepo)({ repoURL, repoPath, keyPath });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let localHead = await (0, git_1.runGit)({ args: ["rev-parse", "HEAD"], cwd: repoPath, keyPath, allowFailure: true });
|
|
68
|
+
if (localHead.status !== 0) {
|
|
69
|
+
// A repo with no commits yet, which is the state every revoke repo starts in. There is
|
|
70
|
+
// nothing to pull and nothing to say.
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
let branch = (await (0, git_1.runGit)({ args: ["rev-parse", "--abbrev-ref", "HEAD"], cwd: repoPath, keyPath })).stdout.trim();
|
|
74
|
+
let listing = (await (0, git_1.runGit)({ args: ["ls-remote", "origin", branch], cwd: repoPath, keyPath })).stdout;
|
|
75
|
+
let remoteSha = (listing.split(/\s+/)[0] || "").trim();
|
|
76
|
+
if (remoteSha && remoteSha === localHead.stdout.trim()) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await (0, git_1.runGit)({ args: ["fetch", "--prune", "origin"], cwd: repoPath, keyPath });
|
|
80
|
+
await (0, git_1.runGit)({ args: ["reset", "--hard", `origin/${branch}`], cwd: repoPath, keyPath });
|
|
81
|
+
await (0, git_1.runGit)({ args: ["clean", "-fdx"], cwd: repoPath, keyPath });
|
|
82
|
+
}
|
|
83
|
+
exports.syncRepoFiles = syncRepoFiles;
|
|
84
|
+
/** Throws when there is no checkout at all. "I have never managed to read this repo" and "this
|
|
85
|
+
repo is empty" are different answers and must not collapse into one. */
|
|
86
|
+
async function requireCheckout(repo) {
|
|
87
|
+
if (!await pathExists(path_1.default.join(repo.repoPath, ".git"))) {
|
|
88
|
+
throw new Error(`Expected a checkout of ${repo.repoURL} at ${repo.repoPath}, there is none`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** One file out of the repo, or undefined if the repo does not have that file. */
|
|
92
|
+
async function readRepoFile(repo, filePath) {
|
|
93
|
+
await requireCheckout(repo);
|
|
94
|
+
try {
|
|
95
|
+
return await promises_1.default.readFile(path_1.default.join(repo.repoPath, filePath), "utf8");
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.readRepoFile = readRepoFile;
|
|
102
|
+
/** The names in one of the repo's directories, or nothing if it has no such directory. */
|
|
103
|
+
async function listRepoDir(repo, directory) {
|
|
104
|
+
await requireCheckout(repo);
|
|
105
|
+
try {
|
|
106
|
+
return (await promises_1.default.readdir(path_1.default.join(repo.repoPath, directory))).sort();
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.listRepoDir = listRepoDir;
|
|
113
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb0ZpbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVwb0ZpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJEQUE2QjtBQUM3QixnREFBd0I7QUFDeEIsa0RBQWlJO0FBQ2pJLHdDQUEwRTtBQUMxRSwrQkFBd0Q7QUFleEQsU0FBZ0IsVUFBVSxDQUFDLFNBQWlCO0lBQ3hDLE9BQU87UUFDSCxPQUFPLEVBQUUsU0FBUztRQUNsQixRQUFRLEVBQUUsSUFBQSx3QkFBYyxFQUFDLFNBQVMsQ0FBQztRQUNuQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxNQUFNLElBQUEsdUJBQWEsRUFBQyxTQUFTLENBQUMsSUFBSSxJQUFBLHVCQUFhLEVBQUMsU0FBUyxDQUFDO0tBQ2xGLENBQUM7QUFDTixDQUFDO0FBTkQsZ0NBTUM7QUFFRCxTQUFnQixVQUFVLENBQUMsU0FBaUI7SUFDeEMsT0FBTztRQUNILE9BQU8sRUFBRSxJQUFBLDRCQUFhLEVBQUMsU0FBUyxDQUFDO1FBQ2pDLFFBQVEsRUFBRSxJQUFBLDZCQUFjLEVBQUMsU0FBUyxDQUFDO1FBQ25DLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDO0tBQzVDLENBQUM7QUFDTixDQUFDO0FBTkQsZ0NBTUM7QUFFRDsrREFDK0Q7QUFDeEQsS0FBSyxVQUFVLGVBQWUsQ0FBQyxTQUFpQjtJQUNuRCxJQUFJLFFBQVEsR0FBRyxNQUFNLElBQUEsNEJBQWEsRUFBQyxTQUFTLENBQUMsQ0FBQztJQUM5QyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ1gsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztJQUNELElBQUksU0FBUyxHQUFHLE1BQU0sSUFBQSx1QkFBYSxFQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQy9DLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLFNBQVMsT0FBTyxJQUFBLHVC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QUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3pFLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1QsT0FBTyxTQUFTLENBQUM7SUFDckIsQ0FBQztBQUNMLENBQUM7QUFQRCxvQ0FPQztBQUVELDBGQUEwRjtBQUNuRixLQUFLLFVBQVUsV0FBVyxDQUFDLElBQWEsRUFBRSxTQUFpQjtJQUM5RCxNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QixJQUFJLENBQUM7UUFDRCxPQUFPLENBQUMsTUFBTSxrQkFBRSxDQUFDLE9BQU8sQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzFFLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1QsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0FBQ0wsQ0FBQztBQVBELGtDQU9DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gXCJmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGRlcml2ZVJldm9rZUtleSwgZmluZFJldm9rZUtleSwgUkVWT0tFX0tFWV9MQUJFTCwgcmV2b2tlS2V5UGF0aCwgcmV2b2tlUmVwb1BhdGgsIHJldm9rZVJlcG9VUkwgfSBmcm9tIFwiLi4vcmV2b2tlU291cmNlXCI7XG5pbXBvcnQgeyBmaW5kU291cmNlS2V5LCBzb3VyY2VLZXlQYXRoLCBzb3VyY2VSZXBvUGF0aCB9IGZyb20gXCIuLi9zb3VyY2VzXCI7XG5pbXBvcnQgeyBjbG9uZVJlcG8sIHJlcG9Jc1VzYWJsZSwgcnVuR2l0IH0gZnJvbSBcIi4vZ2l0XCI7XG5cbi8qKiBSZWFkaW5nIGEgcmVwbywgbWFkZSB0byBsb29rIGxpa2UgcmVhZGluZyBhIGRpcmVjdG9yeS4gQSBjYWxsZXIgYXNrcyBmb3IgYSBmaWxlIGFuZCBnZXRzIGl0c1xuICAgIGNvbnRlbnRzOyBrZWVwaW5nIGEgY2hlY2tvdXQgb24gZGlzaywgY2xvbmluZyBpdCBvbmNlIGFuZCBwdWxsaW5nIGl0IHNpbmNlLCBpcyB0aGlzIG1vZHVsZSdzXG4gICAgYnVzaW5lc3MgYW5kIG5vYm9keSBlbHNlJ3MuXG5cbiAgICBOb3RoaW5nIGhlcmUgZXZlciBhbnN3ZXJzIFwidGhlcmUgaXMgbm90aGluZ1wiIHdoZW4gdGhlIHRydXRoIGlzIFwiSSBjb3VsZCBub3QgbG9va1wiLiBBIHJlcG8gdGhhdFxuICAgIGNhbm5vdCBiZSByZWFjaGVkIHRocm93cywgYW5kIHRoZSBjYWxsZXIgc2tpcHMgdGhhdCBzb3VyY2UsIGJlY2F1c2UgcmVhZGluZyBhbiB1bnJlYWNoYWJsZVxuICAgIHJldm9rZSByZXBvIGFzIGVtcHR5IHdvdWxkIHVuLXJldm9rZSBldmVyeSBrZXkgaW4gaXQuICovXG5leHBvcnQgdHlwZSBSZXBvUmVmID0ge1xuICAgIHJlcG9VUkw6IHN0cmluZztcbiAgICByZXBvUGF0aDogc3RyaW5nO1xuICAgIGtleVBhdGg6ICgpID0+IFByb21pc2U8c3RyaW5nPjtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBzb3VyY2VSZXBvKHNvdXJjZVVSTDogc3RyaW5nKTogUmVwb1JlZiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcmVwb1VSTDogc291cmNlVVJMLFxuICAgICAgICByZXBvUGF0aDogc291cmNlUmVwb1BhdGgoc291cmNlVVJMKSxcbiAgICAgICAga2V5UGF0aDogYXN5bmMgKCkgPT4gYXdhaXQgZmluZFNvdXJjZUtleShzb3VyY2VVUkwpIHx8IHNvdXJjZUtleVBhdGgoc291cmNlVVJMKSxcbiAgICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmV2b2tlUmVwbyhzb3VyY2VVUkw6IHN0cmluZyk6IFJlcG9SZWYge1xuICAgIHJldHVybiB7XG4gICAgICAgIHJlcG9VUkw6IHJldm9rZVJlcG9VUkwoc291cmNlVVJMKSxcbiAgICAgICAgcmVwb1BhdGg6IHJldm9rZVJlcG9QYXRoKHNvdXJjZVVSTCksXG4gICAgICAgIGtleVBhdGg6ICgpID0+IGVuc3VyZVJldm9rZUtleShzb3VyY2VVUkwpLFxuICAgIH07XG59XG5cbi8qKiBUaGUgcmV2b2tlIHJlcG8ncyBrZXkgaXMgd29ya2VkIG91dCBmcm9tIHRoZSBzb3VyY2Uncywgc28gbm90aGluZyBleHRyYSBoYWQgdG8gYmUgdXBsb2FkZWQgYW5kXG4gICAgbm90aGluZyBleHRyYSBpcyBzdG9yZWQgYW55d2hlcmUgaXQgY291bGQgYmUgdGFrZW4gZnJvbS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbnN1cmVSZXZva2VLZXkoc291cmNlVVJMOiBzdHJpbmcpIHtcbiAgICBsZXQgZXhpc3RpbmcgPSBhd2FpdCBmaW5kUmV2b2tlS2V5KHNvdXJjZVVSTCk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgIHJldHVybiBleGlzdGluZztcbiAgICB9XG4gICAgbGV0IHNvdXJjZUtleSA9IGF3YWl0IGZpbmRTb3VyY2VLZXkoc291cmNlVVJMKTtcbiAgICBpZiAoIXNvdXJjZUtleSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGEga2V5IGZvciAke3NvdXJjZVVSTH0gYXQgJHtzb3VyY2VLZXlQYXRoKHNvdXJjZVVSTCl9LCBubyBzdWNoIGZpbGUgZXhpc3RzYCk7XG4gICAgfVxuICAgIGxldCBkZXJpdmVkID0gZGVyaXZlUmV2b2tlS2V5KGF3YWl0IGZzLnJlYWRGaWxlKHNvdXJjZUtleSwgXCJ1dGY4XCIpKTtcbiAgICBsZXQga2V5UGF0aCA9IHJldm9rZUtleVBhdGgoc291cmNlVVJMKTtcbiAgICBhd2FpdCBmcy5ta2RpcihwYXRoLmRpcm5hbWUoa2V5UGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlLCBtb2RlOiAwbzcwMCB9KTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoa2V5UGF0aCwgZGVyaXZlZC5wcml2YXRlS2V5RmlsZSwgeyBtb2RlOiAwbzYwMCB9KTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoYCR7a2V5UGF0aH0ucHViYCwgYCR7ZGVyaXZlZC5wdWJsaWNLZXl9ICR7UkVWT0tFX0tFWV9MQUJFTH1cXG5gLCB7IG1vZGU6IDBvNjQ0IH0pO1xuICAgIGNvbnNvbGUubG9nKGBEZXJpdmVkIHRoZSByZXZva2Uga2V5IGZvciAke3NvdXJjZVVSTH0gaW50byAke2tleVBhdGh9YCk7XG4gICAgcmV0dXJuIGtleVBhdGg7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBhdGhFeGlzdHMoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZzLmFjY2VzcyhmaWxlUGF0aCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLyoqIEJyaW5ncyB0aGUgY2hlY2tvdXQgaW4gbGluZSB3aXRoIHRoZSByZW1vdGUuIENsb25lZCB0aGUgZmlyc3QgdGltZSwgcHVsbGVkIGFmdGVyIHRoYXQsIGFuZCB0aGVcbiAgICB1c3VhbCBjYXNlIG9mIG5vdGhpbmcgaGF2aW5nIGNoYW5nZWQgY29zdHMgb25lIHJlZiBsaXN0aW5nIGFuZCBubyBvYmplY3RzLiBUaHJvd3MgaWYgdGhlIHJlcG9cbiAgICBjYW5ub3QgYmUgcmVhZCwgc28gYSBjYWxsZXIgY2Fubm90IG1pc3Rha2UgdGhhdCBmb3IgYW4gZW1wdHkgcmVwby4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzeW5jUmVwb0ZpbGVzKHJlcG86IFJlcG9SZWYpIHtcbiAgICBsZXQgeyByZXBvVVJMLCByZXBvUGF0aCB9ID0gcmVwbztcbiAgICBsZXQga2V5UGF0aCA9IGF3YWl0IHJlcG8ua2V5UGF0aCgpO1xuICAgIGlmICghYXdhaXQgcmVwb0lzVXNhYmxlKHsgcmVwb1BhdGgsIGtleVBhdGggfSkpIHtcbiAgICAgICAgYXdhaXQgY2xvbmVSZXBvKHsgcmVwb1VSTCwgcmVwb1BhdGgsIGtleVBhdGggfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IGxvY2FsSGVhZCA9IGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIkhFQURcIl0sIGN3ZDogcmVwb1BhdGgsIGtleVBhdGgsIGFsbG93RmFpbHVyZTogdHJ1ZSB9KTtcbiAgICBpZiAobG9jYWxIZWFkLnN0YXR1cyAhPT0gMCkge1xuICAgICAgICAvLyBBIHJlcG8gd2l0aCBubyBjb21taXRzIHlldCwgd2hpY2ggaXMgdGhlIHN0YXRlIGV2ZXJ5IHJldm9rZSByZXBvIHN0YXJ0cyBpbi4gVGhlcmUgaXNcbiAgICAgICAgLy8gbm90aGluZyB0byBwdWxsIGFuZCBub3RoaW5nIHRvIHNheS5cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgYnJhbmNoID0gKGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcInJldi1wYXJzZVwiLCBcIi0tYWJicmV2LXJlZlwiLCBcIkhFQURcIl0sIGN3ZDogcmVwb1BhdGgsIGtleVBhdGggfSkpLnN0ZG91dC50cmltKCk7XG4gICAgbGV0IGxpc3RpbmcgPSAoYXdhaXQgcnVuR2l0KHsgYXJnczogW1wibHMtcmVtb3RlXCIsIFwib3JpZ2luXCIsIGJyYW5jaF0sIGN3ZDogcmVwb1BhdGgsIGtleVBhdGggfSkpLnN0ZG91dDtcbiAgICBsZXQgcmVtb3RlU2hhID0gKGxpc3Rpbmcuc3BsaXQoL1xccysvKVswXSB8fCBcIlwiKS50cmltKCk7XG4gICAgaWYgKHJlbW90ZVNoYSAmJiByZW1vdGVTaGEgPT09IGxvY2FsSGVhZC5zdGRvdXQudHJpbSgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgcnVuR2l0KHsgYXJnczogW1wiZmV0Y2hcIiwgXCItLXBydW5lXCIsIFwib3JpZ2luXCJdLCBjd2Q6IHJlcG9QYXRoLCBrZXlQYXRoIH0pO1xuICAgIGF3YWl0IHJ1bkdpdCh7IGFyZ3M6IFtcInJlc2V0XCIsIFwiLS1oYXJkXCIsIGBvcmlnaW4vJHticmFuY2h9YF0sIGN3ZDogcmVwb1BhdGgsIGtleVBhdGggfSk7XG4gICAgYXdhaXQgcnVuR2l0KHsgYXJnczogW1wiY2xlYW5cIiwgXCItZmR4XCJdLCBjd2Q6IHJlcG9QYXRoLCBrZXlQYXRoIH0pO1xufVxuXG4vKiogVGhyb3dzIHdoZW4gdGhlcmUgaXMgbm8gY2hlY2tvdXQgYXQgYWxsLiBcIkkgaGF2ZSBuZXZlciBtYW5hZ2VkIHRvIHJlYWQgdGhpcyByZXBvXCIgYW5kIFwidGhpc1xuICAgIHJlcG8gaXMgZW1wdHlcIiBhcmUgZGlmZmVyZW50IGFuc3dlcnMgYW5kIG11c3Qgbm90IGNvbGxhcHNlIGludG8gb25lLiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVxdWlyZUNoZWNrb3V0KHJlcG86IFJlcG9SZWYpIHtcbiAgICBpZiAoIWF3YWl0IHBhdGhFeGlzdHMocGF0aC5qb2luKHJlcG8ucmVwb1BhdGgsIFwiLmdpdFwiKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIGNoZWNrb3V0IG9mICR7cmVwby5yZXBvVVJMfSBhdCAke3JlcG8ucmVwb1BhdGh9LCB0aGVyZSBpcyBub25lYCk7XG4gICAgfVxufVxuXG4vKiogT25lIGZpbGUgb3V0IG9mIHRoZSByZXBvLCBvciB1bmRlZmluZWQgaWYgdGhlIHJlcG8gZG9lcyBub3QgaGF2ZSB0aGF0IGZpbGUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFJlcG9GaWxlKHJlcG86IFJlcG9SZWYsIGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICBhd2FpdCByZXF1aXJlQ2hlY2tvdXQocmVwbyk7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGguam9pbihyZXBvLnJlcG9QYXRoLCBmaWxlUGF0aCksIFwidXRmOFwiKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxufVxuXG4vKiogVGhlIG5hbWVzIGluIG9uZSBvZiB0aGUgcmVwbydzIGRpcmVjdG9yaWVzLCBvciBub3RoaW5nIGlmIGl0IGhhcyBubyBzdWNoIGRpcmVjdG9yeS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0UmVwb0RpcihyZXBvOiBSZXBvUmVmLCBkaXJlY3Rvcnk6IHN0cmluZykge1xuICAgIGF3YWl0IHJlcXVpcmVDaGVja291dChyZXBvKTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gKGF3YWl0IGZzLnJlYWRkaXIocGF0aC5qb2luKHJlcG8ucmVwb1BhdGgsIGRpcmVjdG9yeSkpKS5zb3J0KCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxufVxuIl19
|
|
114
|
+
/* _JS_SOURCE_HASH = "7340581691819b6036825721d39ae6393118181e0730254e1cead9650e3aa91e"; */
|
|
Binary file
|