sliftutils 1.7.130 → 1.7.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/index.d.ts +4 -51
  2. package/misc/dist/ownIPs.ts.cache +2 -2
  3. package/package.json +1 -1
  4. package/security/authorizedKeys/authorizedKeys.d.ts +37 -0
  5. package/security/authorizedKeys/daemon/changes.d.ts +17 -0
  6. package/security/authorizedKeys/daemon/dist/changes.ts.cache +2 -2
  7. package/security/authorizedKeys/daemon/dist/git.ts.cache +2 -2
  8. package/security/authorizedKeys/daemon/dist/notify.ts.cache +2 -2
  9. package/security/authorizedKeys/daemon/dist/paths.ts.cache +2 -2
  10. package/security/authorizedKeys/daemon/dist/repoFiles.ts.cache +2 -2
  11. package/security/authorizedKeys/daemon/dist/revocation.ts.cache +0 -0
  12. package/security/authorizedKeys/daemon/dist/sessions.ts.cache +2 -2
  13. package/security/authorizedKeys/daemon/dist/state.ts.cache +2 -2
  14. package/security/authorizedKeys/daemon/dist/trust.ts.cache +2 -2
  15. package/security/authorizedKeys/daemon/git.d.ts +35 -0
  16. package/security/authorizedKeys/daemon/notify.d.ts +8 -0
  17. package/security/authorizedKeys/daemon/paths.d.ts +15 -0
  18. package/security/authorizedKeys/daemon/repoFiles.d.ts +25 -0
  19. package/security/authorizedKeys/daemon/revocation.d.ts +74 -0
  20. package/security/authorizedKeys/daemon/sessions.d.ts +19 -0
  21. package/security/authorizedKeys/daemon/state.d.ts +67 -0
  22. package/security/authorizedKeys/daemon/trust.d.ts +20 -0
  23. package/security/authorizedKeys/dist/authorizedKeys.ts.cache +2 -2
  24. package/security/authorizedKeys/dist/keysRepo.ts.cache +2 -2
  25. package/security/authorizedKeys/dist/revokeSource.ts.cache +2 -2
  26. package/security/authorizedKeys/dist/sources.ts.cache +2 -2
  27. package/security/authorizedKeys/keysRepo.d.ts +10 -0
  28. package/security/authorizedKeys/revokeSource.d.ts +13 -0
  29. package/security/authorizedKeys/sources.d.ts +17 -0
  30. package/security/helpers/dist/paths.ts.cache +2 -2
  31. package/security/helpers/dist/spawn.ts.cache +2 -2
  32. package/security/helpers/paths.d.ts +4 -0
  33. package/security/helpers/spawn.d.ts +16 -0
  34. package/security/keys/deriveKey.d.ts +16 -0
  35. package/security/keys/dist/deriveKey.ts.cache +2 -2
  36. package/security/keys/dist/sshKeyFile.ts.cache +2 -2
  37. package/security/keys/sshKeyFile.d.ts +18 -0
  38. package/security/machines/addMachine.ts +76 -24
  39. package/security/machines/dist/addMachine.ts.cache +6 -5
  40. package/security/machines/dist/identity.ts.cache +2 -2
  41. package/security/machines/dist/machines.ts.cache +81 -14
  42. package/security/machines/machines.d.ts +81 -0
  43. package/security/machines/machines.ts +89 -14
  44. package/security/notifications/discord.d.ts +36 -0
  45. package/security/notifications/dist/discord.ts.cache +2 -2
  46. package/security/signedFiles/dist/manifest.ts.cache +2 -2
  47. package/security/signedFiles/manifest.d.ts +44 -0
  48. package/storage/remoteStorage/ArchivesRemote.ts +8 -10
  49. package/storage/remoteStorage/accessPage.tsx +13 -90
  50. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +11 -12
  51. package/storage/remoteStorage/dist/serverConfig.ts.cache +7 -49
  52. package/storage/remoteStorage/dist/storageController.ts.cache +33 -114
  53. package/storage/remoteStorage/serverConfig.d.ts +0 -10
  54. package/storage/remoteStorage/serverConfig.ts +6 -48
  55. package/storage/remoteStorage/storageController.d.ts +4 -36
  56. package/storage/remoteStorage/storageController.ts +40 -126
  57. package/storage/remoteStorage/storageServer.ts +1 -8
  58. package/storage/remoteStorage/storageServerCli.ts +14 -0
  59. package/storage/remoteStorage/grantAccess.js +0 -4
  60. package/storage/remoteStorage/grantAccessCli.d.ts +0 -1
  61. package/storage/remoteStorage/grantAccessCli.ts +0 -25
