From adf2180d110db34e6496bb2277034fb5236a7b35 Mon Sep 17 00:00:00 2001 From: Jia Chao Date: Mon, 12 Aug 2024 16:31:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Reporter=20=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E4=BD=93=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E6=89=80=E6=9C=89=E6=9B=B4=E6=96=B0=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jia Chao --- Cargo.toml | 2 +- src/analyzer/mod.rs | 104 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6a927d0..c9f48fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ clap = { version = "4.0", features = ["derive"] } serde = { version = "1", features = ["serde_derive"] } serde_json = { version = "1.0" } toml = { version = "0.8" } -updateinfo-xmlparser = { git = "https://git.zhgsun.com:8089/jiachao2130/updateinfo-xmlparser.git", version = "0.1.0" } +updateinfo-xmlparser = { git = "https://git.zhgsun.com:8089/jiachao2130/updateinfo-xmlparser.git", version = "0.1.1" } cvrf-xmlparser = { git = "https://git.zhgsun.com:8089/jiachao2130/cvrf-xmlparser.git", version = "0.1.0" } rpm-rs = { git = "https://git.zhgsun.com:8089/jiachao2130/rpm-rs.git", version = "0.1.0" } lazy_static = { version = "1.5" } diff --git a/src/analyzer/mod.rs b/src/analyzer/mod.rs index 37e7d54..add545b 100644 --- a/src/analyzer/mod.rs +++ b/src/analyzer/mod.rs @@ -30,6 +30,60 @@ lazy_static! { pub mod db; +struct Reporter { + // 已修复的安全更新 + fixed: HashMap>, + + // 可用的安全更新 + avaliable: HashMap>, +} + +impl Reporter { + // 新建一个空的 Reporter + pub fn new() -> Self { + let fixed = HashMap::new(); + let avaliable = HashMap::new(); + + Self { + fixed, avaliable + } + } + + // get fixed, 不可写 + pub fn get_fixed(&self) -> &HashMap> { + &self.fixed + } + + // get avaliable, 只读 + pub fn get_avaliable(&self) -> &HashMap> { + &self.avaliable + } + + // 添加包到已修复 + pub fn add_to_fixed(&mut self, cusa: &CUSA, rpm: RpmInfo) { + // 可以找到则直接 insert + if let Some(rpms) = self.fixed.get_mut(cusa) { + rpms.insert(rpm); + } else { + let mut rpms = HashSet::new(); + rpms.insert(rpm); + self.fixed.insert(cusa.clone(), rpms); + } + } + + // 添加包到可用更新 + pub fn add_to_avaliable(&mut self, cusa: &CUSA, rpm: RpmInfo) { + // 可以找到则直接 insert + if let Some(rpms) = self.avaliable.get_mut(cusa) { + rpms.insert(rpm); + } else { + let mut rpms = HashSet::new(); + rpms.insert(rpm); + self.avaliable.insert(cusa.clone(), rpms); + } + } +} + pub fn cuvat_run(cli: &Cli) -> crate::Result<()> { // 只报告 cve 相关 if cli.cves { @@ -51,7 +105,8 @@ pub fn cuvat_run(cli: &Cli) -> crate::Result<()> { } fn list_cves(cli: &Cli) -> crate::Result<()> { - let avaliable = get_avaliable()?; + let reporter = _reporter()?; + let avaliable = reporter.get_avaliable(); let severity = Severity::from_str(&cli.severity)?; let mut _cves = HashSet::new(); cli.sources.iter().for_each(|id| { _cves.insert(id); }); @@ -60,7 +115,7 @@ fn list_cves(cli: &Cli) -> crate::Result<()> { let mut msg = String::new(); // 仅针对可用更新 - for (cusa, _) in &avaliable { + for (cusa, _) in avaliable { // 过滤 if cusa.severity() < &severity { continue; @@ -92,7 +147,8 @@ fn list_cves(cli: &Cli) -> crate::Result<()> { } fn list_sas(cli: &Cli) -> crate::Result<()> { - let avaliable = get_avaliable()?; + let reporter = _reporter()?; + let avaliable = reporter.get_avaliable(); let severity = Severity::from_str(&cli.severity)?; let mut _sas = HashSet::new(); cli.sources.iter().for_each(|id| { _sas.insert(id); }); @@ -101,7 +157,7 @@ fn list_sas(cli: &Cli) -> crate::Result<()> { let mut msg = String::new(); // 仅针对可用更新 - for (cusa, _) in &avaliable { + for (cusa, _) in avaliable { // 过滤 if cusa.severity() < &severity { continue; @@ -130,20 +186,28 @@ fn list_sas(cli: &Cli) -> crate::Result<()> { Ok(()) } +// 最为详尽的报告,包括当前系统中软件包所涉及到,已修复和可用但未修复 +// 的所有软件包的列表。 fn repoter(cli: &Cli) -> crate::Result<()> { + let reporter = _reporter()?; + let fixed = reporter.get_fixed(); + let avaliable = reporter.get_avaliable(); + let _ = fixed; + let _ = avaliable; println!("TODO..."); Ok(()) } fn summary(cli: &Cli) -> crate::Result<()> { - let avaliable = get_avaliable()?; + let reporter = _reporter()?; + let avaliable = reporter.get_avaliable(); let severity = Severity::from_str(&cli.severity)?; let mut total = 0; let mut res = vec![0; 5]; let mut lists = vec![vec![]; 5]; let mut msg = String::new(); - for (cusa, rpms) in &avaliable { + for (cusa, _) in avaliable { // 过滤 if cusa.severity() < &severity { continue; @@ -183,9 +247,8 @@ fn summary(cli: &Cli) -> crate::Result<()> { Ok(()) } -// 获取当前可用的更新,所有安全检查均基于此 -fn get_avaliable() -> crate::Result>> { - let mut avaliable: HashMap> = HashMap::new(); +fn _reporter() -> crate::Result { + let mut reporter = Reporter::new(); // 当前系统所有已安装的 rpm 包 let installed = get_installed_packages(); // installed 已被消费掉 @@ -211,34 +274,29 @@ fn get_avaliable() -> crate::Result>> { if update.arch() != pkg.arch().unwrap() { continue; } + let sainfo = sadb.db().get(update.sa()).unwrap(); // epoch 判断 match (update.epoch(), pkg.epoch()) { (Some(_), None) => { - _add_to_avaliable(&mut avaliable, update.sa(), update.clone()); + reporter.add_to_avaliable(&sainfo, update.clone()); + } + (None, Some(_)) => { + reporter.add_to_fixed(&sainfo, update.clone()); } - (None, Some(_)) => continue, _ => {} } // evr 对比 if rpmvercmp(&update.evr(), &pkg.evr()) > 0 { - _add_to_avaliable(&mut avaliable, update.sa(), update.clone()); + reporter.add_to_avaliable(&sainfo, update.clone()); + } else { + reporter.add_to_fixed(&sainfo, update.clone()); } } } } - Ok(avaliable) -} - -fn _add_to_avaliable(avaliable: &mut HashMap>, sa: &str, rpm: RpmInfo) { - let sainfo = sadb.db().get(sa).unwrap(); - if let Some(rpms) = avaliable.get_mut(sainfo) { - rpms.push(rpm); - } else { - let rpms = vec![rpm]; - avaliable.insert(sainfo.clone(), rpms); - } + Ok(reporter) } // 对比两个 rpm Package 的版本,返回最新的一个