Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi-tls/src/lib.rs
1692 views
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, Config
15
//! };
16
//! use wasmtime_wasi_tls::{LinkOptions, WasiTls, WasiTlsCtx, WasiTlsCtxBuilder};
17
//!
18
//! struct Ctx {
19
//! table: ResourceTable,
20
//! wasi_ctx: WasiCtx,
21
//! wasi_tls_ctx: WasiTlsCtx,
22
//! }
23
//!
24
//! impl WasiView for Ctx {
25
//! fn ctx(&mut self) -> WasiCtxView<'_> {
26
//! WasiCtxView { ctx: &mut self.wasi_ctx, table: &mut self.table }
27
//! }
28
//! }
29
//!
30
//! #[tokio::main]
31
//! async fn main() -> Result<()> {
32
//! let ctx = Ctx {
33
//! table: ResourceTable::new(),
34
//! wasi_ctx: WasiCtx::builder()
35
//! .inherit_stderr()
36
//! .inherit_network()
37
//! .allow_ip_name_lookup(true)
38
//! .build(),
39
//! wasi_tls_ctx: WasiTlsCtxBuilder::new()
40
//! // Optionally, configure a different TLS provider:
41
//! // .provider(Box::new(wasmtime_wasi_tls_nativetls::NativeTlsProvider::default()))
42
//! .build(),
43
//! };
44
//!
45
//! let mut config = Config::new();
46
//! config.async_support(true);
47
//! let engine = Engine::new(&config)?;
48
//!
49
//! // Set up wasi-cli
50
//! let mut store = Store::new(&engine, ctx);
51
//! let mut linker = Linker::new(&engine);
52
//! wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;
53
//!
54
//! // Add wasi-tls types and turn on the feature in linker
55
//! let mut opts = LinkOptions::default();
56
//! opts.tls(true);
57
//! wasmtime_wasi_tls::add_to_linker(&mut linker, &mut opts, |h: &mut Ctx| {
58
//! WasiTls::new(&h.wasi_tls_ctx, &mut h.table)
59
//! })?;
60
//!
61
//! // ... use `linker` to instantiate within `store` ...
62
//! Ok(())
63
//! }
64
//!
65
//! ```
66
//! [wasi-tls]: https://github.com/WebAssembly/wasi-tls
67
//! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest
68
69
#![deny(missing_docs)]
70
#![doc(test(attr(deny(warnings))))]
71
#![doc(test(attr(allow(dead_code, unused_variables, unused_mut))))]
72
73
use tokio::io::{AsyncRead, AsyncWrite};
74
use wasmtime::component::{HasData, ResourceTable};
75
76
pub mod bindings;
77
mod host;
78
mod io;
79
mod rustls;
80
81
pub use bindings::types::LinkOptions;
82
pub use host::{HostClientConnection, HostClientHandshake, HostFutureClientStreams};
83
pub use rustls::RustlsProvider;
84
85
/// Capture the state necessary for use in the `wasi-tls` API implementation.
86
pub struct WasiTls<'a> {
87
ctx: &'a WasiTlsCtx,
88
table: &'a mut ResourceTable,
89
}
90
91
impl<'a> WasiTls<'a> {
92
/// Create a new Wasi TLS context
93
pub fn new(ctx: &'a WasiTlsCtx, table: &'a mut ResourceTable) -> Self {
94
Self { ctx, table }
95
}
96
}
97
98
/// Add the `wasi-tls` world's types to a [`wasmtime::component::Linker`].
99
pub fn add_to_linker<T: Send + 'static>(
100
l: &mut wasmtime::component::Linker<T>,
101
opts: &mut LinkOptions,
102
f: fn(&mut T) -> WasiTls<'_>,
103
) -> anyhow::Result<()> {
104
bindings::types::add_to_linker::<_, HasWasiTls>(l, &opts, f)?;
105
Ok(())
106
}
107
108
struct HasWasiTls;
109
impl HasData for HasWasiTls {
110
type Data<'a> = WasiTls<'a>;
111
}
112
113
/// Builder-style structure used to create a [`WasiTlsCtx`].
114
pub struct WasiTlsCtxBuilder {
115
provider: Box<dyn TlsProvider>,
116
}
117
118
impl WasiTlsCtxBuilder {
119
/// Creates a builder for a new context with default parameters set.
120
pub fn new() -> Self {
121
Default::default()
122
}
123
124
/// Configure the TLS provider to use for this context.
125
///
126
/// By default, this is set to the [`RustlsProvider`].
127
pub fn provider(mut self, provider: Box<dyn TlsProvider>) -> Self {
128
self.provider = provider;
129
self
130
}
131
132
/// Uses the configured context so far to construct the final [`WasiTlsCtx`].
133
pub fn build(self) -> WasiTlsCtx {
134
WasiTlsCtx {
135
provider: self.provider,
136
}
137
}
138
}
139
impl Default for WasiTlsCtxBuilder {
140
fn default() -> Self {
141
Self {
142
provider: Box::new(RustlsProvider::default()),
143
}
144
}
145
}
146
147
/// Wasi TLS context needed for internal `wasi-tls` state.
148
pub struct WasiTlsCtx {
149
pub(crate) provider: Box<dyn TlsProvider>,
150
}
151
152
/// The data stream that carries the encrypted TLS data.
153
/// Typically this is a TCP stream.
154
pub trait TlsTransport: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
155
impl<T: AsyncRead + AsyncWrite + Send + Unpin + ?Sized + 'static> TlsTransport for T {}
156
157
/// A TLS connection.
158
pub trait TlsStream: AsyncRead + AsyncWrite + Send + Unpin + 'static {}
159
160
/// A TLS implementation.
161
pub trait TlsProvider: Send + Sync + 'static {
162
/// Set up a client TLS connection using the provided `server_name` and `transport`.
163
fn connect(
164
&self,
165
server_name: String,
166
transport: Box<dyn TlsTransport>,
167
) -> BoxFuture<std::io::Result<Box<dyn TlsStream>>>;
168
}
169
170
pub(crate) type BoxFuture<T> = std::pin::Pin<Box<dyn Future<Output = T> + Send>>;
171
172