 All right. I'm going to get started here, because I only have 25 minutes for these sessions, and I got a lot of content to pack in. Thanks, everyone, for joining. And yeah, this is Sleep Better at Night, dapper for zero-trust architectures. And hopefully no one will fall asleep during this session, because I know it's after lunch, so I'll try and keep you a little bit awake with some demos. My name is Alice Gibbons. I am head of customer success at Diagrid. And if you haven't already, come check out our booth at app developer con or at kubecon. We are working on a bunch of different products that work around the dapper project, which I'll be talking about today. So let's get started. I wanted to start off with a definition of zero-trust security. I think a lot of people have heard of zero-trust security, but the Department of Defense sums it up really nicely here. And they say that zero-trust security is essentially no actor, system, network, or service operating outside or within the security network can be trusted. So essentially, this is the idea that you need to verify everything within your security perimeter. And this is like whether this is a device, an application, a transaction. Essentially, you need to verify and double check that what you are talking to or the thing that you are making the connection with is secure. And I think this is a, you can see this by this little picture up here. We have our happy little hackers that have made it inside the security perimeter. And our applications are, of course, our treasure. And that security perimeter is effectively the thing that once you make it in already and you're using a network perimeter security, you have access to really everything within that network boundary. However, using zero-trust security principles, you can see we have a few other little castles within that castle, ensuring that once or if you have a hacker or a bad actor that makes it inside your network, you are securing things at an even higher level. And I just wanted to set that stage here. But this is app developer con. You guys are like, hey, this is app developer con. We're not supposed to be talking about networking. But that's why zero-trust security is not just for infrastructure teams. And that's kind of what we wanted to talk about today. Zero-trust security can be for developers as well. And especially like this paradigm is becoming more and more of a less of a best practice shift and more of standards that really everyone is looking to adopt. OK, so I'm going to use this application. And this is a distributed application, a distributed systems application, pretty standard one. It's what's called a pizza store. So we all like pizza. And we have a pizza store. And we are making placing orders for pizzas. We are calling out to a couple different microservices in order to both make this pizza within the kitchen service and then also deliver this pizza with the delivery service. Fairly simple application here. And it does a number of things that are pretty common distributed apps. So it does service to service invocation between applications. It does asynchronous communication via a message broker. It reaches out to a key value store. And it has a little bit of a front end. Nothing too crazy. But this is what I'm going to be used to illustrating these points through this talk. So taking a look at the network perimeter, we would typically have this network perimeter outside the entire system. And then everything inside that would be considered secure. But thinking about some of these zero trust principles that we're talking about, we're going to actually use that application perimeter and that application boundary as the thing that we want to be verifying and checking. So every call out to my infrastructure layer or my other services, that's going to have to be checked and verified. So how do we do that? How do we do that from the application layer as a developer? And this is kind of, oh yeah, I'm sorry. And there's a number of issues that this brings with it from the development perspective. For instance, I'm a software developer and I have to now think about how I'm encrypting my calls between apps using certificate rotation. I don't want to do that. Or I have to expose my APIs to these front ends in a secure manner that's still following the zero trust model. Or I need an identity, essentially, that is life-cycled with my applications. How do I do all of these things while still staying in that zero trust security model? Or also, yeah, restricting applications, which apps can publish on a message broker? This is typically the idea of kind of the infrastructure teams, but these zero trust principles bringing it into the app level makes it more of a developer responsibility. And this is kind of where Dapper comes in. And there's been a lot of kind of discussion around Dapper today at AppDeveloperCon. But what we wanted to talk about, I just want to give a quick overview. And it is a set of microservices or distributed systems APIs. And it has a number of different capabilities within it. We're not going to dive super deep into all of those today. You can see some of these up here. So you can do things like build stateful workflows. You can access key value stores. You can use the cryptography API to encrypt your applications. And you can use this from any language or runtime. So there are a number of SDKs that work with Dapper or that are Dapper native. Or you can literally use native HTTP and GRPC clients from within your application code in whatever language you're coding in. And these are running as a sidecar. And you were calling out to the Dapper APIs via local host from your applications. And today we're going to talk a little about the security aspects that Dapper also brings. And I did also want to call out that this is, although it's typically hosted on Kubernetes, can be hosted on really any cloud or edge infrastructure. OK, so the first concept that I wanted to talk about was Dapper application identity. And this is really important and kind of intrinsic to Dapper itself. Because what it is doing is it's giving every single application within your system an identity that is a strongly attested cryptographic identity using SPIFI IDs. And you can see the SPIFI ID of this application one at the top here. And these are globally unique. And they have private keys that are aligned with each application replica. They are used for a ton of different things within Dapper, specifically authorizing connections between your applications. But then you can also, they add a lot of niceties for adding various policies and scoping them as well. And then, yeah, I did mention this as well, but Dapper does run as a sidecar within your pod. So you can think of that kind of as a security boundary going forward here. Yeah, and then some of the calls to these Dapper APIs that you would be making. For instance, there's a call here. This one would be to the invoke endpoint. So I'd want to invoke, in this case, my application app one. And maybe I want to call a method on that application. And that's kind of, there's a number of these different kind of Dapper semantic APIs that we would use from your code. So what does this look like in our pizza example, right? We have our two services. We have our pizza store and our kitchen service. In our pizza store, what it's going to do is it's like, hey, you know what, we got a pizza order delivery. Or we got a pizza order coming in. We need to tell the kitchen service, time to make a pizza. And what this is going to do is you can see our two spiffy IDs on the side here. But this is going to make a post request to invoke the kitchen service at its prepare method, right? So it's going to call out to the other service to say, hey, you know, I want this pizza to be prepared. And these spiffy identities take in two really key properties of Dapper. And these are the trust domain and the namespace. And I think namespace is a fairly common concept, especially in like Kubernetes land. But trust domains are essentially an addition, a Dapper addition that what they do is they kind of group trust relationships together. So say if you want to, you know, ensure that pizza store and kitchen service are within that same kind of trusted relationship, you can put them inside the same trust domain. I did also want to call out that, you know, Dapper does do built-in MTLS encryption by default. And that's just kind of a nice idea that it gives you there. Okay, and then yeah, one other thing is there is the addition to add API token authentication. So if I wanted to make this even more secure and kind of move that security boundary from not even just within my pod but even closer towards my application, I can add API token auth, which is going to ensure that every call to the Dapper APIs is actually requires a API token to be sent with it, you know, to ensure like nothing else really can call those APIs. So what is this, how do I configure, you know, how do I configure this, these zero trust capabilities I'm talking about? Well, we use our favorite tool, Gamble, and we have this configuration file here. And what I'm gonna do essentially is I'm only gonna allow the pizza store application to call the kitchen service. So you can kind of see on the right side here, this is my config file, you know, and I'm denying all invoke applications onto that kitchen service except for the call from pizza store. So that's kind of what is showing up on the right here you can have, you can have these default deny policies that say, hey, you know, nothing can even call me except for this one specific method and this one specific HTTP verb in which I'm gonna allow this case. So, you know, of course, if I had another application that is not gonna be allowed to call that. So let's see what that looks like in practice. And I'm just gonna switch over to BS code really quick. I'm realizing I can't hold the mic and do this, but you can try this. What you can see is the kitchen service. I have my pizza store service, which is right here. And as mentioned in the slide, right, we are reaching out and calling that kitchen service application. So this is that prepare call and this is a basic Java application. It's actually using just REST template. So we're not even using the Dapper SDK or the Dapper client in this specific example. We're literally just using REST template within Java. And you can see I'm calling kitchen service by providing that application ID. Again, that spiffy identity that Dapper gives you within the header. And then I'm calling reaching out to prepare and then this Dapper HTTP variable is literally just like the local host plus the port where Dapper is running on. And you can see kind of on the right here, I have that configuration file I was showing where we are denying all applications calling the kitchen service except for that pizza store app. So kind of that principally is privilege access that we want. On the kitchen service side, we have another Java application. In this case, this prepare endpoint, I just wanted to call out that it exists. It's a real endpoint. And essentially, if I flip over to my code or my browser, you can see that this application is actually running. So here's my pizza store application. This is great. This is just, I have port forwarded this. This is all running on Kubernetes. I've port forwarded this to local host. And then what this is gonna do, right, is it's gonna run this application and you can see kind of events kind of coming in and being displayed up within the UI here. So one of the events that's coming in is from the store service. That's the pizza store service. And then you can see that that kitchen store service is actually showing up as well. And then just to even kind of prove my point further, if I head to my logs on the top here, I have my pizza store service. And on the bottom, I have my kitchen service. Pizza store on the top, kitchen on the bottom. And you can see that I have, I'm calling out to calling kitchen service at this local host prepare. Again, because Dapper is running as a sidecar over local host there. And then I get this event within my kitchen store service on the bottom there. So that's great. But what if I wanna try some additional calls that might not be allowed based on my security policy? So if I head into, this is just a rest client that I'm gonna use to kinda showcase this. But essentially what this is, is I'm gonna be making the calls that the pizza store makes to its sidecar. So here's my pizza store Dapper sidecar. And I can pretend that this is my pizza store app calling out to its sidecar. And this is the one that should be allowed, right? So if I hit this, you can see on the right that it's giving a 200 okay, so that's a good thing. And then, but if you remember my kitchen config, I'm only allowing this prepare and put method. So if I change this guy to a post, hard to do with one hand, you can run this through. And I'm actually gonna get this error, direct and vote call directly from Dapper itself. And this is gonna say, hey, this permission was denied explicitly and it's gonna tell me this spiffy ID. And it's gonna say, hey, we're not allowed to use these post verbs based on our security policy. And heading back into here, I'm not gonna, I should have cleared the logs here, but there was no new logs, there was no actual order that was heading into that kitchen service. Additionally, the other thing I just wanted to show on the invocation side is we also can try another one. So we know that this order, this put on the prepare method is actually something that is allowed based on our policy. However, because we're allowing prepare on put. However, I'm gonna try this from the delivery service. So the delivery service is another one of our microservices, but if you remember from my policy, I'm saying, hey, I wanna deny every single thing calling me except for this one pizza store service. I'm gonna send this request and you can see I get another error direct invoke. It's saying, hey, I failed to invoke the kitchen service specifically because my permission was denied based on these policies. So again, these policies just really allowing you to get super granular with your applications and allow you to add that application level security onto synchronous communication in this case. They're like, okay, that's great. What about asynchronous communication or what about like infrastructure access? And this is kind of where I wanted to talk about some of the idea that DAPR has behind DAPR components. And so what a DAPR component is, is we already know we have our application and we already know that it is reaching out to its DAPR sidecar over local host. We also have what is called the DAPR component model. And this is used any single time that you want to access underlying infrastructure. And so we have maybe a key value store that we wanna access in this case. Maybe it's Postgres, maybe we don't care, right? Because DAPR gives you that abstraction to reach out to from your code that essentially allows you to switch out the component at any point in time. So maybe it's Postgres today, but maybe it's Redis tomorrow. The code actually doesn't change. And so what these component files look like is they're more YAML. And you can see kind of my YAML, my fake little YAML component on the bottom here. But this would be the connection details of Postgres. That would actually allow me, allow my application code to reach out to DAPR and then DAPR to load that component with into that sidecar and ensure that I can reach out and connect to that underlying infrastructure layer. And then this abstraction also allows you to provide, again, a lot of niceties around security at the app level because what you can do is you can add like component scoping in this case. And component scoping allows you to apply a principalese privilege access to your infrastructure components at the application level. Well, of course, still abiding by these namespace and trust domain boundaries that I've talked about. Of course, we still wanna use network restriction as well. That's not like taking away from the fact that you need to like restrict your network. But giving you that additional option. Okay, so now we have our kitchen service that we've talked about. We have our pizza store we've talked about. In this case, we want kitchen service to tell pizza store, hey, my pizza, I made the pizza. Pizza's done, print out a message and tell the user that the pizza is done being made. And this is gonna be using asynchronous communication. So we wanna use a message broker for this. And this is very common use case in distributed systems. We're using a different DAPR endpoint in this case, it's the publish pub sub endpoint. And you can kinda see on the bottom here, I'm calling out to the publish URL and I'm calling on the pub sub message broker. And then I'm publishing a message onto a topic. And in this case, my topic is named topic. So I'm gonna be saying topic a lot. And again, as mentioned, right? This is using the component model. It doesn't really matter what infrastructure broker I'm using. So I have, you know, it could be SQS, could be Azure service bus. Could be, you know, RabbitMQ, you choose your favorite cloud or your underlying message provider, that's fine. But DAPR kinda takes care of that for you. And then, you know, on my pizza store side, I have this events endpoint that's gonna be receiving those events and printing them out. So what does this look like in DAPR? I have this component file and then you'll notice it has the infrastructure details of my Kafka pub sub in this case because I'm using Kafka that's running on my Kubernetes cluster. But again, Kafka could really be running anywhere. You just are providing those connection details within that YAML configuration. In this case, I have two scopes at the bottom here. And these scopes are really important because they tell DAPR, hey, only load this DAPR component file into these two application sidecars. So it's gonna only load them into kitchen service and pizza store. So if I have any other application calling it, maybe it's app two, maybe it's, you know, a bad actor or whatever, it's not gonna be granted access to that underlying infrastructure layer because it won't even know it exists. Similarly, I can also add a list of allowed topics. So, you know, we're using a topic named topic, very original, but if I, you know, only wanna lock down that topic to be allowed on that message broker, I can also do that within my allowed topics list. You can see I can add this allowed topics line, which, you know, allows, which only allows kitchen service to publish on the topic topic. And then last but not least, the most granular that you can get is adding these protected topics, saying, hey, you know, I can only allow certain apps to publish and certain apps to subscribe. Of course, in this case, we want kitchen service to publish that message and then, you know, pizza store to subscribe there. And so that's kind of what I'm doing at the bottom there, which, you know, meaning, of course, if I have any other application that wants to publish on a message on that message broker, not only is it not even loading it, but you know, it's not even gonna be able to publish or subscribe to that broker. Okay, so let's see what that looks like from a demo perspective. I think I still have time. Yes, so I'm going to take a quick peek at the Pizza Kitchen service again. And again, this is the one that's actually publishing that message, right? So we want to publish a message saying, hey, you know, my pizza has been made, you know, take a pizza store, like, and then a pizza store will pick it up. And it's going to do this from this emit event method. And this is actually using the Dapper client, the SDK, the Java SDK in this case, and we are using that publish event Dapper client, and we are providing it both the PubSub name, the PubSub topic, and the event. All of these details are matching up with our Dapper component file, which is the same one I showed on the slides, but it's essentially this YAML configuration file on the right here. And it is named PubSub, as you can see. And then we are, you know, only allowing topic-topic, and we're only allowing my kitchen service to publish on that topic, and then pizza store to subscribe on that topic as well. On the subscribing side, we have a pizza store, and essentially this is just listening on the events endpoint, on the events endpoint, and this is listening, this does use cloud events, I didn't mention that, but that's kind of just a nice idea that Dapper gives you in terms of both observability, as well as adding additional metadata properties within the headers, but essentially it's listening on the events, we're subscribing on the events endpoint, and you know, it's just gonna print out, hey, we received this cloud event from the subscription, in this case, it's from the pizza, or the kitchen store service. So let's test that out. We are going to run one of these guys. So in this case, we're gonna test this out by pretending we are the application, the kitchen service application, and we're calling out to the kitchen services sidecar, and we're using this Pub publish, Pub subtopic, the same one that we've been talking about, and this is going to, this should give me a 204 note content, which it did, yay, and then you know, if I head back into my Dapper logs here, you can kind of see this is printing out, emitting kitchen event, that's great, and then you know, I received this cloud event on the pizza store service on the top, which is fantastic. So this is allowed based on our policy, but let's try something that isn't allowed. So if I head down to my next one, I'm gonna pretend that I am the delivery service, in this case, I'm the delivery service and I'm reaching out to the delivery services Dapper sidecar, I'm calling the exact same endpoint, right? I'm calling publish, Pub subtopic, and I'm giving it, you know, everything else is correct, except for the fact that I'm literally from the delivery services Dapper sidecar, using that identity, essentially spoofing its identity in this case. So I'm gonna try this one, and you can see I get an error code that says, hey, Pub sub not found, because if you remember from my configuration, the delivery service isn't even in the picture, right? We're not even allowing this Kafka component to be even scoped to that delivery service. So it doesn't even get loaded by the delivery services Dapper sidecar, meaning that it's not even going to publish anything. So you can head over to the logs, you can see there's no new logs there, it never even went to that kitchen service in the first place, which is what we want. Next, we have the kitchen service Dapper sidecar. So remember, kitchen service is allowed, we're allowing this one, but we wanna publish on a topic that is disallowed. So this is on topic one, so topic should be allowed, topic one should not be allowed in this case. I'm gonna hit this send request, and we get this nice error message from Dapper with a nice error code that tells us, hey, you know, Pub sub is forbidden in this case. We are not allowing topic topic one to even be created on this message broker. And Dapper does some nice things with automatic topic creation in some message brokers do, so this is kind of a good fail-safe. But yeah, we get this Dapper Pub sub for forbidden message, which is what we want. And then kind of last example here, we have the event from the subscriber. So as I mentioned, this is the kitchen store is publishing, and then pizza store is subscribing, and then based on our config here, we are saying, hey, I only want kitchen service to publish and pizza store to subscribe. Let's try publishing as the subscriber, right? So for publishing as that pizza store service, let's see what we're gonna get. And we also get this, hey, you know, Pub sub is forbidden because, you know, this is the subscribing application that we've locked it down to. Again, just giving you super granular access into what you want your applications to do. This is also really nice from a platform team perspective, and we see like a ton of Dapper of people using, platform teams using Dapper because essentially they, because what they like to do is they like the component model, and what they can do is they can actually create these components that I was talking about and then hand these over to the developer teams, allowing like developers who might not be as experienced with some of these security ideas or these principles, these privilege, like zero trust security ideas to actually leave that stuff still to the platform teams. But kind of finishing off, the last thing I just wanted to kind of get to is like the bottom line here is that Dapper can improve your zero trust security posture just by adhering to some of these kind of zero trust principles, specifically in terms of asynchronous and synchronous communication. And like again, keeping that application identity intrinsically within your application. And then that was pretty much it. I think I have like, I think I'm done for time, but if anyone has any questions, feel free to come by the Diagrid booth. We are at K30 all week at KubeCon as well as we have a booth out here at App DeveloperCon, so thanks so much.