From 3f5dcadf25ac0904394ebfc3442880f06da642bb Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 29 Aug 2024 16:30:03 -0400 Subject: [PATCH] SPROCKETS --- Cargo.lock | 158 +++++++++++++++++-- Cargo.toml | 1 + sled-agent/Cargo.toml | 1 + sled-agent/src/bootstrap/client.rs | 32 +++- sled-agent/src/bootstrap/sprockets_server.rs | 33 ++-- workspace-hack/Cargo.toml | 18 ++- 6 files changed, 207 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 923693276a9..29d1d6be4ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,6 +338,21 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "attest-data" +version = "0.2.0" +source = "git+https://github.com/oxidecomputer/dice-util?branch=attest_messages_tq#22c9c8a84bc79a09c51af9cd7f63e3032ed41319" +dependencies = [ + "getrandom", + "hubpack", + "salty", + "serde", + "serde_with", + "sha3", + "static_assertions", + "thiserror", +] + [[package]] name = "atty" version = "0.2.14" @@ -510,7 +525,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "log", @@ -1964,6 +1979,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7993efb860416547839c115490d4951c6d0f8ec04a3594d9dd99d50ed7ec170" +[[package]] +name = "dice-verifier" +version = "0.1.0" +source = "git+https://github.com/oxidecomputer/dice-util?branch=attest_messages_tq#22c9c8a84bc79a09c51af9cd7f63e3032ed41319" +dependencies = [ + "anyhow", + "attest-data", + "const-oid", + "ed25519-dalek", + "env_logger 0.11.5", + "log", + "p384", + "pem-rfc7468", + "sha3", + "x509-cert", +] + [[package]] name = "diesel" version = "2.2.3" @@ -2412,6 +2444,7 @@ dependencies = [ "rand_core", "serde", "sha2", + "signature", "subtle", "zeroize", ] @@ -2539,6 +2572,15 @@ dependencies = [ "syn 2.0.74", ] +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -2563,6 +2605,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -3693,7 +3745,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -3702,9 +3754,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -3741,7 +3793,7 @@ checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "log", "rustls 0.22.4", @@ -3786,16 +3838,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.3.1", + "hyper 1.4.1", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -4457,6 +4509,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libipcc" +version = "0.1.0" +source = "git+https://github.com/oxidecomputer/libipcc?rev=fdffa212373a8f92473ea5f411088912bf458d5f#fdffa212373a8f92473ea5f411088912bf458d5f" +dependencies = [ + "cfg-if", + "libc", + "thiserror", +] + [[package]] name = "libloading" version = "0.8.3" @@ -4464,7 +4526,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -6515,6 +6577,7 @@ dependencies = [ "slog-error-chain", "slog-term", "smf", + "sprockets-tls", "static_assertions", "strum", "subprocess", @@ -6602,13 +6665,14 @@ dependencies = [ "clap", "clap_builder", "console", - "const-oid", "crossbeam-epoch", "crossbeam-utils", "crypto-common", - "der", + "curve25519-dalek", "digest", "dof", + "ecdsa", + "ed25519-dalek", "either", "elliptic-curve", "ff", @@ -6676,6 +6740,7 @@ dependencies = [ "similar", "slog", "smallvec 1.13.2", + "socket2 0.5.7", "spin 0.9.8", "string_cache", "subtle", @@ -6698,6 +6763,7 @@ dependencies = [ "usdt", "usdt-impl", "uuid", + "x509-cert", "zerocopy 0.7.34", "zeroize", ] @@ -9022,6 +9088,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "log", + "once_cell", + "ring 0.17.8", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.7.0" @@ -9154,6 +9235,16 @@ dependencies = [ "cipher", ] +[[package]] +name = "salty" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b947325a585e90733e0e9ec097228f40b637cc346f9bd68f84d5c6297d0fcfef" +dependencies = [ + "subtle", + "zeroize", +] + [[package]] name = "samael" version = "0.0.15" @@ -10102,6 +10193,35 @@ dependencies = [ "der", ] +[[package]] +name = "sprockets-tls" +version = "0.1.0" +source = "git+https://github.com/oxidecomputer/sprockets.git?branch=ipcc#2c5124d39baac1daf26c20cfa7ecec574cc83c67" +dependencies = [ + "anyhow", + "attest-data", + "camino", + "cfg-if", + "clap", + "dice-verifier", + "ed25519-dalek", + "libipcc", + "pem-rfc7468", + "rustls 0.23.10", + "secrecy", + "serde", + "sha2", + "sha3", + "slog", + "slog-async", + "slog-term", + "thiserror", + "tokio", + "tokio-rustls 0.26.0", + "x509-cert", + "zeroize", +] + [[package]] name = "sqlformat" version = "0.2.4" @@ -10870,6 +10990,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.10", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -11067,7 +11198,6 @@ dependencies = [ "tokio", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -12476,9 +12606,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 3d1d19fa65b..00e54bb29ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -567,6 +567,7 @@ slog-term = "2.9.1" smf = "0.2" socket2 = { version = "0.5", features = ["all"] } sp-sim = { path = "sp-sim" } +sprockets-tls = { git = "https://github.com/oxidecomputer/sprockets.git", branch = "ipcc" } sqlformat = "0.2.4" sqlparser = { version = "0.45.0", features = [ "visitor" ] } static_assertions = "1.1.0" diff --git a/sled-agent/Cargo.toml b/sled-agent/Cargo.toml index 2aefd8f4649..500a3165927 100644 --- a/sled-agent/Cargo.toml +++ b/sled-agent/Cargo.toml @@ -80,6 +80,7 @@ slog-async.workspace = true slog-dtrace.workspace = true slog-term.workspace = true smf.workspace = true +sprockets-tls.workspace = true strum.workspace = true tar.workspace = true thiserror.workspace = true diff --git a/sled-agent/src/bootstrap/client.rs b/sled-agent/src/bootstrap/client.rs index bfdaf6e6d4e..53b8e5f68c5 100644 --- a/sled-agent/src/bootstrap/client.rs +++ b/sled-agent/src/bootstrap/client.rs @@ -12,13 +12,14 @@ use crate::bootstrap::views::Response; use crate::bootstrap::views::ResponseEnvelope; use sled_agent_types::sled::StartSledAgentRequest; use slog::Logger; +use sprockets_tls::client::Client as SprocketsClient; +use sprockets_tls::ipcc::{new_tls_client_config, IpccSprocketsClientConfig}; use std::borrow::Cow; use std::io; use std::net::SocketAddrV6; use thiserror::Error; use tokio::io::AsyncReadExt; use tokio::io::AsyncWriteExt; -use tokio::net::TcpStream; #[derive(Debug, Error)] pub enum Error { @@ -67,12 +68,12 @@ pub enum Error { /// bootstrap agent. pub(crate) struct Client { addr: SocketAddrV6, - _log: Logger, + log: Logger, } impl Client { - pub(crate) fn new(addr: SocketAddrV6, _log: Logger) -> Self { - Self { addr, _log } + pub(crate) fn new(addr: SocketAddrV6, log: Logger) -> Self { + Self { addr, log } } /// Start sled agent by sending an initialization request determined from @@ -100,10 +101,27 @@ impl Client { // far larger than we ever expect to see. const MAX_RESPONSE_LEN: u32 = 16 << 20; + let log = self.log.new(o!("component" => "SledAgentSprocketsClient")); // Establish connection and sprockets connection (if possible). - let stream = TcpStream::connect(self.addr) - .await - .map_err(|err| Error::Connect { addr: self.addr, err })?; + //let stream = TcpStream::connect(self.addr) + // .await + // .map_err(|err| Error::Connect { addr: self.addr, err })?; + let client_config = new_tls_client_config( + IpccSprocketsClientConfig { + root_keydir: "/usr/share/oxide/idcerts".into(), + roots: vec![ + "staging.pem".to_string(), + "production.pem".to_string(), + ], + }, + log.clone(), + ) + .unwrap(); + + let stream = + SprocketsClient::connect(client_config, self.addr, log.clone()) + .await + .unwrap(); let mut stream = Box::new(tokio::io::BufStream::new(stream)); diff --git a/sled-agent/src/bootstrap/sprockets_server.rs b/sled-agent/src/bootstrap/sprockets_server.rs index 8d92970d54f..125166cbd25 100644 --- a/sled-agent/src/bootstrap/sprockets_server.rs +++ b/sled-agent/src/bootstrap/sprockets_server.rs @@ -12,12 +12,14 @@ use crate::bootstrap::views::ResponseEnvelope; use crate::bootstrap::views::SledAgentResponse; use sled_agent_types::sled::StartSledAgentRequest; use slog::Logger; +use sprockets_tls::ipcc::{new_tls_server_config, IpccSprocketsServerConfig}; +use sprockets_tls::server::Server; +use sprockets_tls::Stream; use std::io; use std::net::SocketAddrV6; use tokio::io::AsyncReadExt; use tokio::io::AsyncWriteExt; use tokio::io::BufStream; -use tokio::net::TcpListener; use tokio::net::TcpStream; use tokio::sync::mpsc; use tokio::sync::oneshot; @@ -28,7 +30,7 @@ type TxRequestsChannel = mpsc::Sender<( )>; pub(super) struct SprocketsServer { - listener: TcpListener, + listener: Server, tx_requests: TxRequestsChannel, log: Logger, } @@ -39,8 +41,21 @@ impl SprocketsServer { tx_requests: TxRequestsChannel, base_log: &Logger, ) -> io::Result { - let listener = TcpListener::bind(bind_addr).await?; + //let listener = TcpListener::bind(bind_addr).await?; let log = base_log.new(o!("component" => "SledAgentSprocketsServer")); + let config = new_tls_server_config( + IpccSprocketsServerConfig { + root_keydir: "/usr/share/oxide/idcerts".into(), + roots: vec![ + "staging.pem".to_string(), + "production.pem".to_string(), + ], + }, + log.clone(), + ) + .unwrap(); + let listener = + Server::listen(config, bind_addr, log.clone()).await.unwrap(); info!(log, "Started listening"; "local_addr" => %bind_addr); Ok(Self { listener, tx_requests, log }) } @@ -52,9 +67,9 @@ impl SprocketsServer { /// `TcpListener::accept()`, which is cancel-safe. Note that cancelling this /// server does not necessarily cancel any outstanding requests that it has /// already received (and which may still be executing). - pub(super) async fn run(self) { + pub(super) async fn run(mut self) { loop { - let (stream, remote_addr) = match self.listener.accept().await { + let stream = match self.listener.accept().await { Ok(conn) => conn, Err(err) => { error!(self.log, "accept() failed"; "err" => #%err); @@ -62,7 +77,7 @@ impl SprocketsServer { } }; - let log = self.log.new(o!("remote_addr" => remote_addr)); + let log = self.log.new(o!("remote_addr" => "XXXX")); info!(log, "Accepted connection"); let tx_requests = self.tx_requests.clone(); @@ -79,7 +94,7 @@ impl SprocketsServer { } async fn handle_start_sled_agent_request( - stream: TcpStream, + stream: Stream, tx_requests: TxRequestsChannel, log: &Logger, ) -> Result<(), String> { @@ -131,7 +146,7 @@ async fn handle_start_sled_agent_request( } async fn read_request( - stream: &mut Box>, + stream: &mut Box>>, ) -> Result, String> { // Bound to avoid allocating an unreasonable amount of memory from a bogus // length prefix from a client. We authenticate clients via sprockets before @@ -175,7 +190,7 @@ async fn read_request( } async fn write_response( - stream: &mut Box>, + stream: &mut Box>>, response: Result, ) -> Result<(), String> { // Build and serialize response. diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index ab1f8b971ea..94ec9ec571f 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -35,12 +35,13 @@ cipher = { version = "0.4.4", default-features = false, features = ["block-paddi clap = { version = "4.5.16", features = ["cargo", "derive", "env", "wrap_help"] } clap_builder = { version = "4.5.15", default-features = false, features = ["cargo", "color", "env", "std", "suggestions", "usage", "wrap_help"] } console = { version = "0.15.8" } -const-oid = { version = "0.9.6", default-features = false, features = ["db", "std"] } crossbeam-epoch = { version = "0.9.18" } crossbeam-utils = { version = "0.8.19" } crypto-common = { version = "0.1.6", default-features = false, features = ["getrandom", "std"] } -der = { version = "0.7.9", default-features = false, features = ["derive", "flagset", "oid", "pem", "std"] } +curve25519-dalek = { version = "4.1.3", features = ["digest", "legacy_compatibility", "rand_core"] } digest = { version = "0.10.7", features = ["mac", "oid", "std"] } +ecdsa = { version = "0.16.9", features = ["pem", "signing", "std", "verifying"] } +ed25519-dalek = { version = "2.1.1", features = ["digest", "pkcs8", "rand_core"] } either = { version = "1.13.0" } elliptic-curve = { version = "0.13.8", features = ["ecdh", "hazmat", "pem", "std"] } ff = { version = "0.13.0", default-features = false, features = ["alloc"] } @@ -102,6 +103,7 @@ sha2 = { version = "0.10.8", features = ["oid"] } similar = { version = "2.6.0", features = ["bytes", "inline", "unicode"] } slog = { version = "2.7.0", features = ["dynamic-keys", "max_level_trace", "release_max_level_debug", "release_max_level_trace"] } smallvec = { version = "1.13.2", default-features = false, features = ["const_new"] } +socket2 = { version = "0.5.7", default-features = false, features = ["all"] } spin = { version = "0.9.8" } string_cache = { version = "0.8.7" } subtle = { version = "2.5.0" } @@ -120,8 +122,9 @@ unicode-normalization = { version = "0.1.23" } usdt = { version = "0.5.0" } usdt-impl = { version = "0.5.0", default-features = false, features = ["asm", "des"] } uuid = { version = "1.10.0", features = ["serde", "v4"] } +x509-cert = { version = "0.2.5" } zerocopy = { version = "0.7.34", features = ["derive", "simd"] } -zeroize = { version = "1.7.0", features = ["std", "zeroize_derive"] } +zeroize = { version = "1.8.1", features = ["std", "zeroize_derive"] } [build-dependencies] ahash = { version = "0.8.11" } @@ -143,12 +146,13 @@ cipher = { version = "0.4.4", default-features = false, features = ["block-paddi clap = { version = "4.5.16", features = ["cargo", "derive", "env", "wrap_help"] } clap_builder = { version = "4.5.15", default-features = false, features = ["cargo", "color", "env", "std", "suggestions", "usage", "wrap_help"] } console = { version = "0.15.8" } -const-oid = { version = "0.9.6", default-features = false, features = ["db", "std"] } crossbeam-epoch = { version = "0.9.18" } crossbeam-utils = { version = "0.8.19" } crypto-common = { version = "0.1.6", default-features = false, features = ["getrandom", "std"] } -der = { version = "0.7.9", default-features = false, features = ["derive", "flagset", "oid", "pem", "std"] } +curve25519-dalek = { version = "4.1.3", features = ["digest", "legacy_compatibility", "rand_core"] } digest = { version = "0.10.7", features = ["mac", "oid", "std"] } +ecdsa = { version = "0.16.9", features = ["pem", "signing", "std", "verifying"] } +ed25519-dalek = { version = "2.1.1", features = ["digest", "pkcs8", "rand_core"] } either = { version = "1.13.0" } elliptic-curve = { version = "0.13.8", features = ["ecdh", "hazmat", "pem", "std"] } ff = { version = "0.13.0", default-features = false, features = ["alloc"] } @@ -210,6 +214,7 @@ sha2 = { version = "0.10.8", features = ["oid"] } similar = { version = "2.6.0", features = ["bytes", "inline", "unicode"] } slog = { version = "2.7.0", features = ["dynamic-keys", "max_level_trace", "release_max_level_debug", "release_max_level_trace"] } smallvec = { version = "1.13.2", default-features = false, features = ["const_new"] } +socket2 = { version = "0.5.7", default-features = false, features = ["all"] } spin = { version = "0.9.8" } string_cache = { version = "0.8.7" } subtle = { version = "2.5.0" } @@ -231,8 +236,9 @@ unicode-xid = { version = "0.2.4" } usdt = { version = "0.5.0" } usdt-impl = { version = "0.5.0", default-features = false, features = ["asm", "des"] } uuid = { version = "1.10.0", features = ["serde", "v4"] } +x509-cert = { version = "0.2.5" } zerocopy = { version = "0.7.34", features = ["derive", "simd"] } -zeroize = { version = "1.7.0", features = ["std", "zeroize_derive"] } +zeroize = { version = "1.8.1", features = ["std", "zeroize_derive"] } [target.x86_64-unknown-linux-gnu.dependencies] dof = { version = "0.3.0", default-features = false, features = ["des"] }