 So a couple of things first, I just want to thank everybody for coming up to talk about Zero Trust in the cloud. And the other, I apologize if my voice breaks up a little bit during the talk. I'm fighting something off, but thankfully it's not COVID. So today I'm going to talk about Zero Trust in the cloud and how WebAssembly is a key enabling technology for that. So I wrote a book called Programming WebAssembly with Russ. I wrote Cloud Native Go, ASP.NET Core. My books haven't always been on the right side of history. I wrote a Windows Phone 7 programming book. So I created an open source WebAssembly project called WasmCloud. I co-founded Cosmonic, which is a company that's built on top of WasmCloud for managing WasmCloud distributed applications. I'm typically the most paranoid person in the room, which I guess goes hand in hand with being concerned about security. I'm a big WebAssembly fan, but I'm also practical. So while I think WebAssembly solves a ton of really important problems, it doesn't solve them all. And there's my GitHub address. I've got some other contact links at the end of the slides. And this is, by far, my new favorite quote. Runar Bjarnasen, the guy who co-created the Unison programming language, posted this, and I've been stealing it from him ever since. So I want to go from the lowest level WebAssembly technology, so that's the file itself, the virtual machine, and how that enables security. And then I'm going to take a journey from there to run times, and then to above that level to capability security, and then finally we'll talk about some distributed system security, and which parts are enabled by WebAssembly itself, and then which parts are add-ons enabled by open source projects. And if you look at my amazing art skills, you'll see that the green stuff is open source add-ons, and the purple is stuff that's enabled by WebAssembly on its own. So you've seen and probably heard in keynotes and some other sessions how buffer overflows, buffer overruns, things like that are pretty easy attack vectors, and one of my favorite qualities of WebAssembly is that they're simply not possible. You physically cannot buffer overrun in a WebAssembly module. You can't write code that uses system calls. You can't write code that branches to a location that wasn't there when the file loaded to begin with, and in many cases where C and C++ would crash with undefined behavior WebAssembly modules will do what's called a trap, and they will fail to run. And if there's one thing you take away from this session, it would be to click on that YouTube video. It shows a buffer overrun exploit in the original Legend of Zelda game for the Nintendo, and it's by far one of the most fascinating exploits I've ever seen. So if you go and watch that video, then I feel like my work is done here. I'm sorry it's not a shortened URL, but I figured at a security conference nobody's going to click a shortened URL. As I mentioned, the WebAssembly modules have control flow security as well as module security, so you can't create arbitrary pointers. You can't dereference memory that's invalid. There's a number of other things that are prevented by the simple fact that you cannot tell a WebAssembly module to jump to an arbitrary location. You can't have it read past the end of a buffer and then treat whatever's beyond that as code. Linear memory and the code being executed on the stack are two entirely different things that you cannot push together. So I've divided this particular sample into two highly scientific categories, worky and no-worky. So the working sample is, this is Rust in case you're curious, basically this is an add function and the no-mangle there tells the Rust compiler to export that function. At the primitive level, WebAssembly can only exchange numbers with the host and so anything where you need to exchange robust data types, at least today, you have to figure out how to do that on your own. There are some standards coming that will hopefully help make that easier but that's pretty much how it works. So let's see if I can show what this looks like. So these are all the export functions from the WebAssembly module. This is a, it's not actually a WebAssembly language, it's just a textual representation of the byte code. And so you'll see there's a couple of them that Rust adds for you. But the two that are important are memory which is the linear memory block shared by the host and the guest and add and that function is the one that we created. And I don't actually have any tricks up my sleeve. I just, I measure my typing speed in typos per minute so I wanted to make sure I didn't make you suffer through that. So you'll see I just added, I just called the add function with four and four. The wasm time runner reminded me that that particular call interface is not currently stable so it might break. But I got eight and so that's, that's all good. So now let's see what happens if I try and create a malicious actor. In here, this is also Rust but and it's no mangle so I'm going to export the add function. But here I'm going to attempt to read a file and write to the console and then finally just add the number. And again, I'm just running using wasm time to run it and you'll see that it trapped. It failed to invoke add and you'll see, you will see that unreachable thing an awful lot. And generally what it means is you've attempted to execute code that doesn't exist. So in this particular web assembly module, it's not using what's called wazzy so it doesn't have any instructions for accessing the file system. So when the Rust linker created that module, it just placed a bunch of unreachable code, unreachable macros where the real code should be. So that's the basics of level level module level security. All right. So the next thing I want to talk about one level up from the web assembly module security is run time security. And every web assembly module requires a run time. Regardless of what magic or smoke and mirror shows you've seen, all web assembly modules need a run time. So whether that's the browser or node v8 engine or as you saw wasm time. So that run time provides a bunch of security for web assembly modules. First is that host memory is off limits. No matter what you try and do from within a web assembly module, you cannot access the host's memory. You're basically given an isolated sandbox playground vector of bytes and that's it. That's all you can use. The host has its own memory isolated elsewhere. The host supplies the implementation for imports. You saw that I exported a function called add, but if I needed to import something like the ability to access a file, it's up to the host to supply the implementation for that. And what that really means is the host now has the right of last refusal for all operations that that module wants to execute. There are anti forgery checks. So depending on the run time, you'll see a whole bunch of security that prevents the module itself from being tampered with at run time from outside and some run times will compile the web assembly module into machine code when it starts up and that's also a configurable option up to the host or the run time. So there's another standard within the web assembly community called WASI and it stands for the web assembly systems interface and its original design was to close that gap and give web assembly modules some access to system resources. There are a lot of blog posts and even documentation that kind of steer you toward the idea that WASI is basically a web assembly version of POSIX that is not the case and thinking that can actually get you into some trouble. Like I said, the WASI modules are allowed to do certain types of IO, but again the host gets to refuse or grant access to those. If I want a web assembly module that's compiled to WASI to read a file or write a file or do any kind of disk IO, the run time itself needs to pre-approve that file. So when I start a web assembly run time I have to tell it this directory or these files are available to the web assembly module and if I don't tell it that the web assembly module will not be able to access it. So with that I'm going to take a look at a WASI demo and again the categories here are worky and no worky. So we'll take a look at the worky one first and you'll see that there is a print line statement here and in a WASM32 on regular WASM32 unknown target you would be unable to do that. You don't have access to standard out. So but since I'm going to use WASI I do have that ability and you'll see that the target, the rest target here is WASM32 WASI. That's crucial. If I had left that as WASM32 unknown I wouldn't have been able to run this. So here you can see that my web assembly module now wrote to standard out and still performed the math. So now let's go to no worky and see what a malicious actor might try and do. So here it looks pretty much the same as the other Rust code except it's reading from a file called food.txt and I'm going to print the file's metadata here and then add some more you know highly efficient debug statements right there and again the run command is the same. It's just executing against a WASI target. So now again remember the unreachable that I mentioned before. It failed to invoke add and there's also a big panic and this is the important bit which is that it failed to find a pre-opened file descriptor through which food.txt could be open. I don't want to go into too much detail but the WASI API allows for descriptors to be accessed and read from and written to and but they don't have the ability to create their own. So the host has to pre-create a file descriptor in order for the WASI module to be able to read from that file. So next above WASI we're going to switch from the regular Web assembly standards to WASM cloud, the CNCF open source project and that sits on top of WASM time and provides a number of extra features the probably the most important of which is capability security. So I mentioned that for a WASI module you might get a descriptor and you can read from it and write to it but you don't really know why you have no one really knows why you have that descriptor. When you build a regular microservice, a regular application running somewhere without Web assembly, your security policy might grant that thing access to sockets but what it really ever does is allow you to declare why it needs that socket. So the WASM cloud runtime lets you sign your Web assembly modules so that you can declare that one of them needs an HTTP server or a message broker or a data store and the WASM cloud runtime is responsible for vetting that you're allowed to do what you claim you're allowed to do and then actually stitching together the Web assembly module with the capabilities that it needs. So in this Rust code here you can see that there is a key value store I've called increment on the key and I've sent a request on a message topic called security dot day but what's missing there is pretty much everything so there's no connection strings there's no secrets there's no URLs and more importantly you don't even know which key value store you're talking to nor do you know which message broker you're talking to so at runtime when you are in your inner developer loop on your laptop you could use a whole bunch of in-memory things but when you're in development you could use one key value store and then in production you could use Redis or Cassandra or whatever and you don't have to recompile or redeploy your code and that is specifically designed to address things like the log4j vulnerability where in current development models I have to compile all of my dependencies into my deployment unit so my log or the the choice I've made for how I log that's built into this thing that I'm deploying even though you know I might only have four lines of business business logic in there and so Wasm cloud is designed to let me strip away all that write pure business logic and also be confident that these modules are secure so here's another example where it receives an HTTP request and returns an HTTP response but nowhere in there does it say what port it's running on or even if it's running in under a unit test so Wasm cloud embeds JSON web tokens inside the web assembly modules so that we can verify them in isolation and verify them offline. One of the big things that I wanted to be able to do was take a look at a web assembly module and decide whether I should let it do what it wants to do without having to consult the central authority you know if I need to talk to Docker notary or something else then what is the how do I define my security logic for when I can't contact the authority and so this one allows me to access that stuff without potentially without even having network access so this is all right so again I have a workie and no workie if I inspect the claims in this one you'll see the account this is the issuer the module that's essentially the subject um each one of these web assembly modules is issued cryptographically and you can see that this one is allowed to use the HTTP server and the key value store and if I were to look at the no workie you'll see that it has HTTP server but it doesn't have the key value store capability so at runtime the wasm cloud host will reject any attempt by this module to access any key value store and let's see if I can hear exactly how to do this sorry it's not wrong it's JWT only okay so you can see when this was issued which was Monday January 30th the issuer and the subject these are these are ED25519 keys they just have they've been encoded in a way that makes it so that they're double clickable and I can tell from the first character the purpose of the key so the first character here is a means it's an account key first character M means it's a module key and I'm keeping the in the hash of the module so that I can verify whether it's been tampered with and here's the list of capabilities that it's allowed to use so the next thing that I want to talk about is cluster security so when running everything on a single machine offline your security risk is much much smaller than when you're running a big distributed system in production and wasm cloud allows you to form self-healing clusters of wasm cloud hosts that are running your modules and so because these modules are so small you can tell it to run a module on one host you can move it from one host to another you can scale it from one running instance to a hundred all of that is done through the distributed systems functionality so in a wasm cloud cluster every host has a key pair and each host only trusts a certain set of public keys so for any given wasm cloud cluster the hosts have essentially a trust list of which other hosts they they will allow to communicate with and so a an invocation whether it's an actor calling whether it's a web assembly module calling another one or whether it's a module calling the key value store those invocations are also signed and each one of those also contains a jason web token and so anytime a wasm cloud host receives a request to execute something from a remote entity it can verify that it came from a well-known host that it hasn't been tampered with that the host is one of the ones that's allowed to communicate and you can even add extra policy so that you can verify that certain issuers are allowed to exist or allowed to communicate but other ones aren't that comes in pretty handy when you want to set a policy that'll that forces you to use different signature identities in dev and prod so you don't accidentally deploy something destined for dev to production and sorry I kind of went through a little bit fast on that one but if you have any questions feel free to ask kind of covered a lot so um more than I've been answering questions about wasm cloud security web assembly and I believe that qr code is for session feedback uh wasm cloud can run anywhere you can spawn the host process so you can run it as a you can run that host as a you know as a javascript inside the browser tab we have an elixir otp host that we use for the cloud back in there are smaller hosts that we're planning on building that are you know targeting you know like esp 32 devices things like that our host runs on raspberry pies one of my favorite demos is one of my colleagues brings up a wasm cloud host on a raspberry pi and you can see it we'll see if this actually notes itself wi-fi is low and also unreliable anyway when he starts the the host running on the raspberry pi you can see it show up in the network and you can basically treat it like an empty vessel you can send compute down to that raspberry pi so it'll run inside kubernetes it'll run inside anybody else's cloud it'll run in a browser tab basically runs wherever you want to start that runtime yeah um so if you there are a number of performance ones if you go to the our website you'll see some specific measurements but a web assembly module that has business logic in it that was built using rust can be two three hundred k in size or smaller and so when you think about like the startup cost for a particular piece of compute you're not starting up a giant docker image you're not starting up a one gig jvm so there are some startup advantages there are scaling advantages so i can take that one module and run a thousand copies of it across 10 hosts and now i'm i'm automatically spreading the load across those any other questions yeah yes uh so the capabilities are embedded inside the file itself um if i were to i don't have a uh a decent tool to to show the the explorer of it but wash is the wasm cloud uh cli and you can use that to get information on what's inside that module so if i don't want the jwt and i want the user friendly information this is what i get and you'll see that you know there's it has all the usual benefits of adjacent web token like valid before date and expiration and so on and wash will do it yeah um if you're using one of our templates to build one of these modules you can just type wash build and it automatically signs it with the information in the tomo file that's there i think i saw one other hand yeah um so it is um in general we tend to prefer the let it crash uh methodology so if that actor tries to do something that traps uh when it hits that trap we're just going to dispose of the actor and then bring another another one back uh because they're so tiny and they're already sitting the bytes are already sitting in memory it it costs us you know a few microseconds to bring it back after death um and then uh an attempt to use a capability that it's not allowed to use that doesn't actually crash the actor we just reject the call and log the error message any more questions all right thanks very much