Skip to content

Commit 13dd630

Browse files
committed
Fixes to use flakes as normal user
Running a flake is a container based instance provisioning and startup. Some part of this process requires root permissions for example mounting the container instance store for the provisioning step. This commit fixes the required calls to be properly managed by sudo.
1 parent 5ed0b55 commit 13dd630

File tree

2 files changed

+83
-24
lines changed

2 files changed

+83
-24
lines changed

common/src/user.rs

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use std::{process::Command, ffi::OsStr};
2727
use serde::{Serialize, Deserialize};
2828
use crate::command::{CommandExtTrait, CommandError};
2929
use uzers::{get_current_uid, get_current_groupname};
30+
use crate::lookup::{Lookup};
31+
use crate::error::FlakeError;
3032

3133
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
3234
pub struct User<'a> {
@@ -69,11 +71,57 @@ impl User<'_> {
6971
}
7072
}
7173

74+
pub fn exists(filename: &str, user: User) -> Result<bool, FlakeError> {
75+
/*!
76+
check file exists via sudo
77+
!*/
78+
let mut call = user.run("test");
79+
call.arg("-e").arg(filename);
80+
if Lookup::is_debug() {
81+
debug!("{:?}", call.get_args());
82+
}
83+
let output = match call.output() {
84+
Ok(output) => {
85+
output
86+
}
87+
Err(error) => {
88+
return Err(
89+
FlakeError::IOError {
90+
kind: "call failed".to_string(),
91+
message: format!("{error:?}")
92+
}
93+
);
94+
}
95+
};
96+
if output.status.success() {
97+
return Ok(true)
98+
}
99+
Ok(false)
100+
}
101+
102+
pub fn cp(source: &str, target: &str, user: User) -> Result<(), CommandError> {
103+
/*!
104+
copy filename via sudo
105+
!*/
106+
let mut call = user.run("cp");
107+
call.arg(source).arg(target);
108+
if Lookup::is_debug() {
109+
debug!("{:?}", call.get_args());
110+
}
111+
call.perform()?;
112+
Ok(())
113+
}
114+
72115
pub fn chmod(filename: &str, mode: &str, user: User) -> Result<(), CommandError> {
73116
/*!
74117
Chmod filename via sudo
75118
!*/
76-
user.run("chmod").arg(mode).arg(filename).perform()?;
119+
let mut call = user.run("chmod");
120+
call.arg(mode).arg(filename);
121+
if Lookup::is_debug() {
122+
debug!("{:?}", call.get_args());
123+
}
124+
call.perform()?;
77125
Ok(())
78126
}
79127

@@ -90,10 +138,18 @@ pub fn mkdir(dirname: &str, mode: &str, user: User) -> Result<(), CommandError>
90138
targetdir = workdir.to_str().unwrap();
91139
}
92140
if ! Path::new(&targetdir).exists() {
93-
user.run("mkdir")
94-
.arg("-p").arg("-m").arg(mode).arg(targetdir).perform()?;
95-
user.run("chmod")
96-
.arg(mode).arg(targetdir).perform()?;
141+
let mut mkdir_call = user.run("mkdir");
142+
mkdir_call.arg("-p").arg("-m").arg(mode).arg(targetdir);
143+
if Lookup::is_debug() {
144+
debug!("{:?}", mkdir_call.get_args());
145+
}
146+
mkdir_call.perform()?;
147+
let mut chmod_call = user.run("chmod");
148+
chmod_call.arg(mode).arg(targetdir);
149+
if Lookup::is_debug() {
150+
debug!("{:?}", chmod_call.get_args());
151+
}
152+
chmod_call.perform()?;
97153
}
98154
Ok(())
99155
}

podman-pilot/src/podman.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use atty::Stream;
2929
use rand::prelude::*;
3030
use rand_chacha::ChaCha20Rng;
3131

32-
use flakes::user::{User, mkdir};
32+
use flakes::user::{User, mkdir, cp, exists};
3333
use flakes::lookup::Lookup;
3434
use flakes::io::IO;
3535
use flakes::error::FlakeError;
@@ -49,6 +49,7 @@ use std::io::SeekFrom;
4949

5050
use spinoff::{Spinner, spinners, Color};
5151
use tempfile::tempfile;
52+
use tempfile::NamedTempFile;
5253
use regex::Regex;
5354

