fix(api): log an invalid EDGE_KEY master key before stopping

This commit is contained in:
charles-gauthereau
2026-10-20 16:45:10 +02:00
parent bb2d79dc65
commit c6794fd919
2 changed files with 38 additions and 3 deletions
+8 -3
View File
@@ -8,6 +8,7 @@ use reqwest::{Client, Method, RequestBuilder};
use serde::de::DeserializeOwned;
use sha2::{Digest, Sha256};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tracing::error;
type HmacSha256 = Hmac<Sha256>;
@@ -50,9 +51,13 @@ impl ApiClient {
/// Sign every dashboard call with the key derived from the EDGE_KEY master key.
pub fn with_agent_auth(mut self, agent_id: &str, master_key_b64: &str) -> Self {
let master_key = general_purpose::STANDARD
.decode(master_key_b64)
.expect("EDGE_KEY master key is not valid base64");
let master_key = match general_purpose::STANDARD.decode(master_key_b64) {
Ok(key) => key,
Err(_) => {
error!("Invalid EDGE_KEY: master key is not valid base64");
panic!("Cannot initialize AgentContext due to invalid EDGE_KEY");
}
};
self.agent_key = Some(derive_agent_key(&master_key, agent_id));
self
}
+30
View File
@@ -3,6 +3,7 @@ use crate::services::api::client::{derive_agent_key, sign_request};
use base64::{Engine as _, engine::general_purpose};
use reqwest::Method;
use std::sync::{Arc, Mutex};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
@@ -39,6 +40,35 @@ fn request_signature_matches_the_dashboard_vector() {
);
}
#[test]
fn invalid_master_key_logs_an_error_before_panicking() {
#[derive(Clone, Default)]
struct Logs(Arc<Mutex<Vec<u8>>>);
impl std::io::Write for Logs {
fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
self.0.lock().unwrap().extend_from_slice(bytes);
Ok(bytes.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
let logs = Logs::default();
let writer = logs.clone();
let subscriber = tracing_subscriber::fmt()
.with_ansi(false)
.with_writer(move || writer.clone())
.finish();
let result = tracing::subscriber::with_default(subscriber, || {
std::panic::catch_unwind(|| ApiClient::new("http://dashboard").with_agent_auth(AGENT_ID, "not base64!"))
});
assert!(result.is_err(), "an invalid master key must stop the agent");
let output = String::from_utf8(logs.0.lock().unwrap().clone()).unwrap();
assert!(output.contains("ERROR") && output.contains("Invalid EDGE_KEY"), "logs: {output}");
}
#[tokio::test]
async fn every_request_is_signed_with_a_fresh_timestamp() {
let server = MockServer::start().await;