From 5b7b5bfea59906ea76c7f5f02e0df39c0e630b79 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Wed, 31 Jan 2024 15:44:38 -0700 Subject: [PATCH] Add a checksum telemetry request (#7168) We're seeing a bit of nonsense on telemetry. Although the checksum seed isn't secret per-se, it does make sending nonsense a little more effort. Release Notes: - N/A --- .github/workflows/ci.yml | 1 + Cargo.lock | 2 ++ crates/client/Cargo.toml | 2 ++ crates/client/src/telemetry.rs | 38 +++++++++++++++++++++++++++++----- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbaa12ecdd4fcbf2e0858dc6d75342e34d8225c2..9d8cf6522e44a434561e18292ff748052af5cf4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,6 +81,7 @@ jobs: MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} APPLE_NOTARIZATION_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }} APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }} + ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }} steps: - name: Install Node uses: actions/setup-node@v3 diff --git a/Cargo.lock b/Cargo.lock index 564da956df0af52d1a0b937f5668c9e543d3618e..ddb47a656a8cde93cc2ce3da4fb8c5ec5a059b6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1367,6 +1367,7 @@ dependencies = [ "image", "lazy_static", "log", + "once_cell", "parking_lot 0.11.2", "postage", "rand 0.8.5", @@ -1377,6 +1378,7 @@ dependencies = [ "serde_derive", "serde_json", "settings", + "sha2 0.10.7", "smol", "sum_tree", "sysinfo", diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 37d617821ea1e15045ef073e9e002ca866a8e51b..9bf04caa71140357b978326e1a4881edc8c6315e 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -32,6 +32,7 @@ futures.workspace = true image = "0.23" lazy_static.workspace = true log.workspace = true +once_cell = "1.19.0" parking_lot.workspace = true postage.workspace = true rand.workspace = true @@ -39,6 +40,7 @@ schemars.workspace = true serde.workspace = true serde_derive.workspace = true serde_json.workspace = true +sha2 = "0.10" smol.workspace = true sysinfo.workspace = true tempfile.workspace = true diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 1a8627f2867c9a43c925d78f9559e21d100bbfb2..331683d5d1e0a1b5bf848a50a2138a4209087cef 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -4,16 +4,19 @@ use crate::TelemetrySettings; use chrono::{DateTime, Utc}; use futures::Future; use gpui::{AppContext, AppMetadata, BackgroundExecutor, Task}; +use once_cell::sync::Lazy; use parking_lot::Mutex; use release_channel::ReleaseChannel; use serde::Serialize; use settings::{Settings, SettingsStore}; -use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration}; +use sha2::{Digest, Sha256}; +use std::io::Write; +use std::{env, mem, path::PathBuf, sync::Arc, time::Duration}; use sysinfo::{ CpuRefreshKind, Pid, PidExt, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt, }; use tempfile::NamedTempFile; -use util::http::{HttpClient, ZedHttpClient}; +use util::http::{self, HttpClient, Method, ZedHttpClient}; #[cfg(not(debug_assertions))] use util::ResultExt; use util::TryFutureExt; @@ -142,6 +145,13 @@ const FLUSH_INTERVAL: Duration = Duration::from_secs(1); #[cfg(not(debug_assertions))] const FLUSH_INTERVAL: Duration = Duration::from_secs(60 * 5); +static ZED_CLIENT_CHECKSUM_SEED: Lazy> = Lazy::new(|| { + option_env!("ZED_CLIENT_CHECKSUM_SEED") + .unwrap_or("development-checksum-seed") + .as_bytes() + .into() +}); + impl Telemetry { pub fn new(client: Arc, cx: &mut AppContext) -> Arc { let release_channel = @@ -540,9 +550,27 @@ impl Telemetry { serde_json::to_writer(&mut json_bytes, &request_body)?; } - this.http_client - .post_json(&this.http_client.zed_url("/api/events"), json_bytes.into()) - .await?; + let mut summer = Sha256::new(); + summer.update(&*ZED_CLIENT_CHECKSUM_SEED); + summer.update(&json_bytes); + summer.update(&*ZED_CLIENT_CHECKSUM_SEED); + let mut checksum = String::new(); + for byte in summer.finalize().as_slice() { + use std::fmt::Write; + write!(&mut checksum, "{:02x}", byte).unwrap(); + } + + let request = http::Request::builder() + .method(Method::POST) + .uri(&this.http_client.zed_url("/api/events")) + .header("Content-Type", "text/plain") + .header("x-zed-checksum", checksum) + .body(json_bytes.into()); + + let response = this.http_client.send(request?).await?; + if response.status() != 200 { + log::error!("Failed to send events: HTTP {:?}", response.status()); + } anyhow::Ok(()) } .log_err(),