 That's a welcome, my colleague, Siwan Shoo, Hayes from Tertrate, and Hayes from India. Hayes from India, and let's get started. Hello everyone, good morning and welcome to the session. So today I will be covering about how to extend and customize Istio using Wasm plugins. So yeah, let's get started. So we have a basic introduction of how Wasm plugin works in Istio, and then we'll see the internals of Wasm plugins, how they interact with the Envoy. This is required so that we can create advanced use cases like dynamically debug request on the fly, implement application firewall use cases in Envoy using Istio, enforcing network policies, and some advanced routing features that we can have in Envoy using the Wasm plugins. And we'll have a short demo to see things in action. So first of all, what are Wasm plugins? So if you go by the definition, they're like they provide a mechanism to extend the functionalities of Envoy. In our case, it's Istio proxy through WebAssembly filters. And so how exactly it's done, we need to understand the high-level architecture of Envoy. So we have listeners, filters, routes, clusters, and endpoints. What Wasm plugins do, they add a new filter in the filter chain. So for example, if I have multiple filters in my Envoy, I can extend a new filter using a Wasm plugin and create a new filter. So under the hood, what happens is using Envoy native APIs, I create a new Wasm plugin. That Wasm plugin is interacting with the Wasm runtime, which is embedded in Envoy, and it's creating a new filter. But more fundamentally, there are multiple ways to create filters. So there are three types on high-level through which we can create filters in Envoy. One is using native C++ filters. In that, what we do, we create, in a fork of Envoy, we just write our filters in the native C++ and then recompile in Envoy and use that new Envoy binary and create a stuproxy out of it. But this is hard. Another way that we can do is we can create Lua scripts. And this is nice. We can have our Lua script doing the function, but the problem is we need to write the Lua code and it's a bit hard to maintain. So this is how a Lua script would look like. We need to define the complete source code in the YAML itself. This is a high-level, how it looks like. And the other method, which is quite simpler, is creating a new Wasm extension. In that, we need to program whatever functionality that we want using the Wasm native APIs from the Envoy and then using whatever language you want to use, maybe Go or C++, you can create the Wasm extension and can create a Wasm plugin out of it. So this is how a Wasm plugin in Istio looks like. You need to define the VM configs, plugin configs, and the URL of your Wasm plugin. It could be an OCI image or you can directly define the Wasm model path. So basically these three methods we can use to create the Wasm plugin and we'll be talking about how to use Wasm extensions to achieve advanced routing features and network policies. So how it works. So we'll see internally what is happening when we are creating these filters using Wasm plugins in Envoy. So fundamentally we are using Envoy APIs and creating a Wasm extensions using extensions.wasm API available in Envoy. And by default Envoy uses a V8 as a virtual machine to create the Wasm runtime environment for you. You can change that Wasm runtime of your choice, by default it's V8, but we can use V8, VMR, VAM and Wasm time which are available in Envoy and then we can recompile Envoy and Istio to create a Wasm, to create a new Istio proxy based on your Wasm time runtime. But by default it's V8, so we'll be talking about V8. And Envoy operates on a multi-thread model. What does it mean? The main thread is taking the responsibility of running all the global tasks and in the individual threads it creates the individual Wasm VM which is running for every request. So for example, there are multiple S2E streams, there will be multiple worker threads and then there will be multiple Wasm VMs created and those are separate VMs, they have their separate user space and everything. But if you want we can have a single VM which is serving multiple requests and that is required for, if you want to share context between different requests. So for example you want to share, so for an incoming request you want to share something that with another request. You may want to use the concept called shared data. In that what you want to do is, so for example in this first VM which is it has VM ID foo and the Wasm model is hello.wasm and in another VM we have a VM ID foo, again this is the same VM ID as of hello.wasm and it's buy.wasm. So the idea is to I want to share the context between these two different requests and these two different VMs. I can do that by having a shared data and the shared data is like it knows because the VM ID is common in between these two different VMs and these two different VMs running for different threads and using the shared data I can share the context between these two different VMs and that's useful if you want to have like complex routing schemes which we'll talk about in a moment. So let's talk about some use cases. When use case could be you want to dynamically debug your request on the flag. So in that case if you are debugging you maybe want to see some STB headers. What are the headers in your request in the given moment maybe the STB body, the remote address, header injection and you may want to inject some header in the request itself or maybe in the response. Basically you are doing header manipulation and if you want to do header propagation in that case you may want to use something like this. So in the header propagation the idea is without instrumentation you are propagating the header from the inbound to the outbound request. So if the application is instrumented the header can be propagated easily but if the application is not instrumented in that case what you want to do is you want to create two different threads, two different VMs sharing the same VM ID and then using the shared data what you can do is you can save that particular header in the shared data and then use that information based on the request ID to propagate the header but there are issues in the scale but for a small scale it may work. So that's why there's a star. This in theory it's possible but via shared key value stored there are multiple caveats involved and it needs to be taken care of in the production. So let's talk about some of the use cases. So one use case could be you want to have a WAF application firewall in your infrastructure and so one of the most famous is WAF's core rule set. So basically what it does is you can have SQL injection, threat protection against SQL injection, cross side scraping and multiple others attacks some common attacks. So to mitigate all this attacks you can have a WAF implementation and one way to do it is using implementing your own wasm plugin which is extending and why APIs and then you are programming your own firewall. Another way is to like you can use some open source projects so for example Kouraza proxy wasm it does that for you. What it does is it extend the proxy wasm API specifications and embeds the WAF for example in the Kouraza project and then you can just create a wasm plugin and it would work just out of the box in your infrastructure. Another way is to like another use case would be having a network policies in place in your infrastructure. So Istio environment filter can be configured using the authorization filter to delegate authorization decision to OPA. So native ways to use the network policies available in Kubernetes and Istio itself. Another way is to you can use open policy agent and extend the functionalities available in open policy agent and use that in Istio. For that you need to configure and why to use open policy agent as a network policy provider. So you need to install OPA and why and then we need to create a sophisticated wasm plugin which would delegate the authorization to OPA. And what we can do is if the network policies available in open policy agents are not enough we can create a new like, so OPA uses rego policies. We can create our own wasm plugin to enhance what is available in OPA policy agent itself and we can like define our own network policies on top of it using the wasm support in OPA. And then that OPA can use to be configured the network policies in Istio itself. So there are some references. Now how would I do some advance routing in Istio using wasm? So consider use case where depending on the header value you may want to hit a specific subset of a surface. So for example, if the initial header is V1 and so if there are multiple services running and I give the initial header at my ingress gateway as V1 I want all the subsequent request to go to V1 itself. Or I can define pre-define a request flow if I want. So for example, if I define a flow alpha where the first service A uses V1 subset then the service B uses V2 subset and then V3 and V2 for service C and service D. So here I'm defining a request flow and I'm giving it a name as alpha and whenever I give the request header as alpha in my ingress gateway, this path should be followed. Similarly for beta. So this is a bit complex and we cannot do this by configuring virtual service in Istio. If we want to do that, we need to hardcore virtual service all the time but if we want to do this dynamically there we need to use wasm plugins. So one easy way is to use instrumentation. If your application is instrumented you can have virtual service created depending on whatever the request flow is. So for example, in alpha flow I can create a virtual service which would instrument. So if the application instrumented my header is propagated throughout the request chain I can use this propagated header and then create a virtual service out of it which would do a header match for V1 and then V1 if the header is alpha the request would be routed to V1. If the header is beta the request would be routed to V2. But if my application is not instrumented what I can do is I can have a wasm plugin which would use the knowledge of shared data between different PMs and it can do the job but at the moment it's not very efficient. So let's see how it works when we use the wasm plugin. So I'm not sure if it's visible but let's try to understand. So this is the ingress gateway and this is the inbound request coming from the user and the user is defining the custom header as alpha. So when the request with alpha header comes in the ingress gateway just propagates the header and this is product V1. Now here we know that for the incoming request I have this service index created which is zero and for the outbound request from product V1 the header is not propagated. So what I'm doing here is I'm sharing the context between the VM available here and the VM available here and using the shared data I'm using the request ID itself to first store the header alpha in the VM available in this request path and then reuse that alpha to know what the request ID is and corresponding the request ID I'm calculating my service subset which is V2 if the request is alpha. And then based on that service subset I'm just routing using my virtual service to the next subsequent request. Similarly here the custom header is again injected at the response header and then the response header alpha is using the service index one and again the same thing is happening where depending on the custom header alpha I'm storing the request ID and this particular header and then at the response I'm using the ID, request ID using the context sharing between different VMs I'm recalculating what is my service subset and in this case it's V3 and then I'm again routing using my virtual services. So this is kind of a high level flow and how it works. So let's take a look at demo. Let's again trying to connect. So in my cluster, so this is a single cluster setup where I have book in for running in the default name space and it's your setup. Now what I want to do is I want to demo this setup where I'm using this particular wasm plugin configuration using proxy wasm SDK. So what I'm doing is I'm just injecting few headers in my response header where if you can see in this particular line 123 we have proxy wasm go SDK example injected with value as SDP headers and I'm printing all the response headers available in my response. So this is how the response would look like. I would have all the request and response headers printed if I run this thing. But for some reason this is not working with the VPN so I'm just listing the output here. Yeah. Similarly, if we embed the knowledge of sharing VM sharing information between different VMs using the shared data we can have different routing schemes available just like we talked about earlier. So, I mean this is it for the short talk. Any questions? Welcome. I have a question about the VM sharing data storage in some somewhere, yeah. You know, if the VM have the same VM ID then the data will be stored in the same shared sharing, yeah. So, can you give more details about the data storages? It's a volume or something, anything where? Yeah, use it. Okay. So, the shared data thing works in the proxy wasm SDK if you are using the shared data it means that you can have your own data store or there's one cache that is available. So, it's available in the reference itself, this one. So, the idea here is like if there are a thousand requests at the same time they would have their own VM in the individual threads. So, every thread would have its own VM and for inbound and outbound request there is no knowledge sharing, there's no context sharing but what if I want to depending on the request header I want to share that information with the outbound request I need to have some mechanism to share the data between these two requests. So, that's where the shared data comes into picture. Okay. So, another question is about the exploration of the data, you know there are so many data in this sharing data storage but how about if there is a rotation or exploration management for all this data? Yeah. So, this thing is under development that's why it's not provision ready. If I get your question correctly what would happen if around a million requests how would I clean up my data store for the given request IDs? If it's that's your question. So, I mean you can have your own cron job setup to do that but yeah, currently it's not been taken care of. Got it, thank you. Hi, Ma. No, we'll just thank you. Thank you for your excellent speech. Thank you.