From f1b0a26f15d5d3d7f92dd625d1e7441263546cc2 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 12 May 2024 22:22:09 +0900 Subject: [PATCH 1/5] feat(main): adjusted splunk api json format #1083 --- Cargo.lock | 34 +++++++- Cargo.toml | 1 + src/main.rs | 238 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 200 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7998906e..0d08492c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,7 +638,7 @@ dependencies = [ "jemallocator", "log", "memchr", - "quick-xml", + "quick-xml 0.31.0", "rayon", "rpmalloc", "serde_json", @@ -788,6 +788,7 @@ dependencies = [ "num-format", "openssl", "pulldown-cmark", + "quickxml_to_serde", "rand", "regex", "serde", @@ -1146,6 +1147,15 @@ dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "minidom" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe549115a674f5ec64c754d85e37d6f42664bd0ef4ffb62b619489ad99c6cb1a" +dependencies = [ + "quick-xml 0.17.2", +] + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1432,6 +1442,15 @@ dependencies = [ "unicase", ] +[[package]] +name = "quick-xml" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0" +dependencies = [ + "memchr", +] + [[package]] name = "quick-xml" version = "0.31.0" @@ -1441,6 +1460,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "quickxml_to_serde" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286b05c7a00b356ff6ac5218e10d628e0a3be02e777d067ca7286d353c3c407e" +dependencies = [ + "minidom", + "regex", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "quote" version = "1.0.36" diff --git a/Cargo.toml b/Cargo.toml index e21f2a907..775e7e2f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ regex = "1" serde = { version = "1.*", features = ["derive"] } serde_derive = "1.*" serde_json = { version = "1.0"} +quickxml_to_serde = "*" termcolor = "*" terminal_size = "*" tokio = { version = "1", features = ["full"] } diff --git a/src/main.rs b/src/main.rs index aba878ef2..94af5fdf0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,6 +43,7 @@ use libmimalloc_sys::mi_stats_print_out; use mimalloc::MiMalloc; use nested::Nested; use num_format::{Locale, ToFormattedString}; +use quickxml_to_serde::{xml_str_to_json, Config}; use serde_json::{Map, Value}; use std::borrow::BorrowMut; use std::ffi::{OsStr, OsString}; @@ -1763,6 +1764,92 @@ impl App { (detection, record_cnt, tl, recover_records_cnt, detect_infos) } + // 時刻およびチャンネルによるフィルタリングを行い、フィルタリングされた場合はtrueを返す。 + fn is_filtered_record( + &self, + (path, time_filter, target_event_ids, stored_static): ( + &str, + &TargetEventTime, + &TargetIds, + &StoredStatic, + ), + (is_splunk_json, is_splunk_api_json): (bool, bool), + data: &Value, + ) -> bool { + // Computer名がinclude_computerで指定されたものに合致しないまたはexclude_computerで指定されたものに合致した場合はフィルタリングする。 + if utils::is_filtered_by_computer_name( + utils::get_event_value("Event.System.Computer", data, &stored_static.eventkey_alias), + ( + &stored_static.include_computer, + &stored_static.exclude_computer, + ), + ) { + return true; + } + + // EventIDがinclude_eidで指定されたものに合致しないまたはexclude_eidで指定されたものに合致した場合、EventID Filter optionが指定されていないかつtarget_eventids.txtで指定されたEventIDではない場合はフィルタリングする。 + if self.is_filtered_by_eid( + data, + &stored_static.eventkey_alias, + (&stored_static.include_eid, &stored_static.exclude_eid), + stored_static.output_option.as_ref().unwrap().eid_filter, + target_event_ids, + ) { + return true; + } + + // channelがnullである場合はフィルタリングする。 + if !self._is_valid_channel( + data, + &stored_static.eventkey_alias, + "Event.EventData.Channel", + ) { + return true; + } + let target_timestamp = if data["Event"]["EventData"]["@timestamp"].is_null() { + &data["Event"]["EventData"]["TimeGenerated"] + } else { + &data["Event"]["EventData"]["@timestamp"] + }; + let time_fmt = if is_splunk_json { + "%Y-%m-%dT%H:%M:%S%.3f%:z" + } else if is_splunk_api_json { + "%Y-%m-%dT%H:%M:%S%.9fZ" + } else { + "%Y-%m-%dT%H:%M:%S%.3fZ" + }; + // EventID側の条件との条件の混同を防ぐため時間でのフィルタリングの条件分岐を分離した + let timestamp = match NaiveDateTime::parse_from_str( + &target_timestamp + .to_string() + .replace("\\\"", "") + .replace('"', ""), + time_fmt, + ) { + Ok(without_timezone_datetime) => Some(DateTime::::from_naive_utc_and_offset( + without_timezone_datetime, + Utc, + )), + Err(e) => { + AlertMessage::alert(&format!( + "timestamp parse error. filepath:{},{} {}", + path, + &target_timestamp + .to_string() + .replace("\\\"", "") + .replace('"', ""), + e + )) + .ok(); + None + } + }; + if !time_filter.is_target(×tamp) { + return true; + } + false + } + // JSON形式のイベントログファイルを1ファイル分解析する。 fn analysis_json_file( &self, @@ -1786,6 +1873,7 @@ impl App { let path = filepath.display(); let mut record_cnt = 0; let recover_records_cnt = 0; + let mut is_splunk_api_json; let filename = filepath.to_str().unwrap_or_default(); let filepath = if filename.starts_with("./") { check_setting_path(&CURRENT_EXE_PATH.to_path_buf(), filename, true) @@ -1822,15 +1910,84 @@ impl App { if next_rec.is_none() { break; } - record_cnt += 1; let mut data = next_rec.unwrap(); let is_splunk_json = data["Event"]["EventData"]["result"].is_object(); + is_splunk_api_json = !data["Event"]["EventData"]["rows"].is_null(); // ChannelなどのデータはEvent -> Systemに存在する必要があるが、他処理のことも考え、Event -> EventDataのデータをそのまま投入する形にした。cloneを利用しているのはCopy trait実装がserde_json::Valueにないため + if is_splunk_api_json { + let tmp_data = data["Event"]["EventData"]["rows"].clone(); + let tmp_data_value = data["Event"]["EventData"]["fields"].clone(); + let empty = vec![]; + let field_value = tmp_data.as_array().unwrap_or(&empty); + let fields_key = tmp_data_value.as_array().unwrap_or(&empty); + record_cnt += field_value.len(); + let mut rows_raw_idx = 0; + for (idx, name) in fields_key.iter().enumerate() { + if name != "_raw" { + continue; + } + rows_raw_idx = idx; + break; + } + for splunk_api_rec in field_value { + let mut splunk_api_record = xml_str_to_json( + splunk_api_rec[rows_raw_idx].as_str().unwrap_or_default(), + &Config::new_with_defaults(), + ) + .unwrap_or_default(); + for (v_idx, row_name) in fields_key.iter().enumerate() { + if let Some(row) = row_name.as_str() { + // splunk api jsonの場合はrowsとfieldsのデータをEventDataに投入する。rawデータがはレコード情報がそのまま入っているのでその情報を投入したうえでsplunk api json関連のレコード類を投入する + splunk_api_record["Event"]["EventData"][row.to_string()] = + splunk_api_rec[v_idx].clone(); + } + } - if is_splunk_json { + { + let system = splunk_api_record["Event"]["System"] + .as_object() + .unwrap() + .clone(); + for (k, v) in system { + splunk_api_record["Event"]["EventData"][k] = v.clone(); + } + } + splunk_api_record["Event"]["UserData"] = + splunk_api_record["Event"]["EventData"].clone(); + splunk_api_record["Event"]["EventData"]["@timestamp"] = splunk_api_record + ["Event"]["System"]["TimeCreated"]["@SystemTime"] + .clone(); + data["Event"]["System"]["@timestamp"] = splunk_api_record["Event"] + ["System"]["TimeCreated"]["@SystemTime"] + .clone(); + + if stored_static.computer_metrics_flag { + // computer-metricsコマンドでは検知は行わないためカウントのみ行い次のレコードを確認する + countup_event_by_computer( + &splunk_api_record, + &stored_static.eventkey_alias, + &mut tl, + ); + } + if !self.is_filtered_record( + ( + filepath.as_str(), + time_filter, + target_event_ids, + stored_static, + ), + (false, true), + &splunk_api_record, + ) { + records_per_detect.push((splunk_api_record.to_owned(), false)); + } + } + continue; + } else if is_splunk_json { data["Event"]["System"] = data["Event"]["EventData"]["result"].clone(); data["Event"]["EventData"] = data["Event"]["EventData"]["result"].clone(); } + record_cnt += 1; if data["Event"]["EventData"].is_object() { data["Event"]["System"] = data["Event"]["EventData"].clone(); } else if data["Event"]["EventData"].is_array() { @@ -1869,81 +2026,18 @@ impl App { // computer-metricsコマンドでは検知は行わないためカウントのみ行い次のレコードを確認する continue; } - - // Computer名がinclude_computerで指定されたものに合致しないまたはexclude_computerで指定されたものに合致した場合はフィルタリングする。 - if utils::is_filtered_by_computer_name( - utils::get_event_value( - "Event.System.Computer", - &data, - &stored_static.eventkey_alias, - ), + if !self.is_filtered_record( ( - &stored_static.include_computer, - &stored_static.exclude_computer, + filepath.as_str(), + time_filter, + target_event_ids, + stored_static, ), - ) { - continue; - } - - // EventIDがinclude_eidで指定されたものに合致しないまたはexclude_eidで指定されたものに合致した場合、EventID Filter optionが指定されていないかつtarget_eventids.txtで指定されたEventIDではない場合はフィルタリングする。 - if self.is_filtered_by_eid( + (true, false), &data, - &stored_static.eventkey_alias, - (&stored_static.include_eid, &stored_static.exclude_eid), - stored_static.output_option.as_ref().unwrap().eid_filter, - target_event_ids, ) { - continue; + records_per_detect.push((data.to_owned(), false)); } - - // channelがnullである場合はフィルタリングする。 - if !self._is_valid_channel( - &data, - &stored_static.eventkey_alias, - "Event.EventData.Channel", - ) { - continue; - } - let target_timestamp = if data["Event"]["EventData"]["@timestamp"].is_null() { - &data["Event"]["EventData"]["TimeGenerated"] - } else { - &data["Event"]["EventData"]["@timestamp"] - }; - let time_fmt = if is_splunk_json { - "%Y-%m-%dT%H:%M:%S%.3f%:z" - } else { - "%Y-%m-%dT%H:%M:%S%.3fZ" - }; - // EventID側の条件との条件の混同を防ぐため時間でのフィルタリングの条件分岐を分離した - let timestamp = match NaiveDateTime::parse_from_str( - &target_timestamp - .to_string() - .replace("\\\"", "") - .replace('"', ""), - time_fmt, - ) { - Ok(without_timezone_datetime) => Some( - DateTime::::from_naive_utc_and_offset(without_timezone_datetime, Utc), - ), - Err(e) => { - AlertMessage::alert(&format!( - "timestamp parse error. filepath:{},{} {}", - path, - &target_timestamp - .to_string() - .replace("\\\"", "") - .replace('"', ""), - e - )) - .ok(); - None - } - }; - if !time_filter.is_target(×tamp) { - continue; - } - - records_per_detect.push((data.to_owned(), false)); } if records_per_detect.is_empty() { break; From fce0100e8ea9e57d3f6617c4735d51a1fca1c801 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Sun, 12 May 2024 22:52:41 +0900 Subject: [PATCH 2/5] fix(main): fixed errors in variable assignments corrected. #1083 --- src/main.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 94af5fdf0..ceebd3d9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1957,10 +1957,9 @@ impl App { splunk_api_record["Event"]["EventData"]["@timestamp"] = splunk_api_record ["Event"]["System"]["TimeCreated"]["@SystemTime"] .clone(); - data["Event"]["System"]["@timestamp"] = splunk_api_record["Event"] - ["System"]["TimeCreated"]["@SystemTime"] + splunk_api_record["Event"]["System"]["@timestamp"] = splunk_api_record + ["Event"]["System"]["TimeCreated"]["@SystemTime"] .clone(); - if stored_static.computer_metrics_flag { // computer-metricsコマンドでは検知は行わないためカウントのみ行い次のレコードを確認する countup_event_by_computer( From 5a4290b38b49eccecd410110d7d4e388f45512f1 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Thu, 16 May 2024 01:20:36 +0900 Subject: [PATCH 3/5] fix(main, Cargo): removed quickxml_to_serde and fixed all record information output in Details fields #1083 --- Cargo.lock | 34 +----------------------- Cargo.toml | 1 - src/main.rs | 76 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d08492c6..e7998906e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,7 +638,7 @@ dependencies = [ "jemallocator", "log", "memchr", - "quick-xml 0.31.0", + "quick-xml", "rayon", "rpmalloc", "serde_json", @@ -788,7 +788,6 @@ dependencies = [ "num-format", "openssl", "pulldown-cmark", - "quickxml_to_serde", "rand", "regex", "serde", @@ -1147,15 +1146,6 @@ dependencies = [ "libmimalloc-sys", ] -[[package]] -name = "minidom" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe549115a674f5ec64c754d85e37d6f42664bd0ef4ffb62b619489ad99c6cb1a" -dependencies = [ - "quick-xml 0.17.2", -] - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1442,15 +1432,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "quick-xml" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.31.0" @@ -1460,19 +1441,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quickxml_to_serde" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286b05c7a00b356ff6ac5218e10d628e0a3be02e777d067ca7286d353c3c407e" -dependencies = [ - "minidom", - "regex", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "quote" version = "1.0.36" diff --git a/Cargo.toml b/Cargo.toml index 775e7e2f7..e21f2a907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,6 @@ regex = "1" serde = { version = "1.*", features = ["derive"] } serde_derive = "1.*" serde_json = { version = "1.0"} -quickxml_to_serde = "*" termcolor = "*" terminal_size = "*" tokio = { version = "1", features = ["full"] } diff --git a/src/main.rs b/src/main.rs index ceebd3d9c..b63bae4ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,7 +43,6 @@ use libmimalloc_sys::mi_stats_print_out; use mimalloc::MiMalloc; use nested::Nested; use num_format::{Locale, ToFormattedString}; -use quickxml_to_serde::{xml_str_to_json, Config}; use serde_json::{Map, Value}; use std::borrow::BorrowMut; use std::ffi::{OsStr, OsString}; @@ -1921,45 +1920,64 @@ impl App { let field_value = tmp_data.as_array().unwrap_or(&empty); let fields_key = tmp_data_value.as_array().unwrap_or(&empty); record_cnt += field_value.len(); - let mut rows_raw_idx = 0; - for (idx, name) in fields_key.iter().enumerate() { - if name != "_raw" { - continue; - } - rows_raw_idx = idx; - break; - } for splunk_api_rec in field_value { - let mut splunk_api_record = xml_str_to_json( - splunk_api_rec[rows_raw_idx].as_str().unwrap_or_default(), - &Config::new_with_defaults(), - ) - .unwrap_or_default(); + let mut splunk_api_record = Value::Null; for (v_idx, row_name) in fields_key.iter().enumerate() { if let Some(row) = row_name.as_str() { // splunk api jsonの場合はrowsとfieldsのデータをEventDataに投入する。rawデータがはレコード情報がそのまま入っているのでその情報を投入したうえでsplunk api json関連のレコード類を投入する + splunk_api_record["Event"]["System"][row.to_string()] = + splunk_api_rec[v_idx].clone(); splunk_api_record["Event"]["EventData"][row.to_string()] = splunk_api_rec[v_idx].clone(); } } - - { - let system = splunk_api_record["Event"]["System"] - .as_object() - .unwrap() - .clone(); - for (k, v) in system { - splunk_api_record["Event"]["EventData"][k] = v.clone(); + let timestamp = match NaiveDateTime::parse_from_str( + &splunk_api_record["Event"]["System"]["SystemTime"] + .to_string() + .replace("\\\"", "") + .replace(['"', '\''], ""), + "%Y-%m-%dT%H:%M:%S%.9fZ", + ) { + Ok(without_timezone_datetime) => { + DateTime::::from_naive_utc_and_offset( + without_timezone_datetime, + Utc, + ) + .format("%Y-%m-%dT%H:%M:%S%.3fZ") } - } + Err(e) => { + AlertMessage::warn(&format!( + "timestamp parse error. filepath:{},{} {}", + path, + &splunk_api_record["Event"]["System"]["SystemTime"] + .to_string() + .replace("\\\"", "") + .replace('"', ""), + e + )) + .ok(); + DateTime::::default().format("%Y-%m-%dT%H:%M:%S%.3fZ") + } + }; + splunk_api_record["Event"]["UserData"] = splunk_api_record["Event"]["EventData"].clone(); - splunk_api_record["Event"]["EventData"]["@timestamp"] = splunk_api_record - ["Event"]["System"]["TimeCreated"]["@SystemTime"] - .clone(); - splunk_api_record["Event"]["System"]["@timestamp"] = splunk_api_record - ["Event"]["System"]["TimeCreated"]["@SystemTime"] - .clone(); + splunk_api_record["Event"]["EventData"]["@timestamp"] = + Value::String(timestamp.to_string()); + splunk_api_record["Event"]["System"]["@timestamp"] = + splunk_api_record["Event"]["EventData"]["@timestamp"].clone(); + splunk_api_record["Event"]["System"] + .as_object_mut() + .unwrap() + .insert( + "Provider_attributes".to_string(), + Value::Object(Map::from_iter(vec![( + "Name".to_string(), + Value::from(1), + )])), + ); + splunk_api_record["Event"]["System"]["Provider_attributes"]["Name"] = + splunk_api_record["Event"]["EventData"]["Name"].clone(); if stored_static.computer_metrics_flag { // computer-metricsコマンドでは検知は行わないためカウントのみ行い次のレコードを確認する countup_event_by_computer( From cf4027d77e530441f827c31fe4a1c8156cc2c157 Mon Sep 17 00:00:00 2001 From: DastInDark <2350416+hitenkoku@users.noreply.github.com> Date: Thu, 16 May 2024 23:53:43 +0900 Subject: [PATCH 4/5] fix(main): fixed time fmt parse error to regular json input file #1083 --- src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index b63bae4ae..fb40a8694 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1822,7 +1822,7 @@ impl App { &target_timestamp .to_string() .replace("\\\"", "") - .replace('"', ""), + .replace(['"', '\''], ""), time_fmt, ) { Ok(without_timezone_datetime) => Some(DateTime::::from_naive_utc_and_offset( @@ -1993,7 +1993,7 @@ impl App { target_event_ids, stored_static, ), - (false, true), + (is_splunk_json, is_splunk_api_json), &splunk_api_record, ) { records_per_detect.push((splunk_api_record.to_owned(), false)); @@ -2050,7 +2050,7 @@ impl App { target_event_ids, stored_static, ), - (true, false), + (is_splunk_json, is_splunk_api_json), &data, ) { records_per_detect.push((data.to_owned(), false)); From c283803c10ac8539ef758a4f0d5011445c8f2d53 Mon Sep 17 00:00:00 2001 From: Yamato Security <71482215+YamatoSecurity@users.noreply.github.com> Date: Fri, 17 May 2024 09:09:26 +0900 Subject: [PATCH 5/5] update changelog --- CHANGELOG-Japanese.md | 1 + CHANGELOG.md | 1 + Cargo.lock | 167 ++++++++++++++++++++++-------------------- 3 files changed, 88 insertions(+), 81 deletions(-) diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 4d6bb5a7b..bf2b0ff1d 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -13,6 +13,7 @@ **改善:** - `-d, --directory`オプションで複数のフォルダを指定できるようにした。 (#1335) (@hitenkoku) +- REST APIからエクスポートされたSplunkログを分析できるようになった。 (#1083) (@hitenkoku) ## 2.15.0 [2024/04/20] "Sonic Release" diff --git a/CHANGELOG.md b/CHANGELOG.md index 7109a3d9b..4ee871379 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ **Enhancements:** - You can now specify multiple directories with the `-d, --directory` option. (#1335) (@hitenkoku) +- You can now analyze Splunk logs exported from the REST API. (#1083) (@hitenkoku) ## 2.15.0 [2024/04/20] "Sonic Release" diff --git a/Cargo.lock b/Cargo.lock index e7998906e..a5c8f6988 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,47 +61,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -109,9 +110,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "arrayvec" @@ -132,9 +133,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" @@ -201,9 +202,9 @@ checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -241,9 +242,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" dependencies = [ "jobserver", "libc", @@ -330,7 +331,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -350,9 +351,9 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "comfy-table" @@ -521,9 +522,9 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "encode_unicode" @@ -603,9 +604,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -939,11 +940,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -1018,9 +1025,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libgit2-sys" @@ -1174,9 +1181,9 @@ checksum = "ca2b420f638f07fe83056b55ea190bb815f609ec5a35e7017884a10f78839c9e" [[package]] name = "num" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -1188,20 +1195,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -1238,9 +1244,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -1249,11 +1255,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -1261,9 +1266,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -1322,7 +1327,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -1414,9 +1419,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -1575,9 +1580,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" @@ -1608,15 +1613,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring", "rustls-pki-types", @@ -1625,15 +1630,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1652,38 +1657,38 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1776,7 +1781,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -1798,9 +1803,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" dependencies = [ "proc-macro2", "quote", @@ -1846,22 +1851,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -1906,7 +1911,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]] @@ -2034,7 +2039,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", "wasm-bindgen-shared", ] @@ -2056,7 +2061,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2289,22 +2294,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.64", ] [[package]]