Skip to content

Commit

Permalink
feat: ➕ add runner crate for user stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Jisu-Woniu committed Feb 13, 2024
1 parent bafccaf commit df1ad08
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 59 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
/firedbg
/target
/docs/manpages/*
!/docs/manpages/*.adoc
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@
},
"[rust]": {
"editor.defaultFormatter": "dprint.dprint"
}
},
"rust-analyzer.linkedProjects": [
"./Cargo.toml"
]
}
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
workspace = { members = ["xtask"] }
[package]
name = "rsjudge"
[workspace]
members = ["crates/rsjudge-runner", "xtask"]

[workspace.package]
version = "0.1.0"
authors = ["NJUPT-SAST"]
edition = "2021"
license = "Apache-2.0"

[package]
name = "rsjudge"
version.workspace = true
authors.workspace = true
edition = "2021"
license.workspace = true
description = "An online judge sandbox server in Rust."

[package.metadata.deb]
Expand Down Expand Up @@ -74,6 +81,7 @@ uzers = "0.11.3"

# Optional dependencies
axum = { version = "0.7.4", optional = true }
rsjudge-runner = { version = "0.1.0", path = "crates/rsjudge-runner" }
tonic = { version = "0.11.0", optional = true }
utoipa = { version = "4.2.0", features = ["axum_extras"], optional = true }
utoipa-swagger-ui = { version = "6.0.0", features = ["axum"], optional = true }
Expand Down
14 changes: 14 additions & 0 deletions crates/rsjudge-runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "rsjudge-runner"
version.workspace = true
authors.workspace = true
edition = "2021"
license.workspace = true
description = "Command runner for rsjudge"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.79"
nix = { version = "0.27.1", features = ["user"] }
uzers = "0.11.3"
14 changes: 14 additions & 0 deletions crates/rsjudge-runner/examples/demo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use std::process::Command;

use rsjudge_runner::{
user::{builder, runner},
RunAs,
};
fn main() -> anyhow::Result<()> {
let builder_output = Command::new("id").run_as(builder()?).output()?;
println!("{}", String::from_utf8_lossy(&builder_output.stdout));

let runner_output = Command::new("id").run_as(runner()?).output()?;
println!("{}", String::from_utf8_lossy(&runner_output.stdout));
Ok(())
}
25 changes: 25 additions & 0 deletions crates/rsjudge-runner/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::{os::unix::process::CommandExt as _, process::Command};

use nix::unistd::setgroups;
use uzers::User;

pub mod user;
pub trait RunAs {
fn run_as(&mut self, user: &User) -> &mut Command;
}

impl RunAs for Command {
fn run_as(&mut self, user: &User) -> &mut Command {
let uid = user.uid();
let gid = user.primary_group_id();

self.uid(uid).gid(gid);
unsafe {
self.pre_exec(move || {
setgroups(&[gid.into()])?;
Ok(())
})
};
self
}
}
54 changes: 54 additions & 0 deletions crates/rsjudge-runner/src/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::sync::OnceLock;

use anyhow::anyhow;
use uzers::{get_user_by_name, User};

static SUPERVISOR_LOCK: OnceLock<Option<User>> = OnceLock::new();
static BUILDER_LOCK: OnceLock<Option<User>> = OnceLock::new();
static RUNNER_LOCK: OnceLock<Option<User>> = OnceLock::new();

pub fn supervisor() -> anyhow::Result<&'static User> {
SUPERVISOR_LOCK
.get_or_init(|| get_user_by_name("rsjudge-supervisor"))
.as_ref()
.ok_or_else(|| anyhow!("No such user: rsjudge-supervisor"))
}

pub fn builder() -> anyhow::Result<&'static User> {
BUILDER_LOCK
.get_or_init(|| get_user_by_name("rsjudge-builder"))
.as_ref()
.ok_or_else(|| anyhow!("No such user: rsjudge-builder"))
}

pub fn runner() -> anyhow::Result<&'static User> {
RUNNER_LOCK
.get_or_init(|| get_user_by_name("rsjudge-runner"))
.as_ref()
.ok_or_else(|| anyhow!("No such user: rsjudge-runner"))
}

#[cfg(all(test, unix))]
mod tests {
use std::{os::unix::process::CommandExt, process::Command};

use super::*;

#[test]
#[ignore = "Requires additional users."]
fn test_uid() -> anyhow::Result<()> {
let builder = builder()?;
let builder_output = Command::new("id")
.uid(builder.uid())
.gid(builder.primary_group_id())
.output()?;
println!("{}", String::from_utf8_lossy(&builder_output.stdout));
let runner = runner()?;
let runner_output = Command::new("id")
.uid(runner.uid())
.gid(runner.primary_group_id())
.output()?;
println!("{}", String::from_utf8_lossy(&runner_output.stdout));
Ok(())
}
}
4 changes: 0 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use clap::Parser;

use crate::cli::Args;

mod cli;

/// For future use.
pub mod user;

fn main() -> anyhow::Result<()> {
let args = Args::try_parse()?;
println!("{:?}", args);
Expand Down
48 changes: 0 additions & 48 deletions src/user.rs

This file was deleted.

0 comments on commit df1ad08

Please sign in to comment.