WASI
Cos’è WASI?
WASI (WebAssembly System Interface) è un insieme di API standardizzate che permettono ai moduli WebAssembly di interagire con il sistema operativo: file system, variabili d’ambiente, orologi, I/O di rete. L’obiettivo è rendere Wasm un formato universale per eseguire codice ovunque, non solo nel browser.
Capability-Based Security
WASI adotta un modello di sicurezza basato su capability: un modulo Wasm non ha accesso a nulla per default. Il runtime concede esplicitamente i permessi.
# Wasmtime: concedere accesso a una directory specifica
wasmtime run --dir ./data app.wasm
# Concedere accesso con nome diverso
wasmtime run --dir ./data::/app/data app.wasm
# Variabili d'ambiente
wasmtime run --env API_KEY=abc123 app.wasm
# Nessun accesso al file system
wasmtime run app.wasm
Questo è molto più sicuro dei container tradizionali: il codice non può accedere a nulla che non sia stato esplicitamente autorizzato.
Esempio in C
// hello_wasi.c
#include <stdio.h>
#include <stdlib.h>
int main() {
// Funziona perché WASI fornisce fd_write
printf("Ciao da WASI!\n");
// Leggere un file (se il runtime ha concesso accesso)
FILE* f = fopen("/data/config.txt", "r");
if (f) {
char buf[256];
while (fgets(buf, sizeof(buf), f)) {
printf("Letto: %s", buf);
}
fclose(f);
}
// Variabili d'ambiente
const char* key = getenv("API_KEY");
if (key) printf("API_KEY = %s\n", key);
return 0;
}
# Compilare con targeting WASI (Clang + wasi-sdk)
clang --target=wasm32-wasi -o hello.wasm hello_wasi.c
# Oppure con Emscripten
emcc hello_wasi.c -o hello.wasm -s STANDALONE_WASM=1
Esempio in Rust
// main.rs - Compila per wasm32-wasi
use std::env;
use std::fs;
fn main() {
println!("Ciao da Rust WASI!");
// Leggere un file
match fs::read_to_string("/data/input.txt") {
Ok(content) => println!("Contenuto: {}", content),
Err(e) => eprintln!("Errore: {}", e),
}
// Variabili d'ambiente
for (key, value) in env::vars() {
println!("{} = {}", key, value);
}
// Scrivere un file
fs::write("/data/output.txt", "Scritto da Wasm!").unwrap();
}
# Aggiungere il target
rustup target add wasm32-wasi
# Compilare
cargo build --target wasm32-wasi --release
# Eseguire
wasmtime run --dir ./data target/wasm32-wasi/release/app.wasm
Runtime WASI
I principali runtime per eseguire moduli WASI:
Wasmtime
Runtime di riferimento, sviluppato dalla Bytecode Alliance.
# Installare
curl https://wasmtime.dev/install.sh -sSf | bash
# Eseguire un modulo
wasmtime run app.wasm
# Con permessi
wasmtime run --dir . --env NAME=World app.wasm
Wasmer
Runtime con supporto per più backend di compilazione.
# Installare
curl https://get.wasmer.io -sSfL | sh
# Eseguire
wasmer run app.wasm
# Compilare AOT per esecuzione nativa
wasmer compile app.wasm -o app.wasmu
wasmer run app.wasmu
WasmEdge
Ottimizzato per edge computing, cloud e AI inference.
# Installare
curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
# Eseguire
wasmedge app.wasm
# Con supporto AI (ONNX, TensorFlow)
wasmedge --dir .:. ai_model.wasm
WASI Preview 2 e Component Model
WASI Preview 2 introduce il Component Model, una nuova architettura che permette ai moduli Wasm di essere componibili tramite interfacce tipizzate.
Le interfacce sono definite in WIT (Wasm Interface Type):
// http-handler.wit
package example:http;
interface handler {
record request {
method: string,
url: string,
body: option<list<u8>>,
}
record response {
status: u16,
body: list<u8>,
}
handle: func(req: request) -> response;
}
world http-server {
export handler;
}
Implementazione in Rust con wit-bindgen:
wit_bindgen::generate!({
world: "http-server",
});
struct MyHandler;
impl Guest for MyHandler {
fn handle(req: Request) -> Response {
Response {
status: 200,
body: format!("Ricevuto: {} {}", req.method, req.url)
.into_bytes(),
}
}
}
export!(MyHandler);
Confronto WASI Preview 1 vs Preview 2
| Aspetto | Preview 1 | Preview 2 |
|---|---|---|
| API | Funzioni POSIX-like | Interfacce tipizzate (WIT) |
| Modularità | Singolo modulo | Component Model (composizione) |
| Networking | Non supportato | wasi:http, wasi:sockets |
| Tipi | Solo numerici | String, record, variant, list |
| Stato | Stabile, ampiamente supportato | In fase di stabilizzazione |
Casi d’Uso di WASI
- Plugin sicuri: eseguire codice di terze parti in sandbox (es. Shopify Functions, Envoy proxy).
- Serverless: funzioni Wasm con cold start quasi istantaneo (microsecondi vs secondi per container).
- Edge computing: Cloudflare Workers, Fastly Compute usano Wasm per eseguire codice al bordo della rete.
- CLI tools: distribuire tool cross-platform come singolo binario
.wasm. - Database: estensioni sicure per database (es. SingleStore, Redpanda).