Skip to content

Commit 3876511

Browse files
authored
Merge pull request #70 from faasm/bugfix-snp-ci
[ci] Fix SNP Bare Metal Test
2 parents 09ecd42 + 2a90d57 commit 3876511

File tree

13 files changed

+657
-284
lines changed

13 files changed

+657
-284
lines changed

.github/workflows/snp.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ jobs:
4040
BRANCH=${GITHUB_REF_NAME}
4141
fi
4242
./scripts/accli_wrapper.sh dev cvm run -- \
43-
"git fetch origin $BRANCH && git checkout $BRANCH && git reset --hard origin/$BRANCH"
43+
"git fetch origin $BRANCH && git checkout $BRANCH && git reset --hard origin/$BRANCH && ./scripts/apt.sh"
4444
4545
# Build SNP applications and embed the attestation service's certificate.
4646
- name: "Build SNP applications"
47-
run: ./scripts/accli_wrapper.sh applications build --clean --as-cert-dir ./certs/cert.pem --in-cvm
47+
run: ./scripts/accli_wrapper.sh applications build --clean --as-cert-dir ./certs --in-cvm
4848

4949
- name: "Run supported SNP applications"
5050
run: |
5151
# First get the external IP so that we can reach the attestation-service from the cVM.
52-
AS_URL=$(./scripts/accli_wrapper.sh attestation-service health --url "https://0.0.0.0:8443" --cert-path ./certs/cert.pem 2>&1 \
52+
AS_URL=$(./scripts/accli_wrapper.sh attestation-service health --url "https://0.0.0.0:8443" --cert-dir ./certs 2>&1 \
5353
| grep "attestation service is healthy and reachable on:" | awk '{print $NF}')
5454
echo "Got AS URL: ${AS_URL}"
5555
./scripts/accli_wrapper.sh applications run function hello-snp --backend cvm -- --as-url ${AS_URL} --as-cert-path ./certs/cert.pem

accli/src/tasks/applications.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use clap::ValueEnum;
77
use log::error;
88
use std::{
99
fmt::{Display, Formatter, Result as FmtResult},
10+
fs,
1011
path::{Path, PathBuf},
1112
str::FromStr,
1213
};
@@ -163,7 +164,17 @@ impl Applications {
163164
if let Some(host_cert_dir) = as_cert_dir {
164165
let guest_cert_dir =
165166
host_cert_dir_to_target_path(&host_cert_dir, &ApplicationBackend::Cvm)?;
166-
scp_files.push((host_cert_dir, guest_cert_dir.clone()));
167+
for entry in fs::read_dir(&host_cert_dir)? {
168+
let entry = entry?;
169+
let file_type = entry.file_type()?;
170+
if !file_type.is_file() {
171+
anyhow::bail!(
172+
"certificate directory may only contain files (found: {})",
173+
entry.path().display()
174+
);
175+
}
176+
scp_files.push((entry.path(), guest_cert_dir.join(entry.file_name())));
177+
}
167178

168179
cmd.push("--as-cert-dir".to_string());
169180
cmd.push(guest_cert_dir.display().to_string());

accli/src/tasks/attestation_service.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::env::Env;
22
use anyhow::{Context, Result};
3-
use log::info;
3+
use log::{info, warn};
44
use nix::{
55
sys::signal::{Signal, kill},
66
unistd::Pid,
@@ -154,7 +154,15 @@ impl AttestationService {
154154
let path = entry.path();
155155
if path.is_file() && path.extension().is_some_and(|s| s == "pem") {
156156
let cert = fs::read(&path)?;
157-
let cert = reqwest::Certificate::from_pem(&cert)?;
157+
let cert = match reqwest::Certificate::from_pem(&cert) {
158+
Ok(cert) => cert,
159+
Err(e) => {
160+
warn!(
161+
"health(): error parsing certificate PEM file (path={path:?}, error={e:?})"
162+
);
163+
continue;
164+
}
165+
};
158166
client_builder = client_builder.add_root_certificate(cert);
159167
}
160168
}

accli/src/tasks/experiments/plot.rs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
use anyhow::Result;
1212
use csv::ReaderBuilder;
1313
use log::{debug, error, info};
14-
use plotters::prelude::*;
14+
use plotters::{element::DashedPathElement, prelude::*};
1515
use serde::Deserialize;
1616
use std::{
1717
collections::BTreeMap,
@@ -1378,7 +1378,7 @@ fn plot_escrow_cost() {
13781378
))
13791379
.unwrap();
13801380
root.draw(&Text::new(
1381-
"# of users ",
1381+
"# of tenants",
13821382
(120, 280),
13831383
("sans-serif", FONT_SIZE).into_font().color(&BLACK),
13841384
))
@@ -1564,6 +1564,7 @@ fn plot_policy_decryption(data_files: &Vec<PathBuf>) -> Result<()> {
15641564
enum PolicyShape {
15651565
Conjunction,
15661566
Disjunction,
1567+
DisjunctionSingleAuthority,
15671568
}
15681569

15691570
impl PolicyShape {
@@ -1572,6 +1573,7 @@ fn plot_policy_decryption(data_files: &Vec<PathBuf>) -> Result<()> {
15721573
match stem {
15731574
"conjunction" => Some(Self::Conjunction),
15741575
"disjunction" => Some(Self::Disjunction),
1576+
"disjunction-single-authority" => Some(Self::DisjunctionSingleAuthority),
15751577
_ => None,
15761578
}
15771579
}
@@ -1580,15 +1582,22 @@ fn plot_policy_decryption(data_files: &Vec<PathBuf>) -> Result<()> {
15801582
match self {
15811583
Self::Conjunction => "all conjunction policy",
15821584
Self::Disjunction => "all disjunction policy",
1585+
Self::DisjunctionSingleAuthority => "all disjunction policy (single authority)",
15831586
}
15841587
}
15851588

15861589
fn color(&self) -> Result<RGBColor> {
15871590
match self {
15881591
Self::Conjunction => get_color_from_label("dark-red"),
1589-
Self::Disjunction => get_color_from_label("dark-blue"),
1592+
Self::Disjunction | Self::DisjunctionSingleAuthority => {
1593+
get_color_from_label("dark-blue")
1594+
}
15901595
}
15911596
}
1597+
1598+
fn is_dashed(&self) -> bool {
1599+
matches!(self, Self::DisjunctionSingleAuthority)
1600+
}
15921601
}
15931602

15941603
let mut agg: BTreeMap<PolicyShape, BTreeMap<usize, (f64, f64, u32)>> = BTreeMap::new();
@@ -1695,23 +1704,31 @@ fn plot_policy_decryption(data_files: &Vec<PathBuf>) -> Result<()> {
16951704
))?;
16961705

16971706
for (shape, rows) in data {
1698-
let series = rows.iter().map(|(x, vals)| (*x as i32, selector(vals)));
1707+
let series: Vec<(i32, f64)> = rows
1708+
.iter()
1709+
.map(|(x, vals)| (*x as i32, selector(vals)))
1710+
.collect();
16991711

1700-
// Draw line.
1701-
chart.draw_series(LineSeries::new(
1702-
series,
1703-
shape.color()?.stroke_width(STROKE_WIDTH),
1704-
))?;
1712+
if shape.is_dashed() {
1713+
chart.draw_series(std::iter::once(DashedPathElement::new(
1714+
series.clone().into_iter(),
1715+
5,
1716+
5,
1717+
shape.color()?.stroke_width(STROKE_WIDTH),
1718+
)))?;
1719+
} else {
1720+
chart.draw_series(LineSeries::new(
1721+
series.clone(),
1722+
shape.color()?.stroke_width(STROKE_WIDTH),
1723+
))?;
1724+
}
17051725

1706-
// Draw points on line.
17071726
chart
1708-
.draw_series(rows.iter().map(|(x, vals)| {
1709-
Circle::new(
1710-
(*x as i32, selector(vals)),
1711-
5,
1712-
shape.color().unwrap().filled(),
1713-
)
1714-
}))
1727+
.draw_series(
1728+
series
1729+
.iter()
1730+
.map(|(x, y)| Circle::new((*x, *y), 5, shape.color().unwrap().filled())),
1731+
)
17151732
.unwrap();
17161733
}
17171734

@@ -1731,7 +1748,7 @@ fn plot_policy_decryption(data_files: &Vec<PathBuf>) -> Result<()> {
17311748
))
17321749
.unwrap();
17331750

1734-
// legend as color box + text.
1751+
// legend as colored box + text
17351752
let x_pos = 100;
17361753
let y_pos = 5;
17371754
let square_side = 20;

accli/src/tasks/experiments/profile.rs

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use clap::Args;
1212
use csv::Writer;
1313
use indicatif::{ProgressBar, ProgressStyle};
1414
use log::{error, info};
15+
use rand::{seq::SliceRandom, thread_rng};
1516
use std::{
1617
fs::{self, File},
1718
path::PathBuf,
@@ -48,6 +49,21 @@ impl PolicyShape {
4849
}
4950
}
5051

52+
#[derive(Clone, Copy)]
53+
enum AttributeFlavor {
54+
AllAuthorities,
55+
SingleAuthorityOnly,
56+
}
57+
58+
impl AttributeFlavor {
59+
fn file_suffix(&self) -> &'static str {
60+
match self {
61+
AttributeFlavor::AllAuthorities => "",
62+
AttributeFlavor::SingleAuthorityOnly => "-single-authority",
63+
}
64+
}
65+
}
66+
5167
#[derive(serde::Serialize)]
5268
struct Record {
5369
#[serde(rename = "NumAuthorities")]
@@ -64,12 +80,29 @@ fn build_authorities(num: usize) -> Vec<String> {
6480
(0..num).map(|idx| format!("as{idx:02}")).collect()
6581
}
6682

67-
fn build_user_attributes(authorities: &[String]) -> Result<Vec<UserAttribute>> {
83+
fn build_user_attributes(
84+
authorities: &[String],
85+
flavor: AttributeFlavor,
86+
) -> Result<Vec<UserAttribute>> {
6887
let mut user_attrs = Vec::new();
69-
for auth in authorities {
70-
user_attrs.push(UserAttribute::parse(&format!("{auth}.wf:{WORKFLOW_ID}"))?);
71-
user_attrs.push(UserAttribute::parse(&format!("{auth}.node:{NODE_ID}"))?);
72-
}
88+
match flavor {
89+
AttributeFlavor::AllAuthorities => {
90+
for auth in authorities {
91+
user_attrs.push(UserAttribute::parse(&format!("{auth}.wf:{WORKFLOW_ID}"))?);
92+
user_attrs.push(UserAttribute::parse(&format!("{auth}.node:{NODE_ID}"))?);
93+
}
94+
}
95+
AttributeFlavor::SingleAuthorityOnly => {
96+
// Pick an attribute at random.
97+
let mut rng = thread_rng();
98+
if let Some(auth) = authorities.choose(&mut rng) {
99+
user_attrs.push(UserAttribute::parse(&format!("{auth}.wf:{WORKFLOW_ID}"))?);
100+
user_attrs.push(UserAttribute::parse(&format!("{auth}.node:{NODE_ID}"))?);
101+
} else {
102+
anyhow::bail!("cannot build user attributes without authorities");
103+
};
104+
}
105+
};
73106
Ok(user_attrs)
74107
}
75108

@@ -119,12 +152,40 @@ fn measure_single_run(
119152
}
120153

121154
fn run_shape(shape: PolicyShape, args: &ProfileRunArgs) -> Result<()> {
155+
// Skip unsupported combinations.
156+
if matches!(shape, PolicyShape::Conjunction) {
157+
return run_shape_with_flavor(shape, AttributeFlavor::AllAuthorities, args);
158+
}
159+
run_shape_with_flavor(shape, AttributeFlavor::AllAuthorities, args)?;
160+
run_shape_with_flavor(shape, AttributeFlavor::SingleAuthorityOnly, args)
161+
}
162+
163+
fn run_shape_with_flavor(
164+
shape: PolicyShape,
165+
flavor: AttributeFlavor,
166+
args: &ProfileRunArgs,
167+
) -> Result<()> {
168+
if matches!(
169+
(shape, flavor),
170+
(
171+
PolicyShape::Conjunction,
172+
AttributeFlavor::SingleAuthorityOnly
173+
)
174+
) {
175+
info!("Skipping single-authority flavour for conjunction policy");
176+
return Ok(());
177+
}
178+
122179
let data_dir = ensure_data_dir()?;
123180
let mut csv_path = data_dir;
124-
csv_path.push(format!("{}.csv", shape.file_stem()));
181+
csv_path.push(format!("{}{}.csv", shape.file_stem(), flavor.file_suffix()));
125182
let mut writer = Writer::from_writer(File::create(csv_path)?);
126183
let total_iters = (POLICY_SIZES.len() as u64) * (args.num_warmup_runs + args.num_runs) as u64;
127-
let pb = ProgressBar::new(total_iters).with_message(shape.file_stem());
184+
let pb = ProgressBar::new(total_iters).with_message(format!(
185+
"{}{}",
186+
shape.file_stem(),
187+
flavor.file_suffix()
188+
));
128189
pb.set_style(
129190
ProgressStyle::with_template("{msg} [{bar:40.cyan/blue}] {pos}/{len}")
130191
.unwrap()
@@ -133,7 +194,7 @@ fn run_shape(shape: PolicyShape, args: &ProfileRunArgs) -> Result<()> {
133194

134195
for &num_auth in POLICY_SIZES {
135196
let authorities = build_authorities(num_auth);
136-
let user_attrs = build_user_attributes(&authorities)?;
197+
let user_attrs = build_user_attributes(&authorities, flavor)?;
137198
let auths_ref: Vec<&str> = authorities.iter().map(|s| s.as_str()).collect();
138199

139200
let mut rng = StdRng::seed_from_u64(1337 + num_auth as u64);

experiments/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Accless Experiments
2+
3+
Figure 5:
4+
- 5.a: [Escrow Throughput-Latency](./escrow-xput/README.md) - FINISH ME
5+
- 5.a: [Escrow Cost](./escrow-cost/README.md) - FINISH ME
6+
Table 4: [Attribute Minting Latency Breakdown](./secret-release-breakdown/README.md)
7+
8+
List of experiment claims -> Experiment that validates them:
9+
C1. Accless is cheaper than centralized escrow -> E1
10+
C2. Accless has better throughput-latency than centralized escrow -> E1
11+
C3. Accless has better throughput-latency than single-authority CP-ABE -> E1
12+
FIXME: this is not true. what if we increase the size of the VM running the single-auth system?
13+
C4. The size of the policy does not affect decryption time.
14+
C5. The attribute minting protocol introduces negligible overhead compared to ??
15+
C6. The attribute minting protocol introduces negligible overhead compared to cold-start time.
16+
C7. Accless introduces negligible overhead in the end-to-end execution of workflows.
17+
18+
List of experiments:
19+
E1. Throughput-latency of different access control mechanisms.
20+
E2. Micro-benchmark of decryption time as we increase the number of attestation services. (also include encryption time and the corresponding CP-ABE operations like keygen) (needs I6)
21+
E3. Access control breakdown (time to "decrypt" payload)
22+
E4. Cold-start breakdown
23+
24+
Big implementation tasks:
25+
I1. Verify azure cVM reports -> Done
26+
I2. Actually implement the user-side encryption of data from template graph
27+
I3. Run SGX functions from accli
28+
I4. Embed accless checks in S3 library
29+
I5. Support running with multiple replicated attestation-services -> Done
30+
I6. Implement CP-ABE hybrid scheme.
31+
32+
Order:
33+
- Escrow-xput:
34+
- Use as opportunity to fix SNP HW mode
35+
- Use as opportunity to try to run SNP bare-metal stuff from `accli`.
36+
- Use as an opportunity to fix SNP in a para-virtualized VM
37+
- If we could get rid of the annoyint azguestattestaion crate that would be perfect, and vendor in the code.
38+
- Breakdown table:
39+
- Compile to native and cross-compile to WASM
40+
- Use as opportunity to fix SGX HW mode
41+
- Use as opportunity to try to run WASM functions through Faasm in the `accli`.
42+
- SNP breakdown could be run either para-virtualized or bare metal.
43+
- Cold start CDF:
44+
- Use as opportunity to close the loop in generating template graph and uploading encrypted dta
45+
- Chaining ubench
46+
- Use as opportunity to close the loop on the chainig protocol w/ CP-ABE
47+
- Workflows
48+
- Move workflows to `./applications`

experiments/escrow-cost/plots/escrow-cost.svg

Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)