From 438469f3ac5af19d69f2ee7c42c8dbc93cf021a8 Mon Sep 17 00:00:00 2001 From: Reactor Scram Date: Wed, 1 May 2024 10:06:25 -0500 Subject: [PATCH] chore(linux-client): make headless client / IPC service logs group-readable (#4825) ```[tasklist] # Before merging - [x] Add CI test to check that the Unix domain socket is owned by `root:firezone` (#4832 will do this) ``` This allows the GUI (running as a normal user who belongs to the `firezone` group) to read back the connlib logs and export them in the zip file. image --- .../connlib/clients/shared/src/file_logger.rs | 20 +++++++++++++++++++ .../src-tauri/firezone-client-ipc.service | 1 + rust/headless-client/src/imp_linux.rs | 8 -------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/rust/connlib/clients/shared/src/file_logger.rs b/rust/connlib/clients/shared/src/file_logger.rs index 7f3e6b28e..fe42bdf3b 100644 --- a/rust/connlib/clients/shared/src/file_logger.rs +++ b/rust/connlib/clients/shared/src/file_logger.rs @@ -120,9 +120,29 @@ impl Inner { } let file = new_file?; + Self::set_permissions(&file)?; Ok((file, filename)) } + + /// Make the logs group-readable so that the GUI, running as a user in the `firezone` + /// group, can zip them up when exporting logs. + #[cfg(target_os = "linux")] + fn set_permissions(f: &fs::File) -> io::Result<()> { + // I would put this at the top of the file, but it only exists on Linux + use std::os::unix::fs::PermissionsExt; + // user read/write, group read-only, others nothing + let perms = fs::Permissions::from_mode(0o640); + f.set_permissions(perms)?; + Ok(()) + } + + /// Does nothing on non-Linux systems + #[cfg(not(target_os = "linux"))] + #[allow(clippy::unnecessary_wraps)] + fn set_permissions(_f: &fs::File) -> io::Result<()> { + Ok(()) + } } impl io::Write for Appender { diff --git a/rust/gui-client/src-tauri/firezone-client-ipc.service b/rust/gui-client/src-tauri/firezone-client-ipc.service index d03739f70..f34814049 100644 --- a/rust/gui-client/src-tauri/firezone-client-ipc.service +++ b/rust/gui-client/src-tauri/firezone-client-ipc.service @@ -44,6 +44,7 @@ ExecStart=firezone-client-ipc Type=notify # Unfortunately we may need root to control DNS User=root +Group=firezone [Install] WantedBy=default.target diff --git a/rust/headless-client/src/imp_linux.rs b/rust/headless-client/src/imp_linux.rs index 61de99459..d3a4261fd 100644 --- a/rust/headless-client/src/imp_linux.rs +++ b/rust/headless-client/src/imp_linux.rs @@ -185,18 +185,10 @@ pub(crate) fn run_ipc_service(cli: Cli) -> Result<()> { } async fn ipc_listen(cli: Cli) -> Result<()> { - // Find the `firezone` group - let fz_gid = nix::unistd::Group::from_name("firezone") - .context("can't get group by name")? - .context("firezone group must exist on the system")? - .gid; - // Remove the socket if a previous run left it there let sock_path = sock_path(); tokio::fs::remove_file(&sock_path).await.ok(); let listener = UnixListener::bind(&sock_path).context("Couldn't bind UDS")?; - std::os::unix::fs::chown(&sock_path, Some(ROOT_USER), Some(fz_gid.into())) - .context("can't set firezone as the group for the UDS")?; let perms = std::fs::Permissions::from_mode(0o660); std::fs::set_permissions(sock_path, perms)?; sd_notify::notify(true, &[sd_notify::NotifyState::Ready])?;