Skip to content

Commit

Permalink
fix: Paul's comments and follow-up discussion
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Fossati <[email protected]>
  • Loading branch information
thomas-fossati committed Sep 26, 2024
1 parent 5f34516 commit 8c8e917
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 35 deletions.
1 change: 1 addition & 0 deletions rust-keybroker/keybroker-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ ear = { git = "https://github.com/veraison/rust-ear.git" }
regorus = "0.2.5"
serde_json = "1.0.128"
anyhow = "1.0.89"
phf = "0.11.2"
44 changes: 44 additions & 0 deletions rust-keybroker/keybroker-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Reference Values

## Arm CCA

The Arm CCA appraisal policy requires the user to provide one or more RIM values corresponding to known and trusted Realm workloads.

The reference values must be provided in a JSON file that conforms to the following CDDL grammar:

```cddl
start = {
"reference-values": [ + b64-rim ]
}
b64-rim = text .b64c rim
rim = b
```

Note that the RIM values are Base64-encoded and that there must be at least one.

### Example

The following contains reference values for three trusted workloads:

```json
{
"reference-values": [
"MRMUq3NiA1DPdYg0rlxl2ejC3H/r5ufZZUu+hk4wDUk=",
"q3N/r5ufZZUu+iAg0rlxl2ejC3HMRMUhk4wDUk1DPdY=",
"UvZTSVUJ6IZtdtK0GEa5nueYxDcEJDa2vNHYL6RhQbs="
]
}
```

### Mock mode

In "mock" mode, the keybroker server must be started using the following command line:

```sh
keybroker-server \
--mock-challenge \
--verbose \
--reference-values <(echo '{ "reference-values": [ "MRMUq3NiA1DPdYg0rlxl2ejC3H/r5ufZZUu+hk4wDUk=" ] }')
```
4 changes: 4 additions & 0 deletions rust-keybroker/keybroker-server/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ pub enum VerificationErrorKind {
/// It was not possible to find the challenge-response newSession endpoint
#[error("No newChallengeResponseSession endpoint was found on the Veraison server.")]
NoChallengeResponseEndpoint,

/// It was not possible to find an appraisal policy for the evidence type
#[error("No appraisal policy was found for the evidence type.")]
PolicyNotFound,
}

/// Errors happening within the key store.
Expand Down
14 changes: 4 additions & 10 deletions rust-keybroker/keybroker-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ async fn submit_evidence(

let verifier_base = data.args.verifier.clone();

let optional_policy = data.args.policy.clone();
let rims = data.args.rims.clone();
let reference_values = data.args.reference_values.clone();

// We are in an async context, but the verifier client is synchronous, so spawn
// it as a blocking task.
Expand All @@ -106,8 +105,7 @@ async fn submit_evidence(
content_type_str,
&challenge.challenge_value,
&evidence_bytes,
optional_policy,
&rims,
&reference_values,
)
});
let result = handle.await.unwrap();
Expand Down Expand Up @@ -174,13 +172,9 @@ struct Args {
#[arg(short, long, default_value_t = false)]
verbose: bool,

/// Rego file containing the appraisal policy for (EAR) attestation results
#[arg(long, default_value = None)]
policy: Option<String>,

/// File containing a JSON array with base64-encoded known-good RIM values
#[arg(long, default_value = "rims.json")]
rims: String,
#[arg(long, default_value = "reference-values.json")]
reference_values: String,
}

struct ServerState {
Expand Down
36 changes: 15 additions & 21 deletions rust-keybroker/keybroker-server/src/policy.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,28 @@
// Copyright 2024 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0

use crate::error::Result;
use phf::{phf_map, Map};
use regorus::{self, Value};

use crate::error::Result;
pub static MEDIATYPES_TO_POLICY: Map<&'static str, &'static str> = phf_map! {
r#"application/eat-collection; profile="http://arm.com/CCA-SSD/1.0.0""# => include_str!("arm-cca.rego"),
// Other, future mappings
};

// Evaluate an EAR claims-set against the appraisal policy and known-good RIM values
pub(crate) fn rego_eval(
custom_policy: Option<String>,
rims: &str,
ear_claims: &str,
) -> Result<Value> {
const POLICY: &str = include_str!("policy.rego");

pub(crate) fn rego_eval(policy: &str, reference_values: &str, ear_claims: &str) -> Result<Value> {
// Create engine.
let mut engine = regorus::Engine::new();

engine.set_rego_v1(true);
engine.set_strict_builtin_errors(false);

// Add the appraisal policy
match custom_policy {
None => {
engine.add_policy(String::from("policy.rego"), String::from(POLICY))?;
}
Some(file) => {
engine.add_policy_from_file(file)?;
}
}
engine.add_policy(String::from("policy.rego"), String::from(policy))?;

// Load the configured known good RIM values
engine.add_data(Value::from_json_file(rims)?)?;
engine.add_data(Value::from_json_file(reference_values)?)?;

// Set the EAR claims-set to be appraised
engine.set_input(Value::from_json_str(ear_claims)?);
Expand All @@ -47,19 +39,21 @@ mod tests {
#[test]
fn rego_eval_ear_default_policy_ok() {
let ear_claims = include_str!("../../../testdata/ear-claims-ok.json");
let rims = stringify_testdata_path("rims-matching.json");
let reference_values = stringify_testdata_path("rims-matching.json");

let results = rego_eval(None, &rims, ear_claims).expect("successful eval");
let results = rego_eval(include_str!("arm-cca.rego"), &reference_values, ear_claims)
.expect("successful eval");

assert_eq!(results.to_string(), "true");
}

#[test]
fn rego_eval_default_policy_unmatched_rim() {
let ear_claims = include_str!("../../../testdata/ear-claims-ok.json");
let rims = stringify_testdata_path("rims-not-matching.json");
let reference_values = stringify_testdata_path("rims-not-matching.json");

let results = rego_eval(None, &rims, ear_claims).expect("successful eval");
let results = rego_eval(include_str!("arm-cca.rego"), &reference_values, ear_claims)
.expect("successful eval");

assert_eq!(results.to_string(), "false");
}
Expand Down
11 changes: 7 additions & 4 deletions rust-keybroker/keybroker-server/src/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2024 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0

use crate::error::Result;
use crate::error::{Result, VerificationErrorKind};
use crate::policy;
use ear::{Algorithm, Ear};
use veraison_apiclient::*;
Expand All @@ -11,8 +11,7 @@ pub fn verify_with_veraison_instance(
media_type: &str,
challenge: &[u8],
evidence: &[u8],
policy: Option<String>,
rims: &str,
reference_values: &str,
) -> Result<bool> {
// Get the discovery URL from the base URL
let discovery = Discovery::from_base_url(String::from(verifier_base_url))?;
Expand Down Expand Up @@ -65,11 +64,15 @@ pub fn verify_with_veraison_instance(

let ear_claims = serde_json::to_string(&ear)?;

let policy = policy::MEDIATYPES_TO_POLICY
.get(media_type)
.ok_or(VerificationErrorKind::PolicyNotFound)?;

// Appraise the received EAR using the embedded policy (see ./policy.rego)
// unless a custom one has been provided on the command line. The default
// policy also wants to match the RIM value reported by the CCA token with
// the known-good RIM values supplied on the command line.
let results = policy::rego_eval(policy, rims, &ear_claims)?;
let results = policy::rego_eval(policy, reference_values, &ear_claims)?;

Ok(results.to_string() == "true")
}

0 comments on commit 8c8e917

Please sign in to comment.