mod_wasm
mod_wasm is an Apache Server (httpd) extension module able to run and serve WebAssembly binaries as endpoints.
It was unveiled at the ApacheCon North America on Oct 3rd, 2022 (see the slides). In addition, a full-detailed article can be found at VMware's Wasm Labs page.
✅
Features
mod_wasm can be useful in the different scenarios:
- Run existing applications from a variety of languages without modification.
- Execute untrusted third-party code in a secure environment without using containers.
- The Wasm capabilities model allows to enable/disable capabilites per HTTP request.
▶️
Quick Demo
- Run the container:
docker run -p 8080:8080 projects.registry.vmware.com/wasmlabs/containers/httpd-mod-wasm:latest
- Open browser at: http://localhost:8080/wasm-module-endpoint
More details about the 'PrettyFy' WebApp Demo below.
📔
Contents
- Overview
- 'PrettyFy' WebApp Demo
- Examples
- Building mod_wasm
- Building the container image
- Troubleshooting
- Debugging
🔭
Overview
The mod_wasm project is composed by two different libraries:
mod_wasm.so
(written in C) acts as the extension module for the Apache Server (httpd).libwasm_runtime.so
(written in Rust) offers a very high-level C-API to manage WebAssembly modules via Wasmtime.
New Directives
To setup and manage WebAssembly binaries, mod_wasm offers new directives to the httpd.conf
configuration file:
Directive | Description |
---|---|
WasmRoot |
Set the root directory for Wasm modules. |
WasmModule |
Set the Wasm module file name. |
WasmDir |
Pre-open a host directory for the Wasm context. |
WasmMapDir |
Pre-open a host directory for the Wasm context and mount into a given directory. |
WasmArg |
Set an argument to be passed to the Wasm module context. |
WasmEnv |
Set an environment variable to be passed to the Wasm module context. |
WasmEnableCGI |
Enable/Disable CGI emulation mode for HTTP requests. |
Workflow
mod_wasm plays a role in two different stages of the Apache Server workflow:
- The different
WasmXXX
directives are read fromhttpd.conf
during the boot up sequence. Once the configuration if fully processed, mod_wasm requests to the Wasm runtime to start loading the Wasm binaries. This is by far the most expensive operation and that is why it is executed only once during the Apache boot up sequence. When completed, the Apache Sever is ready to response to incoming HTTP requests. - For each HTTP request, mod_wasm builds the WASI context for the already-loaded Wasm binary. Next, the Wasm module is instantiated and the entry point is executed. The
stdout
from the Wasm module is redirected to the HTTP response, and thestderr
is appended to Apache Server's trace (usually at
)./dist/logs/error_log
mod_wasm also offers the ability to build a specific execution context per HTTP request. When setting up WasmEnableCGI On
, mod_wasm will pass HTTP headers as environtment variables to the Wasm module (they will be prefixed as HTTP_
). In addition, URL parameters are also passed in the environment variable QUERY_STRING
.
⭐
'PrettyFy' WebApp Demo
The 'PrettyFy' demo is a simple one-script, Python-based WebApp (see Examples).
- The Python interpreter has been compiled to WebAssembly.
- Note how the system platform is identified:
sys.platform = WASI
. - The app accepts
file=
as URL parameter to highlight a previously uploaded file: - Now, if you try a basic path traversal attack, it won't be succesful thanks to the WebAssembly sandboxed model where the Python interpreter is running:
🕹️
Examples
This repo cointains several pre-built WebAssembly examples to play with.
Feel free to explore, modify and crash them!
🏗️
Building mod_wasm
As introduced in the overview, there are two main libraries in the mod_wasm project, being libwasm_runtime.so
a dependency for mod_wasm.so
. So, you might want to build libwasm_runtime.so
first:
- To build
libwasm_runtime.so
, the Wasm management and runtime library, go to wasm_runtime for detailed instructions. - For
mod_wasm.so
, the Apache Server module extension, go to mod_wasm.
📦
Building the container image
This repository contains all you need to build a local container image. Go to image for detailed instructions.
⚠️
Troubleshooting
modules/mod_wasm.so
into server
Cannot load This is a common error related to LD_LIBRARY_PATH
:
$ httpd
httpd: Syntax error on line XXX of <...>/httpd/dist/conf/httpd.conf:
Cannot load modules/mod_wasm.so into server: libwasm_runtime.so: cannot open shared object file: No such file or directory
Apache is loading modules/mod_wasm.so
but during the process it cannot find libwasm_runtime.so
. Either run Apache with LD_LIBRARY_PATH
pointing to the directory where libwasm_runtime.so
is located, or copy libwasm_runtime.so
to a directory such as /usr/lib
.
🐛
Debugging
To get detailed debugging information about the Wasm execution, run the Apache Server with the following environment variables:
WASMTIME_BACKTRACE_DETAILS=1
RUST_BACKTRACE=full
Also, it is recommended to run Apache in debug mode (-X
option), this means only one process, only one worker, and without detaching from the terminal.
WASMTIME_BACKTRACE_DETAILS=1 RUST_BACKTRACE=full ./httpd -X