Skip to content

Commit 0b23eb1

Browse files
authored
rust-query-crlite: log more relevant information by default (#353)
1 parent 642d676 commit 0b23eb1

File tree

3 files changed

+51
-32
lines changed

3 files changed

+51
-32
lines changed

containers/scripts/crlite-signoff.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ then
3434
exit 1;
3535
fi
3636

37-
if ! "${RUST_QUERY_CRLITE}" -vvv --db "${OUTPUT}" --update "${INSTANCE}" signoff "${crlite_verify_host_file_urls}"
37+
if ! "${RUST_QUERY_CRLITE}" -v --db "${OUTPUT}" --update "${INSTANCE}" signoff "${crlite_verify_host_file_urls}"
3838
then
3939
echo "Verification domains test failed"
4040
exit 1;

rust-query-crlite/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77
base64 = "0.21"
88
bincode = "1.3"
99
byteorder = "1.2.7"
10-
clap = { version = "3.2", features = ["derive"] }
10+
clap = { version = "4.5", features = ["derive"] }
1111
clubcard = "0.3"
1212
clubcard-crlite = "0.3"
1313
der-parser = "9.0"

rust-query-crlite/src/main.rs

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ struct CertRevRecordAttachment {
9898
fn update_intermediates(int_dir: &Path) -> Result<(), CRLiteDBError> {
9999
let intermediates_path = int_dir.join("crlite.intermediates");
100100

101-
info!("Fetching {}", ICA_LIST_URL);
101+
debug!("Fetching {}", ICA_LIST_URL);
102102
let intermediates_bytes = &reqwest::blocking::get(ICA_LIST_URL)
103103
.map_err(|_| CRLiteDBError::from("could not fetch CCADB report"))?
104104
.bytes()
@@ -120,7 +120,7 @@ fn update_db(
120120
base_url: &str,
121121
channel: &CRLiteFilterChannel,
122122
) -> Result<(), CRLiteDBError> {
123-
info!(
123+
debug!(
124124
"Fetching cert-revocations records from remote settings {}",
125125
base_url
126126
);
@@ -157,7 +157,7 @@ fn update_db(
157157
if (extension == Some("delta") || extension == Some("filter"))
158158
&& !expected_filenames.contains(&dir_entry.file_name())
159159
{
160-
info!("Removing {:?}", dir_entry.file_name());
160+
debug!("Removing {:?}", dir_entry.file_name());
161161
let _ = std::fs::remove_file(dir_entry_path);
162162
}
163163
}
@@ -169,13 +169,13 @@ fn update_db(
169169
if path.exists() {
170170
let digest = Sha256::digest(std::fs::read(&path)?);
171171
if expected_digest == digest.as_slice() {
172-
info!("Found existing copy of {}", filter.attachment.filename);
172+
debug!("Found existing copy of {}", filter.attachment.filename);
173173
continue;
174174
}
175175
}
176176

177177
let filter_url = format!("{}{}", attachment_url, filter.attachment.location);
178-
info!(
178+
debug!(
179179
"Fetching {} from {}",
180180
filter.attachment.filename, filter_url
181181
);
@@ -210,25 +210,35 @@ fn get_sct_ids_and_timestamps(cert: &X509Certificate) -> Vec<([u8; 32], u64)> {
210210
}
211211

212212
enum Filter {
213-
Clubcard(CRLiteClubcard),
213+
Clubcard((/* filename */ String, CRLiteClubcard)),
214214
}
215215

216216
impl Filter {
217-
fn from_bytes(bytes: &[u8]) -> Result<Self, CRLiteDBError> {
218-
if let Ok(clubcard) = CRLiteClubcard::from_bytes(bytes) {
219-
return Ok(Filter::Clubcard(clubcard));
217+
fn from_file(file: &PathBuf) -> Result<Self, CRLiteDBError> {
218+
let name = file
219+
.file_name()
220+
.and_then(std::ffi::OsStr::to_str)
221+
.unwrap_or_default();
222+
if let Ok(clubcard) = CRLiteClubcard::from_bytes(&std::fs::read(file)?) {
223+
return Ok(Filter::Clubcard((name.into(), clubcard)));
220224
}
221225
Err(CRLiteDBError::from("could not load filter"))
222226
}
223227

228+
fn name(&self) -> &str {
229+
match self {
230+
Filter::Clubcard((name, _)) => name,
231+
}
232+
}
233+
224234
fn has(
225235
&self,
226236
issuer_spki_hash: &[u8; 32],
227237
serial: &[u8],
228238
timestamps: &[([u8; 32], u64)],
229239
) -> Status {
230240
match self {
231-
Filter::Clubcard(clubcard) => {
241+
Filter::Clubcard((_, clubcard)) => {
232242
let crlite_key = clubcard_crlite::CRLiteKey::new(issuer_spki_hash, serial);
233243
match clubcard.contains(&crlite_key, timestamps.iter().map(|(x, y)| (x, *y))) {
234244
CRLiteStatus::Good => Status::Good,
@@ -259,7 +269,7 @@ impl CRLiteDB {
259269
.extension()
260270
.and_then(|os_str| os_str.to_str());
261271
if extension == Some("delta") || extension == Some("filter") {
262-
filters.push(Filter::from_bytes(&std::fs::read(&dir_entry_path)?)?);
272+
filters.push(Filter::from_file(&dir_entry_path)?);
263273
if let Ok(metadata) = std::fs::metadata(&dir_entry_path) {
264274
if let Ok(modified) = metadata.modified() {
265275
most_recent_time = Some(
@@ -271,6 +281,10 @@ impl CRLiteDB {
271281
}
272282
}
273283

284+
// Sort the filters by name so that (when trace level output is enabled)
285+
// individual results are sorted chronologically.
286+
filters.sort_by_key(|x| x.name().to_string());
287+
274288
if filters.is_empty() {
275289
error!("No CRLite filters found. All results will indicate NotCovered. Use --update to download filters.");
276290
} else if let Some(time) = most_recent_time {
@@ -328,11 +342,13 @@ impl CRLiteDB {
328342

329343
let issuer_spki_hash = Sha256::digest(issuer_spki);
330344
for filter in &self.filters {
331-
match filter.has(
345+
let one_filter_result = filter.has(
332346
issuer_spki_hash.as_ref(),
333347
serial,
334348
&get_sct_ids_and_timestamps(cert),
335-
) {
349+
);
350+
trace!("{}: {:?}", filter.name(), one_filter_result);
351+
match one_filter_result {
336352
Status::Revoked => return Status::Revoked,
337353
Status::Good => maybe_good = true,
338354
Status::NotEnrolled => covered = true,
@@ -516,11 +532,11 @@ fn query_https_addr(
516532
debug!("Loaded certificate from {}", host);
517533
let status = db.query(&cert);
518534
match status {
519-
Status::Expired => warn!("{} {:?}", host, status),
535+
Status::Expired => info!("{} {:?}", host, status),
520536
Status::Good => info!("{} {:?}", host, status),
521-
Status::NotCovered => warn!("{} {:?}", host, status),
522-
Status::NotEnrolled => warn!("{} {:?}", host, status),
523-
Status::Revoked => error!("{} {:?}", host, status),
537+
Status::NotCovered => info!("{} {:?}", host, status),
538+
Status::NotEnrolled => info!("{} {:?}", host, status),
539+
Status::Revoked => info!("{} {:?}", host, status),
524540
}
525541
match status {
526542
Status::Revoked => Ok(CmdResult::SomeRevoked),
@@ -558,9 +574,9 @@ fn query_certs(db: &CRLiteDB, files: &[PathBuf]) -> Result<CmdResult, CRLiteDBEr
558574
match query_cert_pem_or_der_bytes(db, &input) {
559575
Ok(Status::Revoked) => {
560576
found_revoked_certs = true;
561-
error!("{} {:?}", file.display(), Status::Revoked);
577+
info!("{} {:?}", file.display(), Status::Revoked);
562578
}
563-
Ok(status) => warn!("{} {:?}", file.display(), status),
579+
Ok(status) => info!("{} {:?}", file.display(), status),
564580
Err(e) => {
565581
warn!("Query error: {:?}", e);
566582
continue;
@@ -581,11 +597,11 @@ fn query_crtsh_id(db: &CRLiteDB, id: &str) -> Result<CmdResult, CRLiteDBError> {
581597

582598
match query_cert_pem_or_der_bytes(db, cert_bytes) {
583599
Ok(Status::Revoked) => {
584-
error!("{} {:?}", id, Status::Revoked);
600+
info!("{} {:?}", id, Status::Revoked);
585601
Ok(CmdResult::SomeRevoked)
586602
}
587603
Ok(status) => {
588-
warn!("{} {:?}", id, status);
604+
info!("{} {:?}", id, status);
589605
Ok(CmdResult::NoneRevoked)
590606
}
591607
Err(e) => {
@@ -604,20 +620,24 @@ fn query_crtsh_id(db: &CRLiteDB, id: &str) -> Result<CmdResult, CRLiteDBError> {
604620
#[derive(Parser)]
605621
struct Cli {
606622
/// Download a new CRLite filter and associated metadata from Firefox Remote Settings.
607-
#[clap(long, arg_enum)]
623+
#[clap(long, value_enum)]
608624
update: Option<RemoteSettingsInstance>,
609625

610626
/// CRLite filter channel
611627
#[clap(long, value_enum, default_value = "default")]
612628
channel: CRLiteFilterChannel,
613629

614630
/// CRLite directory e.g. <firefox profile>/security_state/.
615-
#[clap(short, long, parse(from_os_str), default_value = "./crlite_db/")]
631+
#[clap(short, long, default_value = "./crlite_db/")]
616632
db: PathBuf,
617633

618-
/// Verbosity. -v => warning, -vv => info, -vvv => debug.
619-
#[clap(short = 'v', parse(from_occurrences))]
620-
verbose: usize,
634+
/// Silence all output.
635+
#[clap(short = 'q')]
636+
quiet: bool,
637+
638+
/// Include debug output in logs.
639+
#[clap(short = 'v', action = clap::ArgAction::Count)]
640+
verbose: u8,
621641

622642
#[clap(subcommand)]
623643
command: Subcommand,
@@ -626,14 +646,12 @@ struct Cli {
626646
#[derive(clap::ValueEnum, Copy, Clone, Default, Deserialize, PartialEq)]
627647
#[serde(rename_all = "lowercase")]
628648
enum CRLiteFilterChannel {
629-
#[serde(rename = "experimental+deltas")]
630-
ExperimentalDeltas,
631649
#[default]
632650
Default,
633651
Compat,
634652
}
635653

636-
#[derive(Clone, clap::ArgEnum)]
654+
#[derive(clap::ValueEnum, Clone)]
637655
enum RemoteSettingsInstance {
638656
Prod,
639657
Stage,
@@ -664,7 +682,8 @@ fn main() {
664682

665683
stderrlog::new()
666684
.module(module_path!())
667-
.verbosity(args.verbose)
685+
.quiet(args.quiet)
686+
.verbosity(std::cmp::min(4, (args.verbose + 2).into()))
668687
.init()
669688
.unwrap();
670689

0 commit comments

Comments
 (0)