@serve.zone/cli 33.9.0 → 33.11.0
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/dist_ts_cliclient/classes.cliclient.d.ts +12 -0
- package/dist_ts_cliclient/classes.cliclient.js +23 -1
- package/dist_ts_cliclient/commands.d.ts +12 -1
- package/dist_ts_cliclient/commands.js +56 -1
- package/dist_ts_cliclient/corestorecontroltoken.d.ts +33 -0
- package/dist_ts_cliclient/corestorecontroltoken.js +48 -0
- package/dist_ts_cliclient/index.d.ts +3 -1
- package/dist_ts_cliclient/index.js +33 -8
- package/dist_ts_cliclient/plugins.d.ts +8 -2
- package/dist_ts_cliclient/plugins.js +10 -3
- package/dist_ts_cliclient/relayauthorization.d.ts +48 -0
- package/dist_ts_cliclient/relayauthorization.js +95 -0
- package/dist_ts_cliclient/tokeninput.d.ts +32 -15
- package/dist_ts_cliclient/tokeninput.js +61 -15
- package/package.json +4 -3
- package/readme.md +43 -2
- package/ts_cliclient/classes.cliclient.ts +32 -0
- package/ts_cliclient/commands.ts +69 -2
- package/ts_cliclient/corestorecontroltoken.ts +71 -0
- package/ts_cliclient/index.ts +53 -9
- package/ts_cliclient/plugins.ts +16 -1
- package/ts_cliclient/readme.md +43 -2
- package/ts_cliclient/relayauthorization.ts +125 -0
- package/ts_cliclient/tokeninput.ts +81 -18
|
@@ -9,5 +9,17 @@ export declare class CliClient {
|
|
|
9
9
|
* the caller's to wipe; the API client seals its own copy and never logs or keeps it.
|
|
10
10
|
*/
|
|
11
11
|
bootstrapGateway(targetArg: plugins.servezoneApi.IExternalGatewayBootstrapTarget, bootstrapTokenArg: Uint8Array): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Writes one cluster relay's bearer to a new 0600 file and prints what describes the file:
|
|
14
|
+
* the cluster, the generation, the size, the SHA-256 and the audit receipt, never the bearer.
|
|
15
|
+
*/
|
|
16
|
+
exportRelayAuthorization(requestArg: plugins.servezoneInterfaces.data.IClusterRelayAuthorizationExportRequest, outputPathArg: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Stores the Corestore control token while it is still exactly at `expectedArg` and prints the
|
|
19
|
+
* state and the receipt the set produced, never the token. The token is the caller's to wipe.
|
|
20
|
+
*/
|
|
21
|
+
setCorestoreControlToken(expectedArg: plugins.servezoneInterfaces.data.TCorestoreControlTokenState, tokenArg: Uint8Array): Promise<void>;
|
|
22
|
+
/** Prints whether Cloudly holds the Corestore control token, its revision and its receipts. */
|
|
23
|
+
getCorestoreControlTokenState(): Promise<void>;
|
|
12
24
|
getGatewayStatus(): Promise<void>;
|
|
13
25
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { CloudlyApiClient } from '@serve.zone/api';
|
|
3
|
+
import { exportRelayAuthorizationToFile } from './relayauthorization.js';
|
|
4
|
+
import { getCorestoreControlTokenState, setCorestoreControlToken } from './corestorecontroltoken.js';
|
|
3
5
|
export class CliClient {
|
|
4
6
|
constructor(cloudlyApiClientArg) {
|
|
5
7
|
this.cloudlyApiClient = cloudlyApiClientArg;
|
|
@@ -19,9 +21,29 @@ export class CliClient {
|
|
|
19
21
|
});
|
|
20
22
|
console.log(JSON.stringify(state, null, 2));
|
|
21
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Writes one cluster relay's bearer to a new 0600 file and prints what describes the file:
|
|
26
|
+
* the cluster, the generation, the size, the SHA-256 and the audit receipt, never the bearer.
|
|
27
|
+
*/
|
|
28
|
+
async exportRelayAuthorization(requestArg, outputPathArg) {
|
|
29
|
+
const output = await exportRelayAuthorizationToFile(this.cloudlyApiClient, requestArg, outputPathArg);
|
|
30
|
+
console.log(JSON.stringify({ ok: true, command: 'relay export-authorization', ...output }));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Stores the Corestore control token while it is still exactly at `expectedArg` and prints the
|
|
34
|
+
* state and the receipt the set produced, never the token. The token is the caller's to wipe.
|
|
35
|
+
*/
|
|
36
|
+
async setCorestoreControlToken(expectedArg, tokenArg) {
|
|
37
|
+
const output = await setCorestoreControlToken(this.cloudlyApiClient, expectedArg, tokenArg);
|
|
38
|
+
console.log(JSON.stringify(output));
|
|
39
|
+
}
|
|
40
|
+
/** Prints whether Cloudly holds the Corestore control token, its revision and its receipts. */
|
|
41
|
+
async getCorestoreControlTokenState() {
|
|
42
|
+
console.log(JSON.stringify(await getCorestoreControlTokenState(this.cloudlyApiClient)));
|
|
43
|
+
}
|
|
22
44
|
async getGatewayStatus() {
|
|
23
45
|
const { state } = await this.cloudlyApiClient.settings.getExternalGatewayEnrollmentState();
|
|
24
46
|
console.log(JSON.stringify(state, null, 2));
|
|
25
47
|
}
|
|
26
48
|
}
|
|
27
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jbGljbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jbGljbGllbnQvY2xhc3Nlcy5jbGljbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbkQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekUsT0FBTyxFQUFFLDZCQUE2QixFQUFFLHdCQUF3QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFckcsTUFBTSxPQUFPLFNBQVM7SUFHcEIsWUFBWSxtQkFBcUM7UUFDL0MsSUFBSSxDQUFDLGdCQUFnQixHQUFHLG1CQUFtQixDQUFDO0lBQzlDLENBQUM7SUFFTSxLQUFLLENBQUMsV0FBVztRQUN0QixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLGdCQUFnQixDQUMzQixTQUErRCxFQUMvRCxpQkFBNkI7UUFFN0IsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxrQ0FBa0MsQ0FBQztZQUN4RixNQUFNLEVBQUUsU0FBUztZQUNqQixjQUFjLEVBQUUsaUJBQWlCO1NBQ2xDLENBQUMsQ0FBQztRQUNILE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyx3QkFBd0IsQ0FDbkMsVUFBb0YsRUFDcEYsYUFBcUI7UUFFckIsTUFBTSxNQUFNLEdBQUcsTUFBTSw4QkFBOEIsQ0FDakQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUNwRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLHdCQUF3QixDQUNuQyxXQUF5RSxFQUN6RSxRQUFvQjtRQUVwQixNQUFNLE1BQU0sR0FBRyxNQUFNLHdCQUF3QixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDNUYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELCtGQUErRjtJQUN4RixLQUFLLENBQUMsNkJBQTZCO1FBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLDZCQUE2QixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRixDQUFDO0lBRU0sS0FBSyxDQUFDLGdCQUFnQjtRQUMzQixNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLGlDQUFpQyxFQUFFLENBQUM7UUFDM0YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxDQUFDO0NBQ0YifQ==
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
2
|
/** What one invocation of the CLI asks for, parsed before anything is read or connected. */
|
|
3
3
|
export type TCliCommand =
|
|
4
4
|
/** No arguments: the default action, listing the clusters. */
|
|
@@ -9,6 +9,17 @@ export type TCliCommand =
|
|
|
9
9
|
} | {
|
|
10
10
|
kind: 'gateway-bootstrap';
|
|
11
11
|
target: plugins.servezoneApi.IExternalGatewayBootstrapTarget;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'relay-export-authorization';
|
|
14
|
+
request: plugins.servezoneInterfaces.data.IClusterRelayAuthorizationExportRequest;
|
|
15
|
+
/** A normalized absolute path in a private directory; the file must not exist yet. */
|
|
16
|
+
outputPath: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'corestore-set-control-token';
|
|
19
|
+
/** Exactly the state the administrator last read; never a minimum. */
|
|
20
|
+
expected: plugins.servezoneInterfaces.data.TCorestoreControlTokenState;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'corestore-control-token-state';
|
|
12
23
|
};
|
|
13
24
|
export declare const cliUsage: string;
|
|
14
25
|
/**
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
1
2
|
export const cliUsage = [
|
|
2
3
|
'Usage:',
|
|
3
4
|
' servezone',
|
|
4
5
|
' servezone gateway status',
|
|
5
6
|
' servezone gateway bootstrap --gateway-url <https url> --client-id <id>',
|
|
6
7
|
' The dcrouter admin token is read from stdin, never from arguments or the environment.',
|
|
8
|
+
' servezone relay export-authorization --cluster-id <id> --expected-generation <n> --output <absolute path>',
|
|
9
|
+
' Writes the relay bearer to a new 0600 file in a directory only you can write; never to stdout.',
|
|
10
|
+
' servezone corestore set-control-token --stdin --expect absent|<revision>',
|
|
11
|
+
' The Corestore control token is read from stdin, never from arguments or the environment.',
|
|
12
|
+
' servezone corestore control-token-state',
|
|
7
13
|
].join('\n');
|
|
8
14
|
/**
|
|
9
15
|
* An invocation the CLI does not run. It never quotes what it was given, because an argument may
|
|
@@ -37,6 +43,10 @@ export const parseCliCommand = (argsArg) => {
|
|
|
37
43
|
if (argsArg.length === 0)
|
|
38
44
|
return { kind: 'clusters' };
|
|
39
45
|
const [group, action, ...rest] = argsArg;
|
|
46
|
+
if (group === 'relay')
|
|
47
|
+
return parseRelayCommand(action, rest);
|
|
48
|
+
if (group === 'corestore')
|
|
49
|
+
return parseCorestoreCommand(action, rest);
|
|
40
50
|
requireUsage(group === 'gateway');
|
|
41
51
|
if (action === 'status') {
|
|
42
52
|
requireUsage(rest.length === 0);
|
|
@@ -49,4 +59,49 @@ export const parseCliCommand = (argsArg) => {
|
|
|
49
59
|
target: { gatewayUrl: options['--gateway-url'], gatewayClientId: options['--client-id'] },
|
|
50
60
|
};
|
|
51
61
|
};
|
|
52
|
-
|
|
62
|
+
/** A positive integer without leading zeros, as a generation or a revision is named. */
|
|
63
|
+
const parseCounter = (valueArg) => {
|
|
64
|
+
requireUsage(/^[1-9][0-9]{0,15}$/.test(valueArg) && Number.isSafeInteger(Number(valueArg)));
|
|
65
|
+
return Number(valueArg);
|
|
66
|
+
};
|
|
67
|
+
/** `relay export-authorization`: the cluster, the exact generation and a normalized absolute output. */
|
|
68
|
+
const parseRelayCommand = (actionArg, restArg) => {
|
|
69
|
+
requireUsage(actionArg === 'export-authorization');
|
|
70
|
+
const options = parseOptions(restArg, ['--cluster-id', '--expected-generation', '--output']);
|
|
71
|
+
const generation = parseCounter(options['--expected-generation']);
|
|
72
|
+
const outputPath = options['--output'];
|
|
73
|
+
requireUsage(plugins.path.isAbsolute(outputPath) && plugins.path.normalize(outputPath) === outputPath
|
|
74
|
+
&& !outputPath.endsWith(plugins.path.sep));
|
|
75
|
+
return {
|
|
76
|
+
kind: 'relay-export-authorization',
|
|
77
|
+
request: { clusterId: options['--cluster-id'], expectedGeneration: generation },
|
|
78
|
+
outputPath,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* `corestore set-control-token --stdin --expect absent|<revision>` and
|
|
83
|
+
* `corestore control-token-state`.
|
|
84
|
+
*
|
|
85
|
+
* `--stdin` names where the token comes from, so no invocation reads it from anywhere else, and
|
|
86
|
+
* `--expect` is the state `control-token-state` answered: `absent`, or the stored revision.
|
|
87
|
+
*/
|
|
88
|
+
const parseCorestoreCommand = (actionArg, restArg) => {
|
|
89
|
+
if (actionArg === 'control-token-state') {
|
|
90
|
+
requireUsage(restArg.length === 0);
|
|
91
|
+
return { kind: 'corestore-control-token-state' };
|
|
92
|
+
}
|
|
93
|
+
requireUsage(actionArg === 'set-control-token');
|
|
94
|
+
// `--stdin` is a flag in an option's place, either before or after `--expect <value>`.
|
|
95
|
+
requireUsage(restArg.length === 3);
|
|
96
|
+
const stdinIndex = restArg[0] === '--stdin' ? 0 : 2;
|
|
97
|
+
requireUsage(restArg[stdinIndex] === '--stdin');
|
|
98
|
+
const options = parseOptions(restArg.filter((_argArg, indexArg) => indexArg !== stdinIndex), ['--expect']);
|
|
99
|
+
const expected = options['--expect'];
|
|
100
|
+
return {
|
|
101
|
+
kind: 'corestore-set-control-token',
|
|
102
|
+
expected: expected === 'absent'
|
|
103
|
+
? { state: 'absent' }
|
|
104
|
+
: { state: 'present', revision: parseCounter(expected) },
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWFuZHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jbGljbGllbnQvY29tbWFuZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFxQnhDLE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBRztJQUN0QixRQUFRO0lBQ1IsYUFBYTtJQUNiLDRCQUE0QjtJQUM1QiwwRUFBMEU7SUFDMUUsMkZBQTJGO0lBQzNGLDZHQUE2RztJQUM3RyxvR0FBb0c7SUFDcEcsNEVBQTRFO0lBQzVFLDhGQUE4RjtJQUM5RiwyQ0FBMkM7Q0FDNUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFFYjs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sYUFBYyxTQUFRLEtBQUs7SUFDdEM7UUFDRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDaEIsSUFBSSxDQUFDLElBQUksR0FBRyxlQUFlLENBQUM7SUFDOUIsQ0FBQztDQUNGO0FBRUQsU0FBUyxZQUFZLENBQUMsWUFBcUI7SUFDekMsSUFBSSxDQUFDLFlBQVk7UUFBRSxNQUFNLElBQUksYUFBYSxFQUFFLENBQUM7QUFDL0MsQ0FBQztBQUVELG1GQUFtRjtBQUNuRixNQUFNLFlBQVksR0FBRyxDQUNuQixPQUEwQixFQUMxQixRQUEwQixFQUNILEVBQUU7SUFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDMUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNyRCxLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDdkQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVCLE1BQU0sS0FBSyxHQUFHLE9B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
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
type TCorestoreControlTokenSetRefusal = plugins.servezoneInterfaces.data.TCorestoreControlTokenSetRefusal;
|
|
3
|
+
/** Cloudly did not store the token, for one of the contract's refusals, which it names. */
|
|
4
|
+
export declare class CorestoreControlTokenSetRefusedError extends Error {
|
|
5
|
+
readonly refusal: TCorestoreControlTokenSetRefusal;
|
|
6
|
+
constructor(refusal: TCorestoreControlTokenSetRefusal);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The contract refusal an error is, or `undefined` for every other error.
|
|
10
|
+
*
|
|
11
|
+
* Cloudly answers a refusal by its name and nothing else, so the name is the whole of the error's
|
|
12
|
+
* message; any other message, Cloudly's one denial text included, is not a refusal.
|
|
13
|
+
*/
|
|
14
|
+
export declare const nameCorestoreControlTokenSetRefusal: (errorArg: unknown) => TCorestoreControlTokenSetRefusal | undefined;
|
|
15
|
+
/** What the CLI prints about a stored token: the state it produced and its receipt, never the token. */
|
|
16
|
+
export interface ICorestoreControlTokenSetOutput extends plugins.servezoneInterfaces.data.ICorestoreControlTokenSetResult {
|
|
17
|
+
ok: true;
|
|
18
|
+
command: 'corestore set-control-token';
|
|
19
|
+
}
|
|
20
|
+
/** What the CLI prints about the token's state: the state and its value-free receipts. */
|
|
21
|
+
export interface ICorestoreControlTokenStateOutput extends plugins.servezoneInterfaces.data.ICorestoreControlTokenStateRead {
|
|
22
|
+
ok: true;
|
|
23
|
+
command: 'corestore control-token-state';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Stores the token through the API client while it is still exactly at `expected`, answering only
|
|
27
|
+
* the state and the receipt. The token bytes are the caller's to wipe; the text the request needs
|
|
28
|
+
* is decoded from them here and never printed, logged or put into an error.
|
|
29
|
+
*/
|
|
30
|
+
export declare const setCorestoreControlToken: (apiClientArg: plugins.servezoneApi.CloudlyApiClient, expectedArg: plugins.servezoneInterfaces.data.TCorestoreControlTokenState, tokenArg: Uint8Array) => Promise<ICorestoreControlTokenSetOutput>;
|
|
31
|
+
/** Whether Cloudly holds the token, at which revision, and its receipts, oldest first. */
|
|
32
|
+
export declare const getCorestoreControlTokenState: (apiClientArg: plugins.servezoneApi.CloudlyApiClient) => Promise<ICorestoreControlTokenStateOutput>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { decodeCorestoreControlToken } from './tokeninput.js';
|
|
3
|
+
/** Cloudly did not store the token, for one of the contract's refusals, which it names. */
|
|
4
|
+
export class CorestoreControlTokenSetRefusedError extends Error {
|
|
5
|
+
constructor(refusal) {
|
|
6
|
+
super(`The Corestore control token was not stored: ${refusal}.`);
|
|
7
|
+
this.refusal = refusal;
|
|
8
|
+
this.name = 'CorestoreControlTokenSetRefusedError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The contract refusal an error is, or `undefined` for every other error.
|
|
13
|
+
*
|
|
14
|
+
* Cloudly answers a refusal by its name and nothing else, so the name is the whole of the error's
|
|
15
|
+
* message; any other message, Cloudly's one denial text included, is not a refusal.
|
|
16
|
+
*/
|
|
17
|
+
export const nameCorestoreControlTokenSetRefusal = (errorArg) => {
|
|
18
|
+
if (!(errorArg instanceof Error))
|
|
19
|
+
return undefined;
|
|
20
|
+
return plugins.servezoneInterfaces.data.corestoreControlTokenSetRefusals
|
|
21
|
+
.find((refusalArg) => refusalArg === errorArg.message);
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Stores the token through the API client while it is still exactly at `expected`, answering only
|
|
25
|
+
* the state and the receipt. The token bytes are the caller's to wipe; the text the request needs
|
|
26
|
+
* is decoded from them here and never printed, logged or put into an error.
|
|
27
|
+
*/
|
|
28
|
+
export const setCorestoreControlToken = async (apiClientArg, expectedArg, tokenArg) => {
|
|
29
|
+
try {
|
|
30
|
+
const { state, receipt } = await apiClientArg.platform.setCorestoreControlToken({
|
|
31
|
+
token: decodeCorestoreControlToken(tokenArg),
|
|
32
|
+
expected: expectedArg,
|
|
33
|
+
});
|
|
34
|
+
return { ok: true, command: 'corestore set-control-token', state, receipt };
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const refusal = nameCorestoreControlTokenSetRefusal(error);
|
|
38
|
+
if (refusal !== undefined)
|
|
39
|
+
throw new CorestoreControlTokenSetRefusedError(refusal);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
/** Whether Cloudly holds the token, at which revision, and its receipts, oldest first. */
|
|
44
|
+
export const getCorestoreControlTokenState = async (apiClientArg) => {
|
|
45
|
+
const { state, receipts } = await apiClientArg.platform.getCorestoreControlTokenState();
|
|
46
|
+
return { ok: true, command: 'corestore control-token-state', state, receipts };
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZXN0b3JlY29udHJvbHRva2VuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfY2xpY2xpZW50L2NvcmVzdG9yZWNvbnRyb2x0b2tlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUk5RCwyRkFBMkY7QUFDM0YsTUFBTSxPQUFPLG9DQUFxQyxTQUFRLEtBQUs7SUFDN0QsWUFBNEIsT0FBeUM7UUFDbkUsS0FBSyxDQUFDLCtDQUErQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBRHZDLFlBQU8sR0FBUCxPQUFPLENBQWtDO1FBRW5FLElBQUksQ0FBQyxJQUFJLEdBQUcsc0NBQXNDLENBQUM7SUFDckQsQ0FBQztDQUNGO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQ0FBbUMsR0FBRyxDQUNqRCxRQUFpQixFQUM2QixFQUFFO0lBQ2hELElBQUksQ0FBQyxDQUFDLFFBQVEsWUFBWSxLQUFLLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNuRCxPQUFPLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsZ0NBQWdDO1NBQ3JFLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxLQUFLLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUMzRCxDQUFDLENBQUM7QUFnQkY7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLEtBQUssRUFDM0MsWUFBbUQsRUFDbkQsV0FBeUUsRUFDekUsUUFBb0IsRUFDc0IsRUFBRTtJQUM1QyxJQUFJLENBQUM7UUFDSCxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sWUFBWSxDQUFDLFFBQVEsQ0FBQyx3QkFBd0IsQ0FBQztZQUM5RSxLQUFLLEVBQUUsMkJBQTJCLENBQUMsUUFBUSxDQUFDO1lBQzVDLFFBQVEsRUFBRSxXQUFXO1NBQ3RCLENBQUMsQ0FBQztRQUNILE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDOUUsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLE9BQU8sR0FBRyxtQ0FBbUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzRCxJQUFJLE9BQU8sS0FBSyxTQUFTO1lBQUUsTUFBTSxJQUFJLG9DQUFvQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25GLE1BQU0sS0FBSyxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLDBGQUEwRjtBQUMxRixNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxLQUFLLEVBQ2hELFlBQW1ELEVBQ1AsRUFBRTtJQUM5QyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sWUFBWSxDQUFDLFFBQVEsQ0FBQyw2QkFBNkIsRUFBRSxDQUFDO0lBQ3hGLE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUM7QUFDakYsQ0FBQyxDQUFDIn0=
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { CliUsageError, parseCliCommand, type TCliCommand } from './commands.js';
|
|
2
|
-
export {
|
|
2
|
+
export { RelayAuthorizationOutputError, exportRelayAuthorizationToFile, requirePrivateOutputDirectory, writeRelayAuthorization, type IRelayAuthorizationOutput, type TRelayAuthorizationOutputRefusal, } from './relayauthorization.js';
|
|
3
|
+
export { BootstrapTokenInputError, CorestoreControlTokenInputError, TokenInputError, readBootstrapTokenInput, readCorestoreControlTokenInput, type TBootstrapTokenInputRefusal, type TTokenInputRefusal, } from './tokeninput.js';
|
|
4
|
+
export { CorestoreControlTokenSetRefusedError, getCorestoreControlTokenState, nameCorestoreControlTokenSetRefusal, setCorestoreControlToken, type ICorestoreControlTokenSetOutput, type ICorestoreControlTokenStateOutput, } from './corestorecontroltoken.js';
|
|
3
5
|
export declare const runCli: () => Promise<void>;
|
|
@@ -1,18 +1,32 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { CliClient } from './classes.cliclient.js';
|
|
3
3
|
import { parseCliCommand } from './commands.js';
|
|
4
|
-
import { readBootstrapTokenInput } from './tokeninput.js';
|
|
4
|
+
import { readBootstrapTokenInput, readCorestoreControlTokenInput } from './tokeninput.js';
|
|
5
|
+
import { requirePrivateOutputDirectory } from './relayauthorization.js';
|
|
5
6
|
export { CliUsageError, parseCliCommand } from './commands.js';
|
|
6
|
-
export {
|
|
7
|
+
export { RelayAuthorizationOutputError, exportRelayAuthorizationToFile, requirePrivateOutputDirectory, writeRelayAuthorization, } from './relayauthorization.js';
|
|
8
|
+
export { BootstrapTokenInputError, CorestoreControlTokenInputError, TokenInputError, readBootstrapTokenInput, readCorestoreControlTokenInput, } from './tokeninput.js';
|
|
9
|
+
export { CorestoreControlTokenSetRefusedError, getCorestoreControlTokenState, nameCorestoreControlTokenSetRefusal, setCorestoreControlToken, } from './corestorecontroltoken.js';
|
|
10
|
+
/** Reads the token the command needs from stdin, before anything connects. */
|
|
11
|
+
const readInvocation = async (commandArg) => {
|
|
12
|
+
if (commandArg.kind === 'gateway-bootstrap') {
|
|
13
|
+
return { ...commandArg, bootstrapToken: await readBootstrapTokenInput(process.stdin) };
|
|
14
|
+
}
|
|
15
|
+
if (commandArg.kind === 'corestore-set-control-token') {
|
|
16
|
+
return { ...commandArg, controlToken: await readCorestoreControlTokenInput(process.stdin) };
|
|
17
|
+
}
|
|
18
|
+
return commandArg;
|
|
19
|
+
};
|
|
7
20
|
export const runCli = async () => {
|
|
8
21
|
// The command and the token are settled before anything connects, so a wrong invocation or a
|
|
9
22
|
// token that could never be one fails without reaching Cloudly.
|
|
10
23
|
let command;
|
|
11
24
|
try {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
command = await readInvocation(parseCliCommand(process.argv.slice(2)));
|
|
26
|
+
// An output the bearer could not be written to fetches no bearer and records no export.
|
|
27
|
+
if (command.kind === 'relay-export-authorization') {
|
|
28
|
+
await requirePrivateOutputDirectory(command.outputPath);
|
|
29
|
+
}
|
|
16
30
|
}
|
|
17
31
|
catch (error) {
|
|
18
32
|
console.error(error.message);
|
|
@@ -31,12 +45,21 @@ export const runCli = async () => {
|
|
|
31
45
|
if (command.kind === 'gateway-bootstrap') {
|
|
32
46
|
await cliClient.bootstrapGateway(command.target, command.bootstrapToken);
|
|
33
47
|
}
|
|
48
|
+
else if (command.kind === 'relay-export-authorization') {
|
|
49
|
+
await cliClient.exportRelayAuthorization(command.request, command.outputPath);
|
|
50
|
+
}
|
|
51
|
+
else if (command.kind === 'corestore-set-control-token') {
|
|
52
|
+
await cliClient.setCorestoreControlToken(command.expected, command.controlToken);
|
|
53
|
+
}
|
|
54
|
+
else if (command.kind === 'corestore-control-token-state') {
|
|
55
|
+
await cliClient.getCorestoreControlTokenState();
|
|
56
|
+
}
|
|
34
57
|
else {
|
|
35
58
|
await cliClient.getGatewayStatus();
|
|
36
59
|
}
|
|
37
60
|
}
|
|
38
61
|
catch (error) {
|
|
39
|
-
// Cloudly answers a refusal by name; it never carries
|
|
62
|
+
// Cloudly answers a refusal by name; it never carries a token or a bearer.
|
|
40
63
|
console.error(error.message);
|
|
41
64
|
process.exitCode = 1;
|
|
42
65
|
}
|
|
@@ -47,6 +70,8 @@ export const runCli = async () => {
|
|
|
47
70
|
finally {
|
|
48
71
|
if (command.kind === 'gateway-bootstrap')
|
|
49
72
|
command.bootstrapToken.fill(0);
|
|
73
|
+
if (command.kind === 'corestore-set-control-token')
|
|
74
|
+
command.controlToken.fill(0);
|
|
50
75
|
}
|
|
51
76
|
};
|
|
52
77
|
/** The API client, started and signed in the way every command of this CLI signs in. */
|
|
@@ -82,4 +107,4 @@ const connect = async () => {
|
|
|
82
107
|
}
|
|
83
108
|
return apiClient;
|
|
84
109
|
};
|
|
85
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
110
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jbGljbGllbnQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxlQUFlLEVBQW9CLE1BQU0sZUFBZSxDQUFDO0FBQ2xFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzFGLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXhFLE9BQU8sRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFvQixNQUFNLGVBQWUsQ0FBQztBQUNqRixPQUFPLEVBQ0wsNkJBQTZCLEVBQzdCLDhCQUE4QixFQUM5Qiw2QkFBNkIsRUFDN0IsdUJBQXVCLEdBR3hCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUNMLHdCQUF3QixFQUN4QiwrQkFBK0IsRUFDL0IsZUFBZSxFQUNmLHVCQUF1QixFQUN2Qiw4QkFBOEIsR0FHL0IsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQ0wsb0NBQW9DLEVBQ3BDLDZCQUE2QixFQUM3QixtQ0FBbUMsRUFDbkMsd0JBQXdCLEdBR3pCLE1BQU0sNEJBQTRCLENBQUM7QUFXcEMsOEVBQThFO0FBQzlFLE1BQU0sY0FBYyxHQUFHLEtBQUssRUFBRSxVQUF1QixFQUEyQixFQUFFO0lBQ2hGLElBQUksVUFBVSxDQUFDLElBQUksS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1FBQzVDLE9BQU8sRUFBRSxHQUFHLFVBQVUsRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztJQUN6RixDQUFDO0lBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxLQUFLLDZCQUE2QixFQUFFLENB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
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
export { crypto, fs, path, };
|
|
1
5
|
import * as servezoneApi from '@serve.zone/api';
|
|
2
6
|
import * as servezoneInterfaces from '@serve.zone/interfaces';
|
|
3
|
-
|
|
7
|
+
import * as servezoneInterfacesRuntime from '@serve.zone/interfaces/runtime';
|
|
8
|
+
export { servezoneApi, servezoneInterfaces, servezoneInterfacesRuntime, };
|
|
4
9
|
import * as projectinfo from '@push.rocks/projectinfo';
|
|
5
10
|
import * as qenv from '@push.rocks/qenv';
|
|
6
|
-
|
|
11
|
+
import * as smartfs from '@push.rocks/smartfs';
|
|
12
|
+
export { projectinfo, qenv, smartfs, };
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
// node native scope
|
|
2
|
+
import * as crypto from 'node:crypto';
|
|
3
|
+
import * as fs from 'node:fs/promises';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
export { crypto, fs, path, };
|
|
1
6
|
// @serve.zone scope
|
|
2
7
|
import * as servezoneApi from '@serve.zone/api';
|
|
3
8
|
import * as servezoneInterfaces from '@serve.zone/interfaces';
|
|
4
|
-
|
|
9
|
+
import * as servezoneInterfacesRuntime from '@serve.zone/interfaces/runtime';
|
|
10
|
+
export { servezoneApi, servezoneInterfaces, servezoneInterfacesRuntime, };
|
|
5
11
|
// @push.rocks scope
|
|
6
12
|
import * as projectinfo from '@push.rocks/projectinfo';
|
|
7
13
|
import * as qenv from '@push.rocks/qenv';
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
import * as smartfs from '@push.rocks/smartfs';
|
|
15
|
+
export { projectinfo, qenv, smartfs, };
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2NsaWNsaWVudC9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9CQUFvQjtBQUNwQixPQUFPLEtBQUssTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUN0QyxPQUFPLEtBQUssRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBRWxDLE9BQU8sRUFDTCxNQUFNLEVBQ04sRUFBRSxFQUNGLElBQUksR0FDTCxDQUFBO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxZQUFZLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxLQUFLLG1CQUFtQixNQUFNLHdCQUF3QixDQUFDO0FBQzlELE9BQU8sS0FBSywwQkFBMEIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUU3RSxPQUFPLEVBQ0wsWUFBWSxFQUNaLG1CQUFtQixFQUNuQiwwQkFBMEIsR0FDM0IsQ0FBQTtBQUVELG9CQUFvQjtBQUNwQixPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUUvQyxPQUFPLEVBQ0wsV0FBVyxFQUNYLElBQUksRUFDSixPQUFPLEdBQ1IsQ0FBQSJ9
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
/** Why the relay bearer was not written, named without quoting the bearer. */
|
|
3
|
+
export type TRelayAuthorizationOutputRefusal =
|
|
4
|
+
/** The output's directory does not exist, or a component of its path is not a directory. */
|
|
5
|
+
'output-directory-missing'
|
|
6
|
+
/**
|
|
7
|
+
* The output's directory is not a private directory of the caller: it is reached through a
|
|
8
|
+
* symbolic link, owned by another user, or writable by its group or by other users.
|
|
9
|
+
*/
|
|
10
|
+
| 'output-directory-not-private'
|
|
11
|
+
/** Something already exists at the output path; it is left untouched. */
|
|
12
|
+
| 'output-exists';
|
|
13
|
+
export declare class RelayAuthorizationOutputError extends Error {
|
|
14
|
+
readonly refusal: TRelayAuthorizationOutputRefusal;
|
|
15
|
+
constructor(refusal: TRelayAuthorizationOutputRefusal);
|
|
16
|
+
}
|
|
17
|
+
/** What the CLI prints about the file it wrote: metadata only, never a byte of the bearer. */
|
|
18
|
+
export interface IRelayAuthorizationOutput {
|
|
19
|
+
clusterId: string;
|
|
20
|
+
generation: number;
|
|
21
|
+
outputPath: string;
|
|
22
|
+
byteLength: number;
|
|
23
|
+
/** Hex SHA-256 of the file's bytes, as `sha256sum` prints it for the same file. */
|
|
24
|
+
sha256: string;
|
|
25
|
+
/** The audit receipt Cloudly recorded for this export. */
|
|
26
|
+
receiptId: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Refuses an output whose directory is not a private directory of the caller, or that exists.
|
|
30
|
+
*
|
|
31
|
+
* Exclusive creation guards only the file's own name, so the directory is checked here: its path
|
|
32
|
+
* resolves to itself (no symbolic link anywhere on it), it is a directory owned by the caller,
|
|
33
|
+
* and neither its group nor other users can write it. Checked before Cloudly is asked, so a bad
|
|
34
|
+
* output fetches no bearer and writes no audit receipt.
|
|
35
|
+
*/
|
|
36
|
+
export declare const requirePrivateOutputDirectory: (outputPathArg: string) => Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Writes the bearer as a new file, mode 0600 whatever the umask, whole or not at all.
|
|
39
|
+
*
|
|
40
|
+
* The write is exclusive and atomic: an existing entry at the path is never replaced or
|
|
41
|
+
* followed, and the bytes go to a private temporary file that is linked into place.
|
|
42
|
+
*/
|
|
43
|
+
export declare const writeRelayAuthorization: (outputPathArg: string, bearerArg: Uint8Array) => Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Fetches one cluster relay's bearer through the API client and writes it to the operator's
|
|
46
|
+
* file, answering only what describes the file.
|
|
47
|
+
*/
|
|
48
|
+
export declare const exportRelayAuthorizationToFile: (apiClientArg: plugins.servezoneApi.CloudlyApiClient, requestArg: plugins.servezoneInterfaces.data.IClusterRelayAuthorizationExportRequest, outputPathArg: string) => Promise<IRelayAuthorizationOutput>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
export class RelayAuthorizationOutputError extends Error {
|
|
3
|
+
constructor(refusal) {
|
|
4
|
+
super(`The relay bearer was not written: ${refusal}.`);
|
|
5
|
+
this.refusal = refusal;
|
|
6
|
+
this.name = 'RelayAuthorizationOutputError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const errorCodeOf = (errorArg) => errorArg instanceof Error && 'code' in errorArg && typeof errorArg.code === 'string'
|
|
10
|
+
? errorArg.code : undefined;
|
|
11
|
+
/** A directory that is not there, or not reachable as one, is the operator's to create. */
|
|
12
|
+
const refuseMissingDirectory = (errorArg) => {
|
|
13
|
+
const code = errorCodeOf(errorArg);
|
|
14
|
+
if (code === 'ENOENT' || code === 'ENOTDIR') {
|
|
15
|
+
throw new RelayAuthorizationOutputError('output-directory-missing');
|
|
16
|
+
}
|
|
17
|
+
throw errorArg;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Refuses an output whose directory is not a private directory of the caller, or that exists.
|
|
21
|
+
*
|
|
22
|
+
* Exclusive creation guards only the file's own name, so the directory is checked here: its path
|
|
23
|
+
* resolves to itself (no symbolic link anywhere on it), it is a directory owned by the caller,
|
|
24
|
+
* and neither its group nor other users can write it. Checked before Cloudly is asked, so a bad
|
|
25
|
+
* output fetches no bearer and writes no audit receipt.
|
|
26
|
+
*/
|
|
27
|
+
export const requirePrivateOutputDirectory = async (outputPathArg) => {
|
|
28
|
+
const directory = plugins.path.dirname(outputPathArg);
|
|
29
|
+
const stats = await plugins.fs.lstat(directory).catch(refuseMissingDirectory);
|
|
30
|
+
const resolved = await plugins.fs.realpath(directory).catch(refuseMissingDirectory);
|
|
31
|
+
// A symbolic link anywhere on the path is a directory someone else could redirect.
|
|
32
|
+
if (resolved !== directory)
|
|
33
|
+
throw new RelayAuthorizationOutputError('output-directory-not-private');
|
|
34
|
+
if (!stats.isDirectory())
|
|
35
|
+
throw new RelayAuthorizationOutputError('output-directory-missing');
|
|
36
|
+
if (stats.uid !== process.getuid?.() || (stats.mode & 0o022) !== 0) {
|
|
37
|
+
throw new RelayAuthorizationOutputError('output-directory-not-private');
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
await plugins.fs.lstat(outputPathArg);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (errorCodeOf(error) === 'ENOENT')
|
|
44
|
+
return;
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
throw new RelayAuthorizationOutputError('output-exists');
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Writes the bearer as a new file, mode 0600 whatever the umask, whole or not at all.
|
|
51
|
+
*
|
|
52
|
+
* The write is exclusive and atomic: an existing entry at the path is never replaced or
|
|
53
|
+
* followed, and the bytes go to a private temporary file that is linked into place.
|
|
54
|
+
*/
|
|
55
|
+
export const writeRelayAuthorization = async (outputPathArg, bearerArg) => {
|
|
56
|
+
await requirePrivateOutputDirectory(outputPathArg);
|
|
57
|
+
const smartFs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
|
|
58
|
+
const bytes = Buffer.from(bearerArg);
|
|
59
|
+
try {
|
|
60
|
+
await smartFs.file(outputPathArg).mode(0o600).exclusive().atomic().write(bytes);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof plugins.smartfs.SmartFsExclusiveWriteError) {
|
|
64
|
+
throw new RelayAuthorizationOutputError(error.code === 'EEXIST' ? 'output-exists' : 'output-directory-missing');
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
bytes.fill(0);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Fetches one cluster relay's bearer through the API client and writes it to the operator's
|
|
74
|
+
* file, answering only what describes the file.
|
|
75
|
+
*/
|
|
76
|
+
export const exportRelayAuthorizationToFile = async (apiClientArg, requestArg, outputPathArg) => {
|
|
77
|
+
await requirePrivateOutputDirectory(outputPathArg);
|
|
78
|
+
const exported = await apiClientArg.cluster.exportClusterRelayAuthorization(requestArg);
|
|
79
|
+
const bearer = new TextEncoder().encode(exported.authorization);
|
|
80
|
+
try {
|
|
81
|
+
await writeRelayAuthorization(outputPathArg, bearer);
|
|
82
|
+
return {
|
|
83
|
+
clusterId: exported.credential.clusterId,
|
|
84
|
+
generation: exported.credential.generation,
|
|
85
|
+
outputPath: outputPathArg,
|
|
86
|
+
byteLength: bearer.byteLength,
|
|
87
|
+
sha256: plugins.crypto.createHash('sha256').update(bearer).digest('hex'),
|
|
88
|
+
receiptId: exported.receipt.id,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
bearer.fill(0);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXlhdXRob3JpemF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfY2xpY2xpZW50L3JlbGF5YXV0aG9yaXphdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQWN4QyxNQUFNLE9BQU8sNkJBQThCLFNBQVEsS0FBSztJQUN0RCxZQUE0QixPQUF5QztRQUNuRSxLQUFLLENBQUMscUNBQXFDLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFEN0IsWUFBTyxHQUFQLE9BQU8sQ0FBa0M7UUFFbkUsSUFBSSxDQUFDLElBQUksR0FBRywrQkFBK0IsQ0FBQztJQUM5QyxDQUFDO0NBQ0Y7QUFjRCxNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQWlCLEVBQXNCLEVBQUUsQ0FDNUQsUUFBUSxZQUFZLEtBQUssSUFBSSxNQUFNLElBQUksUUFBUSxJQUFJLE9BQU8sUUFBUSxDQUFDLElBQUksS0FBSyxRQUFRO0lBQ2xGLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFFaEMsMkZBQTJGO0FBQzNGLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxRQUFpQixFQUFTLEVBQUU7SUFDMUQsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25DLElBQUksSUFBSSxLQUFLLFFBQVEsSUFBSSxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDNUMsTUFBTSxJQUFJLDZCQUE2QixDQUFDLDBCQUEwQixDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUNELE1BQU0sUUFBUSxDQUFDO0FBQ2pCLENBQUMsQ0FBQztBQUVGOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxLQUFLLEVBQUUsYUFBcUIsRUFBaUIsRUFBRTtJQUMxRixNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFh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
|
|
@@ -1,25 +1,42 @@
|
|
|
1
|
-
/** Why
|
|
2
|
-
export type
|
|
1
|
+
/** Why a token piped in was not taken, named without quoting any of it. */
|
|
2
|
+
export type TTokenInputRefusal =
|
|
3
3
|
/** stdin is a terminal, which would echo a token typed into it; pipe the token in instead. */
|
|
4
4
|
'token-input-terminal'
|
|
5
5
|
/** stdin carried more bytes than a token and one line break. */
|
|
6
6
|
| 'token-input-oversized'
|
|
7
|
-
/** What stdin carried is not a token: empty, or a byte
|
|
7
|
+
/** What stdin carried is not a token by the token's own rule: empty, or a byte the rule refuses. */
|
|
8
8
|
| 'token-input-invalid';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/** Why the dcrouter admin token piped into `gateway bootstrap` was not taken. */
|
|
10
|
+
export type TBootstrapTokenInputRefusal = TTokenInputRefusal;
|
|
11
|
+
/** A refused token input: which token, and why, never a byte of what was read. */
|
|
12
|
+
export declare class TokenInputError extends Error {
|
|
13
|
+
readonly refusal: TTokenInputRefusal;
|
|
14
|
+
constructor(refusal: TTokenInputRefusal, subjectArg: string);
|
|
12
15
|
}
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
export declare class BootstrapTokenInputError extends TokenInputError {
|
|
17
|
+
constructor(refusalArg: TTokenInputRefusal);
|
|
18
|
+
}
|
|
19
|
+
export declare class CorestoreControlTokenInputError extends TokenInputError {
|
|
20
|
+
constructor(refusalArg: TTokenInputRefusal);
|
|
21
|
+
}
|
|
22
|
+
/** What a token is read from: the command's stdin, or a stream a test hands in. */
|
|
23
|
+
export type TTokenInput = AsyncIterable<Uint8Array> & {
|
|
15
24
|
isTTY?: boolean;
|
|
16
25
|
};
|
|
26
|
+
export type TBootstrapTokenInput = TTokenInput;
|
|
27
|
+
/**
|
|
28
|
+
* The dcrouter admin token piped into `gateway bootstrap`: at most the bootstrap contract's
|
|
29
|
+
* `maximumTokenBytes` of visible ASCII.
|
|
30
|
+
*/
|
|
31
|
+
export declare const readBootstrapTokenInput: (inputArg: TTokenInput) => Promise<Uint8Array>;
|
|
32
|
+
/**
|
|
33
|
+
* The token as text, exactly as its bytes say: invalid UTF-8 throws, and a leading byte order mark
|
|
34
|
+
* is kept, so the contract judges and Cloudly receives every character that was piped in.
|
|
35
|
+
*/
|
|
36
|
+
export declare const decodeCorestoreControlToken: (tokenArg: Uint8Array) => string;
|
|
17
37
|
/**
|
|
18
|
-
* The
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* the environment leaks into child processes. One trailing line break, `\n` or `\r\n`, is what
|
|
22
|
-
* `echo` or a file adds and is not part of the token; everything else must pass the contract's
|
|
23
|
-
* token rule. Every byte read is wiped before this answers, whatever it answers.
|
|
38
|
+
* The Corestore control token piped into `corestore set-control-token`: what the contract's
|
|
39
|
+
* `isCorestoreControlToken` accepts, so at most `corestoreCredentialRuntimeLimits
|
|
40
|
+
* .maximumControlTokenBytes` of UTF-8 without whitespace.
|
|
24
41
|
*/
|
|
25
|
-
export declare const
|
|
42
|
+
export declare const readCorestoreControlTokenInput: (inputArg: TTokenInput) => Promise<Uint8Array>;
|