@almyty/runner 1.5.2 → 1.5.4
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/README.md +28 -14
- package/dist/binaries.js +8 -1
- package/dist/binaries.js.map +1 -1
- package/dist/cli-args.d.ts +6 -0
- package/dist/cli-args.js +19 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli.d.ts +8 -5
- package/dist/cli.js +34 -19
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.js +21 -8
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +34 -0
- package/dist/daemon.js +117 -18
- package/dist/daemon.js.map +1 -1
- package/dist/enroll.d.ts +91 -0
- package/dist/enroll.js +261 -0
- package/dist/enroll.js.map +1 -0
- package/dist/hosted-setup.d.ts +43 -0
- package/dist/hosted-setup.js +196 -0
- package/dist/hosted-setup.js.map +1 -0
- package/dist/policy.d.ts +26 -0
- package/dist/policy.js +143 -0
- package/dist/policy.js.map +1 -1
- package/dist/streamable-client.d.ts +23 -5
- package/dist/streamable-client.js +32 -5
- package/dist/streamable-client.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Where the volume is mounted when the Deployment does not say. */
|
|
2
|
+
export declare const DEFAULT_WORKSPACE_ROOT = "/workspace";
|
|
3
|
+
/** The checkout's folder inside the workspace. */
|
|
4
|
+
export declare const REPO_DIR_NAME = "repo";
|
|
5
|
+
export interface CommandResult {
|
|
6
|
+
code: number | null;
|
|
7
|
+
timedOut?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Runs one command with its output going to the runner's log. */
|
|
10
|
+
export type RunCommand = (command: string, args: string[], opts: {
|
|
11
|
+
cwd: string;
|
|
12
|
+
env: NodeJS.ProcessEnv;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}) => Promise<CommandResult>;
|
|
15
|
+
export interface PrepareInputs {
|
|
16
|
+
env?: Record<string, string | undefined>;
|
|
17
|
+
run?: RunCommand;
|
|
18
|
+
log?: (line: string) => void;
|
|
19
|
+
warn?: (line: string) => void;
|
|
20
|
+
/** Where the script file is written before it runs. */
|
|
21
|
+
tmpDir?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface PrepareOutcome {
|
|
24
|
+
/** Nothing to do: this volume already carries this environment version. */
|
|
25
|
+
upToDate: boolean;
|
|
26
|
+
cloned: boolean;
|
|
27
|
+
setupRan: boolean;
|
|
28
|
+
/** Clone and setup both succeeded (or were not needed) and the version was recorded. */
|
|
29
|
+
ok: boolean;
|
|
30
|
+
repoDir: string | null;
|
|
31
|
+
}
|
|
32
|
+
export declare function workspaceRoot(env: Record<string, string | undefined>): string;
|
|
33
|
+
export declare function prepareHostedWorkspace(inputs?: PrepareInputs): Promise<PrepareOutcome>;
|
|
34
|
+
/**
|
|
35
|
+
* The token as an HTTP Authorization header for the repository's origin,
|
|
36
|
+
* passed through git's GIT_CONFIG_COUNT/KEY/VALUE variables (git 2.31+).
|
|
37
|
+
* Empty for no token or a URL that is not https.
|
|
38
|
+
*/
|
|
39
|
+
export declare function gitAuthEnv(url: string, token: string | undefined, base?: Record<string, string | undefined>): Record<string, string>;
|
|
40
|
+
/** A URL with any user:password part removed, for log lines. */
|
|
41
|
+
export declare function redactUrl(url: string): string;
|
|
42
|
+
/** The real runner: inherits stdout/stderr, so setup output lands in the pod log. */
|
|
43
|
+
export declare const runCommand: RunCommand;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First start of a hosted workspace: clone the environment's repository
|
|
3
|
+
* and run its setup script, once per environment version.
|
|
4
|
+
*
|
|
5
|
+
* Runs in enroll mode after the runner has its credential and before it
|
|
6
|
+
* opens its stream, so the machine reports ready only once the checkout
|
|
7
|
+
* and setup are in place (docs/hosted-runners.md, "Images and enroll
|
|
8
|
+
* mode"). The design's rule: on the first start of a volume, or when the
|
|
9
|
+
* environment version changed, clone `repo` at `ref`, run `setupScript`,
|
|
10
|
+
* and write `<workspace>/.almyty/env-version`.
|
|
11
|
+
*
|
|
12
|
+
* The inputs are the plain variables the Deployment sets
|
|
13
|
+
* (ALMYTY_WORKSPACE_ROOT, ALMYTY_ENVIRONMENT_VERSION, ALMYTY_REPO_URL,
|
|
14
|
+
* ALMYTY_REPO_REF, ALMYTY_SETUP_SCRIPT) and one from the Secret,
|
|
15
|
+
* ALMYTY_GIT_TOKEN. The git token reaches git through GIT_CONFIG_*
|
|
16
|
+
* variables of that one child process: never on its command line, never
|
|
17
|
+
* in a file, never in the clone's remote URL.
|
|
18
|
+
*
|
|
19
|
+
* A failed clone or setup is reported and the version is not recorded, so
|
|
20
|
+
* the next start tries again; the runner still comes online, so the
|
|
21
|
+
* person can look at what went wrong from a shell instead of watching a
|
|
22
|
+
* pod restart in a loop.
|
|
23
|
+
*/
|
|
24
|
+
import { spawn } from 'node:child_process';
|
|
25
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
26
|
+
import { join } from 'node:path';
|
|
27
|
+
/** Where the volume is mounted when the Deployment does not say. */
|
|
28
|
+
export const DEFAULT_WORKSPACE_ROOT = '/workspace';
|
|
29
|
+
/** The checkout's folder inside the workspace. */
|
|
30
|
+
export const REPO_DIR_NAME = 'repo';
|
|
31
|
+
/** A setup script running longer than this is stopped. Override: ALMYTY_SETUP_TIMEOUT_SECONDS. */
|
|
32
|
+
const DEFAULT_SETUP_TIMEOUT_SECONDS = 1800;
|
|
33
|
+
export function workspaceRoot(env) {
|
|
34
|
+
const root = (env.ALMYTY_WORKSPACE_ROOT ?? '').trim();
|
|
35
|
+
return root.startsWith('/') ? root : DEFAULT_WORKSPACE_ROOT;
|
|
36
|
+
}
|
|
37
|
+
export async function prepareHostedWorkspace(inputs = {}) {
|
|
38
|
+
const env = inputs.env ?? process.env;
|
|
39
|
+
const run = inputs.run ?? runCommand;
|
|
40
|
+
const log = inputs.log ?? ((line) => process.stdout.write(`${line}\n`));
|
|
41
|
+
const warn = inputs.warn ?? ((line) => process.stderr.write(`${line}\n`));
|
|
42
|
+
const root = workspaceRoot(env);
|
|
43
|
+
const stateDir = join(root, '.almyty');
|
|
44
|
+
const versionFile = join(stateDir, 'env-version');
|
|
45
|
+
const version = (env.ALMYTY_ENVIRONMENT_VERSION ?? '').trim() || 'unversioned';
|
|
46
|
+
const repoUrl = (env.ALMYTY_REPO_URL ?? '').trim();
|
|
47
|
+
const repoDir = join(root, REPO_DIR_NAME);
|
|
48
|
+
const recorded = existsSync(versionFile) ? readFileSync(versionFile, 'utf-8').trim() : null;
|
|
49
|
+
if (recorded === version) {
|
|
50
|
+
log(`workspace: environment version ${version} already set up`);
|
|
51
|
+
return { upToDate: true, cloned: false, setupRan: false, ok: true, repoDir: repoUrl ? repoDir : null };
|
|
52
|
+
}
|
|
53
|
+
mkdirSync(stateDir, { recursive: true, mode: 0o700 });
|
|
54
|
+
// A spawned step gets the runner's own variables (the environment's
|
|
55
|
+
// bindings among them); the enrollment token is already gone (enroll.ts).
|
|
56
|
+
const childEnv = { ...env, GIT_TERMINAL_PROMPT: '0' };
|
|
57
|
+
let ok = true;
|
|
58
|
+
let cloned = false;
|
|
59
|
+
if (repoUrl) {
|
|
60
|
+
if (existsSync(join(repoDir, '.git'))) {
|
|
61
|
+
// An existing checkout is the person's work; a new version does not
|
|
62
|
+
// overwrite it. Only the setup script runs again.
|
|
63
|
+
log(`workspace: ${repoDir} already holds a checkout; leaving it as it is`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const result = await cloneRepo({ url: repoUrl, ref: (env.ALMYTY_REPO_REF ?? '').trim(), dir: repoDir, token: env.ALMYTY_GIT_TOKEN, env: childEnv, cwd: root, run, log });
|
|
67
|
+
cloned = result;
|
|
68
|
+
if (!result) {
|
|
69
|
+
ok = false;
|
|
70
|
+
warn(`workspace: cloning ${redactUrl(repoUrl)} failed; it is tried again on the next start`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const script = env.ALMYTY_SETUP_SCRIPT ?? '';
|
|
75
|
+
let setupRan = false;
|
|
76
|
+
if (script.trim() && ok) {
|
|
77
|
+
setupRan = true;
|
|
78
|
+
const tmp = inputs.tmpDir ?? '/tmp';
|
|
79
|
+
const file = join(tmp, `almyty-setup-${process.pid}-${Date.now()}.sh`);
|
|
80
|
+
writeFileSync(file, script, { mode: 0o700 });
|
|
81
|
+
const cwd = repoUrl && existsSync(repoDir) ? repoDir : root;
|
|
82
|
+
const timeoutS = positiveInt(env.ALMYTY_SETUP_TIMEOUT_SECONDS) ?? DEFAULT_SETUP_TIMEOUT_SECONDS;
|
|
83
|
+
log(`workspace: running the setup script in ${cwd}`);
|
|
84
|
+
try {
|
|
85
|
+
const res = await run('bash', [file], { cwd, env: childEnv, timeoutMs: timeoutS * 1000 });
|
|
86
|
+
if (res.code !== 0) {
|
|
87
|
+
ok = false;
|
|
88
|
+
warn(res.timedOut
|
|
89
|
+
? `workspace: the setup script ran past ${timeoutS}s and was stopped; it runs again on the next start`
|
|
90
|
+
: `workspace: the setup script exited ${res.code}; it runs again on the next start`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
rmSync(file, { force: true });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (ok) {
|
|
98
|
+
writeFileSync(versionFile, `${version}\n`, { mode: 0o600 });
|
|
99
|
+
log(`workspace: environment version ${version} set up`);
|
|
100
|
+
}
|
|
101
|
+
return { upToDate: false, cloned, setupRan, ok, repoDir: repoUrl ? repoDir : null };
|
|
102
|
+
}
|
|
103
|
+
async function cloneRepo(o) {
|
|
104
|
+
const env = { ...o.env, ...gitAuthEnv(o.url, o.token, o.env) };
|
|
105
|
+
o.log(`workspace: cloning ${redactUrl(o.url)}${o.ref ? ` at ${o.ref}` : ''} into ${o.dir}`);
|
|
106
|
+
const clone = await o.run('git', ['clone', '--', o.url, o.dir], { cwd: o.cwd, env });
|
|
107
|
+
if (clone.code !== 0) {
|
|
108
|
+
rmSync(o.dir, { recursive: true, force: true });
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
if (!o.ref)
|
|
112
|
+
return true;
|
|
113
|
+
// A branch or tag checks out directly; a commit or another ref may need
|
|
114
|
+
// fetching first.
|
|
115
|
+
const checkout = await o.run('git', ['-C', o.dir, 'checkout', o.ref, '--'], { cwd: o.cwd, env });
|
|
116
|
+
if (checkout.code === 0)
|
|
117
|
+
return true;
|
|
118
|
+
const fetch = await o.run('git', ['-C', o.dir, 'fetch', 'origin', o.ref], { cwd: o.cwd, env });
|
|
119
|
+
if (fetch.code !== 0)
|
|
120
|
+
return false;
|
|
121
|
+
const detached = await o.run('git', ['-C', o.dir, 'checkout', 'FETCH_HEAD', '--'], { cwd: o.cwd, env });
|
|
122
|
+
return detached.code === 0;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The token as an HTTP Authorization header for the repository's origin,
|
|
126
|
+
* passed through git's GIT_CONFIG_COUNT/KEY/VALUE variables (git 2.31+).
|
|
127
|
+
* Empty for no token or a URL that is not https.
|
|
128
|
+
*/
|
|
129
|
+
export function gitAuthEnv(url, token, base = {}) {
|
|
130
|
+
if (!token)
|
|
131
|
+
return {};
|
|
132
|
+
let origin;
|
|
133
|
+
try {
|
|
134
|
+
const u = new URL(url);
|
|
135
|
+
if (u.protocol !== 'https:')
|
|
136
|
+
return {};
|
|
137
|
+
origin = `${u.protocol}//${u.host}/`;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
const n = positiveInt(base.GIT_CONFIG_COUNT) ?? 0;
|
|
143
|
+
const basic = Buffer.from(`x-access-token:${token}`).toString('base64');
|
|
144
|
+
return {
|
|
145
|
+
GIT_CONFIG_COUNT: String(n + 1),
|
|
146
|
+
[`GIT_CONFIG_KEY_${n}`]: `http.${origin}.extraHeader`,
|
|
147
|
+
[`GIT_CONFIG_VALUE_${n}`]: `Authorization: Basic ${basic}`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/** A URL with any user:password part removed, for log lines. */
|
|
151
|
+
export function redactUrl(url) {
|
|
152
|
+
try {
|
|
153
|
+
const u = new URL(url);
|
|
154
|
+
if (u.username || u.password) {
|
|
155
|
+
u.username = '';
|
|
156
|
+
u.password = '';
|
|
157
|
+
}
|
|
158
|
+
return u.toString();
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return url.replace(/\/\/[^@/]*@/, '//');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function positiveInt(value) {
|
|
165
|
+
const n = Number((value ?? '').trim());
|
|
166
|
+
return Number.isInteger(n) && n > 0 ? n : undefined;
|
|
167
|
+
}
|
|
168
|
+
/** The real runner: inherits stdout/stderr, so setup output lands in the pod log. */
|
|
169
|
+
export const runCommand = (command, args, opts) => new Promise((resolve) => {
|
|
170
|
+
// Its own process group, so a timeout stops everything it started,
|
|
171
|
+
// not only the shell.
|
|
172
|
+
const child = spawn(command, args, { cwd: opts.cwd, env: opts.env, stdio: ['ignore', 'inherit', 'inherit'], detached: true });
|
|
173
|
+
let timedOut = false;
|
|
174
|
+
const timer = opts.timeoutMs
|
|
175
|
+
? setTimeout(() => {
|
|
176
|
+
timedOut = true;
|
|
177
|
+
try {
|
|
178
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
child.kill('SIGKILL');
|
|
182
|
+
}
|
|
183
|
+
}, opts.timeoutMs)
|
|
184
|
+
: null;
|
|
185
|
+
child.on('error', () => {
|
|
186
|
+
if (timer)
|
|
187
|
+
clearTimeout(timer);
|
|
188
|
+
resolve({ code: -1, timedOut });
|
|
189
|
+
});
|
|
190
|
+
child.on('close', (code) => {
|
|
191
|
+
if (timer)
|
|
192
|
+
clearTimeout(timer);
|
|
193
|
+
resolve({ code, timedOut });
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
//# sourceMappingURL=hosted-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hosted-setup.js","sourceRoot":"","sources":["../src/hosted-setup.ts"],"names":[],"mappings":"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"}
|
package/dist/policy.d.ts
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import { RunnerConfig } from './types.js';
|
|
2
2
|
/** Drop env keys a payload must not be allowed to set. */
|
|
3
3
|
export declare function sanitizeEnv(env?: Record<string, string>): Record<string, string> | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Parse an allowBinaries list from its environment form: a JSON array of
|
|
6
|
+
* strings (what the backend writes). Anything else throws, so a runner
|
|
7
|
+
* with a list it cannot read refuses to start rather than running
|
|
8
|
+
* unrestricted.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseAllowBinaries(raw: string | undefined): string[] | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The config with an allowBinaries list applied. Only ever narrows: when
|
|
13
|
+
* the config already has a list, the result is the intersection, and an
|
|
14
|
+
* empty intersection throws rather than lifting the restriction.
|
|
15
|
+
*/
|
|
16
|
+
export declare function withAllowBinaries(config: RunnerConfig, allow: string[] | undefined): RunnerConfig;
|
|
17
|
+
/**
|
|
18
|
+
* The command names a shell command line would start: the first word of
|
|
19
|
+
* every simple command, including those inside $( ), backticks, ( ), <( )
|
|
20
|
+
* and >( ), after variable assignments, redirections and keywords. Quotes
|
|
21
|
+
* and backslashes are removed from the word (`"rm"` is rm). A word that is
|
|
22
|
+
* built at run time ($VAR, a glob) is returned as is and never matches an
|
|
23
|
+
* entry, so it is refused.
|
|
24
|
+
*
|
|
25
|
+
* Best effort by design: separators inside quotes split too, which can
|
|
26
|
+
* refuse a harmless line (`echo "a; b"` checks `b`) but never lets a
|
|
27
|
+
* command through unseen.
|
|
28
|
+
*/
|
|
29
|
+
export declare function commandHeads(cmd: string): string[];
|
|
4
30
|
/** Enforce policy for a process.spawn; returns the sanitized env to use. */
|
|
5
31
|
export declare function enforceSpawnPolicy(config: RunnerConfig, opts: {
|
|
6
32
|
binary: string;
|
package/dist/policy.js
CHANGED
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* - Constrain `cwd` to `allowedCwdRoots` (realpath-canonicalized to block
|
|
20
20
|
* symlink/`..` escape).
|
|
21
21
|
* - Strip env keys a payload must never set (PATH, LD_PRELOAD, …).
|
|
22
|
+
* - When `allowBinaries` is set, refuse a binary it does not list (the
|
|
23
|
+
* binary of a spawn, every command a shell line starts).
|
|
22
24
|
*/
|
|
23
25
|
import { realpathSync } from 'fs';
|
|
24
26
|
import { resolve, sep } from 'path';
|
|
@@ -93,6 +95,145 @@ function assertCommandAllowed(config, command) {
|
|
|
93
95
|
throw new RunnerError('package installation is blocked by runner policy (installBlocked)', RUNNER_ERROR_CODES.COMMAND_DENIED);
|
|
94
96
|
}
|
|
95
97
|
}
|
|
98
|
+
// ── allowBinaries ───────────────────────────────────────────────────
|
|
99
|
+
//
|
|
100
|
+
// A hosted environment may name the binaries its runner starts
|
|
101
|
+
// (`egress.allowBinaries`, docs/design/hosted-runners-and-always-on.md).
|
|
102
|
+
// Inside the pod's sandbox this is a guard rail, not the boundary: an
|
|
103
|
+
// allowed shell, interpreter or wrapper (bash, sh, python, node, env, xargs,
|
|
104
|
+
// npm scripts) can still start anything, and the policy says so rather
|
|
105
|
+
// than pretending otherwise.
|
|
106
|
+
//
|
|
107
|
+
// An entry without a slash allows that bare command name, found on PATH
|
|
108
|
+
// (which a payload cannot change, BLOCKED_ENV_KEYS). An entry with a slash
|
|
109
|
+
// allows exactly that absolute path. `./claude` is neither.
|
|
110
|
+
/** Bare command names: letters, digits and . _ + - (no slash, no space). */
|
|
111
|
+
const BINARY_NAME_RE = /^[A-Za-z0-9._+-]+$/;
|
|
112
|
+
/**
|
|
113
|
+
* Shell builtins that cannot start another program themselves, so a
|
|
114
|
+
* command line like `cd app && npm test` needs only npm listed. Builtins
|
|
115
|
+
* that run their arguments (exec, eval, command, builtin, source, ., trap)
|
|
116
|
+
* are not here: they need listing like any binary.
|
|
117
|
+
*/
|
|
118
|
+
const SAFE_BUILTINS = new Set([
|
|
119
|
+
'cd', 'echo', 'printf', 'pwd', 'export', 'unset', 'set', 'test', '[', '[[', ']]',
|
|
120
|
+
'true', 'false', ':', 'exit', 'return', 'shift', 'read', 'wait', 'umask',
|
|
121
|
+
]);
|
|
122
|
+
/** Shell words that open or close a construct; the command follows them. */
|
|
123
|
+
const SHELL_KEYWORDS = new Set(['if', 'then', 'else', 'elif', 'fi', 'do', 'done', 'while', 'until', '!', 'time', '{', '}', 'esac']);
|
|
124
|
+
/** Constructs whose first segment names variables or patterns, not a command. */
|
|
125
|
+
const NON_COMMAND_SEGMENTS = new Set(['for', 'case', 'select', 'function']);
|
|
126
|
+
/**
|
|
127
|
+
* Parse an allowBinaries list from its environment form: a JSON array of
|
|
128
|
+
* strings (what the backend writes). Anything else throws, so a runner
|
|
129
|
+
* with a list it cannot read refuses to start rather than running
|
|
130
|
+
* unrestricted.
|
|
131
|
+
*/
|
|
132
|
+
export function parseAllowBinaries(raw) {
|
|
133
|
+
if (raw === undefined || raw.trim() === '')
|
|
134
|
+
return undefined;
|
|
135
|
+
let parsed;
|
|
136
|
+
try {
|
|
137
|
+
parsed = JSON.parse(raw);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
throw new Error('ALMYTY_ALLOW_BINARIES must be a JSON array of binary names');
|
|
141
|
+
}
|
|
142
|
+
if (!Array.isArray(parsed) || parsed.some((v) => typeof v !== 'string')) {
|
|
143
|
+
throw new Error('ALMYTY_ALLOW_BINARIES must be a JSON array of binary names');
|
|
144
|
+
}
|
|
145
|
+
const out = [...new Set(parsed.map((v) => v.trim()))];
|
|
146
|
+
for (const entry of out) {
|
|
147
|
+
if (!(BINARY_NAME_RE.test(entry) || (entry.startsWith('/') && !/\s/.test(entry)))) {
|
|
148
|
+
throw new Error(`ALMYTY_ALLOW_BINARIES: "${entry}" is neither a command name nor an absolute path`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out.length ? out : undefined;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The config with an allowBinaries list applied. Only ever narrows: when
|
|
155
|
+
* the config already has a list, the result is the intersection, and an
|
|
156
|
+
* empty intersection throws rather than lifting the restriction.
|
|
157
|
+
*/
|
|
158
|
+
export function withAllowBinaries(config, allow) {
|
|
159
|
+
if (!allow || allow.length === 0)
|
|
160
|
+
return config;
|
|
161
|
+
if (!config.allowBinaries?.length)
|
|
162
|
+
return { ...config, allowBinaries: [...allow] };
|
|
163
|
+
const current = new Set(config.allowBinaries);
|
|
164
|
+
const next = allow.filter((b) => current.has(b));
|
|
165
|
+
if (next.length === 0)
|
|
166
|
+
throw new Error('allowBinaries: the environment and the runner config allow no binary in common');
|
|
167
|
+
return { ...config, allowBinaries: next };
|
|
168
|
+
}
|
|
169
|
+
function binaryAllowed(allow, binary) {
|
|
170
|
+
return binary.includes('/') ? binary.startsWith('/') && allow.includes(binary) : allow.includes(binary);
|
|
171
|
+
}
|
|
172
|
+
function denyBinary(binary) {
|
|
173
|
+
throw new RunnerError(`binary not in allowBinaries: ${binary}`, RUNNER_ERROR_CODES.COMMAND_DENIED);
|
|
174
|
+
}
|
|
175
|
+
function assertBinaryAllowed(config, binary) {
|
|
176
|
+
const allow = config.allowBinaries;
|
|
177
|
+
if (!allow || allow.length === 0)
|
|
178
|
+
return;
|
|
179
|
+
if (!binaryAllowed(allow, binary))
|
|
180
|
+
denyBinary(binary);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The command names a shell command line would start: the first word of
|
|
184
|
+
* every simple command, including those inside $( ), backticks, ( ), <( )
|
|
185
|
+
* and >( ), after variable assignments, redirections and keywords. Quotes
|
|
186
|
+
* and backslashes are removed from the word (`"rm"` is rm). A word that is
|
|
187
|
+
* built at run time ($VAR, a glob) is returned as is and never matches an
|
|
188
|
+
* entry, so it is refused.
|
|
189
|
+
*
|
|
190
|
+
* Best effort by design: separators inside quotes split too, which can
|
|
191
|
+
* refuse a harmless line (`echo "a; b"` checks `b`) but never lets a
|
|
192
|
+
* command through unseen.
|
|
193
|
+
*/
|
|
194
|
+
export function commandHeads(cmd) {
|
|
195
|
+
const normalized = cmd
|
|
196
|
+
.replace(/\d*[<>]&(?:\d+|-)/g, ' ') // 2>&1, >&2, <&-
|
|
197
|
+
.replace(/&>>?/g, ' >'); // &> file
|
|
198
|
+
const segments = normalized.split(/\$\(|[<>]\(|\|\||&&|;;|[;&|\n()`]/);
|
|
199
|
+
const heads = [];
|
|
200
|
+
for (const segment of segments) {
|
|
201
|
+
const words = segment.trim().split(/\s+/).filter(Boolean);
|
|
202
|
+
let i = 0;
|
|
203
|
+
while (i < words.length) {
|
|
204
|
+
const w = words[i];
|
|
205
|
+
if (SHELL_KEYWORDS.has(w) || /^[A-Za-z_][A-Za-z0-9_]*(?:\[[^\]]*\])?\+?=/.test(w)) {
|
|
206
|
+
i += 1;
|
|
207
|
+
}
|
|
208
|
+
else if (/^\d*(?:<<?<?|>>?|>\|)$/.test(w)) {
|
|
209
|
+
i += 2; // a redirection and its target
|
|
210
|
+
}
|
|
211
|
+
else if (/^\d*(?:<<?<?|>>?|>\|)\S/.test(w)) {
|
|
212
|
+
i += 1; // a redirection glued to its target
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (i >= words.length)
|
|
219
|
+
continue;
|
|
220
|
+
if (NON_COMMAND_SEGMENTS.has(words[i]))
|
|
221
|
+
continue;
|
|
222
|
+
heads.push(words[i].replace(/["'\\]/g, ''));
|
|
223
|
+
}
|
|
224
|
+
return heads;
|
|
225
|
+
}
|
|
226
|
+
function assertShellBinariesAllowed(config, cmd) {
|
|
227
|
+
const allow = config.allowBinaries;
|
|
228
|
+
if (!allow || allow.length === 0)
|
|
229
|
+
return;
|
|
230
|
+
for (const head of commandHeads(cmd)) {
|
|
231
|
+
if (SAFE_BUILTINS.has(head))
|
|
232
|
+
continue;
|
|
233
|
+
if (!binaryAllowed(allow, head))
|
|
234
|
+
denyBinary(head);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
96
237
|
function canonical(p) {
|
|
97
238
|
const abs = resolve(p);
|
|
98
239
|
try {
|
|
@@ -122,6 +263,7 @@ function assertCwdAllowed(config, cwd) {
|
|
|
122
263
|
export function enforceSpawnPolicy(config, opts) {
|
|
123
264
|
assertIsolationSupported(config);
|
|
124
265
|
assertCwdAllowed(config, opts.cwd);
|
|
266
|
+
assertBinaryAllowed(config, opts.binary);
|
|
125
267
|
assertCommandAllowed(config, [opts.binary, ...opts.args].join(' '));
|
|
126
268
|
return { env: sanitizeEnv(opts.env) };
|
|
127
269
|
}
|
|
@@ -137,6 +279,7 @@ export function enforceShellPolicy(config, cmd, env, cwd) {
|
|
|
137
279
|
assertIsolationSupported(config);
|
|
138
280
|
assertCwdAllowed(config, cwd);
|
|
139
281
|
assertCommandAllowed(config, cmd);
|
|
282
|
+
assertShellBinariesAllowed(config, cmd);
|
|
140
283
|
return { env: sanitizeEnv(env) };
|
|
141
284
|
}
|
|
142
285
|
/**
|
package/dist/policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,10 +22,10 @@ import { WorkerEnvelope } from './protocol.js';
|
|
|
22
22
|
* - Reconnect attempts emit `reconnect` events for observability;
|
|
23
23
|
* persistent failure emits `fatal` and the daemon exits.
|
|
24
24
|
*
|
|
25
|
-
* Auth: Bearer JWT in the Authorization header.
|
|
26
|
-
* @almyty/client's resolveCredentials
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* Auth: Bearer JWT in the Authorization header. A self-hosted runner
|
|
26
|
+
* passes the login token from @almyty/client's resolveCredentials (the
|
|
27
|
+
* daemon restarts when credentials.json changes); a hosted runner passes a
|
|
28
|
+
* function returning its renewable runner credential (enroll.ts).
|
|
29
29
|
*/
|
|
30
30
|
/** The worker stream's route. */
|
|
31
31
|
export declare const RUNNER_STREAM_PATH = "/runners/stream";
|
|
@@ -33,7 +33,17 @@ export declare const RUNNER_STREAM_PATH = "/runners/stream";
|
|
|
33
33
|
export declare const LEGACY_STREAM_PATH = "/mcp/streamable";
|
|
34
34
|
export interface StreamableClientOptions {
|
|
35
35
|
baseUrl: string;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* The bearer token, or a function that returns the current one. A hosted
|
|
38
|
+
* runner passes a function: its credential is renewed while it runs, and
|
|
39
|
+
* every request reads the latest.
|
|
40
|
+
*/
|
|
41
|
+
token: string | (() => string);
|
|
42
|
+
/**
|
|
43
|
+
* A fixed route, e.g. a hosted runner's /runners/hosted/stream. Unset:
|
|
44
|
+
* /runners/stream with the legacy fallback below.
|
|
45
|
+
*/
|
|
46
|
+
streamPath?: string;
|
|
37
47
|
/**
|
|
38
48
|
* Sent as X-Organization-Id on every request, so a user in several
|
|
39
49
|
* organizations opens the session in the same one it registered in.
|
|
@@ -72,6 +82,14 @@ export declare class StreamableClient extends EventEmitter {
|
|
|
72
82
|
* Returns whether it switched.
|
|
73
83
|
*/
|
|
74
84
|
private fellBackFrom404;
|
|
85
|
+
/**
|
|
86
|
+
* Open the GET stream and resolve as soon as it is open, or as soon as
|
|
87
|
+
* its first attempt failed and a reconnect is scheduled; the stream is
|
|
88
|
+
* then read in the background. openStream() itself resolves only when
|
|
89
|
+
* the stream ends, so a caller that awaited it (the daemon did) waited
|
|
90
|
+
* the whole life of the stream before its first heartbeat.
|
|
91
|
+
*/
|
|
92
|
+
startStream(): Promise<void>;
|
|
75
93
|
/** Open the GET stream and dispatch envelopes via emit('envelope'). */
|
|
76
94
|
openStream(): Promise<void>;
|
|
77
95
|
stop(): void;
|
|
@@ -23,10 +23,10 @@ import { WORKER_PROTOCOL_VERSION, isWorkerEnvelope, } from './protocol.js';
|
|
|
23
23
|
* - Reconnect attempts emit `reconnect` events for observability;
|
|
24
24
|
* persistent failure emits `fatal` and the daemon exits.
|
|
25
25
|
*
|
|
26
|
-
* Auth: Bearer JWT in the Authorization header.
|
|
27
|
-
* @almyty/client's resolveCredentials
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* Auth: Bearer JWT in the Authorization header. A self-hosted runner
|
|
27
|
+
* passes the login token from @almyty/client's resolveCredentials (the
|
|
28
|
+
* daemon restarts when credentials.json changes); a hosted runner passes a
|
|
29
|
+
* function returning its renewable runner credential (enroll.ts).
|
|
30
30
|
*/
|
|
31
31
|
/** The worker stream's route. */
|
|
32
32
|
export const RUNNER_STREAM_PATH = '/runners/stream';
|
|
@@ -48,6 +48,8 @@ export class StreamableClient extends EventEmitter {
|
|
|
48
48
|
this.opts = opts;
|
|
49
49
|
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
50
50
|
this.setTimeoutFn = opts.setTimeoutFn ?? setTimeout;
|
|
51
|
+
if (opts.streamPath)
|
|
52
|
+
this.streamPath = opts.streamPath;
|
|
51
53
|
}
|
|
52
54
|
/** Returns the session id once the first POST has assigned one. */
|
|
53
55
|
getSessionId() {
|
|
@@ -55,7 +57,8 @@ export class StreamableClient extends EventEmitter {
|
|
|
55
57
|
}
|
|
56
58
|
/** Authorization plus, when configured, the organization header. */
|
|
57
59
|
authHeaders() {
|
|
58
|
-
const
|
|
60
|
+
const token = typeof this.opts.token === 'function' ? this.opts.token() : this.opts.token;
|
|
61
|
+
const headers = { 'Authorization': `Bearer ${token}` };
|
|
59
62
|
if (this.opts.organizationId)
|
|
60
63
|
headers['X-Organization-Id'] = this.opts.organizationId;
|
|
61
64
|
return headers;
|
|
@@ -114,6 +117,30 @@ export class StreamableClient extends EventEmitter {
|
|
|
114
117
|
this.emit('route-fallback', { from: RUNNER_STREAM_PATH, to: LEGACY_STREAM_PATH });
|
|
115
118
|
return true;
|
|
116
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Open the GET stream and resolve as soon as it is open, or as soon as
|
|
122
|
+
* its first attempt failed and a reconnect is scheduled; the stream is
|
|
123
|
+
* then read in the background. openStream() itself resolves only when
|
|
124
|
+
* the stream ends, so a caller that awaited it (the daemon did) waited
|
|
125
|
+
* the whole life of the stream before its first heartbeat.
|
|
126
|
+
*/
|
|
127
|
+
startStream() {
|
|
128
|
+
return new Promise((resolve, reject) => {
|
|
129
|
+
let settled = false;
|
|
130
|
+
const settle = (fn) => {
|
|
131
|
+
if (settled)
|
|
132
|
+
return;
|
|
133
|
+
settled = true;
|
|
134
|
+
this.off('open', onReady);
|
|
135
|
+
this.off('reconnect', onReady);
|
|
136
|
+
fn();
|
|
137
|
+
};
|
|
138
|
+
const onReady = () => settle(resolve);
|
|
139
|
+
this.on('open', onReady);
|
|
140
|
+
this.on('reconnect', onReady);
|
|
141
|
+
this.openStream().then(onReady, (err) => settle(() => reject(err)));
|
|
142
|
+
});
|
|
143
|
+
}
|
|
117
144
|
/** Open the GET stream and dispatch envelopes via emit('envelope'). */
|
|
118
145
|
async openStream() {
|
|
119
146
|
if (this.stopped)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamable-client.js","sourceRoot":"","sources":["../src/streamable-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,OAAO,EACL,uBAAuB,EAEvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,iCAAiC;AACjC,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AACpD,kFAAkF;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"streamable-client.js","sourceRoot":"","sources":["../src/streamable-client.ts"],"names":[],"mappings":"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"}
|