Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use Rust standard logging. #16

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,94 @@ flowchart LR
RP -->|Evidence fa:fa-receipt| V[Veraison]
V -->|EAR fa:fa-check-square| RP
```

## Building

The `keybroker-demo` has 2 executables: `keybroker-server` and `keybroker-app`.
These are built with:

```console
$ cd rust-keybroker
$ cargo build
```

By default, the executables are in debug mode and located in directory
`target/debug/`.

## Running

The `keybroker-server` and `keybroker-app` can be controlled with command line
options. Use `-h` / `--help` to get their usage, e.g.:

```
$ target/debug/keybroker-server --help
A simple web service that can provide keys and secrets in exchange for verifiable attestation tokens.

Usage: keybroker-server [OPTIONS]

Options:
-a, --addr <ADDR>
The interface on which this server will listen (use 0.0.0.0 to listen on all interfaces) [default: 127.0.0.1]
-p, --port <PORT>
The port on which this server will listen [default: 8088]
-e, --endpoint <ENDPOINT>
The address at which this server can be reached to request a key or submit an evidence. It will be set by default to 'http://{addr}', but this value can be overridden with an FQDN for {addr} in order to use name resolution for example. The port number will be appended, so don't leave a trailing '/' to the FQDN
--verifier <VERIFIER>
The URL where the verifier can be reached [default: http://veraison.test.linaro.org:8080]
-m, --mock-challenge
Use the static CCA example token nonce instead of a randomly generated one
-v, --verbosity...
Increase verbosity
-q, --quiet
Silence all output
--reference-values <REFERENCE_VALUES>
File containing a JSON array with base64-encoded known-good RIM values [default: reference-values.json]
-h, --help
Print help
-V, --version
Print version
```

The simplest way to get started with `keybroker-server` and `keybroker-app` is
to run them locally in _mocking_ mode (i.e they make use of statically known
values).

In a terminal, start `keybroker-server` with:

```console
$ target/debug/keybroker-server -v -m --reference-values ../testdata/rims-matching.json
thomas-fossati marked this conversation as resolved.
Show resolved Hide resolved
INFO starting 11 workers
INFO Actix runtime found; starting in Actix runtime
INFO starting service: "actix-web-service-127.0.0.1:8088", workers: 11, listening on: 127.0.0.1:8088
```

In another terminal, launch `keybroker-app` with:

```console
$ target/debug/keybroker-app -v -m skywalker
INFO Requesting key named 'skywalker' from the keybroker server with URL http://127.0.0.1:8088/keys/v1/key/skywalker
INFO Submitting evidence to URL http://127.0.0.1:8088/keys/v1/evidence/1923965078
INFO Attestation success :-) ! The key returned from the keybroker is 'May the force be with you.'
```

`keybroker-app` is requesting the key named `skywalker` from `keybroker-server`.
As we are in _mocking_ mode with statically known challenges and evidences, the
attestation succeeds: `keyboker-app` receives the key `May the force be with
you.` from `keybroker-server`.

## Logging

`keybroker-server` and `keybroker-app` use Rust's `log` and `stderrlog` crates
for logging. the verbosity can be controlled from the command line with the `-q`
/ `--quiet` (to silence all messages) and `-v` / `--verbose` switches. Note the
`-v` / `--verbose` can be specified multiple times to increase verbosity.

The mapping that has been implemented in `keybroker-server` and `keybroker-app` is:

| Log level | Verbosity threshold | `keybroker-*` |
| --------- | ------------------- | -------------------------------------------------------- |
| Error | 0 | Enabled by default, unless invoked with `-q` / `--quiet` |
| Warning | 1 | Enabled by default, unless invoked with `-q` / `--quiet` |
| Info | 2 | Enabled with `-v` or `--verbose` |
| Debug | 3 | Enabled with `-vv` or `-v -v` or `--verbose --verbose` |
| Trace | 4 | Enabled with `-vvv` or `-v -v -v` or ... |
4 changes: 3 additions & 1 deletion rust-keybroker/keybroker-app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ categories = ["cryptography", "hardware-support"]

[dependencies]
keybroker-client = { path = "../keybroker-client" }
clap = { version = "=4.3.24", features = ["derive", "std"] }
clap = { version = "=4.3.24", features = ["derive", "std"] }
log = { version = "0.4.22", features = ["std", "serde"] }
stderrlog = "0.6.0"
22 changes: 16 additions & 6 deletions rust-keybroker/keybroker-app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ struct Args {
#[arg(short, long, default_value_t = false)]
mock_evidence: bool,

/// Set the application verbosity
/// Increase verbosity
#[arg(short, long, action = clap::ArgAction::Count)]
verbosity: u8,

/// Silence all output
#[arg(short, long, default_value_t = false)]
verbose: bool,
quiet: bool,

/// The key name to use
key_name: String,
Expand All @@ -29,7 +33,13 @@ struct Args {
fn main() {
let args = Args::parse();

let client = KeyBrokerClient::new(&args.endpoint, args.verbose);
stderrlog::new()
.quiet(args.quiet)
.verbosity(1 + usize::from(args.verbosity))
.init()
.unwrap();

let client = KeyBrokerClient::new(&args.endpoint);

let attestation_result = if args.mock_evidence {
client.get_key(&args.key_name, &CcaExampleToken {})
Expand All @@ -43,16 +53,16 @@ fn main() {
let code = match attestation_result {
Ok(key) => {
let plainstring_key = String::from_utf8(key).unwrap();
println!("Attestation success :-) ! The key returned from the keybroker is '{plainstring_key}'");
log::info!("Attestation success :-) ! The key returned from the keybroker is '{plainstring_key}'");
0
}

Err(error) => {
if let KeybrokerError::AttestationFailure(reason, details) = error {
println!("Attestation failure :-( ! {reason}: {details}");
log::info!("Attestation failure :-( ! {reason}: {details}");
1
} else {
eprintln!("The key request failed with: {error:?}");
log::error!("The key request failed with: {error:?}");
2
}
}
Expand Down
4 changes: 3 additions & 1 deletion rust-keybroker/keybroker-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ categories = ["cryptography", "hardware-support"]
[dependencies]
keybroker-common = { path = "../keybroker-common" }
base64 = "0.22.1"
log = { version = "0.4.22", features = ["std", "serde"] }
rand = "0.8.5"
reqwest = { version = "0.12.5", features = ["json", "rustls-tls", "blocking"] }
rsa = "0.9.6"
stderrlog = "0.6.0"
thiserror = "1.0"
tsm_report = { git = "https://github.com/veracruz-project/cca-utils-rs.git", rev = "cb88b76da722f2991365b159e3d575249dfbbe7d"}
tsm_report = { git = "https://github.com/veracruz-project/cca-utils-rs.git", rev = "cb88b76da722f2991365b159e3d575249dfbbe7d"}
34 changes: 10 additions & 24 deletions rust-keybroker/keybroker-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::error::RuntimeErrorKind;
/// The trait that must be implemented so a KeybrokerClient can retrieve the evidence it has
/// to submit to the Keybroker server.
pub trait EvidenceProvider {
fn get_evidence(&self, challenge: &str, verbose: bool) -> Result<Vec<u8>>;
fn get_evidence(&self, challenge: &str) -> Result<Vec<u8>>;
}

/// The CCA example token.
Expand Down Expand Up @@ -164,7 +164,7 @@ const CCA_EXAMPLE_TOKEN: &[u8] = &[
pub struct CcaExampleToken {}

impl EvidenceProvider for CcaExampleToken {
fn get_evidence(&self, _challenge: &str, _verbose: bool) -> Result<Vec<u8>> {
fn get_evidence(&self, _challenge: &str) -> Result<Vec<u8>> {
Ok(CCA_EXAMPLE_TOKEN.to_vec())
}
}
Expand All @@ -177,13 +177,11 @@ impl EvidenceProvider for CcaExampleToken {
pub struct TsmAttestationReport {}

impl EvidenceProvider for TsmAttestationReport {
fn get_evidence(&self, challenge: &str, verbose: bool) -> Result<Vec<u8>> {
fn get_evidence(&self, challenge: &str) -> Result<Vec<u8>> {
match TsmReportPath::new(TsmReportProvider::Cca) {
Ok(tsm_report_path) => match URL_SAFE_NO_PAD.decode(challenge) {
Ok(challenge) => {
if verbose {
println!("Challenge ({} bytes) = {:02x?}", challenge.len(), challenge);
}
log::info!("Challenge ({} bytes) = {:02x?}", challenge.len(), challenge);
if challenge.len() != 64 {
return Err(KeybrokerError::RuntimeError(
RuntimeErrorKind::ChallengeLength(64, challenge.len()),
Expand Down Expand Up @@ -225,22 +223,14 @@ pub struct KeyBrokerClient {

/// The keybroker URL base address.
keybroker_url_base: String,

/// The session verbosity.
///
/// The verbose flag serves 2 purposes: help the developer when diagnosing some
/// issue, but also the new comer to the code base when understanding the overall
/// flow is intended.
verbose: bool,
}

impl KeyBrokerClient {
/// Create a session to the keybroker server located at addr:port.
pub fn new(endpoint: &str, verbose: bool) -> KeyBrokerClient {
pub fn new(endpoint: &str) -> KeyBrokerClient {
KeyBrokerClient {
client: reqwest::blocking::Client::new(),
keybroker_url_base: endpoint.to_string(),
verbose,
}
}

Expand Down Expand Up @@ -269,11 +259,9 @@ impl KeyBrokerClient {
// Construct the URL to request the key.
let key_request_url = format!("{}/keys/v1/key/{}", self.keybroker_url_base, key_name);

if self.verbose {
println!(
"Requesting key named '{key_name}' from the keybroker server with URL {key_request_url}"
);
}
log::info!(
"Requesting key named '{key_name}' from the keybroker server with URL {key_request_url}"
);

// Make the first API call to request the key.
match self.client.post(&key_request_url).json(&key_request).send() {
Expand Down Expand Up @@ -318,9 +306,7 @@ impl KeyBrokerClient {
evidence_submission_url: &str,
evidence: &[u8],
) -> Result<Vec<u8>> {
if self.verbose {
println!("Submitting evidence to URL {evidence_submission_url}")
}
log::info!("Submitting evidence to URL {evidence_submission_url}");

// Make the second API call to submit the evidence.
match self
Expand Down Expand Up @@ -411,7 +397,7 @@ impl KeyBrokerClient {
};

// Produce the evidence.
let evidence = match evidence_provider.get_evidence(&data.challenge, self.verbose) {
let evidence = match evidence_provider.get_evidence(&data.challenge) {
Ok(evidence) => evidence,
Err(error) => {
// TODO: we may want to notify the keybroker server that something went wrong on our side and that it
Expand Down
2 changes: 2 additions & 0 deletions rust-keybroker/keybroker-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ regorus = "0.2.5"
serde_json = "1.0.128"
anyhow = "1.0.89"
phf = "0.11.2"
log = { version = "0.4.22", features = ["std", "serde"] }
stderrlog = "0.6.0"
22 changes: 10 additions & 12 deletions rust-keybroker/keybroker-server/src/challenge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ pub struct Challenge {
pub struct Challenger {
challenge_table: HashMap<u32, Challenge>,
rng: StdRng,
pub verbose: bool,
}

// This is the challenge value from from https://git.trustedfirmware.org/TF-M/tf-m-tools/+/refs/heads/main/iat-verifier/tests/data/cca_example_token.cbor
Expand All @@ -63,7 +62,6 @@ impl Challenger {
Challenger {
challenge_table: HashMap::new(),
rng: StdRng::from_entropy(),
verbose: false,
}
}

Expand Down Expand Up @@ -101,16 +99,16 @@ impl Challenger {

self.challenge_table.insert(challenge_id, challenge.clone());

if self.verbose {
println!("Created challenge:");
println!(" - challenge_id: {}", challenge_id);
println!(" - key_id: {}", challenge.key_id);
println!(
" - challenge value ({} bytes): {:02x?}",
challenge.challenge_value.len(),
challenge.challenge_value
);
}
log::info!(
"Created challenge:\n\
- challenge_id: {}\n\
- key_id: {}\n\
- challenge value ({} bytes): {:02x?}",
challenge_id,
challenge.key_id,
challenge.challenge_value.len(),
challenge.challenge_value
);

challenge
}
Expand Down
21 changes: 14 additions & 7 deletions rust-keybroker/keybroker-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ async fn request_key(
data.endpoint, challenge.challenge_id
);

if data.args.verbose {
println!("Created attestation challenge at {}", location);
}
log::info!("Created attestation challenge at {}", location);

HttpResponse::Created()
.append_header((http::header::LOCATION, location))
Expand Down Expand Up @@ -168,9 +166,13 @@ struct Args {
#[arg(short, long, default_value_t = false)]
mock_challenge: bool,

/// Set the server verbosity
/// Increase verbosity
#[arg(short, long, action = clap::ArgAction::Count)]
verbosity: u8,

/// Silence all output
#[arg(short, long, default_value_t = false)]
verbose: bool,
quiet: bool,

/// File containing a JSON array with base64-encoded known-good RIM values
#[arg(long, default_value = "reference-values.json")]
Expand All @@ -188,9 +190,14 @@ struct ServerState {
async fn main() -> std::io::Result<()> {
let args = Args::parse();

stderrlog::new()
.quiet(args.quiet)
.verbosity(1 + usize::from(args.verbosity))
.init()
.unwrap();

let mut keystore = KeyStore::new();
let mut challenger = Challenger::new();
challenger.verbose = args.verbose;
let challenger = Challenger::new();

// TODO: Just storing one hard-coded item in the store. Would be better to read from an input file.
keystore.store_key(
Expand Down