You have probably heard of Blazor and that it uses WebAssembly to run .NET code inside a browser. But did you know you can use WebAssembly for much more? In this post, we will show you a few cool things to do with WebAssembly.
What is WebAssembly?
WebAssembly was invented as a language to run binary code inside a web browser. Applications running in WebAssembly run isolated, just like Docker containers. The use of virtualization allows a WebAssembly program to be portable across operating systems and different processor without modification. It runs on Windows, Mac, Linux, and devices like the Raspberry Pi equally well. This is a big difference from containers, which are created for specific operating systems and processor types.
Beyond the browser
WebAssembly does not make any assumptions about the host environment it runs on. This means that WebAssembly can also run outside of a browser. The ‘WebAssembly System Interface’ or ‘WASI’ enables this. WASI is an API that provides WebAssembly with operating-system functionality like access to the file system and communication over networks. This works using the function imports mentioned earlier. Most modern browsers implement the WASI interface, and a few stand-alone implementations are also available. Having a stand-alone WASI runtime means that a browser is no longer required to run WebAssembly code. As with any good OSS technology, there are quite a few WASI runtimes to choose from: wasmtime, WAMR, Wasmer, WasmEdgeRuntime, Wasm3 and others. For this article, we selected a host called wasmtime.
Developing with WebAssembly
By now, you’re probably anxious to get started running some WebAssembly code. We will start by building and running a simple ‘hello world’ WebAssembly program inside a browser, using the Rust programming language on Linux. Please note that if you are running Windows, you can use WSL2 to follow the steps in this post.
Running WebAssembly in your browser
We will create some Rust code and compile it into WebAssembly. If you don’t have them installed yet, please run this command to install the Rust tools:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh Now, let's create a simple Hello-World library in Rust by running: cargo new --lib hello-wasm Change the directory to the newly created program folder: cd hello-wasm/
Change the directory to the newly created program folder:
The ‘hello-wasm’ folder contains a file named Cargo.toml that describes how to build the project and a folder ‘src’ with file named lib.rs which we will change now. Modify the file to create a program that outputs ‘Hello world!‘ when run. Use your favorite text editor to change the code as displayed in Figure 1:
Finally, change the Cargo.toml file to include the dependency to the wasm-pack tool with the content from Figure 2.
We are now ready to run wasm-pack to compile the project using this command:
wasm-pack build --target web
After about half a minute, you should see output similar to this:
[INFO]: :-) Done in 27.08s [INFO]: :-) Your wasm pkg is ready to publish at /home/user/xpirit/magazine/rust/hello-wasm/pkg.
Congratulations! You have just built your first WebAssembly module, hosted inside the browser!
Running WebAssembly without a browser
rustup target add wasm32-wasi
Now that you have installed the correct build target, we will create a new project. You can do that by running the following command:
cargo new hellowasi Change the directory to the newly created program folder: cd hellowasi/ Next, compile the program to WASI compliant WebAssembly, by running: cargo build --release --target wasm32-wasi To run the compiled WebAssembly, we will need a stand-alone host. We will use wasmtime for that. Install wasmtime using: curl https://wasmtime.dev/install.sh -sSf | bash
Run the hellowasi program with:
The output should say “Hello, World!“.
Congratulations! You have just built and run your first native WebAssembly program.
Running WebAssembly with WAGI
We now have a nice console program writing its output to the stdout stream. But what if you want to develop APIs in WebAssembly and host them on any platform? This is where the current experimental WebAssembly Gateway Interface (WAGI) comes in. To quote the WAGI website, “WAGI allows you to run WebAssembly WASI binaries as HTTP handlers.”
“Did you know Deis Labs used to be Deis which are the founders of Helm for Kubernetes. It became Deis Labs after the acquisition by Microsoft in April 2017. Deis Labs currently runs many experimental programs revolving around WebAssembly and Kubernetes.”
“If WASM+WASI existed in 2008, we wouldn’t have needed to created Docker. That’s how important it is. Webassembly on the server is the future of computing. A standardized system interface was the missing link. Let’s hope WASI is up to the task!”
– Solomon Hyke, Co-founder of Docker
To get started with WAGI, download the latest release from https://github.com/deislabs/wagi/releases and unpack it. Next, we will need to add a configuration file to tell WAGI where the WebAssembly program we want to run is located for each requested URL. In our example, we will use the root path at “/”.
Create a wagi.toml file containing the content from Figure 5.
Because WAGI acts as an HTTP server, we need to make sure to write required content-type headers to the output streams in our WebAssembly program. Make sure your main.rs file looks like Figure 6.
Recompile the program using:
cargo build --release --target wasm32-wasi After that, you should be able to WAGI to run your WebAssembly program with the following command: wagi -c wagi.toml
When WAGI is running, you can visit https://localhost:3000 to see the output. The result should look similar to Figure 7.
Congratulations! You have just built and run your first WebAssembly API server using WAGI.
Moving to the Cloud
Running code in a light-weight isolated sandbox may seem familiar to you. The way that code is executed in WebAssembly bears a lot of resemblance with the way we run code inside containers. So, what if we want to run our WebAssembly API at scale in the Cloud? We can do this using Azure Kubernetes Service and an experimental service called Krustlet, developed by Deis Labs. Krustlet acts as a Kubernetes node that allows you to run WebAssembly programs on Kubernetes. Similar to how Kubernetes nodes run containers based on images stored in an OCI registry, Krustlet runs WebAssembly programs based on OCI artifacts (in our case the wasm file).
OCI artifacts support many different formats. Aside from container images, you can also store your WebAssembly program as OCI artifacts in a suitable registry (for example, Azure Container Registry). To do this, you will need another program called wasm-to-oci.
Download the latest release from https://github.com/engineerd/wasm-to-oci/releases and then install it using the following commands:
mv linux-amd64-wasm-to-oci wasm-to-oci chmod +x wasm-to-oci sudo cp wasm-to-oci /usr/local/bin Make sure to have Azure Container Registry (ACR) available to test things on and enable the ‘anonymous pull’ feature to allow WAGI to access it without logging in. Login to ACR and push your WebAssembly program to ACR with: az acr login --name acrwasmwasi az acr update --name acrwasmwasi --anonymous-pull-enabled true wasm-to-oci push ./target/wasm32-wasi/release/hellowasi.wasm acrwasmwasi.azurecr.io/hellowasi:v1 Note: make sure to replace acrwasmwasi with the name of your container registry. Out of the box, WAGI, which we used earlier in the previous paragraph, supports OCI artifacts as a source for WebAssembly code. You can try this by updating the wagi.toml file created earlier to look like Figure 8.
The run WAGI again using this command:
wagi -c wagi.toml
If this is successful, the output in the browser on https://localhost:3000 should look the same as it did in Figure 7.
Running WebAssembly on AKS
Because Deis Labs is part of Microsoft, preview support for Krustlet nodes is already available in Azure. If you want to learn more and try it for yourself, follow the walkthrough on https://docs.microsoft.com/en-us/azure/aks/use-wasi-node-pools
You have seen a few interesting applications of WebAssembly. It could be considered a highly secure way of running code in an isolated sandbox locally, in the browser, in Kubernetes etc.
But there are some things you need to be aware of…
WebAssembly code in a binary format is hard to read. It’s difficult to know what code in a wasm file does from the outside, especially when it is also obfuscated. Combine this with high execution speed and browser support, and it becomes easy to see how WebAssembly can be used for naughty things like running crypto-miners inside an unwitting user’s web browser. At the time of writing, there are no security scanning platforms to scan images for malware and vulnerabilities.
Most, or all, of the current hosts are vulnerable to attacks like SPECTRE, so at this time the examples shown here should not be used in a production environment.
In the future, if these security risks are mitigated, WebAssembly could become the next big thing after containers.
|https:www.hacks.mozilla.org/2018/10/webassemblys-post-mvp-future||Describes the current state and future plans for WebAssembly|
|https:www.bytecodealliance.org||Website of the ByteCode Alliance.|
|https:www.github.com/bytecodealliance/wasmtime-dotnet||Wasmtime for .NET|
|https:www.deislabs.io||Website of Deis Labs part of Microsoft.|
|https:www.github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM||Microsoft experimental runtime that compiles C# to wasm.|
Quote to put somewhere inside a square box:
If WASM+WASI existed in 2008, we wouldn’t have needed to created Docker. That’s how important it is. Webassembly on the server is the future of computing. A standardized system interface was the missing link. Let’s hope WASI is up to the task!
Solomon Hyke, Co-founder of Docker
Another quote to put somewhere inside a square box:
Did you know Deis Labs used to be Deis which are the founders of Helm for Kubernetes. It became Deis Labs after the acquisition by Microsoft in April 2017. Deis Labs currently runs many experimental programs revolving around WebAssembly and Kubernetes.