This session covers the basic mechanics of WebAssembly—what does it look like, how do you create one, and how do you run it?—and shows some examples of the newest, coolest server-side use cases. The aim will be to run untrusted code (a user-defined function) in a Spring Boot application, enabling the application and its deployment to be completely separated from the business logic. In a true serverless fashion, the application becomes the platform. It will be demonstrated that there are immediate uses for such a pattern in Spring Cloud Data Flow and Spring Cloud Gateway.
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Running Untrusted Code in Spring with WebAssembly
1. Running Untrusted Code in Spring
with WebAssembly
Dave Syer (2022)
@david_syer dsyer@vmware.com
2. What is WebAssembly?
● Host = application code (e.g. browser)
● Guest = WASM, compiled from C, C#, AssemblyScript, Rust, etc.
● Spec: https://github.com/WebAssembly/spec
● Originally targeted at browsers, so JavaScript is most common host
● Other hosts include Rust, Go, Python, C#, Java
● Sandbox - flexible with secure defaults
Host
Guest
3. Show me Some Code
(module
(func (export "add") (param i32) (param i32)
(result i32)
local.get 0
local.get 1
i32.add
)
)
Example playground:
https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/Numeric/Addition
4. Linear Memory
(module
(memory (export "memory") 1)
(func (export "get") (param i32)
(result i32)
(i32.load (local.get 0))
)
)
1 page of memory is exported and accessed externally via the “get” function
5. Imports and Exports
(module
(import "env" "get" (func $get (result i32)))
(func (export "echo") (result i32)
(call $get)
)
)
The result of the “get” function is echoed back to the caller of “echo”
6. Options:
● Emscripten: https://github.com/emscripten-core/emscripten
● Wasi SDK: https://github.com/WebAssembly/wasi-sdk
● Binaryen: https://github.com/WebAssembly/binaryen
● Llvm/Clang: https://github.com/llvm/llvm-project
Echo Guest: C
int get();
int echo() {
return get();
}
Try it out at https://wasdk.github.io/WasmFiddle/
14. Exchanging Data Between Host and Guest
● Choose a binary format, e.g. Protobuf, Avro, MessagePack, JSON string
● Convert input and copy into shared memory
● Call WASM function with [ptr, len] tuple
● Output is another [ptr, len] tuple
● Copy output from shared memory and convert
ptr (input)
len
ptr (output)
len
15. Application Binary Interface (ABI)
Contract for exchanging data:
● Allocate and free memory (host and guest have to agree on location)
● Binary encoding format, e.g. Protobuf definitions
● Signature for exports - structure of input and output pointers
● (Optional as necessary) signature of imports
Draft spec for standardization: https://github.com/WebAssembly/component-model
16. Message Exchange Host: JavaScript
var encoded = encode(msg);
const bytes = malloc(encoded.length);
new Uint8Array(memory.buffer).set(encoded, bytes);
const output = malloc(8);
const input = malloc(8);
new Uint32Array(memory.buffer, input, 2).set([bytes, encoded.length]);
wasm.instance.exports.call(output, input);
var buffer = new Uint32Array(memory.buffer, output, 2).slice();
var result = message.SpringMessage.deserializeBinary(new Uint8Array(memory.buffer, buffer[0],
buffer[1]));
free(output);
free(input);
return decode(result);
input object
memory management (imported from wasm)
17. Message Exchange Host: Java
var buffer = memory.buffer(store);
try (var input = new Wrapper(buffer, message);
var output = new Wrapper(buffer)) {
linker.get(store, "", "call").get().func().call(store, Val.fromI32(output.ptr()),
Val.fromI32(input.ptr()));
return output.get(SpringMessage.class);
}
input object
memory management
18. Spring Host Ideas
● Some glue code for boilerplate WASM host stuff
● Spring Cloud Gateway - predicates and filters
● Spring Cloud Function - generic data transformation
● Kubernetes operator - webhook or controller, e.g. Cartographer
Demos:
● https://github.com/dsyer/spring-wasm-demo (client: C; host: Spring)
● https://github.com/dsyer/async-wasm (client: C, AS, Rust; host: javascript)