diff --git a/Cargo.lock b/Cargo.lock index 26749f14ca..05d678d77e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4376,7 +4376,7 @@ dependencies = [ [[package]] name = "outbound-http" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 0.2.12", @@ -4394,7 +4394,7 @@ dependencies = [ [[package]] name = "outbound-mqtt" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "rumqttc", @@ -4410,7 +4410,7 @@ dependencies = [ [[package]] name = "outbound-mysql" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "flate2", @@ -4429,7 +4429,7 @@ dependencies = [ [[package]] name = "outbound-pg" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "native-tls", @@ -4447,7 +4447,7 @@ dependencies = [ [[package]] name = "outbound-redis" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "redis 0.21.7", @@ -5330,7 +5330,7 @@ dependencies = [ [[package]] name = "runtime-tests" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "env_logger", @@ -5950,7 +5950,7 @@ dependencies = [ [[package]] name = "spin-app" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -5965,7 +5965,7 @@ dependencies = [ [[package]] name = "spin-build" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "futures", @@ -5981,7 +5981,7 @@ dependencies = [ [[package]] name = "spin-cli" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6064,7 +6064,7 @@ dependencies = [ [[package]] name = "spin-common" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "dirs 4.0.0", @@ -6076,7 +6076,7 @@ dependencies = [ [[package]] name = "spin-componentize" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6099,7 +6099,7 @@ dependencies = [ [[package]] name = "spin-core" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6124,7 +6124,7 @@ dependencies = [ [[package]] name = "spin-doctor" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6145,7 +6145,7 @@ dependencies = [ [[package]] name = "spin-expressions" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6160,7 +6160,7 @@ dependencies = [ [[package]] name = "spin-http" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 1.1.0", @@ -6179,7 +6179,7 @@ dependencies = [ [[package]] name = "spin-key-value" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "lru 0.9.0", @@ -6193,7 +6193,7 @@ dependencies = [ [[package]] name = "spin-key-value-azure" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "azure_data_cosmos", @@ -6207,7 +6207,7 @@ dependencies = [ [[package]] name = "spin-key-value-redis" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "redis 0.21.7", @@ -6220,7 +6220,7 @@ dependencies = [ [[package]] name = "spin-key-value-sqlite" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "once_cell", @@ -6233,7 +6233,7 @@ dependencies = [ [[package]] name = "spin-llm" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "bytesize", @@ -6245,7 +6245,7 @@ dependencies = [ [[package]] name = "spin-llm-local" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "candle-core", @@ -6269,7 +6269,7 @@ dependencies = [ [[package]] name = "spin-llm-remote-http" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 0.2.12", @@ -6286,7 +6286,7 @@ dependencies = [ [[package]] name = "spin-loader" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6324,7 +6324,7 @@ dependencies = [ [[package]] name = "spin-locked-app" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6337,7 +6337,7 @@ dependencies = [ [[package]] name = "spin-manifest" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "glob", @@ -6354,7 +6354,7 @@ dependencies = [ [[package]] name = "spin-oci" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-compression", @@ -6382,7 +6382,7 @@ dependencies = [ [[package]] name = "spin-outbound-networking" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 1.1.0", @@ -6396,7 +6396,7 @@ dependencies = [ [[package]] name = "spin-plugins" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "bytes", @@ -6422,7 +6422,7 @@ dependencies = [ [[package]] name = "spin-serde" -version = "2.4.2" +version = "2.4.3" dependencies = [ "base64 0.21.7", "serde", @@ -6430,7 +6430,7 @@ dependencies = [ [[package]] name = "spin-sqlite" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6443,7 +6443,7 @@ dependencies = [ [[package]] name = "spin-sqlite-inproc" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6457,7 +6457,7 @@ dependencies = [ [[package]] name = "spin-sqlite-libsql" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6471,7 +6471,7 @@ dependencies = [ [[package]] name = "spin-telemetry" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 0.2.12", @@ -6489,7 +6489,7 @@ dependencies = [ [[package]] name = "spin-templates" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6523,7 +6523,7 @@ dependencies = [ [[package]] name = "spin-testing" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 1.1.0", @@ -6541,7 +6541,7 @@ dependencies = [ [[package]] name = "spin-trigger" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6592,7 +6592,7 @@ dependencies = [ [[package]] name = "spin-trigger-http" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6633,7 +6633,7 @@ dependencies = [ [[package]] name = "spin-trigger-redis" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6653,7 +6653,7 @@ dependencies = [ [[package]] name = "spin-variables" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -6672,7 +6672,7 @@ dependencies = [ [[package]] name = "spin-world" -version = "2.4.2" +version = "2.4.3" dependencies = [ "wasmtime", ] @@ -6853,7 +6853,7 @@ dependencies = [ [[package]] name = "table" -version = "2.4.2" +version = "2.4.3" [[package]] name = "tar" @@ -6901,7 +6901,7 @@ dependencies = [ [[package]] name = "terminal" -version = "2.4.2" +version = "2.4.3" dependencies = [ "atty", "once_cell", @@ -7536,7 +7536,7 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "ui-testing" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "dirs 4.0.0", diff --git a/Cargo.toml b/Cargo.toml index 0778f036a1..1b77025bb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = { workspace = true } license = { workspace = true } [workspace.package] -version = "2.4.2" +version = "2.4.3" authors = ["Fermyon Engineering "] edition = "2021" license = "Apache-2.0 WITH LLVM-exception" diff --git a/crates/trigger-http/benches/baseline.rs b/crates/trigger-http/benches/baseline.rs index a925c4fbb4..2eac1aa6b0 100644 --- a/crates/trigger-http/benches/baseline.rs +++ b/crates/trigger-http/benches/baseline.rs @@ -114,7 +114,12 @@ async fn run(trigger: &HttpTrigger, path: &str) { .body(Default::default()) .unwrap(); let resp = trigger - .handle(req, Scheme::HTTP, "127.0.0.1:55555".parse().unwrap()) + .handle( + req, + Scheme::HTTP, + "127.0.0.1:3000".parse().unwrap(), + "127.0.0.1:55555".parse().unwrap(), + ) .await .unwrap(); assert_http_response_success(&resp); diff --git a/crates/trigger-http/src/lib.rs b/crates/trigger-http/src/lib.rs index e4db3fbd1b..387b02e50a 100644 --- a/crates/trigger-http/src/lib.rs +++ b/crates/trigger-http/src/lib.rs @@ -226,9 +226,10 @@ impl HttpTrigger { &self, mut req: Request, scheme: Scheme, - addr: SocketAddr, + server_addr: SocketAddr, + client_addr: SocketAddr, ) -> Result> { - set_req_uri(&mut req, scheme)?; + set_req_uri(&mut req, scheme, server_addr)?; strip_forbidden_headers(&mut req); spin_telemetry::extract_trace_context(&req); @@ -266,7 +267,7 @@ impl HttpTrigger { &self.base, &trigger.route, req, - addr, + client_addr, ) .await } @@ -281,7 +282,7 @@ impl HttpTrigger { &self.base, &trigger.route, req, - addr, + client_addr, ) .await } @@ -329,7 +330,8 @@ impl HttpTrigger { fn serve_connection( self_: Arc, stream: S, - addr: SocketAddr, + server_addr: SocketAddr, + client_addr: SocketAddr, ) { task::spawn(async move { if let Err(e) = http1::Builder::new() @@ -342,8 +344,8 @@ impl HttpTrigger { "handle_http_request", "otel.kind" = "server", "http.request.method" = %request.method(), - "network.peer.address" = %addr.ip(), - "network.peer.port" = %addr.port(), + "network.peer.address" = %client_addr.ip(), + "network.peer.port" = %client_addr.port(), "network.protocol.name" = "http", "url.path" = request.uri().path(), "url.query" = request.uri().query().unwrap_or(""), @@ -362,7 +364,8 @@ impl HttpTrigger { .boxed() }), Scheme::HTTP, - addr, + server_addr, + client_addr, ) .instrument(span) .await @@ -384,8 +387,8 @@ impl HttpTrigger { .with_context(|| format!("Unable to listen on {}", listen_addr))?; loop { - let (stream, addr) = listener.accept().await?; - Self::serve_connection(self_.clone(), stream, addr); + let (stream, client_addr) = listener.accept().await?; + Self::serve_connection(self_.clone(), stream, listen_addr, client_addr); } } @@ -401,7 +404,7 @@ impl HttpTrigger { loop { let (stream, addr) = listener.accept().await?; match acceptor.accept(stream).await { - Ok(stream) => Self::serve_connection(self_.clone(), stream, addr), + Ok(stream) => Self::serve_connection(self_.clone(), stream, listen_addr, addr), Err(err) => tracing::error!(?err, "Failed to start TLS session"), } } @@ -421,21 +424,15 @@ fn parse_listen_addr(addr: &str) -> anyhow::Result { addrs.into_iter().next().context("couldn't resolve address") } -fn set_req_uri(req: &mut Request, scheme: Scheme) -> Result<()> { - const DEFAULT_HOST: &str = "localhost"; - - let authority_hdr = req - .headers() - .get(http::header::HOST) - .map(|h| h.to_str().context("Expected UTF8 header value (authority)")) - .unwrap_or(Ok(DEFAULT_HOST))?; +/// The incoming request's scheme and authority +/// +/// The incoming request's URI is relative to the server, so we need to set the scheme and authority +fn set_req_uri(req: &mut Request, scheme: Scheme, addr: SocketAddr) -> Result<()> { let uri = req.uri().clone(); let mut parts = uri.into_parts(); - parts.authority = authority_hdr - .parse() - .map(Option::Some) - .map_err(|e| anyhow::anyhow!("Invalid authority {:?}", e))?; + let authority = format!("{}:{}", addr.ip(), addr.port()).parse().unwrap(); parts.scheme = Some(scheme); + parts.authority = Some(authority); *req.uri_mut() = Uri::from_parts(parts).unwrap(); Ok(()) } diff --git a/examples/spin-timer/Cargo.lock b/examples/spin-timer/Cargo.lock index 757d7054c0..d49b3b1383 100644 --- a/examples/spin-timer/Cargo.lock +++ b/examples/spin-timer/Cargo.lock @@ -2731,7 +2731,7 @@ dependencies = [ [[package]] name = "outbound-http" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 0.2.11", @@ -2749,7 +2749,7 @@ dependencies = [ [[package]] name = "outbound-mqtt" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "rumqttc", @@ -2765,7 +2765,7 @@ dependencies = [ [[package]] name = "outbound-mysql" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "flate2", @@ -2784,7 +2784,7 @@ dependencies = [ [[package]] name = "outbound-pg" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "native-tls", @@ -2802,7 +2802,7 @@ dependencies = [ [[package]] name = "outbound-redis" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "redis", @@ -3901,7 +3901,7 @@ dependencies = [ [[package]] name = "spin-app" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -3916,7 +3916,7 @@ dependencies = [ [[package]] name = "spin-common" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "dirs 4.0.0", @@ -3928,7 +3928,7 @@ dependencies = [ [[package]] name = "spin-componentize" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "wasm-encoder 0.200.0", @@ -3939,7 +3939,7 @@ dependencies = [ [[package]] name = "spin-core" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -3961,7 +3961,7 @@ dependencies = [ [[package]] name = "spin-expressions" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -3974,7 +3974,7 @@ dependencies = [ [[package]] name = "spin-key-value" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "lru 0.9.0", @@ -3988,7 +3988,7 @@ dependencies = [ [[package]] name = "spin-key-value-azure" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "azure_data_cosmos", @@ -4002,7 +4002,7 @@ dependencies = [ [[package]] name = "spin-key-value-redis" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "redis", @@ -4015,7 +4015,7 @@ dependencies = [ [[package]] name = "spin-key-value-sqlite" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "once_cell", @@ -4028,7 +4028,7 @@ dependencies = [ [[package]] name = "spin-llm" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "bytesize", @@ -4040,7 +4040,7 @@ dependencies = [ [[package]] name = "spin-llm-remote-http" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 0.2.11", @@ -4057,7 +4057,7 @@ dependencies = [ [[package]] name = "spin-loader" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4094,7 +4094,7 @@ dependencies = [ [[package]] name = "spin-locked-app" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4107,7 +4107,7 @@ dependencies = [ [[package]] name = "spin-manifest" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -4121,7 +4121,7 @@ dependencies = [ [[package]] name = "spin-outbound-networking" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 1.0.0", @@ -4135,7 +4135,7 @@ dependencies = [ [[package]] name = "spin-serde" -version = "2.4.2" +version = "2.4.3" dependencies = [ "base64 0.21.7", "serde", @@ -4143,7 +4143,7 @@ dependencies = [ [[package]] name = "spin-sqlite" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4156,7 +4156,7 @@ dependencies = [ [[package]] name = "spin-sqlite-inproc" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4170,7 +4170,7 @@ dependencies = [ [[package]] name = "spin-sqlite-libsql" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4184,7 +4184,7 @@ dependencies = [ [[package]] name = "spin-telemetry" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "http 0.2.11", @@ -4202,7 +4202,7 @@ dependencies = [ [[package]] name = "spin-trigger" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4251,7 +4251,7 @@ dependencies = [ [[package]] name = "spin-variables" -version = "2.4.2" +version = "2.4.3" dependencies = [ "anyhow", "async-trait", @@ -4269,7 +4269,7 @@ dependencies = [ [[package]] name = "spin-world" -version = "2.4.2" +version = "2.4.3" dependencies = [ "wasmtime", ] @@ -4425,7 +4425,7 @@ dependencies = [ [[package]] name = "table" -version = "2.4.2" +version = "2.4.3" [[package]] name = "tar" @@ -4467,7 +4467,7 @@ dependencies = [ [[package]] name = "terminal" -version = "2.4.2" +version = "2.4.3" dependencies = [ "atty", "once_cell", diff --git a/tests/integration.rs b/tests/integration.rs index 762e9b3fa2..36bce277ce 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1346,4 +1346,30 @@ route = "/..." Ok(()) } + + #[test] + /// Test that the HOST header does not allow outbound http arbitrary calls to hosts + fn test_spin_inbound_http_host_header() -> anyhow::Result<()> { + run_test( + "outbound-http-to-same-app", + SpinAppType::Http, + [], + testing_framework::ServicesConfig::none(), + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::full( + Method::GET, + "/test/outbound-allowed/hello", + &[("Host", "google.com")], + Some(""), + ), + Response::new_with_body(200, "Hello, Fermyon!\n"), + )?; + Ok(()) + }, + )?; + Ok(()) + } } diff --git a/tests/testing-framework/src/runtimes/in_process_spin.rs b/tests/testing-framework/src/runtimes/in_process_spin.rs index 117ef99cd2..aa63acb367 100644 --- a/tests/testing-framework/src/runtimes/in_process_spin.rs +++ b/tests/testing-framework/src/runtimes/in_process_spin.rs @@ -33,7 +33,8 @@ impl InProcessSpin { .handle( req, http::uri::Scheme::HTTP, - (std::net::Ipv4Addr::LOCALHOST, 80).into(), + (std::net::Ipv4Addr::LOCALHOST, 3000).into(), + (std::net::Ipv4Addr::LOCALHOST, 7000).into(), ) .await?; use http_body_util::BodyExt;