xref: /wasmtime-44.0.1/crates/wasi-tls/src/lib.rs (revision 51732cfe)
1 //! # Wasmtime's [wasi-tls] (Transport Layer Security) Implementation
2 //!
3 //! This crate provides the Wasmtime host implementation for the [wasi-tls] API.
4 //! The [wasi-tls] world allows WebAssembly modules to perform SSL/TLS operations,
5 //! such as establishing secure connections to servers. TLS often relies on other wasi networking systems
6 //! to provide the stream so it will be common to enable the [wasi:cli] world as well with the networking features enabled.
7 //!
8 //! # An example of how to configure [wasi-tls] is the following:
9 //!
10 //! ```rust
11 //! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};
12 //! use wasmtime::{
13 //!     component::{Linker, ResourceTable},
14 //!     Store, Engine, Result,
15 //! };
16 //! use wasmtime_wasi_tls::{WasiTlsCtx, WasiTlsCtxBuilder, WasiTlsView, WasiTlsCtxView};
17 //! use wasmtime_wasi_tls::p2::LinkOptions;
18 //!
19 //! struct Ctx {
20 //!     table: ResourceTable,
21 //!     wasi_ctx: WasiCtx,
22 //!     wasi_tls_ctx: WasiTlsCtx,
23 //! }
24 //!
25 //! impl WasiView for Ctx {
26 //!     fn ctx(&mut self) -> WasiCtxView<'_> {
27 //!         WasiCtxView { ctx: &mut self.wasi_ctx, table: &mut self.table }
28 //!     }
29 //! }
30 //!
31 //! impl WasiTlsView for Ctx {
32 //!     fn tls(&mut self) -> WasiTlsCtxView<'_> {
33 //!         WasiTlsCtxView { ctx: &mut self.wasi_tls_ctx, table: &mut self.table }
34 //!     }
35 //! }
36 //!
37 //! #[tokio::main]
38 //! async fn main() -> Result<()> {
39 //!     let ctx = Ctx {
40 //!         table: ResourceTable::new(),
41 //!         wasi_ctx: WasiCtx::builder()
42 //!             .inherit_stderr()
43 //!             .inherit_network()
44 //!             .allow_ip_name_lookup(true)
45 //!             .build(),
46 //!         wasi_tls_ctx: WasiTlsCtxBuilder::new()
47 //!             // Optionally, configure a specific TLS provider:
48 //!             // .provider(Box::new(wasmtime_wasi_tls::RustlsProvider::default()))
49 //!             // .provider(Box::new(wasmtime_wasi_tls::NativeTlsProvider::default()))
50 //!             // .provider(Box::new(wasmtime_wasi_tls::OpenSslProvider::default()))
51 //!             .build(),
52 //!     };
53 //!
54 //!     let engine = Engine::default();
55 //!
56 //!     // Set up wasi-cli
57 //!     let mut store = Store::new(&engine, ctx);
58 //!     let mut linker: Linker<Ctx> = Linker::new(&engine);
59 //!     wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
60 //!
61 //!     // Add wasi-tls types and turn on the feature in linker
62 //!     let mut opts = LinkOptions::default();
63 //!     opts.tls(true);
64 //!     wasmtime_wasi_tls::p2::add_to_linker(&mut linker, &opts)?;
65 //!
66 //!     // ... use `linker` to instantiate within `store` ...
67 //!     Ok(())
68 //! }
69 //!
70 //! ```
71 //! [wasi-tls]: https://github.com/WebAssembly/wasi-tls
72 //! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest
73 
74 #![deny(missing_docs)]
75 #![doc(test(attr(deny(warnings))))]
76 #![doc(test(attr(allow(dead_code, unused_variables, unused_mut))))]
77 
78 use tokio::io::{AsyncRead, AsyncWrite};
79 mod error;
80 mod providers;
81 
82 /// WASIp2 (`wasi:[email protected]`) host implementation.
83 #[cfg(feature = "p2")]
84 pub mod p2;
85 /// WASIp3 (`wasi:[email protected]`) host implementation.
86 #[cfg(feature = "p3")]
87 pub mod p3;
88 
89 pub use error::Error;
90 pub use providers::*;
91 
92 #[cfg(any(feature = "p2", feature = "p3"))]
93 use wasmtime::component::{HasData, ResourceTable};
94 
95 /// Builder-style structure used to create a [`WasiTlsCtx`].
96 #[cfg(any(feature = "p2", feature = "p3"))]
97 pub struct WasiTlsCtxBuilder {
98     provider: Box<dyn TlsProvider>,
99 }
100 #[cfg(any(feature = "p2", feature = "p3"))]
101 impl WasiTlsCtxBuilder {
102     /// Creates a builder for a new context with default parameters set.
new() -> Self103     pub fn new() -> Self {
104         Default::default()
105     }
106 
107     /// Configure the TLS provider to use for this context.
108     ///
109     /// By default, this is set to the [`DefaultProvider`] which is picked at
110     /// compile time based on feature flags. If this crate is compiled with
111     /// multiple TLS providers, this method can be used to specify the provider
112     /// at runtime.
provider(mut self, provider: Box<dyn TlsProvider>) -> Self113     pub fn provider(mut self, provider: Box<dyn TlsProvider>) -> Self {
114         self.provider = provider;
115         self
116     }
117 
118     /// Uses the configured context so far to construct the final [`WasiTlsCtx`].
build(self) -> WasiTlsCtx119     pub fn build(self) -> WasiTlsCtx {
120         WasiTlsCtx {
121             provider: self.provider,
122         }
123     }
124 }
125 #[cfg(any(feature = "p2", feature = "p3"))]
126 impl Default for WasiTlsCtxBuilder {
default() -> Self127     fn default() -> Self {
128         Self {
129             provider: Box::new(DefaultProvider::default()),
130         }
131     }
132 }
133 
134 /// Wasi TLS context needed for internal `wasi-tls` state.
135 #[cfg(any(feature = "p2", feature = "p3"))]
136 pub struct WasiTlsCtx {
137     pub(crate) provider: Box<dyn TlsProvider>,
138 }
139 
140 /// The type for which this crate implements the `wasi:tls` interfaces.
141 #[cfg(any(feature = "p2", feature = "p3"))]
142 pub(crate) struct WasiTls;
143 #[cfg(any(feature = "p2", feature = "p3"))]
144 impl HasData for WasiTls {
145     type Data<'a> = WasiTlsCtxView<'a>;
146 }
147 
148 /// View into [`WasiTlsCtx`] implementation and [`ResourceTable`].
149 #[cfg(any(feature = "p2", feature = "p3"))]
150 pub struct WasiTlsCtxView<'a> {
151     /// Mutable reference to table used to manage resources.
152     pub table: &'a mut ResourceTable,
153 
154     /// Mutable reference to the WASI TLS context.
155     pub ctx: &'a mut WasiTlsCtx,
156 }
157 
158 /// A trait which provides internal WASI TLS state.
159 #[cfg(any(feature = "p2", feature = "p3"))]
160 pub trait WasiTlsView: Send {
161     /// Return a [`WasiTlsCtxView`] from mutable reference to self.
tls(&mut self) -> WasiTlsCtxView<'_>162     fn tls(&mut self) -> WasiTlsCtxView<'_>;
163 }
164 
165 /// The data stream that carries the encrypted TLS data.
166 /// Typically this is a TCP stream.
167 pub trait TlsTransport: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
168 impl<T: AsyncRead + AsyncWrite + Send + Unpin + ?Sized + 'static> TlsTransport for T {}
169 
170 /// A TLS connection.
171 pub trait TlsStream: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
172 
173 /// A TLS implementation.
174 pub trait TlsProvider: Send + Sync + 'static {
175     /// Set up a client TLS connection using the provided `server_name` and `transport`.
connect(&self, server_name: String, transport: Box<dyn TlsTransport>) -> BoxFutureTlsStream176     fn connect(&self, server_name: String, transport: Box<dyn TlsTransport>) -> BoxFutureTlsStream;
177 }
178 
179 pub(crate) type BoxFutureTlsStream =
180     std::pin::Pin<Box<dyn Future<Output = Result<Box<dyn TlsStream>, Error>> + Send>>;
181