@rubytech/taskmaster 1.9.7 → 1.9.8
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/build-info.json
CHANGED
|
@@ -122,15 +122,35 @@ export const tailscaleHandlers = {
|
|
|
122
122
|
message: typeof errObj.message === "string" ? errObj.message : "",
|
|
123
123
|
};
|
|
124
124
|
};
|
|
125
|
-
const
|
|
125
|
+
const isPermissionDenied = (output) => {
|
|
126
126
|
const lower = output.toLowerCase();
|
|
127
127
|
return (lower.includes("access denied") ||
|
|
128
128
|
lower.includes("permission denied") ||
|
|
129
129
|
lower.includes("use 'sudo tailscale") ||
|
|
130
130
|
lower.includes("requires root"));
|
|
131
131
|
};
|
|
132
|
+
// Ensure the gateway's OS user is set as the Tailscale operator.
|
|
133
|
+
// This is a persistent setting — once applied, `tailscale up` works
|
|
134
|
+
// without root for the lifetime of the Tailscale install.
|
|
135
|
+
const ensureOperator = async (binary) => {
|
|
136
|
+
const whoami = (await runExec("whoami", [], { timeoutMs: 3_000 }).catch(() => ({ stdout: "" }))).stdout.trim();
|
|
137
|
+
if (!whoami)
|
|
138
|
+
return false;
|
|
139
|
+
context.logGateway.info(`tailscale.enable: setting Tailscale operator to "${whoami}"`);
|
|
140
|
+
try {
|
|
141
|
+
await runExec("sudo", ["-n", binary, "set", `--operator=${whoami}`], {
|
|
142
|
+
timeoutMs: 10_000,
|
|
143
|
+
});
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
context.logGateway.warn("tailscale.enable: failed to set operator (sudo -n not available)");
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
132
151
|
// Run `tailscale up` (with optional extra args) and capture output.
|
|
133
|
-
// If the command fails with a permission error,
|
|
152
|
+
// If the command fails with a permission error, sets the current user
|
|
153
|
+
// as Tailscale operator (permanent fix) and retries without sudo.
|
|
134
154
|
// `tailscale up` blocks until auth completes, so timeouts are expected —
|
|
135
155
|
// the auth URL appears in stdout/stderr before the timeout kills it.
|
|
136
156
|
const runTailscaleUp = async (binary, extraArgs = []) => {
|
|
@@ -138,10 +158,17 @@ export const tailscaleHandlers = {
|
|
|
138
158
|
const execOpts = { timeoutMs: 60_000, maxBuffer: 100_000 };
|
|
139
159
|
const result = await runExec(binary, args, execOpts).catch((err) => captureExecOutput(err));
|
|
140
160
|
const output = `${result.stdout}\n${result.stderr}`;
|
|
141
|
-
if (!
|
|
161
|
+
if (!isPermissionDenied(output))
|
|
142
162
|
return output;
|
|
143
|
-
// Permission denied —
|
|
144
|
-
|
|
163
|
+
// Permission denied — fix permanently by setting operator, then retry
|
|
164
|
+
const fixed = await ensureOperator(binary);
|
|
165
|
+
if (fixed) {
|
|
166
|
+
// Operator set — retry without sudo (clean output capture)
|
|
167
|
+
const retryResult = await runExec(binary, args, execOpts).catch((err) => captureExecOutput(err));
|
|
168
|
+
return `${retryResult.stdout}\n${retryResult.stderr}`;
|
|
169
|
+
}
|
|
170
|
+
// Fallback: direct sudo attempt
|
|
171
|
+
context.logGateway.info(`tailscale.enable: falling back to sudo: ${args.join(" ")}`);
|
|
145
172
|
const sudoResult = await runExec("sudo", ["-n", binary, ...args], execOpts).catch((err) => captureExecOutput(err));
|
|
146
173
|
return `${sudoResult.stdout}\n${sudoResult.stderr}`;
|
|
147
174
|
};
|