Skip to content

Commit b86ad1b

Browse files
committed
Merge pull-request #594
2 parents a25802f + 80d58a7 commit b86ad1b

File tree

10 files changed

+167
-69
lines changed

10 files changed

+167
-69
lines changed

src/Cargo.lock

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

src/integration/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
2323
borsh = { workspace = true }
2424
nix = { workspace = true }
2525
rustls = { workspace = true }
26+
serde_json = { workspace = true }
2627
webpki-roots = { workspace = true }
2728
tokio-rustls = { workspace = true }
2829

src/integration/examples/boot_enclave.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use std::{
77
process::{Command, Stdio},
88
};
99

10-
use borsh::de::BorshDeserialize;
1110
use integration::{LOCAL_HOST, PCR3_PRE_IMAGE_PATH, QOS_DIST_DIR};
1211
use qos_core::protocol::{
1312
services::{
@@ -104,14 +103,13 @@ async fn main() {
104103
.success());
105104

106105
// Check the manifest written to file
107-
let manifest =
108-
Manifest::try_from_slice(&fs::read(&cli_manifest_path).unwrap())
109-
.unwrap();
106+
let manifest: Manifest =
107+
serde_json::from_slice(&fs::read(&cli_manifest_path).unwrap()).unwrap();
110108

111-
let genesis_output = {
109+
let genesis_output: GenesisOutput = {
112110
let contents =
113111
fs::read("./mock/boot-e2e/genesis-dir/genesis_output").unwrap();
114-
GenesisOutput::try_from_slice(&contents).unwrap()
112+
serde_json::from_slice(&contents).unwrap()
115113
};
116114
// For simplicity sake, we use the same keys for the share set and manifest
117115
// set.
@@ -222,9 +220,8 @@ async fn main() {
222220
assert!(child.wait().unwrap().success());
223221

224222
// Read in the generated approval to check it was created correctly
225-
let approval =
226-
Approval::try_from_slice(&fs::read(approval_path).unwrap())
227-
.unwrap();
223+
let approval: Approval =
224+
serde_json::from_slice(&fs::read(approval_path).unwrap()).unwrap();
228225
let personal_pair = P256Pair::from_hex_file(format!(
229226
"{}/{}.secret",
230227
personal_dir(alias),

src/integration/tests/boot.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,8 @@ async fn standard_boot_e2e() {
103103
.success());
104104

105105
// Check the manifest written to file
106-
let manifest =
107-
Manifest::try_from_slice(&fs::read(&cli_manifest_path).unwrap())
108-
.unwrap();
106+
let manifest: Manifest =
107+
serde_json::from_slice(&fs::read(&cli_manifest_path).unwrap()).unwrap();
109108

110109
let genesis_output = {
111110
let contents =
@@ -238,9 +237,8 @@ async fn standard_boot_e2e() {
238237
assert!(child.wait().unwrap().success());
239238

240239
// Read in the generated approval to check it was created correctly
241-
let approval =
242-
Approval::try_from_slice(&fs::read(approval_path).unwrap())
243-
.unwrap();
240+
let approval: Approval =
241+
serde_json::from_slice(&fs::read(approval_path).unwrap()).unwrap();
244242
let personal_pair = P256Pair::from_hex_file(format!(
245243
"{}/{}.secret",
246244
personal_dir(alias),

src/qos_client/src/cli/services.rs

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,8 @@ pub enum Error {
113113
},
114114
/// Failed to decode some hex
115115
CouldNotDecodeHex(qos_hex::HexError),
116-
/// Failed to deserialize something from borsh.
117-
#[allow(clippy::enum_variant_names)]
118-
BorshError,
116+
/// Failed to deserialize something from borsh or json
117+
Deserialize,
119118
FailedToReadDrKey(qos_p256::P256Error),
120119
QosAttest(String),
121120
/// Pivot file
@@ -141,9 +140,15 @@ pub enum Error {
141140
SecretDoesNotMatch,
142141
}
143142

143+
impl From<serde_json::Error> for Error {
144+
fn from(_: serde_json::Error) -> Self {
145+
Self::Deserialize
146+
}
147+
}
148+
144149
impl From<borsh::io::Error> for Error {
145150
fn from(_: borsh::io::Error) -> Self {
146-
Self::BorshError
151+
Self::Deserialize
147152
}
148153
}
149154

@@ -759,7 +764,7 @@ pub(crate) fn generate_manifest<P: AsRef<Path>>(
759764

760765
write_with_msg(
761766
manifest_path.as_ref(),
762-
&borsh::to_vec(&manifest).unwrap(),
767+
&serde_json::to_vec(&manifest).expect("failed to serialize manifest"),
763768
"Manifest",
764769
);
765770

@@ -862,7 +867,7 @@ pub(crate) fn approve_manifest<P: AsRef<Path>>(
862867
));
863868
write_with_msg(
864869
&approval_path,
865-
&borsh::to_vec(&approval).expect("Failed to serialize approval"),
870+
&serde_json::to_vec(&approval).expect("Failed to serialize approval"),
866871
"Manifest Approval",
867872
);
868873

@@ -1010,7 +1015,7 @@ pub(crate) fn generate_manifest_envelope<P: AsRef<Path>>(
10101015
);
10111016
write_with_msg(
10121017
&path,
1013-
&borsh::to_vec(&manifest_envelope)
1018+
&serde_json::to_vec(&manifest_envelope)
10141019
.expect("Failed to serialize manifest envelope"),
10151020
"Manifest Envelope",
10161021
);
@@ -1076,7 +1081,7 @@ pub(crate) fn export_key<P: AsRef<Path>>(
10761081

10771082
write_with_msg(
10781083
encrypted_quorum_key_path.as_ref(),
1079-
&borsh::to_vec(&encrypted_quorum_key).expect("valid borsh. qed."),
1084+
&serde_json::to_vec(&encrypted_quorum_key).expect("valid borsh. qed."),
10801085
"Encrypted Quorum Key",
10811086
);
10821087

@@ -1087,10 +1092,10 @@ pub(crate) fn inject_key<P: AsRef<Path>>(
10871092
uri: &str,
10881093
encrypted_quorum_key_path: P,
10891094
) -> Result<(), Error> {
1090-
let encrypted_quorum_key = {
1095+
let encrypted_quorum_key: EncryptedQuorumKey = {
10911096
let bytes = std::fs::read(encrypted_quorum_key_path)
10921097
.map_err(|_| Error::FailedToReadEncryptedQuorumKey)?;
1093-
EncryptedQuorumKey::try_from_slice(&bytes)
1098+
serde_json::from_slice(&bytes)
10941099
.map_err(|_| Error::InvalidEncryptedQuorumKey)?
10951100
};
10961101

@@ -1201,8 +1206,8 @@ pub(crate) fn get_attestation_doc<P: AsRef<Path>>(
12011206
);
12021207
write_with_msg(
12031208
manifest_envelope_path.as_ref(),
1204-
&borsh::to_vec(&manifest_envelope)
1205-
.expect("manifest enevelope is valid borsh"),
1209+
&serde_json::to_vec(&manifest_envelope)
1210+
.expect("manifest enevelope is valid json"),
12061211
"Manifest envelope",
12071212
);
12081213
}
@@ -1313,7 +1318,7 @@ pub(crate) fn proxy_re_encrypt_share<P: AsRef<Path>>(
13131318
eph_pub.encrypt(plaintext_share).expect("Envelope encryption error")
13141319
};
13151320

1316-
let approval = borsh::to_vec(&Approval {
1321+
let approval = serde_json::to_vec(&Approval {
13171322
signature: pair
13181323
.sign(&manifest_envelope.manifest.qos_hash())
13191324
.expect("Failed to sign"),
@@ -1573,26 +1578,28 @@ pub(crate) fn display<P: AsRef<Path>>(
15731578
file_path: P,
15741579
json: bool,
15751580
) -> Result<(), Error> {
1576-
let bytes =
1577-
fs::read(file_path).map_err(|e| Error::ReadShare(e.to_string()))?;
15781581
match *display_type {
15791582
DisplayType::Manifest => {
1580-
let decoded = Manifest::try_from_slice_compat(&bytes)?;
1583+
let decoded = read_manifest(file_path)?;
1584+
15811585
if json {
15821586
println!("{}", serde_json::to_string(&decoded).unwrap());
15831587
} else {
15841588
println!("{decoded:#?}");
15851589
}
15861590
}
15871591
DisplayType::ManifestEnvelope => {
1588-
let decoded = ManifestEnvelope::try_from_slice(&bytes)?;
1592+
let decoded = read_manifest_envelope(file_path)?;
1593+
15891594
if json {
15901595
println!("{}", serde_json::to_string(&decoded).unwrap());
15911596
} else {
15921597
println!("{decoded:#?}");
15931598
}
15941599
}
15951600
DisplayType::GenesisOutput => {
1601+
let bytes = fs::read(file_path)
1602+
.map_err(|e| Error::ReadShare(e.to_string()))?;
15961603
let decoded = GenesisOutput::try_from_slice(&bytes)?;
15971604
println!("{decoded:#?}");
15981605
}
@@ -1952,7 +1959,7 @@ fn find_approvals<P: AsRef<Path>>(
19521959
return None;
19531960
};
19541961

1955-
let approval = Approval::try_from_slice(
1962+
let approval: Approval = serde_json::from_slice(
19561963
&fs::read(path).expect("Failed to read in approval"),
19571964
)
19581965
.expect("Failed to deserialize approval");
@@ -1981,9 +1988,16 @@ fn find_approvals<P: AsRef<Path>>(
19811988
}
19821989

19831990
fn read_manifest<P: AsRef<Path>>(file: P) -> Result<Manifest, Error> {
1984-
let buf = fs::read(file).map_err(Error::FailedToReadManifestFile)?;
1985-
Manifest::try_from_slice(&buf)
1986-
.map_err(|_| Error::FileDidNotHaveValidManifest)
1991+
let bytes = fs::read(file).map_err(Error::FailedToReadManifestFile)?;
1992+
1993+
// try getting Manifest from json
1994+
let result = serde_json::from_slice::<Manifest>(&bytes);
1995+
if result.is_err() {
1996+
// if not try the old borsh format
1997+
Manifest::try_from_slice_compat(&bytes).map_err(Error::from)
1998+
} else {
1999+
result.map_err(Error::from)
2000+
}
19872001
}
19882002

19892003
fn read_attestation_doc<P: AsRef<Path>>(
@@ -2003,10 +2017,16 @@ fn read_attestation_doc<P: AsRef<Path>>(
20032017
fn read_manifest_envelope<P: AsRef<Path>>(
20042018
file: P,
20052019
) -> Result<ManifestEnvelope, Error> {
2006-
let buf =
2007-
fs::read(file).map_err(Error::FailedToReadManifestEnvelopeFile)?;
2008-
ManifestEnvelope::try_from_slice(&buf)
2009-
.map_err(|_| Error::FileDidNotHaveValidManifestEnvelope)
2020+
let bytes = fs::read(file).map_err(Error::FailedToReadManifestFile)?;
2021+
2022+
// try getting Manifest from json
2023+
let result = serde_json::from_slice::<ManifestEnvelope>(&bytes);
2024+
if result.is_err() {
2025+
// if not try the old borsh format
2026+
ManifestEnvelope::try_from_slice_compat(&bytes).map_err(Error::from)
2027+
} else {
2028+
result.map_err(Error::from)
2029+
}
20102030
}
20112031

20122032
fn read_attestation_approval<P: AsRef<Path>>(
@@ -2015,7 +2035,7 @@ fn read_attestation_approval<P: AsRef<Path>>(
20152035
let manifest_envelope =
20162036
fs::read(path).map_err(Error::FailedToReadAttestationApproval)?;
20172037

2018-
Approval::try_from_slice(&manifest_envelope)
2038+
serde_json::from_slice(&manifest_envelope)
20192039
.map_err(|_| Error::FileDidNotHaveValidAttestationApproval)
20202040
}
20212041

src/qos_core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ borsh = { workspace = true }
2222
aws-nitro-enclaves-nsm-api = { workspace = true }
2323

2424
serde_bytes = { workspace = true }
25+
serde_json = { workspace = true }
2526
serde = { workspace = true }
2627

2728
futures = { workspace = true }

src/qos_core/src/handles.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
//! Logic for accessing read only QOS state.
22
3-
use std::{fs, os::unix::fs::PermissionsExt, path::Path};
3+
use std::{
4+
fs,
5+
os::unix::fs::PermissionsExt,
6+
path::{Path, PathBuf},
7+
};
48

5-
use borsh::BorshDeserialize;
69
use qos_p256::P256Pair;
710

811
use crate::protocol::{services::boot::ManifestEnvelope, ProtocolError};
@@ -179,8 +182,9 @@ impl Handles {
179182
) -> Result<ManifestEnvelope, ProtocolError> {
180183
let contents = fs::read(&self.manifest)
181184
.map_err(|_| ProtocolError::FailedToGetManifestEnvelope)?;
182-
let manifest = ManifestEnvelope::try_from_slice(&contents)
185+
let manifest = serde_json::from_slice(&contents)
183186
.map_err(|_| ProtocolError::FailedToGetManifestEnvelope)?;
187+
184188
Ok(manifest)
185189
}
186190

@@ -195,7 +199,8 @@ impl Handles {
195199
) -> Result<(), ProtocolError> {
196200
Self::write_as_read_only(
197201
&self.manifest,
198-
&borsh::to_vec(manifest_envelope)?,
202+
&serde_json::to_vec(manifest_envelope)
203+
.map_err(|_| ProtocolError::FailedToPutManifestEnvelope)?,
199204
ProtocolError::FailedToPutManifestEnvelope,
200205
)
201206
}
@@ -219,8 +224,12 @@ impl Handles {
219224
&self.manifest,
220225
std::fs::Permissions::from_mode(0o666),
221226
)?;
222-
fs::write(&self.manifest, borsh::to_vec(&manifest_envelope)?)
223-
.map_err(|_| ProtocolError::FailedToPutManifestEnvelope)?;
227+
fs::write(
228+
&self.manifest,
229+
serde_json::to_vec(&manifest_envelope)
230+
.map_err(|_| ProtocolError::FailedToPutManifestEnvelope)?,
231+
)
232+
.map_err(|_| ProtocolError::FailedToPutManifestEnvelope)?;
224233

225234
// Set the permissions back to read only
226235
fs::set_permissions(
@@ -272,7 +281,7 @@ impl Handles {
272281
Path::new(&self.pivot).exists()
273282
}
274283

275-
/// Helper function for ready only writes.
284+
/// Helper function for ready only writes that also ensures full write atomicity by renaming at the end.
276285
fn write_as_read_only<P: AsRef<Path>>(
277286
path: P,
278287
buf: &[u8],
@@ -288,7 +297,13 @@ impl Handles {
288297
}
289298
}
290299

291-
fs::write(&path, buf).map_err(|_| err.clone())?;
300+
let tmp_path = PathBuf::from(path.as_ref()).with_extension("tmp");
301+
302+
fs::write(&tmp_path, buf).map_err(|_| err.clone())?;
303+
304+
// atomically move to destination once fully written to prevent partial reads
305+
fs::rename(&tmp_path, &path)?;
306+
292307
fs::set_permissions(&path, fs::Permissions::from_mode(0o444))
293308
.map_err(|_| err)?;
294309

0 commit comments

Comments
 (0)