From 0a4e9be259af0125c44394cb0e1463f85d1c7930 Mon Sep 17 00:00:00 2001 From: Lukasz Woznicki Date: Thu, 10 Feb 2022 00:08:29 +0000 Subject: Use 'time' instead of 'chrono' due to CVE for c8y_smartrest and all dependent crates Signed-off-by: Lukasz Woznicki --- crates/core/c8y_smartrest/Cargo.toml | 7 +++-- .../c8y_smartrest/src/smartrest_deserializer.rs | 12 ++++----- crates/core/tedge_agent/Cargo.toml | 3 +-- crates/core/tedge_agent/src/error.rs | 3 +++ crates/core/tedge_agent/src/operation_logs.rs | 30 +++++++++++++++------- crates/core/tedge_mapper/Cargo.toml | 2 ++ .../core/tedge_mapper/src/sm_c8y_mapper/error.rs | 9 ++++--- .../tedge_mapper/src/sm_c8y_mapper/http_proxy.rs | 10 +++++--- .../core/tedge_mapper/src/sm_c8y_mapper/mapper.rs | 7 +++-- 9 files changed, 51 insertions(+), 32 deletions(-) (limited to 'crates/core') diff --git a/crates/core/c8y_smartrest/Cargo.toml b/crates/core/c8y_smartrest/Cargo.toml index 2f613061..03f575bb 100644 --- a/crates/core/c8y_smartrest/Cargo.toml +++ b/crates/core/c8y_smartrest/Cargo.toml @@ -7,13 +7,12 @@ rust-version = "1.58.1" [dependencies] agent_interface = { path = "../agent_interface" } -download = { path = "../../common/download" } -thin_edge_json = { path = "../thin_edge_json" } -time = { version = "0.3", features = ["macros"] } -chrono = { version = "0.4", features = ["serde"] } csv = "1.1" +download = { path = "../../common/download" } serde = { version = "1.0", features = ["derive"] } +thin_edge_json = { path = "../thin_edge_json" } thiserror = "1.0" +time = { version = "0.3", features = ["formatting", "macros", "parsing", "serde"] } [dev-dependencies] anyhow = "1.0" diff --git a/crates/core/c8y_smartrest/src/smartrest_deserializer.rs b/crates/core/c8y_smartrest/src/smartrest_deserializer.rs index f6809569..a5265279 100644 --- a/crates/core/c8y_smartrest/src/smartrest_deserializer.rs +++ b/crates/core/c8y_smartrest/src/smartrest_deserializer.rs @@ -1,11 +1,11 @@ use crate::error::SmartRestDeserializerError; use agent_interface::{SoftwareModule, SoftwareModuleUpdate, SoftwareUpdateRequest}; -use chrono::{DateTime, FixedOffset}; use csv::ReaderBuilder; use download::DownloadInfo; use serde::de::Error; use serde::{Deserialize, Deserializer, Serialize}; use std::convert::{TryFrom, TryInto}; +use time::{format_description, OffsetDateTime}; #[derive(Debug)] enum CumulocitySoftwareUpdateActions { @@ -166,11 +166,11 @@ impl SmartRestUpdateSoftwareModule { } } -fn to_datetime<'de, D>(deserializer: D) -> Result, D::Error> +fn to_datetime<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - // NOTE `NaiveDateTime` is used here because c8y uses for log requests a date time string which + // NOTE `OffsetDateTime` is used here because c8y uses for log requests a date time string which // does not exactly equal `chrono::DateTime::parse_from_rfc3339` // c8y result: // 2021-10-23T19:03:26+0100 @@ -191,7 +191,7 @@ where _ => date_string, }; - match DateTime::parse_from_rfc3339(&date_string) { + match OffsetDateTime::parse(&date_string, &format_description::well_known::Rfc3339) { Ok(result) => Ok(result), Err(e) => Err(D::Error::custom(&format!("Error: {}", e))), } @@ -207,9 +207,9 @@ pub struct SmartRestLogRequest { pub device: String, pub log_type: String, #[serde(deserialize_with = "to_datetime")] - pub date_from: DateTime, + pub date_from: OffsetDateTime, #[serde(deserialize_with = "to_datetime")] - pub date_to: DateTime, + pub date_to: OffsetDateTime, pub needle: Option, pub lines: usize, } diff --git a/crates/core/tedge_agent/Cargo.toml b/crates/core/tedge_agent/Cargo.toml index 30b43c60..9ba0e7fe 100644 --- a/crates/core/tedge_agent/Cargo.toml +++ b/crates/core/tedge_agent/Cargo.toml @@ -25,7 +25,6 @@ stop-on-upgrade = false agent_interface = { path = "../agent_interface" } anyhow = "1.0" async-trait = "0.1" -chrono = "0.4" flockfile = { path = "../../common/flockfile" } futures = "0.3" mockall = "0.10" @@ -36,8 +35,8 @@ serde_json = "1.0" structopt = "0.3" tedge_config = { path = "../../common/tedge_config" } tedge_utils = { path = "../../common/tedge_utils", features = ["logging"] } -time = { version = "0.3", features = ["formatting"] } thiserror = "1.0" +time = { version = "0.3", features = ["formatting"] } tokio = { version = "1.8", features = ["fs","process", "rt"] } toml = "0.5" tracing = { version = "0.1", features = ["attributes", "log"] } diff --git a/crates/core/tedge_agent/src/error.rs b/crates/core/tedge_agent/src/error.rs index e514490f..0c5d6444 100644 --- a/crates/core/tedge_agent/src/error.rs +++ b/crates/core/tedge_agent/src/error.rs @@ -46,6 +46,9 @@ pub enum AgentError { #[error("Could not convert {timestamp:?} to unix timestamp. Error message: {}")] TimestampConversionError { timestamp: i64, error_msg: String }, + + #[error(transparent)] + FromOperationsLogs(#[from] crate::operation_logs::OperationLogsError), } #[derive(Debug, thiserror::Error)] diff --git a/crates/core/tedge_agent/src/operation_logs.rs b/crates/core/tedge_agent/src/operation_logs.rs index 3bb12284..77988f54 100644 --- a/crates/core/tedge_agent/src/operation_logs.rs +++ b/crates/core/tedge_agent/src/operation_logs.rs @@ -1,10 +1,19 @@ -use chrono::{SecondsFormat, Utc}; use plugin_sm::log_file::LogFile; use std::cmp::Reverse; use std::collections::BinaryHeap; use std::path::PathBuf; +use time::{format_description, OffsetDateTime}; use tracing::log; +#[derive(Debug, thiserror::Error)] +pub enum OperationLogsError { + #[error(transparent)] + FromIo(#[from] std::io::Error), + + #[error(transparent)] + FromTimeFormat(#[from] time::error::Format), +} + #[derive(Debug)] pub struct OperationLogs { log_dir: PathBuf, @@ -17,11 +26,11 @@ pub enum LogKind { SoftwareList, } -const UPDATE_PREFIX: &'static str = "software-update"; -const LIST_PREFIX: &'static str = "software-list"; +const UPDATE_PREFIX: &str = "software-update"; +const LIST_PREFIX: &str = "software-list"; impl OperationLogs { - pub fn try_new(log_dir: PathBuf) -> Result { + pub fn try_new(log_dir: PathBuf) -> Result { std::fs::create_dir_all(log_dir.clone())?; let operation_logs = OperationLogs { log_dir, @@ -38,14 +47,15 @@ impl OperationLogs { Ok(operation_logs) } - pub async fn new_log_file(&self, kind: LogKind) -> Result { + pub async fn new_log_file(&self, kind: LogKind) -> Result { if let Err(err) = self.remove_outdated_logs() { // In no case a log-cleaning error should prevent the agent to run. // Hence the error is logged but not returned. log::warn!("Fail to remove the out-dated log files: {}", err); } - let now = Utc::now(); + let now = OffsetDateTime::now_utc(); + let file_prefix = match kind { LogKind::SoftwareUpdate => UPDATE_PREFIX, LogKind::SoftwareList => LIST_PREFIX, @@ -53,16 +63,18 @@ impl OperationLogs { let file_name = format!( "{}-{}.log", file_prefix, - now.to_rfc3339_opts(SecondsFormat::Secs, true) + now.format(&format_description::well_known::Rfc3339)? ); let mut log_file_path = self.log_dir.clone(); log_file_path.push(file_name); - LogFile::try_new(log_file_path).await + LogFile::try_new(log_file_path) + .await + .map_err(OperationLogsError::FromIo) } - pub fn remove_outdated_logs(&self) -> Result<(), std::io::Error> { + pub fn remove_outdated_logs(&self) -> Result<(), OperationLogsError> { let mut update_logs = BinaryHeap::new(); let mut list_logs = BinaryHeap::new(); for entry in self.log_dir.read_dir()? { diff --git a/crates/core/tedge_mapper/Cargo.toml b/crates/core/tedge_mapper/Cargo.toml index f6da873c..c1a13215 100644 --- a/crates/core/tedge_mapper/Cargo.toml +++ b/crates/core/tedge_mapper/Cargo.toml @@ -49,6 +49,7 @@ tedge_users = { path = "../../common/tedge_users" } tedge_utils = { path = "../../common/tedge_utils", features = ["logging"] } thin_edge_json = { path = "../thin_edge_json" } thiserror = "1.0" +time = "0.3" tokio = { version = "1.8", features = ["rt", "sync", "time"] } toml = "0.5" tracing = { version = "0.1", features = ["attributes", "log"] } @@ -62,6 +63,7 @@ serde_json = "1.0" serial_test = "0.5" tempfile = "3.2" test-case = "1.2" +time = { version = "0.3", features = ["macros"] } tokio-test = "0.4" [features] diff --git a/crates/core/tedge_mapper/src/sm_c8y_mapper/error.rs b/crates/core/tedge_mapper/src/sm_c8y_mapper/error.rs index 9678a549..e3d96cab 100644 --- a/crates/core/tedge_mapper/src/sm_c8y_mapper/error.rs +++ b/crates/core/tedge_mapper/src/sm_c8y_mapper/error.rs @@ -29,15 +29,18 @@ pub enum SMCumulocityMapperError { #[error(transparent)] FromTedgeConfig(#[from] tedge_config::ConfigSettingError), + #[error(transparent)] + FromTimeFormat(#[from] time::error::Format), + + #[error(transparent)] + FromTimeParse(#[from] time::error::Parse), + #[error("Invalid date in file name: {0}")] InvalidDateInFileName(String), #[error("Invalid path. Not UTF-8.")] InvalidUtf8Path, - #[error(transparent)] - FromChronoParse(#[from] chrono::ParseError), - #[error(transparent)] FromIo(#[from] std::io::Error), diff --git a/crates/core/tedge_mapper/src/sm_c8y_mapper/http_proxy.rs b/crates/core/tedge_mapper/src/sm_c8y_mapper/http_proxy.rs index cababb50..4013bc0a 100644 --- a/crates/core/tedge_mapper/src/sm_c8y_mapper/http_proxy.rs +++ b/crates/core/tedge_mapper/src/sm_c8y_mapper/http_proxy.rs @@ -5,7 +5,6 @@ use crate::sm_c8y_mapper::json_c8y::{ use crate::sm_c8y_mapper::mapper::SmartRestLogEvent; use async_trait::async_trait; use c8y_smartrest::smartrest_deserializer::SmartRestJwtResponse; -use chrono::{DateTime, Local}; use mqtt_channel::{Connection, PubChannel, StreamExt, Topic, TopicFilter}; use reqwest::Url; use std::time::Duration; @@ -13,6 +12,7 @@ use tedge_config::{ C8yUrlSetting, ConfigSettingAccessor, ConfigSettingAccessorStringExt, DeviceIdSetting, MqttPortSetting, TEdgeConfig, }; +use time::{format_description, OffsetDateTime}; use tracing::{error, info, instrument}; const RETRY_TIMEOUT_SECS: u64 = 60; @@ -200,16 +200,18 @@ impl JwtAuthHttpProxy { /// Make a POST request to /event/events and return the event id from response body. /// The event id is used to upload the binary. fn create_log_event(&self) -> C8yCreateEvent { - let local: DateTime = Local::now(); + let local = OffsetDateTime::now_utc(); let c8y_managed_object = C8yManagedObject { id: self.end_point.c8y_internal_id.clone(), }; C8yCreateEvent::new( - c8y_managed_object.to_owned(), + c8y_managed_object, "c8y_Logfile", - &local.format("%Y-%m-%dT%H:%M:%SZ").to_string(), + &local + .format(&format_description::well_known::Rfc3339) + .unwrap(), "software-management", ) } diff --git a/crates/core/tedge_mapper/src/sm_c8y_mapper/mapper.rs b/crates/core/tedge_mapper/src/sm_c8y_mapper/mapper.rs index 88077a09..251e0f90 100644 --- a/crates/core/tedge_mapper/src/sm_c8y_mapper/mapper.rs +++ b/crates/core/tedge_mapper/src/sm_c8y_mapper/mapper.rs @@ -25,14 +25,13 @@ use c8y_smartrest::{ SmartRestSetSupportedLogType, }, }; -use chrono::{DateTime, FixedOffset}; use download::{Auth, DownloadInfo}; use mqtt_channel::{Config, Connection, MqttError, SinkExt, StreamExt, Topic, TopicFilter}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; - use std::{convert::TryInto, process::Stdio}; use tedge_config::{ConfigSettingAccessor, MqttPortSetting, TEdgeConfig}; +use time::{format_description, OffsetDateTime}; use tracing::{debug, error, info, instrument}; const AGENT_LOG_DIR: &str = "/var/log/tedge/agent"; @@ -502,7 +501,7 @@ pub struct SmartRestLogEvent { /// ``` fn get_datetime_from_file_path( log_path: &PathBuf, -) -> Result, SMCumulocityMapperError> { +) -> Result { if let Some(stem_string) = log_path.file_stem().and_then(|s| s.to_str()) { // a typical file stem looks like this: software-list-2021-10-27T10:29:58Z. // to extract the date, rsplit string on "-" and take (last) 3 @@ -511,7 +510,7 @@ fn get_datetime_from_file_path( stem_string_vec.reverse(); // join on '-' to get the date string let date_string = stem_string_vec.join("-"); - let dt = DateTime::parse_from_rfc3339(&date_string)?; + let dt = OffsetDateTime::parse(&date_string, &format_description::well_known::Rfc3339)?; return Ok(dt); } -- cgit v1.2.3