diff --git a/sled-agent/src/http_entrypoints.rs b/sled-agent/src/http_entrypoints.rs index d7c55c537e5..5d14f74ac8d 100644 --- a/sled-agent/src/http_entrypoints.rs +++ b/sled-agent/src/http_entrypoints.rs @@ -1853,9 +1853,11 @@ impl SledAgentApi for SledAgentImpl { path_params: Path, ) -> Result, HttpError> { let sa = request_context.context(); - let rot = sa.rot_attestor(path_params.into_inner().rot); sa.latencies() .instrument_dropshot_handler(&request_context, async { + let remote_addr = request_context.request.remote_addr(); + let rot = + sa.rot_attestor(path_params.into_inner().rot, remote_addr)?; let log = rot.get_measurement_log().await?; Ok(HttpResponseOk(log.into())) }) @@ -1867,9 +1869,11 @@ impl SledAgentApi for SledAgentImpl { path_params: Path, ) -> Result, HttpError> { let sa = request_context.context(); - let rot = sa.rot_attestor(path_params.into_inner().rot); sa.latencies() .instrument_dropshot_handler(&request_context, async { + let remote_addr = request_context.request.remote_addr(); + let rot = + sa.rot_attestor(path_params.into_inner().rot, remote_addr)?; let chain = rot.get_certificate_chain().await?; Ok(HttpResponseOk(chain.into())) }) @@ -1882,10 +1886,12 @@ impl SledAgentApi for SledAgentImpl { body: TypedBody, ) -> Result, HttpError> { let sa = request_context.context(); - let rot = sa.rot_attestor(path_params.into_inner().rot); let nonce = body.into_inner(); sa.latencies() .instrument_dropshot_handler(&request_context, async { + let remote_addr = request_context.request.remote_addr(); + let rot = + sa.rot_attestor(path_params.into_inner().rot, remote_addr)?; let attestation = rot.attest(nonce.into()).await?; Ok(HttpResponseOk(attestation.into())) }) diff --git a/sled-agent/src/sled_agent.rs b/sled-agent/src/sled_agent.rs index 4f9b682920e..3f16ccac89b 100644 --- a/sled-agent/src/sled_agent.rs +++ b/sled-agent/src/sled_agent.rs @@ -104,7 +104,7 @@ use slog::Logger; use slog_error_chain::{InlineErrorChain, SlogInlineError}; use sprockets_tls::keys::SprocketsConfig; use std::collections::BTreeMap; -use std::net::{Ipv6Addr, SocketAddrV6}; +use std::net::{Ipv6Addr, SocketAddr, SocketAddrV6}; use std::sync::Arc; use uuid::Uuid; @@ -795,10 +795,16 @@ impl SledAgent { &self.inner.hardware_monitor } - pub(crate) fn rot_attestor(&self, rot: Rot) -> &RotAttestationHandle { + pub(crate) fn rot_attestor( + &self, + rot: Rot, + remote_addr: SocketAddr, + ) -> Result<&RotAttestationHandle, HttpError> { // We currently only support the LPC55 RoT let Rot::Oxide = rot; - &self.inner.rot_attestor + // And we only serve sled-local clients + self.ensure_sled_local_request(remote_addr)?; + Ok(&self.inner.rot_attestor) } /// Trigger a request to Nexus informing it that the current sled exists, @@ -1100,6 +1106,30 @@ impl SledAgent { .map_err(Error::from) } + /// Validate if the given [`SocketAddr`] represents a peer on the same + /// underlay subnet as the current sled. + pub fn ensure_sled_local_request( + &self, + remote_addr: SocketAddr, + ) -> Result<(), HttpError> { + let SocketAddr::V6(remote_addr) = remote_addr else { + return Err(HttpError::for_client_error( + None, + dropshot::ClientErrorStatusCode::FORBIDDEN, + String::from("unexpected non-v6 request"), + )); + }; + let underlay_subnet = self.inner.subnet.net(); + if !underlay_subnet.contains(*remote_addr.ip()) { + return Err(HttpError::for_client_error( + None, + dropshot::ClientErrorStatusCode::FORBIDDEN, + String::from("non-sled-local request not allowed"), + )); + } + Ok(()) + } + pub fn bootstore(&self) -> bootstore::NodeHandle { self.inner.bootstore.clone() }