Skip to content

Commit cc637c2

Browse files
authored
Initial proof of concept of a constellation-based verification service (#62)
* Initial proof of concept of a constellation-based verification service * Require origin when requesting verification.
1 parent 11a6c0d commit cc637c2

File tree

13 files changed

+489
-1
lines changed

13 files changed

+489
-1
lines changed

Cargo.lock

Lines changed: 166 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
members = [
33
"rust/usuba",
44
"rust/usuba-compat",
5-
"rust/usuba-bundle"
5+
"rust/usuba-bundle",
6+
"rust/verification-svc"
67
]
78

89
# See: https://github.com/rust-lang/rust/issues/90148#issuecomment-949194352
@@ -14,6 +15,7 @@ async-trait = { version = "0.1" }
1415
axum = { version = "0.7" }
1516
blake3 = { version = "1.5" }
1617
bytes = { version = "1" }
18+
clap = { version = "4.5" }
1719
deno_emit = { version = "0.42" }
1820
deno_graph = { version = "0.78" }
1921
http = { version = "1.1" }

rust/verification-svc/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "verification-svc"
3+
description = "A local service that can verify a Constellation cluster"
4+
version = "0.1.0"
5+
edition = "2021"
6+
7+
[dependencies]
8+
anyhow = { workspace = true }
9+
async-trait = { workspace = true }
10+
axum = { workspace = true }
11+
clap = { workspace = true, features = ["derive"] }
12+
serde = { workspace = true, features = ["derive"] }
13+
serde_json = { workspace = true }
14+
yaml-rust2 = { version = "0.8.1" }
15+
tempfile = { workspace = true }
16+
thiserror = { workspace = true }
17+
tokio = { workspace = true, features = ["rt-multi-thread", "process", "fs"] }
18+
tower-http = { workspace = true, features = ["cors"] }
19+
tracing = { workspace = true }
20+
tracing-subscriber = { workspace = true }
21+
url = { workspace = true }

rust/verification-svc/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# verification-svc
2+
3+
Initial prototype exposing `constellation verify` to a web service to report
4+
cluster verification to other properties. This is a part of evaluating Constellation and how to expose external verification of a cluster, will most likely be significantly reworked, and should *not* be trusted as anything beyond a demo.
5+
6+
## Usage
7+
8+
Run providing a path to a directory containing `constellation-state.yaml` and `constellation-conf.yaml`, ensuring `constellation` is installed and configured:
9+
10+
```sh
11+
$ verification-svc /path/to/constellation_dir
12+
```
13+
14+
```sh
15+
$ curl -H "Content-Type: application/json" -d '{"origin":"50.0.0.20"}' http://0.0.0.0:30125/api/v0/verify
16+
{"success":true}
17+
```

rust/verification-svc/src/cli.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use clap::Parser;
2+
use std::path::PathBuf;
3+
4+
#[derive(Parser)]
5+
#[command(version, about, long_about = None)]
6+
pub struct Cli {
7+
/// The path to the directory containing
8+
/// `constellation-conf.yaml` and `constellation-state.yaml`
9+
pub config_dir: PathBuf,
10+
11+
/// Port to listen on
12+
#[arg(short, long, default_value_t = 30125)]
13+
pub port: u16,
14+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use anyhow::{anyhow, Result};
2+
use std::{
3+
fs,
4+
path::{Path, PathBuf},
5+
process::Command,
6+
};
7+
use yaml_rust2::YamlLoader;
8+
9+
fn check_path_exists(path: &Path) -> Result<()> {
10+
match path.exists() {
11+
true => Ok(()),
12+
false => Err(anyhow!("{} could not be found.", path.to_string_lossy())),
13+
}
14+
}
15+
16+
/// Represents stored measurements for a cluster by origin.
17+
#[derive(Clone)]
18+
pub struct ClusterMeasurements {
19+
measurements_dir: PathBuf,
20+
origin: String,
21+
}
22+
23+
impl ClusterMeasurements {
24+
pub fn measurements_dir(&self) -> &Path {
25+
&self.measurements_dir
26+
}
27+
28+
pub fn origin(&self) -> &str {
29+
&self.origin
30+
}
31+
32+
/// Verify cluster against stored measurements.
33+
pub fn verify(&self) -> Result<bool> {
34+
//pub fn verify(cluster_url: &Url, cluster_id: &str) -> Result<bool> {
35+
let output = Command::new("constellation")
36+
.current_dir(&self.measurements_dir)
37+
.arg("verify")
38+
//.arg("-e")
39+
//.arg(cluster_url.as_str())
40+
//.arg("--cluster-id")
41+
//.arg(cluster_id)
42+
.output()?;
43+
Ok(output.status.success())
44+
}
45+
}
46+
47+
impl TryFrom<&Path> for ClusterMeasurements {
48+
type Error = anyhow::Error;
49+
fn try_from(measurements_dir: &Path) -> std::result::Result<Self, Self::Error> {
50+
let state_path = measurements_dir.join("constellation-state.yaml");
51+
let conf_path = measurements_dir.join("constellation-conf.yaml");
52+
check_path_exists(&state_path)?;
53+
check_path_exists(&conf_path)?;
54+
55+
let state_yaml = YamlLoader::load_from_str(&fs::read_to_string(&state_path)?)?;
56+
let endpoint_yaml = &state_yaml[0]["infrastructure"]["clusterEndpoint"];
57+
if endpoint_yaml.is_badvalue() {
58+
return Err(anyhow!(
59+
"constellation-conf.yaml does not contain cluster endpoint."
60+
));
61+
}
62+
let origin = endpoint_yaml
63+
.as_str()
64+
.ok_or_else(|| anyhow!("constellation-conf.yaml cluster endpoint is not a string."))?;
65+
66+
Ok(ClusterMeasurements {
67+
origin: origin.to_owned(),
68+
measurements_dir: measurements_dir.to_owned(),
69+
})
70+
}
71+
}

0 commit comments

Comments
 (0)