Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Running Untrusted Code in Spring with WebAssembly

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige

Hier ansehen

1 von 19 Anzeige

Running Untrusted Code in Spring with WebAssembly

Herunterladen, um offline zu lesen

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.

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.

Anzeige
Anzeige

Weitere Verwandte Inhalte

Ähnlich wie Running Untrusted Code in Spring with WebAssembly (20)

Weitere von VMware Tanzu (20)

Anzeige

Aktuellste (20)

Running Untrusted Code in Spring with WebAssembly

  1. 1. Running Untrusted Code in Spring with WebAssembly Dave Syer (2022) @david_syer dsyer@vmware.com
  2. 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. 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. 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. 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. 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/
  7. 7. Echo Guest: AssemblyScript // @ts-ignore: decorator @external("env", "get") declare function get(): i32 export function echo() : i32 { return get(); }
  8. 8. Echo Guest: Rust extern "C" { pub fn get() -> i32; } #[no_mangle] pub extern "C" fn echo() -> i32 { get() }
  9. 9. Echo Guest: Java Options: ● TeamVM: https://github.com/konsoletyper/teavm ● JSweet: https://github.com/cincheo/jsweet ● J2cl: https://github.com/google/j2cl public class HelloWorld { public static void main(String[] args) throws Exception {} @Export(name = "echo") public static int echo() { return get(); } @Import(module = "env", name = "get") public static native int get(); }
  10. 10. Echo Host: JavaScript var wasmModule = new WebAssembly.Module(wasmCode); var wasmInstance = new WebAssembly.Instance( wasmModule, {"env": {"get": () => 1234}} ); log(wasmInstance.exports.echo()); byte array
  11. 11. Echo Host: Java try (Store<Void> store = Store.withoutData(); Engine engine = store.engine(); Module module = new Module(engine, wasmCode); Linker linker = new Linker(store.engine())) { linker.define("env", "get", Extern.fromFunc(WasmFunctions.wrap(store, I32, () -> 1234))); linker.module(store, "", module); try (Func func = linker.get(store, "", "echo").get().func()) { Function0<Integer> echo = WasmFunctions.func(store, func, I32); int result = echo.call(); System.out.println(result); } } Using https://github.com/kawamuray/wasmtime-java
  12. 12. Something Less Trivial? ● Strings ● POJOs ● JSON
  13. 13. Exchanging Data Between Host and Guest Host Guest memory
  14. 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. 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. 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. 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. 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)
  19. 19. Links ● https://github.com/dsyer/spring-wasm-demo ● https://developer.mozilla.org/en-US/docs/WebAssembly/Reference - MDN docs with WAT/Javascript playground ● https://mbebenita.github.io/WasmExplorer/ - playground with C/C++/WAT/assembly ● https://github.com/WebAssembly/component-model ● https://cartographer.sh/

×