@@ -1,19 +1,13 @@
1
1
  import path from "path";
2
- import { getFileStorageNested2 } from "../FileFolderAPI";
3
- import { TransactionStorage } from "../TransactionStorage";
4
- import { JSONStorage } from "../JSONStorage";
5
- import type { IStorage } from "../IStorage";
6
- import type { AccessRequest, TrustRecord } from "./storageController";
7
2
  import { getArg } from "./cliArgs";
8
3
 
9
- // The storage server's process-level identity and system state: which server we are (config, extra ports), whether writes are allowed, and the trust/request stores.
4
+ // The storage server's process-level identity and system state: which server we are (config, extra
5
+ // ports), and whether writes are allowed.
10
6
 
11
7
  export type StorageServerConfig = {
12
8
  domain: string;
13
9
  port: number;
14
10
  rootDomain: string;
15
- sshTarget: string;
16
- serverCommand: string;
17
11
  folder: string;
18
12
  };
19
13
 
@@ -52,46 +46,10 @@ export function getStorageFolder(): string {
52
46
  return path.resolve(folder);
53
47
  }
54
48
 
55
- const systemStorages = new Map<string, Promise<IStorage<unknown>>>();
56
- function getSystemStorage<T>(name: string): Promise<IStorage<T>> {
57
- let storage = systemStorages.get(name);
58
- if (!storage) {
59
- storage = (async () => {
60
- let root = await getFileStorageNested2(getStorageFolder());
61
- let system = await root.folder.getStorage("system2");
62
- let transactionName = "storage" + name[0].toUpperCase() + name.slice(1);
63
- return new JSONStorage<unknown>(new TransactionStorage(await system.folder.getStorage(name), transactionName));
64
- })();
65
- systemStorages.set(name, storage);
66
- }
67
- return storage as Promise<IStorage<T>>;
68
- }
69
- export function getTrust(): Promise<IStorage<TrustRecord>> {
70
- return getSystemStorage<TrustRecord>("trust");
71
- }
72
- export function getRequests(): Promise<IStorage<AccessRequest[]>> {
73
- return getSystemStorage<AccessRequest[]>("requests");
74
- }
75
-
76
- export async function setTrustedMachines(config: { account: string; machineIds: string[] }): Promise<void> {
77
- let trust = await getTrust();
78
- let prefix = `${config.account}|`;
79
- let desired = new Set(config.machineIds);
80
- for (let key of await trust.getKeys()) {
81
- if (!key.startsWith(prefix)) continue;
82
- let machineId = key.slice(prefix.length);
83
- if (desired.has(machineId)) {
84
- desired.delete(machineId);
85
- continue;
86
- }
87
- console.log(`Removing trust for machine ${machineId} on account ${config.account}`);
88
- await trust.remove(key);
89
- }
90
- for (let machineId of desired) {
91
- console.log(`Adding trust for machine ${machineId} on account ${config.account}`);
92
- await trust.set(`${prefix}${machineId}`, { account: config.account, machineId, ip: "", time: Date.now() });
93
- }
94
- }
49
+ // Which machines this server trusts is not kept here any more. It lives in the signed
50
+ // authorized_keys repo, read through security/machines, so every machine shares one list, with
51
+ // revocation and address checking that a per-server store never had. setTrustedMachines, the trust
52
+ // store and the access request store all went with it.
95
53
 
96
54
  const extraListenPorts = new Set<number>();
