diff --git a/Cargo.lock b/Cargo.lock index 2f5fa4eb0..70d7fadf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4658,7 +4658,7 @@ dependencies = [ [[package]] name = "wasi-experimental-http-wasmtime" version = "0.9.0" -source = "git+https://github.com/deislabs/wasi-experimental-http?rev=4ed321d6943f75546e38bba80e14a59797aa29de#4ed321d6943f75546e38bba80e14a59797aa29de" +source = "git+https://github.com/deislabs/wasi-experimental-http?rev=9a143fa7d8be2a66d6d636c5c1b0c6e2bad68912#9a143fa7d8be2a66d6d636c5c1b0c6e2bad68912" dependencies = [ "anyhow", "bytes 1.1.0", @@ -4689,7 +4689,7 @@ dependencies = [ "tracing", "tracing-futures", "url 2.2.2", - "wasi-experimental-http-wasmtime 0.9.0 (git+https://github.com/deislabs/wasi-experimental-http?rev=4ed321d6943f75546e38bba80e14a59797aa29de)", + "wasi-experimental-http-wasmtime 0.9.0 (git+https://github.com/deislabs/wasi-experimental-http?rev=9a143fa7d8be2a66d6d636c5c1b0c6e2bad68912)", "wit-bindgen-wasmtime", ] diff --git a/crates/outbound-http/Cargo.toml b/crates/outbound-http/Cargo.toml index 2302c5105..f54e4f388 100644 --- a/crates/outbound-http/Cargo.toml +++ b/crates/outbound-http/Cargo.toml @@ -19,5 +19,5 @@ tokio = { version = "1.4.0", features = [ "full" ] } tracing = { version = "0.1", features = [ "log" ] } tracing-futures = "0.2" url = "2.2.1" -wasi-experimental-http-wasmtime = { git = "https://github.com/deislabs/wasi-experimental-http", rev = "4ed321d6943f75546e38bba80e14a59797aa29de" } -wit-bindgen-wasmtime = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "2f46ce4cc072107153da0cefe15bdc69aa5b84d0" } \ No newline at end of file +wasi-experimental-http-wasmtime = { git = "https://github.com/deislabs/wasi-experimental-http", rev = "9a143fa7d8be2a66d6d636c5c1b0c6e2bad68912" } +wit-bindgen-wasmtime = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "2f46ce4cc072107153da0cefe15bdc69aa5b84d0" } diff --git a/crates/outbound-http/src/lib.rs b/crates/outbound-http/src/lib.rs index f1fd0bf43..d0c558ef0 100644 --- a/crates/outbound-http/src/lib.rs +++ b/crates/outbound-http/src/lib.rs @@ -12,6 +12,8 @@ pub use wasi_outbound_http::add_to_linker; wit_bindgen_wasmtime::export!("../../wit/ephemeral/wasi-outbound-http.wit"); +const ALLOW_ALL_HOSTS: &str = "insecure:allow-all"; + /// A very simple implementation for outbound HTTP requests. #[derive(Default, Clone)] pub struct OutboundHttp { @@ -25,7 +27,8 @@ impl OutboundHttp { } /// Check if guest module is allowed to send request to URL, based on the list of - /// allowed hosts defined by the runtime. + /// allowed hosts defined by the runtime. If the list of allowed hosts contains + /// `insecure:allow-all`, then all hosts are allowed. /// If `None` is passed, the guest module is not allowed to send the request. fn is_allowed(url: &str, allowed_hosts: Option>) -> Result { let url_host = Url::parse(url) @@ -35,13 +38,20 @@ impl OutboundHttp { .to_owned(); match allowed_hosts.as_deref() { Some(domains) => { - let allowed: Result, _> = domains.iter().map(|d| Url::parse(d)).collect(); - let allowed = allowed.map_err(|_| HttpError::InvalidUrl)?; - - Ok(allowed - .iter() - .map(|u| u.host_str().unwrap()) - .any(|x| x == url_host.as_str())) + tracing::info!("Allowed hosts: {:?}", domains); + // check domains has any "insecure:allow-all" wildcard + if domains.iter().any(|domain| domain == ALLOW_ALL_HOSTS) { + Ok(true) + } else { + let allowed: Result, _> = + domains.iter().map(|d| Url::parse(d)).collect(); + let allowed = allowed.map_err(|_| HttpError::InvalidUrl)?; + + Ok(allowed + .iter() + .map(|u| u.host_str().unwrap()) + .any(|x| x == url_host.as_str())) + } } None => Ok(false), } diff --git a/examples/http-rust-oubound-http/.cargo/config.toml b/examples/http-rust-oubound-http/.cargo/config.toml new file mode 100644 index 000000000..bc255e30b --- /dev/null +++ b/examples/http-rust-oubound-http/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-wasi" \ No newline at end of file diff --git a/examples/http-rust-oubound-http/Cargo.lock b/examples/http-rust-oubound-http/Cargo.lock new file mode 100644 index 000000000..624475e4e --- /dev/null +++ b/examples/http-rust-oubound-http/Cargo.lock @@ -0,0 +1,358 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" + +[[package]] +name = "async-trait" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "http" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-rust-outbound-http" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "http", + "spin-sdk", + "wit-bindgen-rust", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "proc-macro2" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "pulldown-cmark" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "spin-macro" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "http", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-gen-core", + "wit-bindgen-gen-rust-wasm", + "wit-bindgen-rust", +] + +[[package]] +name = "spin-sdk" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "http", + "spin-macro", + "wasi-experimental-http", + "wit-bindgen-rust", +] + +[[package]] +name = "syn" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tracing" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi-experimental-http" +version = "0.9.0" +source = "git+https://github.com/deislabs/wasi-experimental-http?rev=a82ae3d6c85c4251b3663035febeb8100068f51d#a82ae3d6c85c4251b3663035febeb8100068f51d" +dependencies = [ + "anyhow", + "bytes", + "http", + "thiserror", + "tracing", +] + +[[package]] +name = "wit-bindgen-gen-core" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=2f46ce4cc072107153da0cefe15bdc69aa5b84d0#2f46ce4cc072107153da0cefe15bdc69aa5b84d0" +dependencies = [ + "anyhow", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-gen-rust" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=2f46ce4cc072107153da0cefe15bdc69aa5b84d0#2f46ce4cc072107153da0cefe15bdc69aa5b84d0" +dependencies = [ + "heck", + "wit-bindgen-gen-core", +] + +[[package]] +name = "wit-bindgen-gen-rust-wasm" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=2f46ce4cc072107153da0cefe15bdc69aa5b84d0#2f46ce4cc072107153da0cefe15bdc69aa5b84d0" +dependencies = [ + "heck", + "wit-bindgen-gen-core", + "wit-bindgen-gen-rust", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=2f46ce4cc072107153da0cefe15bdc69aa5b84d0#2f46ce4cc072107153da0cefe15bdc69aa5b84d0" +dependencies = [ + "async-trait", + "bitflags", + "wit-bindgen-rust-impl", +] + +[[package]] +name = "wit-bindgen-rust-impl" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=2f46ce4cc072107153da0cefe15bdc69aa5b84d0#2f46ce4cc072107153da0cefe15bdc69aa5b84d0" +dependencies = [ + "proc-macro2", + "syn", + "wit-bindgen-gen-core", + "wit-bindgen-gen-rust-wasm", +] + +[[package]] +name = "wit-parser" +version = "0.1.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=2f46ce4cc072107153da0cefe15bdc69aa5b84d0#2f46ce4cc072107153da0cefe15bdc69aa5b84d0" +dependencies = [ + "anyhow", + "id-arena", + "pulldown-cmark", + "unicode-normalization", + "unicode-xid", +] diff --git a/examples/http-rust-oubound-http/Cargo.toml b/examples/http-rust-oubound-http/Cargo.toml new file mode 100644 index 000000000..860c58041 --- /dev/null +++ b/examples/http-rust-oubound-http/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "http-rust-outbound-http" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = [ "cdylib" ] + +[dependencies] +# Useful crate to handle errors. +anyhow = "1" +# Crate to simplify working with bytes. +bytes = "1" +# General-purpose crate with common HTTP types. +http = "0.2" +# The Spin SDK. +spin-sdk = { path = "../../sdk/rust", version = "0.1.0" } +# Crate that generates Rust Wasm bindings from a WebAssembly interface. +wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "2f46ce4cc072107153da0cefe15bdc69aa5b84d0" } + +[workspace] \ No newline at end of file diff --git a/examples/http-rust-oubound-http/spin.toml b/examples/http-rust-oubound-http/spin.toml new file mode 100644 index 000000000..ceb8c7907 --- /dev/null +++ b/examples/http-rust-oubound-http/spin.toml @@ -0,0 +1,24 @@ +spin_version = "1" +authors = ["Fermyon Engineering "] +description = "A simple application that makes an outbound http call." +name = "spin-outbound-http" +trigger = { type = "http", base = "/" } +version = "1.0.0" + +[[component]] +id = "rust-outbound-http" +source = "target/wasm32-wasi/release/http_rust_outbound_http.wasm" +allowed_http_hosts = ["https://some-random-api.ml"] +[component.trigger] +route = "/outbound" +[component.build] +command = "cargo build --target wasm32-wasi --release" + +[[component]] +id = "rust-outbound-http-wildcard" +source = "target/wasm32-wasi/release/http_rust_outbound_http.wasm" +allowed_http_hosts = ["insecure:allow-all"] +[component.trigger] +route = "/wildcard" +[component.build] +command = "cargo build --target wasm32-wasi --release" diff --git a/examples/http-rust-oubound-http/src/lib.rs b/examples/http-rust-oubound-http/src/lib.rs new file mode 100644 index 000000000..b245e2c70 --- /dev/null +++ b/examples/http-rust-oubound-http/src/lib.rs @@ -0,0 +1,20 @@ +use anyhow::Result; +use spin_sdk::{ + http::{Request, Response}, + http_component, +}; + +/// Send an HTTP request and return the response. +#[http_component] +fn send_outbound(_req: Request) -> Result { + let mut res = spin_sdk::outbound_http::send_request( + http::Request::builder() + .method("GET") + .uri("https://some-random-api.ml/facts/dog") + .body(None)?, + )?; + res.headers_mut() + .insert("spin-component", "rust-outbound-http".try_into()?); + println!("{:?}", res); + Ok(res) +} \ No newline at end of file