mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
feat(windows): use ProgramData to store device ID instead of per-user… (#3172)
Fulfills #3159. This means the device ID is only tied to the Windows install instead of the user account. I also fixed up the logs and errors for that module real quick since I was already there.
This commit is contained in:
10
rust/Cargo.lock
generated
10
rust/Cargo.lock
generated
@@ -2053,6 +2053,7 @@ dependencies = [
|
||||
"hostname",
|
||||
"ipconfig",
|
||||
"keyring",
|
||||
"known-folders",
|
||||
"rand 0.8.5",
|
||||
"ring 0.17.7",
|
||||
"secrecy",
|
||||
@@ -3232,6 +3233,15 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "known-folders"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4397c789f2709d23cfcb703b316e0766a8d4b17db2d47b0ab096ef6047cae1d8"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kuchikiki"
|
||||
version = "0.8.2"
|
||||
|
||||
@@ -41,6 +41,7 @@ tracing-panic = "0.1.1"
|
||||
zip = { version = "0.6.6", features = ["deflate", "time"], default-features = false }
|
||||
rand = "0.8.5"
|
||||
windows-implement = "0.52.0"
|
||||
known-folders = "1.1.0"
|
||||
|
||||
# These dependencies are locked behind `cfg(windows)` because they either can't compile at all on Linux, or they need native dependencies like glib that are difficult to get. Try not to add more here.
|
||||
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
use known_folders::{get_known_folder_path, KnownFolder};
|
||||
use tokio::fs;
|
||||
|
||||
/// Get the device ID, generating it if it's not already on disk.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub(crate) enum Error {
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("Can't find well-known folder")]
|
||||
KnownFolder,
|
||||
}
|
||||
|
||||
/// Returns the device ID, generating it and saving it to disk if needed.
|
||||
///
|
||||
/// Per <https://github.com/firezone/firezone/issues/2697> and <https://github.com/firezone/firezone/issues/2711>,
|
||||
/// clients must generate their own random IDs and persist them to disk, to handle situations like VMs where a hardware ID is not unique or not available.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `identifier` - Our Tauri bundle identifier, e.g. "dev.firezone.client"
|
||||
///
|
||||
/// Returns: The UUID as a String, suitable for sending verbatim to `connlib_client_shared::Session::connect`.
|
||||
///
|
||||
/// Errors: If the disk is unwritable when initially generating the ID, or unwritable when re-generating an invalid ID.
|
||||
pub(crate) async fn device_id(
|
||||
app_local_data_dir: &crate::client::AppLocalDataDir,
|
||||
) -> anyhow::Result<String> {
|
||||
let dir = app_local_data_dir.0.join("config");
|
||||
pub(crate) async fn device_id(identifier: &str) -> Result<String, Error> {
|
||||
let dir = get_known_folder_path(KnownFolder::ProgramData)
|
||||
.ok_or(Error::KnownFolder)?
|
||||
.join(identifier)
|
||||
.join("config");
|
||||
let path = dir.join("device_id.json");
|
||||
|
||||
// Try to read it back from disk
|
||||
@@ -18,8 +34,9 @@ pub(crate) async fn device_id(
|
||||
.ok()
|
||||
.and_then(|s| serde_json::from_str::<DeviceIdJson>(&s).ok())
|
||||
{
|
||||
tracing::debug!("device ID loaded from disk is {}", j.id.to_string());
|
||||
return Ok(j.device_id());
|
||||
let device_id = j.device_id();
|
||||
tracing::debug!(?device_id, "Loaded device ID from disk");
|
||||
return Ok(device_id);
|
||||
}
|
||||
|
||||
// Couldn't read, it's missing or invalid, generate a new one and save it.
|
||||
@@ -28,9 +45,14 @@ pub(crate) async fn device_id(
|
||||
// TODO: This file write has the same possible problems with power loss as described here https://github.com/firezone/firezone/pull/2757#discussion_r1416374516
|
||||
// Since the device ID is random, typically only written once in the device's lifetime, and the read will error out if it's corrupted, it's low-risk.
|
||||
fs::create_dir_all(&dir).await?;
|
||||
fs::write(&path, serde_json::to_string(&j)?).await?;
|
||||
fs::write(
|
||||
&path,
|
||||
serde_json::to_string(&j).expect("Device ID should always be serializable"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
tracing::debug!("device ID saved to disk is {}", j.id.to_string());
|
||||
let device_id = j.device_id();
|
||||
tracing::debug!(?device_id, "Saved device ID to disk");
|
||||
Ok(j.device_id())
|
||||
}
|
||||
|
||||
|
||||
@@ -309,7 +309,7 @@ impl Controller {
|
||||
advanced_settings: AdvancedSettings,
|
||||
notify_controller: Arc<Notify>,
|
||||
) -> Result<Self> {
|
||||
let device_id = client::device_id::device_id(&app_local_data_dir(&app)?).await?;
|
||||
let device_id = client::device_id::device_id(&app.config().tauri.bundle.identifier).await?;
|
||||
|
||||
let mut this = Self {
|
||||
advanced_settings,
|
||||
|
||||
Reference in New Issue
Block a user