5455
use uzers::{get_current_username};
@@ -151,7 +152,7 @@ pub fn create(
151152
mkdir(defaults::FLAKES_REGISTRY, "777", User::ROOT)?;
152153

153154
let current_user = get_current_username().unwrap();
154-
let user = User::from(current_user.to_str().unwrap());
155+
let user = User::from("root");
155156

156157
let container_cid_file = format!(
157158
"{}/{}{}_{}.cid",
@@ -477,36 +478,35 @@ pub fn start(program_name: &str, cid: &str) -> Result<(), FlakeError> {
477478
let RuntimeSection { resume, attach, .. } = config().runtime();
478479

479480
let pilot_options = Lookup::get_pilot_run_options();
480-
let current_user = get_current_username().unwrap();
481-
let user = User::from(current_user.to_str().unwrap());
481+
let root_user = User::from("root");
482482

483-
let is_running = container_running(cid, user)?;
484-
let is_created = container_exists(cid, user)?;
483+
let is_running = container_running(cid, root_user)?;
484+
let is_created = container_exists(cid, root_user)?;
485485
let mut is_removed = false;
486486

487487
if is_running {
488488
if attach {
489489
// 1. Attach to running container
490-
call_instance("attach", cid, program_name, user)?;
490+
call_instance("attach", cid, program_name, root_user)?;
491491
} else {
492492
// 2. Execute app in running container
493-
call_instance("exec", cid, program_name, user)?;
493+
call_instance("exec", cid, program_name, root_user)?;
494494
}
495495
} else if resume {
496496
// 3. Startup resume type container and execute app
497-
call_instance("start", cid, program_name, user)?;
498-
call_instance("exec", cid, program_name, user)?;
497+
call_instance("start", cid, program_name, root_user)?;
498+
call_instance("exec", cid, program_name, root_user)?;
499499
} else {
500500
// 4. Startup container
501-
call_instance("start", cid, program_name, user)?;
501+
call_instance("start", cid, program_name, root_user)?;
502502
if ! attach || ! is_created {
503-
call_instance("rm_force", cid, program_name, user)?;
503+
call_instance("rm_force", cid, program_name, root_user)?;
504504
is_removed = true
505505
}
506506
};
507507

508508
if pilot_options.contains_key("%remove") && ! is_removed {
509-
call_instance("rm_force", cid, program_name, user)?;
509+
call_instance("rm_force", cid, program_name, root_user)?;
510510
};
511511
Ok(())
512512
}
@@ -641,6 +641,7 @@ pub fn sync_host(
641641
!*/
642642
let mut removed_files_contents = String::new();
643643
let files_from = format!("{}/{}", &target, from);
644+
let mut temp_files_from = NamedTempFile::new()?;
644645
removed_files.seek(SeekFrom::Start(0))?;
645646
removed_files.read_to_string(&mut removed_files_contents)?;
646647

@@ -650,8 +651,8 @@ pub fn sync_host(
650651
}
651652
return Ok(())
652653
}
653-
654-
File::create(&files_from)?.write_all(removed_files_contents.as_bytes())?;
654+
temp_files_from.write_all(removed_files_contents.as_bytes())?;
655+
cp(temp_files_from.path().to_str().unwrap(), &files_from, User::ROOT)?;
655656

656657
let mut call = user.run("rsync");
657658
call.arg("-av");
@@ -863,7 +864,7 @@ pub fn build_system_dependencies(
863864
to be provisioned from the host
864865
!*/
865866
let system_deps = format!("{}/{}", &target, dependency_file);
866-
if Path::new(&system_deps).exists() {
867+
if exists(&system_deps, User::ROOT)? {
867868
if Lookup::is_debug() {
868869
debug!("Calling system deps generator: {system_deps}");
869870
}
@@ -907,17 +908,19 @@ pub fn build_system_dependencies(
907908

908909
pub fn update_removed_files(
909910
target: &String, mut accumulated_file: &File
910-
) -> Result<(), std::io::Error> {
911+
) -> Result<(), FlakeError> {
911912
/*!
912913
Take the contents of the given removed_file and append it
913914
to the accumulated_file
914915
!*/
915916
let host_deps = format!("{}/{}", &target, defaults::HOST_DEPENDENCIES);
916-
if Path::new(&host_deps).exists() {
917+
if exists(&host_deps, User::ROOT)? {
917918
if Lookup::is_debug() {
918919
debug!("Adding host deps from {host_deps}");
919920
}
920-
let data = fs::read_to_string(&host_deps)?;
921+
let temp_host_deps = NamedTempFile::new()?;
922+
cp(&host_deps, temp_host_deps.path().to_str().unwrap(), User::ROOT)?;
923+
let data = fs::read_to_string(temp_host_deps.path())?;
921924
// The subsequent rsync call logs enough information
922925
// Let's keep this for convenience debugging
923926
// if Lookup::is_debug() {

0 commit comments

Comments
 (0)