Skip to main content

xensec_internal_tools/
config.rs

1// Copyright 2021 Citrix
2// SPDX-License-Identifier: MIT OR Apache-2.0
3// There is NO WARRANTY.
4
5pub use crate::prelude::*;
6
7#[derive(Debug,Clone,StructOpt)]
8pub struct CommonOpts {
9  /// default log level (verbosity)
10  #[structopt(long="log", short="L")]
11  pub log_level: Option<log::LevelFilter>,
12
13  /// skip `git-pull` and `git-fetch` operations
14  #[structopt(long)]
15  pub no_pull: bool,
16
17  /// force refresh from xsa.git and cvelist upstream, disregarding caches
18  #[structopt(long)]
19  pub refresh: bool,
20
21  /// Do not make any remote changes (local updates still done).
22  #[structopt(long)]
23  pub dry_run: bool,
24}
25
26#[derive(Debug,Clone)]
27pub struct Config {
28  pub co: CommonOpts,
29  pub done_cache:              String,
30  pub git_ssh_command:         Option<String>,
31  pub xsa_git:                 String,
32  pub cvelist_git:             String,
33  pub cvelist_remote_upstream: String,
34  pub cvelist_remote_xensec:   String,
35  pub cvelist_upstream:        upstream::forge::Config,
36  pub committer_name:          String,
37  pub committer_email:         String,
38}
39
40#[derive(Debug,Clone,Default)]
41#[derive(StructOpt)]
42#[derive(Deserialize)]
43#[derive(merge::Merge)]
44pub struct ConfigSpec {
45  /// sqlite3 db for cacheing work already done
46  #[structopt(long, name="DB.SQLITE3")]
47  pub done_cache: Option<String>,
48
49  /// path to xsa.git working tree
50  #[structopt(long, name="XSA.GIT")]
51  pub xsa_git: Option<String>,
52
53  /// path to cvelist.git tree (can be bare)
54  #[structopt(long, name="CVELIST.GIT")]
55  pub cvelist_git: Option<String>,
56
57  /// remote name for cvelist.git upstream
58  #[structopt(long, name="REMOTE")]
59  pub cvelist_remote_upstream: Option<String>,
60
61  /// remote name for cvelist.git upstream
62  // 'Non-unique argument name: REMOTE is already in use' wat
63  #[structopt(long, name="REMOTE(XENSEC)")]
64  pub cvelist_remote_xensec: Option<String>,
65
66  /// Path to cvelist upstream forge access token
67  #[structopt(long, name="TOKEN/FILE")]
68  pub cvelist_upstream_token: Option<PathBuf>,
69
70  /// Value to set for GIT_SSH_COMMAND environment variable
71  #[structopt(skip)]
72  pub git_ssh_command: Option<String>,
73
74  /// Name to put in git commits in the cvelist git history
75  #[structopt(skip)]
76  pub committer_name: Option<String>,
77
78  /// Email address to put in git commits in the cvelist git history
79  #[structopt(skip)]
80  pub committer_email: Option<String>,
81
82  /// Upstream forge details
83  #[serde(default)]
84  #[structopt(skip)]
85  #[merge(skip)]
86  pub cvelist_upstream: upstream::forge::Config,
87}
88
89impl CommonOpts {
90  #[throws(AE)]
91  pub fn log_init(&self) {
92    let mut log_builder = env_logger::Builder::from_env("XENCNA_LOG");
93    if let Some(filter) = self.log_level { log_builder.filter_level(filter); }
94    log_builder.init();
95  }
96}
97
98impl ConfigSpec {
99  #[throws(AE)]
100  pub fn resolve(self, co: &CommonOpts) -> Config {
101    let config::ConfigSpec {
102      xsa_git, done_cache, git_ssh_command,
103      cvelist_git, cvelist_remote_upstream, cvelist_remote_xensec,
104      cvelist_upstream_token, mut cvelist_upstream,
105      committer_name, committer_email,
106    } = self;
107
108    macro_rules! defstr { { $v:ident = $def:expr } => {
109      let $v = $v.unwrap_or($def .into());
110    } }
111
112    defstr!{ xsa_git                 = "../xsa"             }
113    defstr!{ done_cache              = "cache.sqlite3"      }
114    defstr!{ cvelist_git             = "../cvelist"         }
115    defstr!{ cvelist_remote_upstream = "origin"             }
116    defstr!{ cvelist_remote_xensec   = "xensec-github"      }
117    defstr!{ committer_name          = "Xen Project Security Team" }
118    defstr!{ committer_email         = "security@xenproject.org"   }
119
120    if let Some(path) = cvelist_upstream_token {
121      cvelist_upstream.token = Some(upstream::forge::TokenConfig::Path(path));
122    }
123    Upstream::config_resolve(&mut cvelist_upstream)?;
124
125    Config {
126      co: co.clone(),
127      xsa_git, done_cache, git_ssh_command,
128      cvelist_git, cvelist_remote_upstream, cvelist_remote_xensec,
129      cvelist_upstream,
130      committer_name, committer_email,
131    }
132  }
133}
134
135impl Config {
136  #[throws(AE)]
137  pub fn git_command(&self) -> Command { Command::new("git") }
138}
139
140pub struct Ctx {
141  pub cfg: Arc<Config>,
142  pub xsas: xsagit::Repo,
143  pub cvelist: cvelist::Local,
144  pub cache: cache::Cache,
145  pub upstream: Upstream,
146}
147
148impl Ctx {
149  #[throws(AE)]
150  pub fn new(cfg: Config) -> Self {
151    let cfg = Arc::new(cfg);
152    let mut cache = cache::Cache::new(&cfg)?;
153    let xsas = xsagit::Repo::new(&cfg, &mut cache)?;
154    let cvelist = cvelist::Local::new(&cfg, &mut cache)?;
155    let upstream = Upstream::new(&cfg, &cvelist)?;
156    // xxx pull xsas, cves
157    Ctx { cfg, xsas, cache, cvelist, upstream }
158  }
159}