forked from lix-project/lix-installer
Sudo in harmonic (#109)
* Perform sudo in harmonic * Remove sudo in scripts * A bit more tweaking... * Yay unix * Preserve environments we require * Preserve GITHUB_PATH too * Correct trace * Remove unused vars * Only pass --preserve-env if required
This commit is contained in:
parent
72792372ee
commit
148625c85f
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
|
@ -72,11 +72,11 @@ jobs:
|
|||
- name: Set executable
|
||||
run: chmod +x ./harmonic
|
||||
- name: Initial install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install linux-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install linux-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
- name: Repeated install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install linux-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install linux-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix`
|
||||
|
@ -99,7 +99,7 @@ jobs:
|
|||
if: success() || failure()
|
||||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
|
||||
run-steam-deck:
|
||||
name: Run Steam Deck (mock)
|
||||
|
@ -119,11 +119,11 @@ jobs:
|
|||
sudo chmod +x /bin/steamos-readonly
|
||||
sudo useradd -m deck
|
||||
- name: Initial install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
- name: Repeated install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix`
|
||||
|
@ -146,7 +146,7 @@ jobs:
|
|||
if: success() || failure()
|
||||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
|
||||
build-x86_64-darwin:
|
||||
name: Build x86_64 Darwin
|
||||
|
@ -179,11 +179,11 @@ jobs:
|
|||
- name: Set executable
|
||||
run: chmod +x ./harmonic
|
||||
- name: Initial install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
- name: Repeated install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: echo $PATH
|
||||
run: echo $PATH
|
||||
- name: Test `nix`
|
||||
|
@ -206,5 +206,5 @@ jobs:
|
|||
if: success() || failure()
|
||||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
run: GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
|
|
@ -93,11 +93,6 @@ main() {
|
|||
exit 1
|
||||
fi
|
||||
|
||||
local maybe_sudo=""
|
||||
if [ "$(id -u)" -ne 0 ] && command -v sudo > /dev/null; then
|
||||
maybe_sudo="sudo"
|
||||
fi
|
||||
|
||||
if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then
|
||||
# The installer is going to want to ask for confirmation by
|
||||
# reading stdin. This script was piped into `sh` though and
|
||||
|
@ -107,9 +102,9 @@ main() {
|
|||
err "Unable to run interactively. Run with -y to accept defaults, --help for additional options"
|
||||
fi
|
||||
|
||||
ignore "$maybe_sudo" "$_file" "$@" < /dev/tty
|
||||
ignore "$_file" "$@" < /dev/tty
|
||||
else
|
||||
ignore "$maybe_sudo" "$_file" "$@"
|
||||
ignore "$_file" "$@"
|
||||
fi
|
||||
|
||||
local _retval=$?
|
||||
|
|
|
@ -7,7 +7,9 @@ mod interaction;
|
|||
pub(crate) mod subcommand;
|
||||
|
||||
use clap::Parser;
|
||||
use std::process::ExitCode;
|
||||
use eyre::WrapErr;
|
||||
use owo_colors::OwoColorize;
|
||||
use std::{ffi::CString, process::ExitCode};
|
||||
use tokio::sync::broadcast::{Receiver, Sender};
|
||||
|
||||
use self::subcommand::HarmonicSubcommand;
|
||||
|
@ -77,5 +79,55 @@ pub(crate) async fn signal_channel() -> eyre::Result<(Sender<()>, Receiver<()>)>
|
|||
}
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
nix::unistd::getuid() == nix::unistd::Uid::from_raw(0)
|
||||
let euid = nix::unistd::Uid::effective();
|
||||
tracing::trace!("Running as EUID {euid}");
|
||||
euid.is_root()
|
||||
}
|
||||
|
||||
pub fn ensure_root() -> eyre::Result<()> {
|
||||
if !is_root() {
|
||||
eprintln!(
|
||||
"{}",
|
||||
"Harmonic needs to run as `root`, attempting to escalate now via `sudo`..."
|
||||
.yellow()
|
||||
.dimmed()
|
||||
);
|
||||
let sudo_cstring = CString::new("sudo").wrap_err("Making C string of `sudo`")?;
|
||||
|
||||
let args = std::env::args();
|
||||
let mut arg_vec_cstring = vec![];
|
||||
arg_vec_cstring.push(sudo_cstring.clone());
|
||||
|
||||
let mut preserve_env_list = vec![];
|
||||
for (key, _value) in std::env::vars() {
|
||||
let preserve = match key.as_str() {
|
||||
// Rust logging/backtrace bits we use
|
||||
"RUST_LOG" | "RUST_BACKTRACE" => true,
|
||||
// CI
|
||||
"GITHUB_PATH" => true,
|
||||
// Our own environments
|
||||
key if key.starts_with("HARMONIC") => true,
|
||||
_ => false,
|
||||
};
|
||||
if preserve {
|
||||
preserve_env_list.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
if !preserve_env_list.is_empty() {
|
||||
arg_vec_cstring.push(
|
||||
CString::new(format!("--preserve-env={}", preserve_env_list.join(",")))
|
||||
.wrap_err("Building a `--preserve-env` argument for `sudo`")?,
|
||||
);
|
||||
}
|
||||
|
||||
for arg in args {
|
||||
arg_vec_cstring.push(CString::new(arg).wrap_err("Making arg into C string")?);
|
||||
}
|
||||
|
||||
tracing::trace!("Execvp'ing `{sudo_cstring:?}` with args `{arg_vec_cstring:?}`");
|
||||
nix::unistd::execvp(&sudo_cstring, &arg_vec_cstring)
|
||||
.wrap_err("Executing Harmonic as `root` via `sudo`")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use crate::{
|
||||
action::ActionState,
|
||||
cli::{interaction, is_root, signal_channel, CommandExecute},
|
||||
cli::{ensure_root, interaction, signal_channel, CommandExecute},
|
||||
plan::RECEIPT_LOCATION,
|
||||
planner::Planner,
|
||||
BuiltinPlanner, InstallPlan,
|
||||
|
@ -53,11 +53,7 @@ impl CommandExecute for Install {
|
|||
explain,
|
||||
} = self;
|
||||
|
||||
if !is_root() {
|
||||
return Err(eyre!(
|
||||
"`harmonic install` must be run as `root`, try `sudo harmonic install`"
|
||||
));
|
||||
}
|
||||
ensure_root()?;
|
||||
|
||||
let existing_receipt: Option<InstallPlan> = match Path::new(RECEIPT_LOCATION).exists() {
|
||||
true => {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
cli::{is_root, signal_channel},
|
||||
cli::{ensure_root, signal_channel},
|
||||
plan::RECEIPT_LOCATION,
|
||||
InstallPlan,
|
||||
};
|
||||
|
@ -47,11 +47,7 @@ impl CommandExecute for Uninstall {
|
|||
explain,
|
||||
} = self;
|
||||
|
||||
if !is_root() {
|
||||
return Err(eyre!(
|
||||
"`harmonic install` must be run as `root`, try `sudo harmonic install`"
|
||||
));
|
||||
}
|
||||
ensure_root()?;
|
||||
|
||||
// During install, `harmonic` will store a copy of itself in `/nix/harmonic`
|
||||
// If the user opted to run that particular copy of Harmonic to do this uninstall,
|
||||
|
@ -89,6 +85,7 @@ impl CommandExecute for Uninstall {
|
|||
let temp_exe_cstring = CString::new(temp_exe.to_string_lossy().into_owned())
|
||||
.wrap_err("Making C string of executable path")?;
|
||||
|
||||
tracing::trace!("Execv'ing `{temp_exe_cstring:?} {arg_vec_cstring:?}`");
|
||||
nix::unistd::execv(&temp_exe_cstring, &arg_vec_cstring)
|
||||
.wrap_err("Executing copied Harmonic")?;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue