From 584495870dee0a2206ee1c2d988f4dff0eafbdba Mon Sep 17 00:00:00 2001 From: banditopazzo Date: Tue, 24 Sep 2024 19:25:29 +0200 Subject: [PATCH] feat: better xtask run as sudo command --- .cargo/config.toml | 1 + .github/workflows/integration.yaml | 2 +- Cargo.lock | 2 + xtask/Cargo.toml | 8 +++- xtask/README.md | 8 ++-- xtask/src/lib.rs | 1 + xtask/src/main.rs | 24 ++++------ xtask/src/run.rs | 41 ---------------- xtask/src/surun.rs | 72 ++++++++++++++++++++++++++++ xtask/src/{test.rs => test_suite.rs} | 0 10 files changed, 98 insertions(+), 61 deletions(-) create mode 100644 xtask/src/lib.rs delete mode 100644 xtask/src/run.rs create mode 100644 xtask/src/surun.rs rename xtask/src/{test.rs => test_suite.rs} (100%) diff --git a/.cargo/config.toml b/.cargo/config.toml index d6111b08..e32f01da 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,6 @@ [alias] xtask = "run --package xtask --" +surun = "run --package xtask -- surun" [target.x86_64-unknown-linux-gnu] rustflags = [ diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index ab6ca98d..569b24e8 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -46,7 +46,7 @@ jobs: - name: Integration tests if: endsWith(matrix.platform.target, 'musl') run: | - cargo xtask test \ + cargo xtask test-suite \ --force-architest \ --target=${{ matrix.platform.target }} \ --kernel-versions=${{ matrix.platform.kernel-versions }} \ diff --git a/Cargo.lock b/Cargo.lock index 1fe92872..f009124d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3690,8 +3690,10 @@ version = "0.8.1" dependencies = [ "anyhow", "clap", + "env_logger", "flate2", "indicatif", + "log", "num_cpus", "reqwest", "serde", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 1c47ef97..c92e3b05 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -11,9 +11,15 @@ clap = { workspace = true, features = ["derive"] } flate2 = { workspace = true } indicatif = { workspace = true } num_cpus = { workspace = true } -reqwest = { workspace = true, default-features = false, features = ["blocking", "json", "rustls-tls"] } +reqwest = { workspace = true, default-features = false, features = [ + "blocking", + "json", + "rustls-tls", +] } serde = { workspace = true, features = ["derive"] } signal-hook = { workspace = true } tar = { workspace = true } uuid = { workspace = true, features = ["v4"] } xshell = { workspace = true } +log = { workspace = true } +env_logger = { workspace = true } diff --git a/xtask/README.md b/xtask/README.md index 8c9830a9..9d571d35 100644 --- a/xtask/README.md +++ b/xtask/README.md @@ -11,26 +11,26 @@ with `sudo`. To run the eBPF test suite you can use: ```sh -cargo xtask test +cargo xtask test-suite ``` ## Run pulsar daemon To run the agent daemon you can use: ```sh -cargo xtask pulsard +cargo surun pulsard ``` ## Run pulsar client To run the agent client you can use: ```sh -cargo xtask pulsar +cargo surun pulsar ``` ## Run single probe To run a single module you can use: ```sh -cargo xtask probe file-system-monitor +cargo surun --example standalone-probes file-system-monitor ``` diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs new file mode 100644 index 00000000..73fb313d --- /dev/null +++ b/xtask/src/lib.rs @@ -0,0 +1 @@ +pub mod surun; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 14a1a092..ca69d408 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,10 +1,9 @@ use clap::Parser; -use run::run_with_sudo; use signal_hook::{consts::TERM_SIGNALS, iterator::Signals}; +use xtask::surun::SuRunCommand; -mod run; mod tempdir; -mod test; +mod test_suite; mod vmlinux; #[derive(Debug, Parser)] @@ -16,14 +15,11 @@ pub struct Options { #[derive(Debug, Parser)] enum Command { - /// Run pulsar daemon with admin privileges - Pulsard(run::Options), - /// Run pulsar cli with admin privileges - Pulsar(run::Options), - /// Run a single module with admin privileges - Probe(run::Options), + /// Same as `cargo run` but with admin privileges (using `sudo -E` as runner) + #[clap(name = "surun")] + SuRun(SuRunCommand), /// Run eBPF test suite with admin privileges - Test(test::Options), + TestSuite(test_suite::Options), /// Build headers with BTF type definitions. Vmlinux(vmlinux::Options), } @@ -31,14 +27,14 @@ enum Command { fn main() { let opts = Options::parse(); + env_logger::init(); + // Drop term signals: register a handler, but never check it let _ = Signals::new(TERM_SIGNALS).expect("error setting signal handler"); let ret = match opts.command { - Command::Pulsard(opts) => run_with_sudo("pulsar-exec", &["pulsard"], opts), - Command::Pulsar(opts) => run_with_sudo("pulsar-exec", &["pulsar"], opts), - Command::Probe(opts) => run_with_sudo("probe", &[], opts), - Command::Test(opts) => test::run(opts), + Command::SuRun(cmd) => cmd.run(), + Command::TestSuite(opts) => test_suite::run(opts), Command::Vmlinux(opts) => vmlinux::run(opts), }; diff --git a/xtask/src/run.rs b/xtask/src/run.rs deleted file mode 100644 index 57de914a..00000000 --- a/xtask/src/run.rs +++ /dev/null @@ -1,41 +0,0 @@ -use anyhow::Result; -use clap::Parser; -use xshell::{cmd, Shell}; - -#[derive(Debug, Parser)] -pub struct Options { - /// Build and run the release target - #[clap(long)] - pub release: bool, - /// Arguments to pass to your application - #[clap(name = "args")] - pub run_args: Vec, -} - -/// Build the binary -pub fn build(binary: &str, release: bool) -> Result<()> { - let sh = Shell::new()?; - let cargo = std::env::var("CARGO").unwrap(); - let args = if release { Some("--release") } else { None }; - cmd!(sh, "{cargo} build --workspace --bin {binary} {args...}").run()?; - - Ok(()) -} - -/// Build and run the binary with admin privileges -pub fn run_with_sudo(binary: &str, prefix: &[&str], opts: Options) -> Result<()> { - build(binary, opts.release)?; - - let sh = Shell::new()?; - - let target = if opts.release { "release" } else { "debug" }; - let args = opts.run_args; - // -E preserves the environment - cmd!( - sh, - "sudo -E ./target/{target}/{binary} {prefix...} {args...}" - ) - .run()?; - - Ok(()) -} diff --git a/xtask/src/surun.rs b/xtask/src/surun.rs new file mode 100644 index 00000000..f0d2544e --- /dev/null +++ b/xtask/src/surun.rs @@ -0,0 +1,72 @@ +use anyhow::{Context, Result}; +use clap::Parser; +use xshell::{cmd, Shell}; + +#[derive(Debug, Parser)] +pub struct SuRunCommand { + /// Arguments normally passed to `cargo run` + #[clap(name = "ARGS", allow_hyphen_values = true)] + pub run_args: Vec, +} + +impl SuRunCommand { + pub fn run(&self) -> Result<()> { + let cargo = std::env::var("CARGO").unwrap(); + + let target_triple = match self + .run_args + .iter() + .skip_while(|arg| *arg != "--target") + .skip(1) // advance the `--target` identifier + .next() + { + Some(target_triple) => target_triple.to_owned(), + None => get_default_target(&cargo) + .context(format!("failed to get target triple with {cargo}"))?, + }; + + log::debug!("Detected host triple: {target_triple}"); + + let target_triple_env_runner = { + let tt_env_format = target_triple.to_uppercase().replace("-", "_"); + format!("CARGO_TARGET_{tt_env_format}_RUNNER") + }; + + log::debug!("Overriding env variable: {target_triple_env_runner}"); + + let sh = Shell::new()?; + + sh.set_var(target_triple_env_runner, "sudo -E"); + + let args = &self.run_args; + + cmd!(sh, "{cargo} run {args...}").run()?; + + Ok(()) + } +} + +/// Calls `cargo -vV`` in a subprocess and returns the default Clang target triple. +fn get_default_target(cargo_path: &str) -> Result { + /// The [`rustc`][1] output field name that shows the target. + /// + /// [1]: https://doc.rust-lang.org/rustc/what-is-rustc.html + const TARGET_FIELD: &str = "host: "; + + // Query rustc for defaults. + let output = std::process::Command::new(cargo_path) + .arg("-vV") + .output() + .context(format!("failed to execute `{cargo_path} -vV`"))?; + + // Decode stdout. + let stdout = std::str::from_utf8(&output.stdout).context("failed to read stdout into uft8")?; + + // Parse the default target from stdout. + stdout + .lines() + .find(|l| l.starts_with(TARGET_FIELD)) + .map(|l| &l[TARGET_FIELD.len()..]) + .context(format!("failed to parse target from {cargo_path} output")) + .map(str::to_owned) +} diff --git a/xtask/src/test.rs b/xtask/src/test_suite.rs similarity index 100% rename from xtask/src/test.rs rename to xtask/src/test_suite.rs