From a3612aef9abec3fe62369dbb1aa8cea17d4dce99 Mon Sep 17 00:00:00 2001 From: Marcel Guzik Date: Tue, 20 Aug 2024 19:33:36 +0200 Subject: [PATCH] only use tedge-write if no write permissions Configuration file deployment was changed to always do a regular copy first, and only use tedge-write if copy failes due to lacking permissions. Signed-off-by: Marcel Guzik --- .../tedge_config_manager/src/actor.rs | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/crates/extensions/tedge_config_manager/src/actor.rs b/crates/extensions/tedge_config_manager/src/actor.rs index ca312934e23..aa58d395f3a 100644 --- a/crates/extensions/tedge_config_manager/src/actor.rs +++ b/crates/extensions/tedge_config_manager/src/actor.rs @@ -6,6 +6,7 @@ use log::error; use log::info; use serde_json::json; use std::collections::HashMap; +use std::io::ErrorKind; use tedge_actors::fan_in_message_type; use tedge_actors::Actor; use tedge_actors::ChannelError; @@ -30,6 +31,7 @@ use tedge_mqtt_ext::QoS; use tedge_mqtt_ext::Topic; use tedge_uploader_ext::UploadRequest; use tedge_uploader_ext::UploadResult; +use tedge_utils::fs::AtomFileError; use tedge_write::CopyOptions; use crate::TedgeWriteStatus; @@ -420,9 +422,8 @@ impl ConfigManagerActor { /// deployed. /// /// This function ensures that the configuration file under `dest` is overwritten by a new - /// version currently stored in a temporary directory under `src`. Depending on if - /// `use_tedge_write` is used, either a new `tedge-write` process is spawned, or a file is - /// copied directly. + /// version currently stored in a temporary directory under `src`. If we have no write + /// permissions, use tedge-write for permission elevation if `use_tedge_write` is enabled. fn deploy_config_file( &self, from: &Utf8Path, @@ -435,25 +436,36 @@ impl ConfigManagerActor { let group = file_entry.file_permissions.group.as_deref(); let to = Utf8PathBuf::from(&file_entry.path); + let src_file = std::fs::File::open(from)?; - match self.config.use_tedge_write.clone() { - TedgeWriteStatus::Disabled => { - let src_file = std::fs::File::open(from)?; - tedge_utils::fs::atomically_write_file_sync(&to, src_file)?; + // try doing a regular copy, return if success or error other than permissions + debug!("deploying config file from '{from}' to '{to}'"); + let err = match tedge_utils::fs::atomically_write_file_sync(&to, src_file) { + Ok(()) => return Ok(to), + Err(err) => { + let AtomFileError::WriteError { source, .. } = &err; + if source.kind() != ErrorKind::PermissionDenied { + return Err(err.into()); + } + err } + }; + // if we got permission denied and tedge-write is enabled, use it for privilege elevation + let TedgeWriteStatus::Enabled { sudo } = self.config.use_tedge_write.clone() else { + return Err(err.into()); + }; - TedgeWriteStatus::Enabled { sudo } => { - let options = CopyOptions { - from, - to: to.as_path(), - sudo, - mode, - user, - group, - }; - options.copy()?; - } - } + debug!("using tedge-write for privilege elevation"); + + let options = CopyOptions { + from, + to: to.as_path(), + sudo, + mode, + user, + group, + }; + options.copy()?; Ok(to) }