97
55
  export function addExtraListenPort(port: number): void {
@@ -2,6 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import { ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus, FindConfig, SourceConfig } from "../IArchives";
4
4
  import { ActiveBucketInfo, ServerBucketInfo } from "./storageServerState";
5
+ import { MachineState } from "../../security/machines/machines";
5
6
  import { AccessTotals, AccessSummaryState } from "./accessStats";
6
7
  import { LogFileInfo } from "../StreamingLogs";
7
8
  import type { SummaryEntry } from "../../treeSummary";
@@ -19,25 +20,13 @@ export type AuthToken = {
19
20
  signature: string;
20
21
  data: AuthTokenData;
21
22
  };
22
- export type AccessRequest = {
23
- requestId: string;
24
- account: string;
25
- machineId: string;
26
- ip: string;
27
- time: number;
28
- };
29
- export type TrustRecord = {
30
- account: string;
31
- machineId: string;
32
- ip: string;
33
- time: number;
34
- };
35
23
  export type AccessState = {
36
24
  machineId: string;
37
25
  ip: string;
38
26
  hasAccess: boolean;
39
- grantAccessCommand?: string;
40
- trustedMachines?: TrustRecord[];
27
+ reason?: string;
28
+ addMachineCommand?: string;
29
+ trustedMachines?: MachineState[];
41
30
  };
42
31
  export declare function broadcastRoutingChanged(): void;
43
32
  export declare const RemoteStorageController: import("socket-function/SocketFunctionTypes").SocketRegistered<{
@@ -46,34 +35,13 @@ export declare const RemoteStorageController: import("socket-function/SocketFunc
46
35
  machineId: string;
47
36
  ip: string;
48
37
  }>;
49
- requestAccess: (config: {
50
- account: string;
51
- }) => Promise<{
52
- machineId: string;
53
- ip: string;
54
- requestId: string;
55
- grantAccessCommand: string;
56
- }>;
57
38
  getAccessState: (config: {
58
39
  account: string;
59
40
  }) => Promise<AccessState>;
60
- listRequestsForIP: (config: {
61
- account: string;
62
- ip: string;
63
- }) => Promise<AccessRequest[]>;
64
- grantAccess: (config: {
65
- requestId: string;
66
- }) => Promise<TrustRecord>;
67
41
  adminListActiveBuckets: () => Promise<{
68
42
  account: string;
69
43
  bucketName: string;
70
44
  }[]>;
71
- adminListRequests: (config: {
72
- ip: string;
73
- }) => Promise<AccessRequest[]>;
74
- adminGrantAccess: (config: {
75
- requestId: string;
76
- }) => Promise<TrustRecord>;
77
45
  get2: (config: {
78
46
  account: string;
79
47
  bucketName: string;
@@ -15,7 +15,8 @@ import {
15
15
  debugGetActiveBucket, activateBucket, getActiveBucketKeys,
16
16
  } from "./storageServerState";
17
17
  import { debugClearAccountWriteStats } from "./accessStats";
18
- import { getStorageServerConfig, getTrust, getRequests, assertWritesAllowed } from "./serverConfig";
18
+ import { getStorageServerConfig, assertWritesAllowed } from "./serverConfig";
19
+ import { getTrustedMachines, isMachineAccepted, MachineState } from "../../security/machines/machines";
19
20
  import { BlobStore } from "./blobStore";
20
21
  import { getRoutingFileResult } from "./bucketDisk";
21
22
  import { StorageClientController } from "./storageClientController";
@@ -45,25 +46,15 @@ export type AuthToken = {
45
46
  signature: string;
46
47
  data: AuthTokenData;
47
48
  };
48
- export type AccessRequest = {
49
- requestId: string;
50
- account: string;
51
- machineId: string;
52
- ip: string;
53
- time: number;
54
- };
55
- export type TrustRecord = {
56
- account: string;
57
- machineId: string;
58
- ip: string;
59
- time: number;
60
- };
61
49
  export type AccessState = {
62
50
  machineId: string;
63
51
  ip: string;
64
52
  hasAccess: boolean;
65
- grantAccessCommand?: string;
66
- trustedMachines?: TrustRecord[];
53
+ // Why not, and what to run about it, when there is no access.
54
+ reason?: string;
55
+ addMachineCommand?: string;
56
+ // Everything the repo trusts, when there is.
57
+ trustedMachines?: MachineState[];
67
58
  };
68
59
 
69
60
  const sessions = new Map<string, string>();
@@ -114,24 +105,29 @@ function requireAdmin(): string {
114
105
  }
115
106
  return machineId;
116
107
  }
108
+ /** Who may talk to this server, decided by the signed authorized_keys repo rather than by anything
109
+ this server keeps for itself.
110
+
111
+ The identity is the same machine id it always was - a machine that was trusted here before is
112
+ trusted the moment its id is in the repo - but the record of who is trusted now lives in one
113
+ signed place shared by every machine, with revocation and everything else that comes with it.
114
+ The address is checked too, which the trust store here never did. */
117
115
  async function requireAccess(account: string): Promise<string> {
118
116
  assertValidName(account, "account");
119
117
  let machineId = getCallerMachineId();
120
118
  if (isAdmin(machineId)) return machineId;
121
- let trust = await getTrust();
122
- let trusted = await trust.get(`${account}|${machineId}`);
123
- if (!trusted) {
124
- let { domain, port } = getStorageServerConfig();
125
- throw new Error(`${STORAGE_ACCESS_DENIED} Machine has no access to this account. Machine ${machineId}, account ${JSON.stringify(account)}. Visit https://${domain}:${port}/${account} for access instructions.`);
119
+ let { rootDomain } = getStorageServerConfig();
120
+ let ip = getCallerIP();
121
+ let verdict = await isMachineAccepted({ machineId, ip, domain: rootDomain });
122
+ if (!verdict.accepted) {
123
+ throw new Error(
124
+ `${STORAGE_ACCESS_DENIED} ${verdict.reason}`
125
+ + ` Machine ${machineId}, address ${ip}, account ${JSON.stringify(account)}.`
126
+ );
126
127
  }
127
128
  return machineId;
128
129
  }
129
130
 
130
- function getGrantAccessCommand(requestId: string): string {
131
- let { sshTarget, serverCommand } = getStorageServerConfig();
132
- return `ssh ${sshTarget} '${serverCommand} --requestId ${requestId}'`;
133
- }
134
-
135
131
  class RemoteStorageControllerBase {
136
132
  async ping(): Promise<{}> {
137
133
  trackCaller();
@@ -166,114 +162,37 @@ class RemoteStorageControllerBase {
166
162
  return { machineId, ip: getCallerIP() };
167
163
  }
168
164
 
169
- @assertValidArgs
170
- async requestAccess(config: { account: string }): Promise<{ machineId: string; ip: string; requestId: string; grantAccessCommand: string }> {
171
- let account = config.account;
172
- let machineId = getCallerMachineId();
173
- let ip = getCallerIP();
174
- let requestsStorage = await getRequests();
175
- let requests = await requestsStorage.get(ip) || [];
176
- let existing = requests.find(x => x.account === account && x.machineId === machineId);
177
- if (existing) {
178
- existing.time = Date.now();
179
- } else {
180
- existing = {
181
- requestId: Math.random().toString(36).slice(2, 10),
182
- account,
183
- machineId,
184
- ip,
185
- time: Date.now(),
186
- };
187
- requests.push(existing);
188
- }
189
- while (requests.length > MAX_REQUESTS_PER_IP) requests.shift();
190
- await requestsStorage.set(ip, requests);
191
- return { machineId, ip, requestId: existing.requestId, grantAccessCommand: getGrantAccessCommand(existing.requestId) };
192
- }
165
+ /** Whether the caller may use this account, and if not, exactly what to run to change that.
193
166
 
167
+ There is nothing to request and nothing to grant here any more: trust lives in the signed
168
+ authorized_keys repo, so the answer is "run addmachine in that repo", which only somebody
169
+ holding the hardware key can do. */
194
170
  @assertValidArgs
195
171
  async getAccessState(config: { account: string }): Promise<AccessState> {
196
- let account = config.account;
172
+ assertValidName(config.account, "account");
197
173
  let machineId = getCallerMachineId();
198
174
  let ip = getCallerIP();
199
- let trust = await getTrust();
200
- let hasAccess = isAdmin(machineId) || !!await trust.get(`${account}|${machineId}`);
201
- let result: AccessState = { machineId, ip, hasAccess };
202
- if (!hasAccess) {
203
- let requests = await getRequests();
204
- let ownRequest = (await requests.get(ip) || []).find(x => x.account === account && x.machineId === machineId);
205
- if (ownRequest) {
206
- result.grantAccessCommand = getGrantAccessCommand(ownRequest.requestId);
207
- }
208
- return result;
175
+ let { rootDomain } = getStorageServerConfig();
176
+ if (isAdmin(machineId)) {
177
+ return { machineId, ip, hasAccess: true, trustedMachines: await getTrustedMachines() };
209
178
  }
210
-
211
- let trustedMachines: TrustRecord[] = [];
212
- for (let key of await trust.getKeys()) {
213
- if (!key.startsWith(`${account}|`)) continue;
214
- let record = await trust.get(key);
215
- if (record) trustedMachines.push(record);
216
- }
217
- result.trustedMachines = trustedMachines;
218
- return result;
219
- }
220
-
221
- async listRequestsForIP(config: { account: string; ip: string }): Promise<AccessRequest[]> {
222
- let requests = await getRequests();
223
- return (await requests.get(config.ip) || []).filter(x => x.account === config.account);
224
- }
225
-
226
- async grantAccess(config: { requestId: string }): Promise<TrustRecord> {
227
- let requestId = config.requestId;
228
- let callerMachineId = getCallerMachineId();
229
- let trust = await getTrust();
230
- let requests = await getRequests();
231
- for (let ip of await requests.getKeys()) {
232
- for (let request of await requests.get(ip) || []) {
233
- if (request.requestId !== requestId) continue;
234
- if (!isAdmin(callerMachineId) && !await trust.get(`${request.account}|${callerMachineId}`)) {
235
- throw new Error(`${STORAGE_ACCESS_DENIED} Machine has no access to this account. Machine ${callerMachineId}, account ${JSON.stringify(request.account)}`);
236
- }
237
- let record: TrustRecord = {
238
- account: request.account,
239
- machineId: request.machineId,
240
- ip: request.ip,
241
- time: Date.now(),
242
- };
243
- await trust.set(`${request.account}|${request.machineId}`, record);
244
- return record;
245
- }
179
+ let verdict = await isMachineAccepted({ machineId, ip, domain: rootDomain });
180
+ if (!verdict.accepted) {
181
+ return {
182
+ machineId,
183
+ ip,
184
+ hasAccess: false,
185
+ reason: verdict.reason,
186
+ addMachineCommand: `yarn addmachine ${rootDomain} ${machineId} ${ip} git`,
187
+ };
246
188
  }
247
- throw new Error(`No access request found with id ${JSON.stringify(requestId)}. It may have already been granted or expired.`);
189
+ return { machineId, ip, hasAccess: true, trustedMachines: await getTrustedMachines() };
248
190
  }
249
191
 
250
192
  /** Admin (so only this machine's own processes can call it): the buckets this process has loaded. A deploy successor asks its predecessor for this, so it activates exactly the buckets that are in use instead of every bucket on disk. */
251
193
  async adminListActiveBuckets(): Promise<{ account: string; bucketName: string }[]> {
252
194
  return getActiveBucketKeys();
253
195
  }
254
- async adminListRequests(config: { ip: string }): Promise<AccessRequest[]> {
255
- let requests = await getRequests();
256
- return await requests.get(config.ip) || [];
257
- }
258
- async adminGrantAccess(config: { requestId: string }): Promise<TrustRecord> {
259
- let requestId = config.requestId;
260
- let trust = await getTrust();
261
- let requests = await getRequests();
262
- for (let ip of await requests.getKeys()) {
263
- for (let request of await requests.get(ip) || []) {
264
- if (request.requestId !== requestId) continue;
265
- let record: TrustRecord = {
266
- account: request.account,
267
- machineId: request.machineId,
268
- ip: request.ip,
269
- time: Date.now(),
270
- };
271
- await trust.set(`${request.account}|${request.machineId}`, record);
272
- return record;
273
- }
274
- }
275
- throw new Error(`No access request found with id ${JSON.stringify(requestId)}. It may have already been granted or expired.`);
276
- }
277
196
 
278
197
  @assertValidArgs
279
198
  @trackAccessCall("get")
@@ -586,13 +505,8 @@ export const RemoteStorageController = SocketFunction.register(
586
505
  () => ({
587
506
  ping: {},
588
507
  authenticate: {},
589
- requestAccess: {},
590
508
  getAccessState: {},
591
- listRequestsForIP: { hooks: [accountAccess] },
592
- grantAccess: {},
593
- adminListRequests: { hooks: [adminAccess] },
594
509
  adminListActiveBuckets: { hooks: [adminAccess] },
595
- adminGrantAccess: { hooks: [adminAccess] },
596
510
  get2: { hooks: [accountAccess] },
597
511
  set: { hooks: [accountAccess] },
598
512
  del: { hooks: [accountAccess] },
@@ -36,7 +36,7 @@ function getInternalIP(): string {
36
36
  return candidates.find(ip => /^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.)/.test(ip)) || candidates[0];
37
37
  }
38
38
 
39
- // The remote storage server, as a library function: consumers call hostStorageServer() from their own process to start hosting (or use the storageserver bin, see storageServerCli.ts). The grantAccess.js bootstrap (next to this file) is what the access page's shown SSH command points at.
39
+ // The remote storage server, as a library function: consumers call hostStorageServer() from their own process to start hosting (or use the storageserver bin, see storageServerCli.ts). Who may talk to it comes from the signed authorized_keys repo, read through security/machines - there is nothing to grant here.
40
40
 
41
41
  export type HostStorageServerConfig = {
42
42
  // Full URL of this storage server, e.g. "https://1-2-3-4.example.com:4444". The subdomain must be an ip domain - this machine's external IP with dashes, or 127-0-0-1 for local testing (see the validation in hostStorageServer). The domain and port are extracted from it (bucket routing URLs clients use look like
@@ -82,11 +82,6 @@ async function checkDiskSpace(config: { folder: string; threshold: number }): Pr
82
82
  }
83
83
  }
84
84
 
85
- // Full path to the grantAccess CLI bootstrap that lives next to this file. The SSH command shown on the access page invokes it via `node <path> ...` (found through __dirname so consumers don't have to know where our source lives).
86
- function getGrantAccessCliPath(): string {
87
- return path.join(__dirname, "grantAccess.js");
88
- }
89
-
90
85
  export async function hostStorageServer(config: HostStorageServerConfig): Promise<void> {
91
86
  let { url, folder } = config;
92
87
  let { address: domain, port } = parseStorageUrl(url);
@@ -104,8 +99,6 @@ export async function hostStorageServer(config: HostStorageServerConfig): Promis
104
99
  domain,
105
100
  port,
106
101
  rootDomain,
107
- sshTarget: `${os.userInfo().username}@${ip}`,
108
- serverCommand: `node ${getGrantAccessCliPath()} --url ${url}`,
109
102
  folder: path.resolve(folder),
110
103
  });
111
104
 
@@ -1,5 +1,6 @@
1
1
  import { hostStorageServer } from "./storageServer";
2
2
  import { getArg, getFlag } from "./cliArgs";
3
+ import { keysRepo } from "../../security/machines/machines";
3
4
 
4
5
  // Hosts a storage server from the command line (via the storageserver bin, see package.json).
5
6
 
@@ -11,6 +12,19 @@ process.on("uncaughtException", (error) => {
11
12
  });
12
13
 
13
14
  async function main() {
15
+ // Checked before anything is hosted. Who may talk to this server comes from the authorized_keys
16
+ // repo, so a machine without one would start up and refuse every caller with an error about a
17
+ // repo, which is a confusing way to learn the machine was never set up.
18
+ try {
19
+ let { repoPath, sourceURL } = await keysRepo();
20
+ console.log(`Trusting the machines in ${sourceURL} (${repoPath})`);
21
+ } catch (e) {
22
+ throw new Error(
23
+ `This machine has no authorized_keys repo, so it has no way to know which machines to`
24
+ + ` trust, and every caller would be refused.\n${e}`
25
+ );
26
+ }
27
+
14
28
  let url = getArg("url");
15
29
  if (!url) throw new Error(`--url is required (ex: --url https://storage.example.com:4444)`);
16
30
  let folder = getArg("folder");
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- require("typenode");
4
- require("./grantAccessCli");
@@ -1 +0,0 @@
1
- export {};
@@ -1,25 +0,0 @@
1
- import { SocketFunction } from "socket-function/SocketFunction";
2
- import { RemoteStorageController } from "./storageController";
3
- import { authenticateStorage, parseStorageUrl } from "./ArchivesRemote";
4
- import { getArg } from "./cliArgs";
5
-
6
- // The grantAccess CLI. Invoked via the sibling grantAccess.js bootstrap (which loads typenode and then requires this file). Grants a specific access request by its requestId; must be run on the storage machine itself (its certs.ts identity is what the server trusts as admin).
7
-
8
- async function main() {
9
- let url = getArg("url");
10
- if (!url) throw new Error(`--url is required (ex: --url https://storage.example.com:4444)`);
11
- let requestId = getArg("requestId");
12
- if (!requestId) throw new Error(`--requestId is required (the request id shown on the access page)`);
13
-
14
- let { address, port } = parseStorageUrl(url);
15
- let nodeId = SocketFunction.connect({ address, port });
16
- await authenticateStorage({ address, port, nodeId });
17
- let record = await RemoteStorageController.nodes[nodeId].adminGrantAccess({ requestId });
18
- console.log(`Granted machine ${record.machineId} access to account ${JSON.stringify(record.account)}`);
19
- process.exit(0);
20
- }
21
-
22
- main().catch(e => {
23
- console.error(e);
24
- process.exit(1);
25
- });