Add support for the Dockerfile USER directive so that the container's CMD/ENTRYPOINT runs as the configured user instead of root. Changes: - inject.rs: Add user field to Config struct, write /slim/user at build time - build.rs: Pass config.user through to inject() - slim-init.sh: Read /slim/user and drop privileges via su before executing the command. Numeric uids are resolved to usernames via /etc/passwd (BusyBox su does not accept numeric args). When dropping privileges, run as a child (not exec) so PID 1 stays root and can poweroff after the command exits. - test.sh: Add test_user verifying build-time CMD and --cmd override both run as the configured user Closes #7
This commit is contained in:
+23
-24
@@ -22,6 +22,8 @@ pub struct Config {
|
||||
pub env: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub working_dir: Option<String>,
|
||||
#[serde(default)]
|
||||
pub user: Option<String>,
|
||||
}
|
||||
|
||||
pub fn inspect_config(image: &str) -> Result<Config> {
|
||||
@@ -85,33 +87,30 @@ pub fn build_exec_script(command: &str, env: &[String], working_dir: Option<&str
|
||||
lines
|
||||
}
|
||||
|
||||
/// Inject /slim/init and /slim/exec into a mounted container image rootfs.
|
||||
pub fn inject(mount_path: &Path, exec_script: &str) -> Result<()> {
|
||||
/// Install `content` into the mounted rootfs at `<mount>/slim/<name>` with
|
||||
/// the given mode.
|
||||
fn install_into_rootfs(mount: &str, name: &str, mode: &str, content: &str) -> Result<()> {
|
||||
let temp = tempfile::NamedTempFile::new()?;
|
||||
fs::write(temp.path(), content)?;
|
||||
let src = temp.path().to_str().context("temp path is not UTF-8")?;
|
||||
let dest = format!("{mount}/slim/{name}");
|
||||
cmd(&[
|
||||
"podman", "unshare", "--", "install", "-D", "-m", mode, src, &dest,
|
||||
])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inject /slim/init, /slim/exec, and optionally /slim/user into a mounted
|
||||
/// container image rootfs.
|
||||
pub fn inject(mount_path: &Path, exec_script: &str, user: Option<&str>) -> Result<()> {
|
||||
let mount_str = mount_path.to_str().context("mount path is not UTF-8")?;
|
||||
|
||||
let init_temp = tempfile::NamedTempFile::new()?;
|
||||
let exec_temp = tempfile::NamedTempFile::new()?;
|
||||
fs::write(init_temp.path(), SLIM_INIT)?;
|
||||
fs::write(exec_temp.path(), exec_script)?;
|
||||
install_into_rootfs(mount_str, "init", "755", SLIM_INIT)?;
|
||||
install_into_rootfs(mount_str, "exec", "755", exec_script)?;
|
||||
|
||||
let init_src = init_temp
|
||||
.path()
|
||||
.to_str()
|
||||
.context("temp path is not UTF-8")?;
|
||||
let exec_src = exec_temp
|
||||
.path()
|
||||
.to_str()
|
||||
.context("temp path is not UTF-8")?;
|
||||
|
||||
let init_dest = format!("{mount_str}/slim/init");
|
||||
let exec_dest = format!("{mount_str}/slim/exec");
|
||||
|
||||
cmd(&[
|
||||
"podman", "unshare", "--", "install", "-D", "-m", "755", init_src, &init_dest,
|
||||
])?;
|
||||
cmd(&[
|
||||
"podman", "unshare", "--", "install", "-D", "-m", "755", exec_src, &exec_dest,
|
||||
])?;
|
||||
if let Some(user) = user.filter(|u| !u.is_empty()) {
|
||||
install_into_rootfs(mount_str, "user", "644", user)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user