fix(sandbox): default to current user profile for debian/ubuntu env (#337)
This commit is contained in:
parent
0ae59056d1
commit
3be8b6dc34
|
@ -8,12 +8,67 @@ import { execSync, spawnSync, spawn } from 'node:child_process';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
import { quote } from 'shell-quote';
|
import { quote } from 'shell-quote';
|
||||||
import {
|
import {
|
||||||
USER_SETTINGS_DIR,
|
USER_SETTINGS_DIR,
|
||||||
SETTINGS_DIRECTORY_NAME,
|
SETTINGS_DIRECTORY_NAME,
|
||||||
} from '../config/settings.js';
|
} from '../config/settings.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the sandbox container should be run with the current user's UID and GID.
|
||||||
|
* This is often necessary on Linux systems (especially Debian/Ubuntu based) when using
|
||||||
|
* rootful Docker without userns-remap configured, to avoid permission issues with
|
||||||
|
* mounted volumes.
|
||||||
|
*
|
||||||
|
* The behavior is controlled by the `SANDBOX_SET_UID_GID` environment variable:
|
||||||
|
* - If `SANDBOX_SET_UID_GID` is "1" or "true", this function returns `true`.
|
||||||
|
* - If `SANDBOX_SET_UID_GID` is "0" or "false", this function returns `false`.
|
||||||
|
* - If `SANDBOX_SET_UID_GID` is not set:
|
||||||
|
* - On Debian/Ubuntu Linux, it defaults to `true`.
|
||||||
|
* - On other OSes, or if OS detection fails, it defaults to `false`.
|
||||||
|
*
|
||||||
|
* For more context on running Docker containers as non-root, see:
|
||||||
|
* https://medium.com/redbubble/running-a-docker-container-as-a-non-root-user-7d2e00f8ee15
|
||||||
|
*
|
||||||
|
* @returns {Promise<boolean>} A promise that resolves to true if the current user's UID/GID should be used, false otherwise.
|
||||||
|
*/
|
||||||
|
async function shouldUseCurrentUserInSandbox(): Promise<boolean> {
|
||||||
|
const envVar = process.env.SANDBOX_SET_UID_GID?.toLowerCase().trim();
|
||||||
|
|
||||||
|
if (envVar === '1' || envVar === 'true') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (envVar === '0' || envVar === 'false') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If environment variable is not explicitly set, check for Debian/Ubuntu Linux
|
||||||
|
if (os.platform() === 'linux') {
|
||||||
|
try {
|
||||||
|
const osReleaseContent = await readFile('/etc/os-release', 'utf8');
|
||||||
|
if (
|
||||||
|
osReleaseContent.includes('ID=debian') ||
|
||||||
|
osReleaseContent.includes('ID=ubuntu') ||
|
||||||
|
osReleaseContent.match(/^ID_LIKE=.*debian.*/m) || // Covers derivatives
|
||||||
|
osReleaseContent.match(/^ID_LIKE=.*ubuntu.*/m) // Covers derivatives
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
'INFO: Defaulting to use current user UID/GID for Debian/Ubuntu-based Linux.',
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (_err) {
|
||||||
|
// Silently ignore if /etc/os-release is not found or unreadable.
|
||||||
|
// The default (false) will be applied in this case.
|
||||||
|
console.warn(
|
||||||
|
'Warning: Could not read /etc/os-release to auto-detect Debian/Ubuntu for UID/GID default.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; // Default to false if no other condition is met
|
||||||
|
}
|
||||||
|
|
||||||
// node.js equivalent of scripts/sandbox_command.sh
|
// node.js equivalent of scripts/sandbox_command.sh
|
||||||
export function sandbox_command(sandbox?: string | boolean): string {
|
export function sandbox_command(sandbox?: string | boolean): string {
|
||||||
// note environment variable takes precedence over argument (from command line or settings)
|
// note environment variable takes precedence over argument (from command line or settings)
|
||||||
|
@ -388,10 +443,9 @@ export async function start_sandbox(sandbox: string) {
|
||||||
args.push('--authfile', emptyAuthFilePath);
|
args.push('--authfile', emptyAuthFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// specify --user as "$(id -u):$(id -g)" if SANDBOX_SET_UID_GID is 1|true
|
// Determine if the current user's UID/GID should be passed to the sandbox.
|
||||||
// only necessary if user mapping is not handled by sandboxing setup on host
|
// See shouldUseCurrentUserInSandbox for more details.
|
||||||
// (e.g. rootful docker on linux w/o userns-remap configured)
|
if (await shouldUseCurrentUserInSandbox()) {
|
||||||
if (['1', 'true'].includes(process.env.SANDBOX_SET_UID_GID ?? '')) {
|
|
||||||
const uid = execSync('id -u').toString().trim();
|
const uid = execSync('id -u').toString().trim();
|
||||||
const gid = execSync('id -g').toString().trim();
|
const gid = execSync('id -g').toString().trim();
|
||||||
args.push('--user', `${uid}:${gid}`);
|
args.push('--user', `${uid}:${gid}`);
|
||||||
|
|
Loading…
Reference in New Issue