Skip to main content

krabka_audit/operator_keys/
error.rs

1//! The startup failures that a bad `[[operator_keys]]` entry raises.
2//!
3//! Every variant here stops the broker at boot. A trust set is all or nothing,
4//! so one unusable entry fails the load. It never shrinks the set that the
5//! later signature checks run against.
6
7use std::{io::Error, path::PathBuf};
8
9/// Failures that stop [`OperatorKeys::load`](crate::operator_keys::OperatorKeys::load),
10/// and with it the broker.
11///
12/// Every variant is a startup error. A key set that a broker cannot load is
13/// never downgraded to a smaller one: a signature checked against a partial
14/// trust set is a signature check that silently does nothing.
15#[derive(Debug, thiserror::Error)]
16#[non_exhaustive]
17pub enum OperatorKeyError {
18    /// A `key_id` or a `principal` is blank. Neither can be matched against a
19    /// signed record, so the entry could never authorize anything.
20    #[error("[[operator_keys]] entry {index} has a blank {field}")]
21    BlankField {
22        /// Zero-based position of the entry in the configured array.
23        index: usize,
24        /// Name of the blank field, `key_id` or `principal`.
25        field: &'static str,
26    },
27    /// The `public_key_path` could not be read.
28    #[error("operator key {key_id:?}: cannot read {}: {source}", path.display())]
29    Unreadable {
30        /// The entry's `key_id`.
31        key_id: String,
32        /// The path that could not be read.
33        path: PathBuf,
34        /// The underlying I/O failure.
35        #[source]
36        source: Error,
37    },
38    /// The file does not hold a raw Ed25519 public key.
39    #[error(
40        "operator key {key_id:?}: {} holds {found} bytes; a raw Ed25519 public key is 32 bytes",
41        path.display()
42    )]
43    Malformed {
44        /// The entry's `key_id`.
45        key_id: String,
46        /// The path that was read.
47        path: PathBuf,
48        /// How many bytes the file holds.
49        found: usize,
50    },
51    /// Two entries share a `key_id`. A signed record names one key, so a
52    /// repeated id makes the key it selects depend on the file order.
53    #[error("duplicate operator key_id {key_id:?}")]
54    DuplicateKeyId {
55        /// The repeated `key_id`.
56        key_id: String,
57    },
58    /// Two entries bind the same principal. The broker checks that a record's
59    /// claimed author is the principal bound to the signing key, and a
60    /// principal with two keys makes that check ambiguous.
61    #[error("operator keys {first:?} and {second:?} are both bound to principal {principal:?}")]
62    DuplicatePrincipal {
63        /// The repeated principal.
64        principal: String,
65        /// The `key_id` that claimed the principal first.
66        first: String,
67        /// The `key_id` that claimed it again.
68        second: String,
69    },
70}