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

Update Rust crate tough to 0.19.0 #6974

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
440 changes: 185 additions & 255 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ async-bb8-diesel = "0.2"
async-trait = "0.1.83"
atomicwrites = "0.4.4"
authz-macros = { path = "nexus/authz-macros" }
aws-lc-rs = "1.10.0"
backoff = { version = "0.4.0", features = [ "tokio" ] }
base64 = "0.22.1"
bcs = "0.1.6"
Expand Down Expand Up @@ -618,7 +619,7 @@ tokio-tungstenite = "0.23.1"
tokio-util = { version = "0.7.12", features = ["io", "io-util"] }
toml = "0.8.19"
toml_edit = "0.22.22"
tough = { version = "0.17.1", features = [ "http" ] }
tough = { version = "0.19.0", features = [ "http" ] }
trybuild = "1.0.100"
tufaceous = { path = "tufaceous" }
tufaceous-lib = { path = "tufaceous-lib" }
Expand Down Expand Up @@ -726,6 +727,8 @@ opt-level = 3
opt-level = 3
[profile.dev.package.aes-gcm]
opt-level = 3
[profile.dev.package.aws-lc-sys]
opt-level = 3
[profile.dev.package.bcrypt-pbkdf]
opt-level = 3
[profile.dev.package.blake2]
Expand Down
2 changes: 1 addition & 1 deletion dev-tools/releng/src/tuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub(crate) async fn build_tuf_repo(
let manifest = ArtifactManifest::from_deserialized(&output_dir, manifest)?;
manifest.verify_all_present()?;
// Assemble the repo.
let keys = vec![Key::generate_ed25519()];
let keys = vec![Key::generate_ed25519()?];
let expiry = Utc::now().with_nanosecond(0).unwrap() + Duration::weeks(1);
OmicronRepoAssembler::new(
&logger,
Expand Down
5 changes: 3 additions & 2 deletions tufaceous-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ workspace = true
[dependencies]
anyhow = { workspace = true, features = ["backtrace"] }
async-trait.workspace = true
aws-lc-rs.workspace = true
base64.workspace = true
buf-list.workspace = true
bytes.workspace = true
camino.workspace = true
Expand All @@ -24,9 +26,9 @@ hex.workspace = true
hubtools.workspace = true
itertools.workspace = true
omicron-common.workspace = true
omicron-workspace-hack.workspace = true
parse-size.workspace = true
rand.workspace = true
ring = { workspace = true, features = ["std"] }
serde.workspace = true
serde_json.workspace = true
serde_path_to_error.workspace = true
Expand All @@ -38,7 +40,6 @@ toml.workspace = true
tough.workspace = true
url.workspace = true
zip.workspace = true
omicron-workspace-hack.workspace = true

[dev-dependencies]
omicron-test-utils.workspace = true
Expand Down
72 changes: 19 additions & 53 deletions tufaceous-lib/src/key.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use anyhow::{bail, Result};
use hex::FromHex;
use rand::{rngs::OsRng, RngCore};
use ring::rand::SecureRandom;
use ring::signature::Ed25519KeyPair;
use aws_lc_rs::rand::SystemRandom;
use aws_lc_rs::signature::Ed25519KeyPair;
use base64::{engine::general_purpose::URL_SAFE, Engine};
use std::fmt::Display;
use std::str::FromStr;
use tough::async_trait;
Expand All @@ -15,43 +14,25 @@ pub(crate) fn boxed_keys(keys: Vec<Key>) -> Vec<Box<dyn KeySource>> {

#[derive(Debug, Clone)]
pub enum Key {
Ed25519(
// We could store this as a `ring::signature::Ed25519KeyPair`, but that
// doesn't impl `Clone`.
[u8; 32],
),
Ed25519 { pkcs8: Vec<u8> },
}

impl Key {
pub fn generate_ed25519() -> Key {
let mut key = [0; 32];
OsRng.fill_bytes(&mut key);
Key::Ed25519(key)
pub fn generate_ed25519() -> Result<Key> {
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&SystemRandom::new())?;
Ok(Key::Ed25519 { pkcs8: pkcs8.as_ref().to_vec() })
}

pub(crate) fn as_sign(&self) -> SignKeyPair {
fn as_sign_key_pair(&self) -> Result<SignKeyPair> {
match self {
Key::Ed25519(key) => SignKeyPair::ED25519(
Ed25519KeyPair::from_seed_unchecked(key)
.expect("ed25519 key length mismatch"),
),
Key::Ed25519 { pkcs8 } => {
Ok(SignKeyPair::ED25519(Ed25519KeyPair::from_pkcs8(pkcs8)?))
}
}
}
}

#[async_trait]
impl Sign for Key {
fn tuf_key(&self) -> tough::schema::key::Key {
self.as_sign().tuf_key()
}

async fn sign(
&self,
msg: &[u8],
rng: &(dyn SecureRandom + Sync),
) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync + 'static>>
{
self.as_sign().sign(msg, rng).await
pub(crate) fn as_tuf_key(&self) -> Result<tough::schema::key::Key> {
Ok(self.as_sign_key_pair()?.tuf_key())
}
}

Expand All @@ -61,7 +42,7 @@ impl KeySource for Key {
&self,
) -> Result<Box<dyn Sign>, Box<dyn std::error::Error + Send + Sync + 'static>>
{
Ok(Box::new(self.clone()))
Ok(Box::new(self.as_sign_key_pair()?))
}

async fn write(
Expand All @@ -78,7 +59,9 @@ impl FromStr for Key {

fn from_str(s: &str) -> Result<Key> {
match s.split_once(':') {
Some(("ed25519", hex)) => Ok(Key::Ed25519(FromHex::from_hex(hex)?)),
Some(("ed25519", base64)) => {
Ok(Key::Ed25519 { pkcs8: URL_SAFE.decode(base64)? })
Comment on lines +62 to +63
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swapping from hex to base64 -- is this a problem for existing serialization? Do we have any stringified keys stored anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also changes from being the bare private key to a PKCS8 document containing both the private and public keys, so it's a format change either way. aws-lc-rs provides no mechanism to load only a private key anymore. (AIUI this is because there are different ways you could convert a private key into a public key?)

I am fairly certain we don't have any keys of importance stored anywhere unless folks are testing with a specific set of keys. The keys used to generate the repo in CI are generated on the fly and thrown away.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it's only used for ephemeral keys and local testing.

}
Some((kind, _)) => bail!("Invalid key source kind: {}", kind),
None => bail!("Invalid key source (format is `kind:data`)"),
}
Expand All @@ -88,25 +71,8 @@ impl FromStr for Key {
impl Display for Key {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Key::Ed25519(key) => {
write!(f, "ed25519:{}", hex::encode(key))
}
}
}
}

#[cfg(test)]
mod tests {
use super::Key;
use ring::signature::Ed25519KeyPair;
use std::str::FromStr;

#[test]
fn test_from_str() {
let key = Key::from_str("ed25519:9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60").unwrap();
match key {
Key::Ed25519(key) => {
let _ = Ed25519KeyPair::from_seed_unchecked(&key).unwrap();
Key::Ed25519 { pkcs8 } => {
write!(f, "ed25519:{}", URL_SAFE.encode(pkcs8))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tufaceous-lib/src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ mod tests {
&logctx.log,
tempdir.path(),
"0.0.0".parse().unwrap(),
vec![Key::generate_ed25519()],
vec![Key::generate_ed25519().unwrap()],
Utc::now() + Days::new(1),
)
.await
Expand Down
5 changes: 2 additions & 3 deletions tufaceous-lib/src/root.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::key::Key;
use anyhow::Result;
use aws_lc_rs::rand::SystemRandom;
use chrono::{DateTime, Utc};
use ring::rand::SystemRandom;
use std::collections::HashMap;
use std::num::NonZeroU64;
use tough::editor::signed::SignedRole;
use tough::schema::{KeyHolder, RoleKeys, RoleType, Root};
use tough::sign::Sign;

pub(crate) async fn new_root(
keys: Vec<Key>,
Expand All @@ -22,7 +21,7 @@ pub(crate) async fn new_root(
_extra: HashMap::new(),
};
for key in &keys {
let key = key.as_sign().tuf_key();
let key = key.as_tuf_key()?;
root.keys.insert(key.key_id()?, key);
}
for kind in [
Expand Down
15 changes: 9 additions & 6 deletions tufaceous/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Args {

match self.command {
Command::Init { system_version, no_generate_key } => {
let keys = maybe_generate_keys(self.keys, no_generate_key);
let keys = maybe_generate_keys(self.keys, no_generate_key)?;

let repo = OmicronRepo::initialize(
&log,
Expand Down Expand Up @@ -161,7 +161,7 @@ impl Args {
manifest.verify_all_present()?;
}

let keys = maybe_generate_keys(self.keys, no_generate_key);
let keys = maybe_generate_keys(self.keys, no_generate_key)?;
let mut assembler = OmicronRepoAssembler::new(
&log,
manifest,
Expand Down Expand Up @@ -245,12 +245,15 @@ enum Command {
},
}

fn maybe_generate_keys(keys: Vec<Key>, no_generate_key: bool) -> Vec<Key> {
if !no_generate_key && keys.is_empty() {
let key = Key::generate_ed25519();
fn maybe_generate_keys(
keys: Vec<Key>,
no_generate_key: bool,
) -> Result<Vec<Key>> {
Ok(if !no_generate_key && keys.is_empty() {
let key = Key::generate_ed25519()?;
crate::hint::generated_key(&key);
vec![key]
} else {
keys
}
})
}
4 changes: 2 additions & 2 deletions tufaceous/tests/integration-tests/command_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use tufaceous_lib::{Key, OmicronRepo};
async fn test_init_and_add() -> Result<()> {
let logctx = test_setup_log("test_init_and_add");
let tempdir = tempfile::tempdir().unwrap();
let key = Key::generate_ed25519();
let key = Key::generate_ed25519()?;

let mut cmd = make_cmd_with_repo(tempdir.path(), &key);
cmd.args(["init", "0.0.0"]);
Expand Down Expand Up @@ -114,7 +114,7 @@ async fn test_init_and_add() -> Result<()> {
fn test_assemble_fake() -> Result<()> {
let logctx = test_setup_log("test_assemble_fake");
let tempdir = tempfile::tempdir().unwrap();
let key = Key::generate_ed25519();
let key = Key::generate_ed25519()?;

let archive_path = tempdir.path().join("archive.zip");

Expand Down
16 changes: 6 additions & 10 deletions workspace-hack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ workspace = true
ahash = { version = "0.8.11" }
aho-corasick = { version = "1.1.3" }
anyhow = { version = "1.0.92", features = ["backtrace"] }
aws-lc-rs = { version = "1.10.0", features = ["prebuilt-nasm"] }
base16ct = { version = "0.2.0", default-features = false, features = ["alloc"] }
base64 = { version = "0.22.1" }
base64ct = { version = "1.6.0", default-features = false, features = ["std"] }
Expand Down Expand Up @@ -98,8 +99,9 @@ regex = { version = "1.11.0" }
regex-automata = { version = "0.4.8", default-features = false, features = ["dfa", "hybrid", "meta", "nfa", "perf", "unicode"] }
regex-syntax = { version = "0.8.5" }
reqwest = { version = "0.12.8", features = ["blocking", "cookies", "json", "rustls-tls", "stream"] }
ring = { version = "0.17.8", features = ["std"] }
rsa = { version = "0.9.6", features = ["serde", "sha2"] }
rustls = { version = "0.23.14", features = ["ring"] }
rustls-webpki = { version = "0.102.8", default-features = false, features = ["aws_lc_rs", "ring", "std"] }
schemars = { version = "0.8.21", features = ["bytes", "chrono", "uuid1"] }
scopeguard = { version = "1.2.0" }
semver = { version = "1.0.23", features = ["serde"] }
Expand Down Expand Up @@ -137,6 +139,7 @@ zip = { version = "0.6.6", default-features = false, features = ["bzip2", "defla
ahash = { version = "0.8.11" }
aho-corasick = { version = "1.1.3" }
anyhow = { version = "1.0.92", features = ["backtrace"] }
aws-lc-rs = { version = "1.10.0", features = ["prebuilt-nasm"] }
base16ct = { version = "0.2.0", default-features = false, features = ["alloc"] }
base64 = { version = "0.22.1" }
base64ct = { version = "1.6.0", default-features = false, features = ["std"] }
Expand Down Expand Up @@ -215,8 +218,9 @@ regex = { version = "1.11.0" }
regex-automata = { version = "0.4.8", default-features = false, features = ["dfa", "hybrid", "meta", "nfa", "perf", "unicode"] }
regex-syntax = { version = "0.8.5" }
reqwest = { version = "0.12.8", features = ["blocking", "cookies", "json", "rustls-tls", "stream"] }
ring = { version = "0.17.8", features = ["std"] }
rsa = { version = "0.9.6", features = ["serde", "sha2"] }
rustls = { version = "0.23.14", features = ["ring"] }
rustls-webpki = { version = "0.102.8", default-features = false, features = ["aws_lc_rs", "ring", "std"] }
schemars = { version = "0.8.21", features = ["bytes", "chrono", "uuid1"] }
scopeguard = { version = "1.2.0" }
semver = { version = "1.0.23", features = ["serde"] }
Expand Down Expand Up @@ -262,7 +266,6 @@ linux-raw-sys = { version = "0.4.14", default-features = false, features = ["elf
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }

[target.x86_64-unknown-linux-gnu.build-dependencies]
Expand All @@ -274,7 +277,6 @@ linux-raw-sys = { version = "0.4.14", default-features = false, features = ["elf
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }

[target.x86_64-apple-darwin.dependencies]
Expand All @@ -284,7 +286,6 @@ hyper-util = { version = "0.1.9", features = ["full"] }
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }

[target.x86_64-apple-darwin.build-dependencies]
Expand All @@ -294,7 +295,6 @@ hyper-util = { version = "0.1.9", features = ["full"] }
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }

[target.aarch64-apple-darwin.dependencies]
Expand All @@ -304,7 +304,6 @@ hyper-util = { version = "0.1.9", features = ["full"] }
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }

[target.aarch64-apple-darwin.build-dependencies]
Expand All @@ -314,7 +313,6 @@ hyper-util = { version = "0.1.9", features = ["full"] }
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }

[target.x86_64-unknown-illumos.dependencies]
Expand All @@ -326,7 +324,6 @@ indicatif = { version = "0.17.8", features = ["rayon"] }
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }
toml_edit-cdcf2f9584511fe6 = { package = "toml_edit", version = "0.19.15", features = ["serde"] }

Expand All @@ -339,7 +336,6 @@ indicatif = { version = "0.17.8", features = ["rayon"] }
mio = { version = "1.0.2", features = ["net", "os-ext"] }
once_cell = { version = "1.20.2" }
rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }
rustls = { version = "0.23.14", default-features = false, features = ["logging", "ring", "std", "tls12"] }
tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }
toml_edit-cdcf2f9584511fe6 = { package = "toml_edit", version = "0.19.15", features = ["serde"] }

Expand Down
Loading