 2018 was before WebAssembly and at that time I was working at VMware on what is known today as Tanzu Service Mesh. In the team I was in charge of everything DevOps. I searched our closely with a small group of developers. One day one of them came to me and said Emmanuel come over here I want to show you something. I went. When in front of me he demoed a custom filter. In his demo I witnessed how is a filter secret queries can be introspected. One time statistics can be captured in a way that is completely transparent to the database server. I was fascinated. I asked the developer how he had done it. He went on to describe this step-by-step. First he said I forked the invoices code. I built the extension in C++. Rebuilds Envoy to finally test the resulting binary. He was a C++ expert and as a DevOps I thought there was no way I could write a custom filter. But you know what you can do he said. Know that I'm done. You can package my code in a Docker image, distribute the image in all of environments, update the version of Envoy in all of our dev staging and pod clusters and of course as a DevSecOps. Emmanuel do not forget to incorporate patches and other improvements. Thanks. It turns out that back then what we were working on is what is today the Envoy native MySQL filter. Fast forward to present days. I joined another company. Three months ago I was hired by American Express where I joined the identity group. As such once completed with the onboarding process I was immediately approached by the team that managed all of our IPA gateways. We are migrating to Envoy they said. With the expected number of requests we need to squeeze as much performance from this proxy as we can get. Emmanuel can you help? Of course I immediately thought of using the open policy agent OPPA. But I quickly found out that with custom policies and required support for 8 plus type of Jotoken OPPA was useless. What those people were really asking me was if I could write a custom filter. Thanks. So I started reading the docs. And this is when I learned about web assembly. With wasm Envoy doesn't need to be recompiled. Filters do not need to be written in C++. Thanks to LDS custom filters can now be dynamically loaded. At American Express we are currently evaluating the glue API gateway from solo.io. There is an open source version with which anyone, I, you can get started. I got started with web assembly simply by going through their web assembly hub tutorial. During this tutorial you will just add a header to your request. But also you will be introduced to the wasm CLI. Wasm init to create a scaffold or boilerplate code. Wasm build to compile your code to wasm file. Wasm push to push it to a public registry called web assembly hub very similar to Docker hub but for wasm filter. And finally once you don't publish your filter to deploy it you can simply use wasm deploy. Now if you are using Istio to deploy your filter you are even given the alternative of using a custom or source definition. As a DevOps I really love what solo.io is doing. Now if like me you have your use and you want to find out how the configuration of your Envoy has changed during the deployment of your filter you can simply connect to the Envoy admin UI. To do so, keep control port forward to the pod with the proxy you want to introspect. Select the Envoy container and map the port of its admin interface to a port on your local host. After doing so you will be able to connect to Envoy in particular to the admin interface using a web browser. Then select config dump to see your Envoy's active configuration. The configuration snippets on this slide is what is added for wasm filter. vcml blob may seem a little bit complicated to those of you who are new to Envoy but essentially to configure a filter you need to provide a runtime here it's runtime v8 and the location of your wasm bytecode here a local file. Now as described earlier to use your filter on Kubernetes you need to compile your filter locally, package it, push it to the web assembly hub, deploy it to the CRD and wait for the deployment to complete. This workflow is awesome but it is way too slow for development purposes. For the development of your filter you need a much faster turnaround higher velocity. To achieve this a solution is to use Docker Compose. This diagram represents my first iteration in Docker Compose but ultimately I was left with a question with wasm. Can you do more than just add, remove, update headers? To find the answer to that question and develop my authorization filter I started iterating. I iterated, I experimented, I read the available but limited documentation. I went online trying to find examples. I looked at the source code and occasionally reached out on Slack to select people. Given the current lack of documentation for proxy wasm you may think it's a bit early to get started. But what I found is that if you know where to look the answers are already there. Now before you get started a couple of warning. First today vanilla Envoy does not support wasm. To experiment with wasm like me you will have to use the recent version of Glow Envoy or Easter Proxy. In addition today the implementation of the application binary interface or ABI is near completion but is not 100% completed. As a result when you grade from one version of Envoy to the next you may have to tweak the source code of your filter. So you iterate, you iterate until you finally arrive to something that looks like this. Don't tilt your head. I'm not expecting you to understand the details just yet. Let me just say that I am not using several Envoy proxies, different versions and wasm extensions are everywhere. Now let me share some of the key highlights on what I learned. Let me start by introducing to you YTT, the YML templating tool. If you have ever dealt with the YML configuration file, which I'm sure everyone here has, stop watching this video right now and immediately go to http carvel.dev. Check YTT, this tool is fantastic. To give you a preview the YTT CLI takes for input a YML file, parses its contents, look for the commands and replace the commands with the content of other YML files. In short, this allows for a YML file to import other YML files. On this slide I extracted the code snippet for my input configuration. The transformation of this original YML file is possible thanks to a programming language very similar to Python called Starlark. As a result, now instead of having to deal with lengthy, unending, confusing YML files, you can work at the level of components, such as individual filters or even group of components, such as group of filters. By far in this project, YTT is a common line utility that gave me the most productivity boost. Check it out. A word about programming language, you can use with ProxyWazm. One of the promises of ProxyWazm is to allow the programming of Envoi Extension with non-C++ programming languages. If you want to write a Proxy Extension today, there are four programming languages available. They are C++, Rust, AssemblyScript and Go. Starting from the bottom, Go to TinyGo is the latest addition to the list. It's very new. I have not personally tried TinyGo to write a Wazm filter. But based on my reading, the main issue with Go, or similar programming language, is that no Wazm VM or Wazm sandbox can yet deal with garbage collection. Then you have AssemblyScript, a strongly typed JavaScript which is promoted in our community by solo.io. AssemblyScript defines itself as a language made for Wazm. After experimenting with it, I was immediately confronted with the limited number of libraries. Therefore, it is my opinion that AssemblyScript is not yet made for ProxyWazm just yet. Then you have Rust. Like AssemblyScript, Rust itself is a relatively new programming language. Rust has very strong potential. Most of us will have to learn it. Finally, back to C++. Certainly the core developers of Envoy, Istio, EnvoyWazm are all well versed with C++. Most examples of Wazm filters are found online written in C++. Additionally, if like me, in a past life, you had to program an embedded system, C++ would clearly be the winning choice. Indeed, compiling C++ code to JavaScript to run in LLVM, a VM on time, is very similar to embedded system programming. As such, today, it is my opinion that ProxyWazm fail on its promise of using a non-C++ programming language. Thankfully, the ecosystem is fast evolving. Regardless of the primary language you choose, you will have to understand the application binary interface. Your compile code, your Wazm extension is running in a Wazm sandbox. An interface with Envoy using this ABI. You can find the description of the ABI in the software development kit of your chosen programming language. You can think of your Wazm extension as a library that needs to implement a given set of functions or methods that Envoy thread recall. For example, when you bootstrap Envoy, the Wazm sandbox also starts. The on-start method is called. Likewise, when a request is processed by the listener to which you filter as attached, the on-request header, on-request body methods will trigger. This is what is represented in blue on this slide as the Envoy extension lifecycle. But Envoy must also be thought of as the operating system of the Wazm sandbox. Indeed, in your Wazm filter, if you want to introspect the request headers, read, write in memory, execute an external HTTP call, you will need to call following functions. To illustrate with my authorization project, I use the get request header function on the authorization header to extract the authorization header to find out its content. In my case, the content of that header is a request error token. If like me, you choose to build your extension in C++, you will need to understand Bazel. Bazel is a build tool developed by Google similar to CMEK, Maven, or even the simpler Clumec. It is used to compile C++ code of your filter. I am sure several of you have had some exposure to Bazel because Bazel, as it turns out, is also used to build and compile Envoy. For those of you who are new to Bazel, there are two concepts or files that are important. First, the workspace file. This is where you define all of your external dependencies and how to import them. In the workspace file for your C++ wasm extension, you will need at the minimum to import the unscripted compiler and toolchain required to compile C++ to run in the V8. And two, you will need to fetch a code that describes the application binary interface. This can be done by importing the sources of Istio proxy. The second concept to understand with Bazel is a build file. This is where you define your targets, what you want to build. In Bazel, you define targets by using predefined or custom macros written in Starlark. Those macros in Bazel are called Bazel rules. At the bottom left, I show the Bazel rule to build a custom library. At the bottom right, I show the Bazel command to build it. Now, without uttering too much in the details, I would like to share some of the external dependencies I imported in my Bazel workspace. The Google test framework. Very useful to test custom libraries. Boost. Yes, the very popular C++ Boost library I must have for C++ filters of medium to advanced complexity. Rapid JSON. In my case that I use to manipulate JSON documents such as my authorization policy or my bare token claims. Finally, once all the dependencies are imported in your workspace, the next thing is to build the wasm file. This is done here with the wasm cc binary Starlark macro. In English, what that Bazel rule means is to build the binary file, worker app token wasm, compile the source file, worker app token dot cc, and link the resulting object to the ABI. Boost rapid json and my custom library. Now let's get out of the weeds and go back to a higher level. There are two types of wasm extension. First type are wasm filters attached to listener can therefore dynamically be configured with a listener discovery service or LDS. And are triggered by request. The second type of wasm extensions are singletons. In the next few slides, I will introduce them. But before I do so, I would like to share or convey that filters and singletons can communicate with each other. This is done by using either a message queue or shared data or in a shared memory. Let me illustrate all of this with my filter and my singleton in my authorization project. Let's go back for this to the docker compose developer environment I flashed earlier and let's zoom in on one of my envoy. On this Istio Envoy, three listeners and the admin interface have been configured. At the top of your screen on port 8080 is a listener I used to simulate an Envoy SciCard to HTTP. Just below on port 8007 is a listener configured with a wasm filter and a simulated backend. Such a configuration is extremely useful for performance measurements. For example, using Fortuno, a low generator, you can send requests and measure the impact of your wasm filter on latency. Finally, on port 8443 is a listener of interest. This listener use a wasm filter chain and a singleton stack. Now, here is an early version of my singleton stack. Its purpose is to fetch and then refresh the local copy of American Express authorization policy. As you can see, singletons are not on the request path and therefore their number and performance have no impact on request latency. In my case, the execution of my singleton is triggered at regular interval by a timer. Every 10 seconds, the top one pulls from a remote location a document assumed to be the global authorization policy. That document is fetched and then stored in shared memory. The bottom one, every 10 seconds, read the document stored in shared memory and execute input validation. Now, you may wonder why we have several singleton instances instead of just one. The short answer is that we are experimenting. But one clear advantage with this approach is that we can maximize call reuse. And additionally, if we want to upgrade a individual component, we minimize disruption. As mentioned earlier, at American Express, we support different types of JSON Web Token. They picked at the center of this slide are three filters for validating user application inspired Web Token. At both extreme are two filters I call bookends. Indeed, the purpose of the first filter at the extreme left is to do a deep introspection of request and to mark which upstream filter should process it. Meanwhile, the purpose of the last filter at the extreme right is to make sure that the request has been properly processed. It turns out that wasm filters have another way to communicate with one another by using the request itself. This can be done with metadata or with what I call hidden request header. Again, we are just experimenting. So what's next? The end of this presentation is still to be written. But beside some new additional requirements I was given, last week, Solow released a new version of the API gateway with better wasm support. Additionally, I just found out that Tetrates has upgraded their get and voice CLI to build in Rust a filter scaffold. So clearly I will continue exploring. Now, let me turn the question around and ask what's next for you. If on one hand you are interested in better understanding envoy and encourage you to play with wasm. If on the other hand you are contemplating getting serious with wasm and envoy, I'd love to hear from you and potentially help. I look forward to your questions. Hello everybody. Thank you for attending my presentation. I have, this presentation was recorded a few days ago and I shared with the video with the meeting organizer and a few things happened in between. And I have to say that a lot of innovation is being done with envoy in the wasm space. The first thing that happened last weekend is that to date, as I mentioned in the video, you had to use a specific version of envoy to experiment with wasm. It turns out that the wasm envoy or the source code or the new addition has been no merged into the upstream of envoy, which means that soon, I think it will start in version 117. In the version 117 of envoy, wasm will be available everywhere. Something else I haven't talked about in this presentation not too much because lack of time maybe was about metrics and logs as well. It turns out that wasm filters, just like native filters, can also interact with envoys and communicate with the outside world using from a use matrix or metrics published. Those metrics will be published in the admin interface, which is in the semi UI introduced earlier at the slash stats path. So you can, for me, wasm filter, you can add metrics that could be meaningful. In my particular case, for example, in my single terms, I'm looking into finding out why my filters would not behave correctly. For example, if I'm trying to reach out to the policy and for some reason I cannot want to know that. Of course, once your metrics are input media, if you're interested, you can also alert on some triggers, which can be useful as well. To develop my filter, I'm using logs also. Actually, that's my main source of troubleshooting. When you start envoys, you can specify some command line parameters, such as component logs. This is really on the command line of envoys. If you use the containers, you will have to add this as the command parameters to the envoy process itself. You can specify the log level of components. In particular, there is a component for all wasm filter, which is called wasm. You can set this envoy component called wasm to the level debug, and then you will be able to see all the debug messages, which is quite useful when you are troubleshooting. That being said, when it's in production, make sure that you do not run your end goal in debug level, including for wasm filters. It turns out also that in the past few days, I have been experimenting with Get-Envoys CLA, which I just talked about, which offers Rust scaffold to develop filters. I'm really getting started with this. I am very pleased by what Rust provides in terms of the developer experience. I'm really looking forward to it. You don't have to deal with this anymore, because there is no there is cargo, there is a concept of crates. You have also tests that are integrated in the language. I'm kind of experimenting again with this. What I found is that if you put too many libraries into the wasm filters, you end up having the wasm binary itself becomes larger and larger. I'm wondering if we should not be monitoring the size of the wasm filter. Obviously, in my case, it's being fetched from a remote location, but you have also the concepts of concurrences. I do not know yet if the size of the filter is something that should be monitored. In which case, C++ or even assembly script, which had the smallest size for what I've seen. C++, you can really take only exactly what you need. I'm not too sure if it's possible with Rust. I assume it is, but so far, what I found with Rust is that my filter was just to add or extract errors was a little bit too big to my test. Another thing I want to talk about is about performance. It turns out that over an external authorization filter, such as OPAR, and compared to a wasm filter, which is completely compiled in or running inside and void, I think you can have about 20 times improvement in performance, which is significant. That being said, with wasm, you have also the concept of runtime. I talked about the runtime, the runtime that I've been using was mostly the V8 sandbox, which I think is the most mature to date, but they are the sandbox that are coming. With the V8 sandbox, really compared to native filters, you can reach approximately 40% of the performance of a native filter, which is quite significant. But some new type of runtime are on the way, where you will be able to get even closer to native performance. There is the WebEM, with which you would be expected to reach about 90% the performance of native filters. A new VM where, basically, you are using the wasm SDK, but it's actually almost compiled into an void. It's quite possible in the future that native filters will be built into wasm to benefit from the fact that you can bring them in and out based on the configuration of the filter itself. I looked at performance from a request performance. As I said, filters wasm on the request path. In my particular case, I want to make sure I'm getting as much performance as possible. As you have seen in the architecture I have, I know I have several filters. I don't know if it's the right strategy on the request path, at least, but that's something I will have to find out. The way I do it, or I tend to do it, is by using Fortuno. I briefly talked about this and to try to experiment with the architecture of the system. It turns out that, right now, instead of trying to improve the performance, I've been trying to saturate my filter that slows down the request to see what would be the behavior of an void when it's being saturated. That's something that is very interesting to me to see what is the expected behavior of an void itself with wasm. Getting the highest performance as possible, I've been trying to build a filter that slows down my request and sleeps and sends the request half a second later on. Then I send a lot of requests and I look at what an void does. For me, that's interesting. That's something that I'm exploring as well. To conclude, really, if you think about what WebAssembly is, and if you have been working with containers for a while, I think it has the potential to have a huge impact in the container space. For example, some people say you can replace containers themselves with WebAssembly. Actually, that's something I looked at. I wanted, actually, at some point to have a WebAssembly singleton that would read my policy, transform it into a rego policy and feed it to the OPA extended filter. I have not completed the work, but I was thinking, oh, you know, that would allow us to migrate from our custom policies to something that is more open, which would be in the OPA open policy agent, rego policies, and to try to see if that's the way to do the transition. But if you work also with function as a service, you can see that, actually, what Envoy is, it's really invoking functions. Those functions are actually the functions that are in my wasm filter. In the space of function as a service, wasm can have a huge impact. Lots of work is being done there. I encourage you to have a look at it. And finally, the last notes, I think, there is, as I said, Envoy, the wasm extension has been merged into the upstream on Envoy. Even so, the code has been merged. There is still a lot of work in terms of the documentation that needs to happen. There is no documentation there. I think it will be there in the 117 version of Envoy documentation. So there are a lot of opportunities for some of you, including myself, for that matter, to contribute to the open source community that way. And if you do not know how to do that, feel free to reach out to me. I'll be happy to help you out in any way I can. You can find me, of course, on the Envoy Slack channel, and a few others as well. So I look forward to hearing from you very soon. Thank you.