fix: pwsh modules nsjail (#2845)

This commit is contained in:
HugoCasa
2023-12-13 14:16:08 +01:00
committed by GitHub
parent 3d49fe3eae
commit 297a31d468
2 changed files with 140 additions and 17 deletions
@@ -0,0 +1,115 @@
name: "powershell run script"
mode: ONCE
hostname: "powershell"
log_level: ERROR
disable_rl: true
cwd: "/tmp"
clone_newnet: false
clone_newuser: {CLONE_NEWUSER}
keep_caps: false
keep_env: true
mount_proc: true
mount {
src: "/bin"
dst: "/bin"
is_bind: true
}
mount {
src: "/opt/microsoft"
dst: "/opt/microsoft"
is_bind: true
}
mount {
src: "/lib"
dst: "/lib"
is_bind: true
}
mount {
src: "/lib64"
dst: "/lib64"
is_bind: true
}
mount {
src: "/usr"
dst: "/usr"
is_bind: true
}
mount {
src: "/dev/null"
dst: "/dev/null"
is_bind: true
rw: true
}
mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=800000000"
}
mount {
src: "{JOB_DIR}/main.sh"
dst: "/tmp/main.sh"
is_bind: true
mandatory: false
}
mount {
src: "/etc"
dst: "/etc"
is_bind: true
}
mount {
src: "/dev/random"
dst: "/dev/random"
is_bind: true
}
mount {
src: "/dev/urandom"
dst: "/dev/urandom"
is_bind: true
}
mount {
src: "{JOB_DIR}/result.json"
dst: "/tmp/result.json"
rw: true
is_bind: true
}
mount {
src: "{JOB_DIR}/result.out"
dst: "/tmp/result.out"
rw: true
is_bind: true
}
iface_no_lo: true
mount {
src: "{CACHE_DIR}"
dst: "/tmp/windmill/cache/powershell"
is_bind: true
rw: true
mandatory: false
}
{SHARED_MOUNT}
envar: "HOME=/tmp"
+25 -17
View File
@@ -1,6 +1,5 @@
use std::{collections::HashMap, fs, process::Stdio};
use itertools::Itertools;
use regex::Regex;
use serde_json::{json, value::RawValue};
use sqlx::types::Json;
@@ -10,6 +9,8 @@ use windmill_queue::CanceledBy;
const BIN_BASH: &str = "/bin/bash";
const NSJAIL_CONFIG_RUN_BASH_CONTENT: &str = include_str!("../nsjail/run.bash.config.proto");
const NSJAIL_CONFIG_RUN_POWERSHELL_CONTENT: &str =
include_str!("../nsjail/run.powershell.config.proto");
lazy_static::lazy_static! {
static ref RE_POWERSHELL_IMPORTS: Regex = Regex::new(r#"^Import-Module\s+(?:-Name\s+)?"?([^-\s"]+)"?"#).unwrap();
@@ -200,14 +201,11 @@ pub async fn handle_powershell_job(
.collect::<Vec<(String, String)>>();
args_owned
.iter()
.map(|(n, v)| format!("--{n} {v}"))
.join(" ")
.map(|(n, v)| vec![format!("--{n}"), format!("{v}")])
.flatten()
.collect::<Vec<_>>()
};
let content = content
.replace('$', r"\$") // escape powershell variables
.replace("`", r"\`"); // escape powershell backticks
let installed_modules = fs::read_dir(POWERSHELL_CACHE_DIR)?
.filter_map(|x| {
x.ok().map(|x| {
@@ -271,11 +269,11 @@ pub async fn handle_powershell_job(
// make sure default (only allhostsallusers) modules are loaded, disable autoload (cache can be large to explore especially on cloud) and add /tmp/windmill/cache to PSModulePath
let profile = format!(
"\\$PSModuleAutoloadingPreference = 'None'
\\$PSModulePathBackup = \\$env:PSModulePath
\\$env:PSModulePath = (\\$Env:PSModulePath -split ':')[-1]
"$PSModuleAutoloadingPreference = 'None'
$PSModulePathBackup = $env:PSModulePath
$env:PSModulePath = ($Env:PSModulePath -split ':')[-1]
Get-Module -ListAvailable | Import-Module
\\$env:PSModulePath = \"{}:\\$env:PSModulePathBackup\"",
$env:PSModulePath = \"{}:$PSModulePathBackup\"",
POWERSHELL_CACHE_DIR
);
// make sure param() is first
@@ -292,7 +290,7 @@ Get-Module -ListAvailable | Import-Module
format!("{}\n{}", profile, content)
};
write_file(job_dir, "main.sh", &format!("set -e\ncat > script.ps1 << EOF\n{content}\nEOF\npwsh -File script.ps1 {pwsh_args}\necho \"\"\nsleep 0.02")).await?;
write_file(job_dir, "main.ps1", content.as_str()).await?;
let token = client.get_token().await;
let mut reserved_variables = get_reserved_variables(job, &token, db).await?;
reserved_variables.insert("RUST_LOG".to_string(), "info".to_string());
@@ -304,13 +302,22 @@ Get-Module -ListAvailable | Import-Module
let _ = write_file(
job_dir,
"run.config.proto",
&NSJAIL_CONFIG_RUN_BASH_CONTENT
&NSJAIL_CONFIG_RUN_POWERSHELL_CONTENT
.replace("{JOB_DIR}", job_dir)
.replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string())
.replace("{SHARED_MOUNT}", shared_mount),
.replace("{SHARED_MOUNT}", shared_mount)
.replace("{CACHE_DIR}", POWERSHELL_CACHE_DIR),
)
.await?;
let cmd_args = vec!["--config", "run.config.proto", "--", "/bin/bash", "main.sh"];
let mut cmd_args = vec![
"--config",
"run.config.proto",
"--",
"pwsh",
"-F",
"main.ps1",
];
cmd_args.extend(pwsh_args.iter().map(|x| x.as_str()));
Command::new(NSJAIL_PATH.as_str())
.current_dir(job_dir)
.env_clear()
@@ -323,8 +330,9 @@ Get-Module -ListAvailable | Import-Module
.stderr(Stdio::piped())
.spawn()?
} else {
let cmd_args = vec!["main.sh"];
Command::new("/bin/bash")
let mut cmd_args = vec!["-F", "main.ps1"];
cmd_args.extend(pwsh_args.iter().map(|x| x.as_str()));
Command::new("pwsh")
.current_dir(job_dir)
.env_clear()
.envs(envs)