diff --git a/Cargo.lock b/Cargo.lock index 3250e918b68..0bb799249b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,7 +203,7 @@ dependencies = [ "base64ct", "blake2", "cpufeatures", - "password-hash 0.5.0", + "password-hash", ] [[package]] @@ -573,28 +573,26 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.12.4" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd755adf9707cf671e31d944a189be3deaaeee11c8bc1d669bb8022ac90fbd0" +checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" dependencies = [ "aws-lc-sys", - "paste", "untrusted 0.7.1", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.26.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9dd2e03ee80ca2822dd6ea431163d2ef259f2066a4d6ccaca6d9dcb386aa43" +checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" dependencies = [ "bindgen 0.69.5", "cc", "cmake", "dunce", "fs_extra", - "paste", ] [[package]] @@ -675,7 +673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2" dependencies = [ "blowfish", - "pbkdf2 0.12.2", + "pbkdf2", "sha2", ] @@ -2449,6 +2447,17 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "delegate" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6178a82cf56c836a3ba61a7935cdb1c49bfaa6fa4327cd5bf554a503087de26b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "der" version = "0.7.9" @@ -2581,15 +2590,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "des" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" -dependencies = [ - "cipher", -] - [[package]] name = "dev-tools-common" version = "0.1.0" @@ -3126,7 +3126,6 @@ version = "0.1.0" dependencies = [ "anstyle", "anyhow", - "async-trait", "base64 0.22.1", "bytes", "chrono", @@ -3152,7 +3151,6 @@ dependencies = [ "rand 0.8.5", "reqwest", "russh", - "russh-keys", "serde", "serde_json", "sled-agent-types", @@ -3183,6 +3181,18 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "env_filter" version = "0.1.2" @@ -5253,6 +5263,34 @@ dependencies = [ "serde_json", ] +[[package]] +name = "internal-russh-forked-ssh-key" +version = "0.6.11+upstream-0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a77eae781ed6a7709fb15b64862fcca13d886b07c7e2786f5ed34e5e2b9187" +dependencies = [ + "argon2", + "bcrypt-pbkdf", + "ecdsa", + "ed25519-dalek", + "hex", + "hmac", + "num-bigint-dig", + "p256", + "p384", + "p521", + "rand_core 0.6.4", + "rsa", + "sec1", + "sha1", + "sha2", + "signature", + "ssh-cipher", + "ssh-encoding", + "subtle", + "zeroize", +] + [[package]] name = "internet-checksum" version = "0.2.1" @@ -9428,6 +9466,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pageant" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd27df01428302f915ea74737fe88170dd1bab4cbd00ff9548ca85618fcd4e4" +dependencies = [ + "bytes", + "delegate", + "futures", + "log", + "rand 0.8.5", + "thiserror 1.0.69", + "tokio", + "windows 0.58.0", +] + [[package]] name = "papergrid" version = "0.11.0" @@ -9556,17 +9610,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "password-hash" version = "0.5.0" @@ -9608,18 +9651,6 @@ dependencies = [ "camino", ] -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash 0.4.2", - "sha2", -] - [[package]] name = "pbkdf2" version = "0.12.2" @@ -9863,7 +9894,7 @@ dependencies = [ "aes", "cbc", "der", - "pbkdf2 0.12.2", + "pbkdf2", "scrypt", "sha2", "spki", @@ -11271,106 +11302,90 @@ dependencies = [ [[package]] name = "russh" -version = "0.45.0" +version = "0.54.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a229f2a03daea3f62cee897b40329ce548600cca615906d98d58b8db3029b19" +checksum = "de956421c15e2068e207578852cf1af4f24b32ede68ab3ae60d8489444ff31df" dependencies = [ "aes", - "aes-gcm", - "async-trait", + "aws-lc-rs", + "base64ct", "bitflags 2.9.1", + "block-padding", "byteorder", + "bytes", "cbc", - "chacha20", "ctr", "curve25519-dalek", - "des", + "data-encoding", + "delegate", + "der", "digest", + "ecdsa", + "ed25519-dalek", "elliptic-curve", + "enum_dispatch", "flate2", "futures", "generic-array", + "getrandom 0.2.15", "hex-literal", "hmac", + "home", + "inout", + "internal-russh-forked-ssh-key", "log", + "md5", "num-bigint", "once_cell", "p256", "p384", "p521", - "poly1305", + "pageant", + "pbkdf2", + "pkcs1", + "pkcs5", + "pkcs8", "rand 0.8.5", "rand_core 0.6.4", + "rsa", "russh-cryptovec", - "russh-keys", + "russh-util", + "sec1", "sha1", "sha2", + "signature", + "spki", "ssh-encoding", - "ssh-key", "subtle", "thiserror 1.0.69", "tokio", + "typenum", + "zeroize", ] [[package]] name = "russh-cryptovec" -version = "0.7.3" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadd2c0ab350e21c66556f94ee06f766d8bdae3213857ba7610bfd8e10e51880" +checksum = "4fb0ed583ff0f6b4aa44c7867dd7108df01b30571ee9423e250b4cc939f8c6cf" dependencies = [ "libc", + "log", + "nix 0.29.0", + "ssh-encoding", "winapi", ] [[package]] -name = "russh-keys" -version = "0.45.0" +name = "russh-util" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89757474f7c9ee30121d8cc7fe293a954ba10b204a82ccf5850a5352a532ebc7" +checksum = "668424a5dde0bcb45b55ba7de8476b93831b4aa2fa6947e145f3b053e22c60b6" dependencies = [ - "aes", - "async-trait", - "bcrypt-pbkdf", - "block-padding", - "byteorder", - "cbc", - "ctr", - "data-encoding", - "der", - "digest", - "ecdsa", - "ed25519-dalek", - "elliptic-curve", - "futures", - "hmac", - "home", - "inout", - "log", - "md5", - "num-integer", - "p256", - "p384", - "p521", - "pbkdf2 0.11.0", - "pkcs1", - "pkcs5", - "pkcs8", - "rand 0.8.5", - "rand_core 0.6.4", - "rsa", - "russh-cryptovec", - "sec1", - "serde", - "sha1", - "sha2", - "spki", - "ssh-encoding", - "ssh-key", - "thiserror 1.0.69", + "chrono", "tokio", - "tokio-stream", - "typenum", - "zeroize", + "wasm-bindgen", + "wasm-bindgen-futures", ] [[package]] @@ -11750,7 +11765,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" dependencies = [ - "pbkdf2 0.12.2", + "pbkdf2", "salsa20", "sha2", ] @@ -12913,33 +12928,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" dependencies = [ "base64ct", + "bytes", "pem-rfc7468", "sha2", ] -[[package]] -name = "ssh-key" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafc" -dependencies = [ - "bcrypt-pbkdf", - "ed25519-dalek", - "num-bigint-dig", - "p256", - "p384", - "p521", - "rand_core 0.6.4", - "rsa", - "sec1", - "sha2", - "signature", - "ssh-cipher", - "ssh-encoding", - "subtle", - "zeroize", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/end-to-end-tests/Cargo.toml b/end-to-end-tests/Cargo.toml index c3010bb5d21..14977a43cae 100644 --- a/end-to-end-tests/Cargo.toml +++ b/end-to-end-tests/Cargo.toml @@ -9,7 +9,6 @@ workspace = true [dependencies] anyhow = { workspace = true, features = ["backtrace"] } -async-trait.workspace = true base64.workspace = true bytes.workspace = true chrono.workspace = true @@ -25,8 +24,7 @@ oxide-client.workspace = true oxide-tokio-rt.workspace = true rand.workspace = true reqwest = { workspace = true, features = ["cookies"] } -russh = "0.45.0" -russh-keys = "0.45.0" +russh = "0.54.0" serde.workspace = true serde_json.workspace = true sled-agent-types.workspace = true diff --git a/end-to-end-tests/src/instance_launch.rs b/end-to-end-tests/src/instance_launch.rs index 84fb8adb58e..b9b9abb7625 100644 --- a/end-to-end-tests/src/instance_launch.rs +++ b/end-to-end-tests/src/instance_launch.rs @@ -2,7 +2,6 @@ use crate::helpers::{ctx::Context, generate_name}; use anyhow::{Context as _, Result, ensure}; -use async_trait::async_trait; use omicron_test_utils::dev::poll::{CondCheckError, wait_for_condition}; use oxide_client::types::{ ByteCount, DiskCreate, DiskSource, ExternalIp, ExternalIpCreate, @@ -10,9 +9,13 @@ use oxide_client::types::{ InstanceNetworkInterfaceAttachment, InstanceState, SshKeyCreate, }; use oxide_client::{ClientCurrentUserExt, ClientDisksExt, ClientInstancesExt}; +use rand::RngCore; +use russh::client::AuthResult; +use russh::keys::{ + PrivateKey, PrivateKeyWithHashAlg, PublicKey, PublicKeyBase64, + ssh_key::private::{Ed25519PrivateKey, KeypairData}, +}; use russh::{ChannelMsg, Disconnect}; -use russh_keys::PublicKeyBase64; -use russh_keys::key::{KeyPair, PublicKey}; use std::sync::Arc; use std::time::Duration; @@ -21,8 +24,7 @@ async fn instance_launch() -> Result<()> { let ctx = Context::new().await?; eprintln!("generate SSH key"); - let key = - Arc::new(KeyPair::generate_ed25519().context("key generation failed")?); + let key = generate_private_key()?; let public_key_str = format!("ssh-ed25519 {}", key.public_key_base64()); eprintln!("create SSH key: {}", public_key_str); let ssh_key_name = generate_name("key")?; @@ -151,16 +153,10 @@ async fn instance_launch() -> Result<()> { .and_then(|(lines, _)| { lines.trim().lines().find(|line| line.starts_with("ssh-ed25519")) }) - .and_then(|line| line.split_whitespace().nth(1)) .context("failed to get SSH host key from serial console")?; - eprintln!("host key: ssh-ed25519 {}", host_key); - let host_key = PublicKey::parse( - b"ssh-ed25519", - &base64::Engine::decode( - &base64::engine::general_purpose::STANDARD, - host_key, - )?, - )?; + eprintln!("host key: {host_key}"); + let host_key = PublicKey::from_openssh(host_key) + .context("failed to parse host key")?; eprintln!("connecting ssh"); let mut session = russh::client::connect( @@ -171,7 +167,8 @@ async fn instance_launch() -> Result<()> { .await?; eprintln!("authenticating ssh"); ensure!( - session.authenticate_publickey("debian", key).await?, + session.authenticate_publickey("debian", key).await? + == AuthResult::Success, "authentication failed" ); @@ -302,7 +299,6 @@ struct SshClient { host_key: PublicKey, } -#[async_trait] impl russh::client::Handler for SshClient { type Error = anyhow::Error; @@ -313,3 +309,18 @@ impl russh::client::Handler for SshClient { Ok(&self.host_key == server_public_key) } } + +fn generate_private_key() -> anyhow::Result { + // Generate random bytes ourselves since upstream is still on rand 0.8. + let mut seed = [0u8; Ed25519PrivateKey::BYTE_SIZE]; + rand::thread_rng().fill_bytes(&mut seed); + let private_key = PrivateKey::new( + KeypairData::Ed25519(Ed25519PrivateKey::from_bytes(&seed).into()), + "random private key", + ) + .context("key generation failed")?; + Ok(PrivateKeyWithHashAlg::new( + Arc::new(private_key), + /* hash_alg is ignored for non-RSA keys */ None, + )) +} diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 04e7e38a3ce..380eb6794ae 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -21,7 +21,7 @@ workspace = true ahash = { version = "0.8.12" } aho-corasick = { version = "1.1.3" } anyhow = { version = "1.0.98", features = ["backtrace"] } -aws-lc-rs = { version = "1.12.4", features = ["prebuilt-nasm"] } +aws-lc-rs = { version = "1.13.3", 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"] } @@ -134,7 +134,7 @@ time = { version = "0.3.36", features = ["formatting", "local-offset", "macros", tokio = { version = "1.47.0", features = ["full", "test-util"] } tokio-postgres = { version = "0.7.13", features = ["with-chrono-0_4", "with-serde_json-1", "with-uuid-1"] } tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] } -tokio-stream = { version = "0.1.17", features = ["net", "sync"] } +tokio-stream = { version = "0.1.17", features = ["sync"] } tokio-util = { version = "0.7.15", features = ["codec", "io-util", "rt", "time"] } toml = { version = "0.7.8" } toml_datetime = { version = "0.6.11", default-features = false, features = ["serde"] } @@ -156,7 +156,7 @@ zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = ahash = { version = "0.8.12" } aho-corasick = { version = "1.1.3" } anyhow = { version = "1.0.98", features = ["backtrace"] } -aws-lc-rs = { version = "1.12.4", features = ["prebuilt-nasm"] } +aws-lc-rs = { version = "1.13.3", 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"] } @@ -272,7 +272,7 @@ time-macros = { version = "0.2.18", default-features = false, features = ["forma tokio = { version = "1.47.0", features = ["full", "test-util"] } tokio-postgres = { version = "0.7.13", features = ["with-chrono-0_4", "with-serde_json-1", "with-uuid-1"] } tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] } -tokio-stream = { version = "0.1.17", features = ["net", "sync"] } +tokio-stream = { version = "0.1.17", features = ["sync"] } tokio-util = { version = "0.7.15", features = ["codec", "io-util", "rt", "time"] } toml = { version = "0.7.8" } toml_datetime = { version = "0.6.11", default-features = false, features = ["serde"] } @@ -299,6 +299,7 @@ hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio" hyper-util = { version = "0.1.16", features = ["full"] } linux-raw-sys = { version = "0.4.14", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "std", "system", "xdp"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -311,6 +312,7 @@ hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio" hyper-util = { version = "0.1.16", features = ["full"] } linux-raw-sys = { version = "0.4.14", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "std", "system", "xdp"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -321,6 +323,7 @@ getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.16", features = ["full"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -331,6 +334,7 @@ getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.16", features = ["full"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -341,6 +345,7 @@ getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.16", features = ["full"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -351,6 +356,7 @@ getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.16", features = ["full"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -364,6 +370,7 @@ hyper-util = { version = "0.1.16", features = ["full"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10.5" } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } toml_edit-cdcf2f9584511fe6 = { package = "toml_edit", version = "0.19.15", features = ["serde"] } @@ -380,6 +387,7 @@ hyper-util = { version = "0.1.16", features = ["full"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10.5" } mio = { version = "1.0.2", features = ["net", "os-ext"] } +nix = { version = "0.29.0", default-features = false, features = ["mman"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } toml_edit-cdcf2f9584511fe6 = { package = "toml_edit", version = "0.19.15", features = ["serde"] }