 Okay, so yeah, this is a good fence to make good neighbors. I am Nick Young, I'm not gonna be doing much walking around because of this thing, but yeah, let's get started. So, my name is Nick Young, I am a senior systems engineer with Isovalent, I do a lot of work on Selim service mesh there, but my other hat is that I am a maintainer on the gateway API, and that's where all of this work on reference grant mainly comes from. So, as an Australian, I feel like it's quite important that I mention that I'm not talking about this type of neighbors, although the theme song tells us that this type of neighbors often become good friends. The TV show is not what I'm talking about today. What I am talking about is that, the idea for this talk sort of came from this statement that it's a bit of a cliche, but good fences to make good neighbors is all about the fact that if you're living right next to somebody, the thing you need to do is talk to them about, you need to have agreements about what happens between the two of you, it's all about agreements and having clear delineation between neighbors is what makes neighbors good friends, that's what the, and so that's sort of where the theme of the talk came from. So, here's what we'll talk about today. So, namespaces is one of the most important security boundaries in Kubernetes. Making references across namespaces is actually really easy to get wrong, very easy to do in a not great way. There is a little bit of prior art here before reference grant, and then this is how we do it in Gateway API, including reference grant and what is a reference grant. And then actually, there's been a lot of developments in next steps for reference grant. I had to literally update this like three times this week because there's been some stuff happen this week. So, I'll get to that at the end. So, Kubernetes namespaces, hopefully, you're all reasonably familiar with Kubernetes, and namespaces are the main way you enclose a trust domain in Kubernetes. Most users have access to a bunch of resources in a whole namespace. It's pretty unusual to have people share a namespace and not sort of have access to all the same things. So, generally in this sort of use case, we've assumed in general that basically that people pretty much have admin over their namespace, like that they can read, read, write, and patch all resources in their namespace generally. Obviously, that's not always the case, but most of the design that we're doing here assumes that. It is sometimes really handy to have cross-namespace references. A good example here is TLS secrets that you might want some config to be able to consume, but you don't want people to actually be able to read. So, an example of that would be you've got some TLS secret that is the key pair for your, the wildcard key pair for your company domain. You don't want everybody to be able to read that key pair, but you probably do want a lot of people to be able to use things to make arbitrary sub-domains for Ingress or something like that. And so, that is a really good use case where it's really good to be able to have, to be able to say, you can use this, but you can't read it. And another one is that, this is another Ingress example, some people want to have Ingress config live in one namespace and the back ends in another. With V1 Ingress, one of the problems with it is that you can do that really easily, but it's kind of not ideal because of some of the reasons I'll go into. Yeah, so cross-namespace references are actually really hard because it's really easy to accidentally grant too much access. So, if you think about it, if Alice owns a namespace and Bob owns a namespace and Alice wants to use something in Bob's namespace and the primitives you're using just say, okay, Alice gets to use anything that's in Bob's namespace, Bob has no control, Bob doesn't understand what's being used and has no way to say you can't use this. Maybe Bob has something he doesn't want other people using, but there's no way unless you do something like this to make sure that you do that. And so, that's where we come to the key. The key is that two people need to agree. The person who is making the reference needs to be able to signal their intent that they want to use a reference across namespaces and the person who owns the thing that is being referred, the referent, need to be able to say this type of reference is okay. So, that's the sort of the key. There needs to be a two-way handshake for cross-namespace references to be more secure. I won't say secure because we're at a security conference, we all know there's no such thing as secure, but more secure I think is probably the best we can aim for you. I should note that I kind of feel like this is a pretty good general security design principle that if you're talking about any sort of crossing trust domain relationship, both sides of any trust relationship need to agree. Seems pretty stupid and simple when you say it outside, but we all know common sense is not that common, right? So, oh, great, my slides have not helped. Thank you for changing my things. Okay, so here's a piece of prior art. Well, I mean, for full disclosure, I was a maintainer on Contour, I didn't build this, but I certainly used it a lot. And so, we needed to solve that exact problem I talked about before with having Ingress Config live in one namespace and the TLS certificate live in another namespace. And so, we came up with this resource called TLS certificate delegation. And so, the way it worked was it lived alongside the secret that you wanna share access to and basically said, for this secret, this secret is available to be used by anything in the following namespaces. Notably, you could have star, which means all namespaces. So, it's up to the owner to, it is an option for the owner to be super insecure, but they need to actively opt into it. Yeah, so this then allowed you to use it in our customer resource HTTP proxy. We cribbed a thing that you could do in V1, V1, Ingress where you were allowed to put a slash in the name of the secret. And so, we said, okay, that means it's in a different namespace. Pretty hacky way to do this. Would've been much better to have a separate field. But, yeah, this is what we ended up doing at the time. So, yeah, that's sort of the main thing here is that it lives next to the secret that's being delegated and grants access to it from other namespaces. So, in Gateway API, we wanted to do this in a more stable, we wanted to do this exact same thing, but in a more stable, structured way. And so, this is our standard diagram for Gateway API and how the resources break down. One of the other things that we're trying to do at the Gateway API is we're trying to make it so that we break down the resources by the persona that needs to use them. So, Gateway class is roughly analogous to Ingress class, but it's designed for the people who own the infrastructure. The people who set up controllers who have full view, a large amount of access to a cluster. And then, individual cluster operators can create individual gateways which roughly correspond to a load balancer. Roughly, roughly, not always, but a lot of the time. And then, application developers can create routes of different types. HTTP route is about terminated HTTP traffic. There's TLS route, TCP route, UDP route, a bunch of other stuff. But the key part here is that we're sort of trying to break things down by persona. And so, when we're talking about these personas, it's pretty common that, say, the Gateway and the HTTP route will be owned by different people because they're different personas. A lot of it, sometimes, maybe they won't, maybe they'll all be, all these personas will simultaneously exist in the same person, but the whole point of it is that we're designing it so that they don't have to. And so, what we ended up doing is we ended up trying to find ways that we could solve this sort of problem. We've got a shared gateway in a shared namespace, and then you have HTTP routes living in the individual app namespaces that refer to that shared gateway. And so, this is, again, a classic, hey, we want to be able to do a cross-namespace reference kind of problem. But we want there to be this agreement between these two parties, between the owner of the gateway and the owner of the HTTP route. So, the way that we ended up doing that is because gateway is a new thing, it's a new CID and we have control of the entire spec and we can change anything we like. The way that we did it was that we made it so that HTTP routes basically request, so you can see on the right-hand side here, the HTTP route has a parent ref section that specifies the name and the namespace of a gateway. That's actually, there's actually a few other fields in there that we're not using here, you can do other types of things other than gateway, but the important part for this talk is that the shared gateway is in a different namespace to the HTTP route. And so, on the shared gateway then, you have this allowed route stanza that lets you say, hey, only namespaces that have the shared gateway access true label are allowed to have HTTP routes use this gateway. And so, that's again, this is the two-way handshake, right? Like, you've got the HTTP route requesting to be able to use a gateway and the gateway has to sort of accept. It's almost like, the allowed routes is almost like building a lock and then the HTTP route may have the right key. So, again, two-way handshakes, that's the order of the day here. But yeah, and this one was only possible because we control both sides of the spec of both sides of these objects. So, when we start talking about, yeah, hang on, I haven't missed anything there, good, good. So, when we start talking about core objects though, we can't change secret or service or any of the other core Kubernetes objects because they're GA objects and we don't get to make changes to them. So, we needed to come up with a way that we could have owners of those objects be able to do this sort of granting of permissions. And so, that's what reference grant is. Reference grant is the same idea that we had with that prior art of contours with the TL certificate delegation just kicked up a notch to make it a bit more generic. So, here's a reference grant. This reference grant sits in the app name space with the service. It allows references from HDDP routes in the namespace prod to anything that's a service in the app namespace. So, I'm pretty reasonably simple spec here. It's all just about creating that lock that sort of says I explicitly allow this access. And we're very careful here that there's no implied access here. If you create an empty spec, it means nothing. You have to actively opt in to every one of these fields. You have to put them in specifically. There is no sort of default behavior for a reference grant unless you specifically put things in. And so, here's another one that's a secret, similar idea. This one in the Gateway API only gateways are referenced to your Sconfig. So, they're the only ones that need to be able to reference secrets. And so, this one allows references from the gateway in the prod namespace to secrets in the secrets of your namespace. So, same idea, it's just allowing those references in. So, here's the design goals for a reference grant. For things that we couldn't change a spec of easily, service and secret are the first ones. But basically, you can use these for anything that you can't easily add fields to both sides of. There, I'll mention a bit more later, but some of the folks from SIG Storage have used this for some new support in a PVC controller to be able to do cross namespace references to PVs, which I thought was pretty neat. But yeah, and the other key things here is it's owned by the owner of the granted object and lives in the same namespace. Yeah, sure. No, no, no, so it's literally just the secret. So, the question was, what do I mean by the granted object? Does it make a copy of the secret? No, the original secret stays where it is. And then the controller that you implement this with needs to respect this behavior. It's one of the problems that if you want your controller to support reference grant, you have to like watch reference grants from everywhere and you have to implement this behavior that says you don't allow cross namespace references unless there's a reference grant that allows it. Yes, exactly, yeah, so. Yeah, yeah, so yes, you do, assuming that the controller can, oh, I'm just repeating for the recording, yeah. Exactly, yeah, yeah. Yeah, yeah, so it's not that you're, I mean, we actually called this reference policy originally, but that was an even worse name because we have, in Gateway API, we have another thing called policy attachment that is completely different to this, so we wanted to not reuse the same word for two things, which you'll be naming no, no. But yeah, so I think the key parts here are that the secret lives where it is, the controller that is implementing this whole behavior needs read access to like everything that you want to grant access to everywhere. Again, this comes from the world of Ingress where it's quite common for your Ingress controller to have read access to secrets across the entire cluster, whether or not that's a good idea, that is historically how it's been. If you want to be able to do a very dynamic Ingress controller where you have, you can create an Ingress or a HD Proxy or a Gateway or a route anywhere, then practically there's no way around that, like you can't get away from the fact that you have to just grant and bear read access to all secrets, and that's because although there are secrets have a type, you can't sub, you can't sub allocate the, the RBAC based on the type. Ideally, you would have a RBAC that says only grant access to TLS secrets, but we don't have that. We've only got by client, not by resource, technically, but not by subtype. Great question, thank you. So yeah, so because we really wanted to avoid the problem of having to have the thing that we were building to do cross namespace references, have cross namespace references itself, so that's why the reference grant lives in the same, has to live in alongside the thing that you're granting access to so that you don't have that chicken and egg problem. The grants access to things by group kind and namespace. The idea here being that if right now it's, it defaults, the group and the kind defaults to the gateway API group and kind so that you have left config when you're doing gateway API ones, but the, but yeah, and then of course it allows a namespace, I used label selectors there for the, the reference grant does not currently allow label selectors though. So the, the HTTP route and gateway interaction does allow label selectors, but the reference grant one does not. That's because when you have the label selectors plus the reference grant, plus all the other things you've got to watch, adding in label selectors for namespaces means you also have to watch namespaces and then you have like a whole extra reconciliation loop in case of namespace label updates. And so this is just about making these a little bit easier to implement. Yeah, when I come to the cap, there's a couple of changes that people have requested and that is one of them. So yeah, here's some other notes, I think I talked about this. The reference grant has to be fully reconciled. So you can't just say, hey, I saw a reference granted startup, now things are good. You have to watch the reference grants and if the reference grant is removed, that constitutes revocation of that, of the granted access. And so if someone removes a reference grant that allows access to a TLS secret for a gateway, you have removed, effectively removed the TLS secret and that gateway is now invalid because there's no TLS secret. And so the exact behavior here can depend on the exact type of reference and what you're doing with it and a bunch of other stuff like that. But the key part here is that if you revoke the reference grant by deleting it or by changing it such that the thing that you were referencing is no longer in scope, then you have to revoke the access. And again, yeah, controllers are expected to be granted very broad read access and then self limit based on the reference grant. So I mean, that doesn't help in the case that you're worried about controller compromise. And you know, like if you're worried about your ingress controller being compromised and then having a read access, this does not help you. You know, I think that is definitely a problem that we all should think about solving but this is not designed to solve that problem. In notably, right now there is no way to grant access to all namespaces. We talked about maybe using a special star name to say it to mean all namespaces. Again, I'm kind of in favor of that because my experience with this has been a lot of the time people are like, I know what I'm doing, I wanna be insecure. And I'm like, that's fine. As long as you're very clearly opting into something that's a terrible idea, you know, in general. And so having to take definite action to do something like really insecure is sort of my design goals for an API. Sure, so next steps. In terms of next steps, yeah, as I said, it's already used in Sieg storage for cross namespace data sources for persistent volume claims. So you can right now, it's in our file in the latest release of Kubernetes but in a persistent volume claim, you can reference a snapshot of a persistent volume that's in another namespace using a reference grant object. And so when the folks from the storage were doing that work, they were sort of like, it kind of sucks that we've got to import all the gateway API objects just to be able to get reference grant. And we were like, we agree, that does kind of suck. So we were hoping to, we opened a cap to move reference grant to a new API group home. And so yeah, those two QR codes are the blog post and the cap itself. That cap, as of like two days ago, has actually been merged as provisional. However, one of the things that happened is all the reviewers, which I was really surprised about, were like, oh no, we don't want this to be a CRD. The Sieg author reviews were like, no, this should not be a CRD, this should be an entry call resource. And I was like, okay, that's surprising. I thought everyone would be more in favor of this being a CRD, but in order for it to be a core resource, it needs to be much more generic than it currently is. It currently makes a lot of assumptions about the fact that you're running, probably running something like an ingress controller and about what sorts of things you're talking about and what sorts of access you're granting, most importantly. Like you're almost always granting read access or read only access to something. But the Sieg author reviewers raised the very reasonable question of what about if you want to do a cross namespace reference where you're kind of implicitly granting some sort of right access. And you want to restrict that separately to the read access. So it looks like probably we're gonna need to add like some other stuff like verbs to sort of further slice the access that you're granting down and some other stuff like that. So really interesting work. The original, the initial cap has merged as provisional. And so we're iterating on that cap right now and looking at doing some of the stuff like I just mentioned. And yeah, I think that part in particular will be really interesting. I mean, I'd be really happy if this ended up as a core resource in a future version of Kubernetes. It'd be really great. I think that it would be really handy for people. Notably, nobody is suggesting although this resource might be in core, it will not be reconciled in core. It'll be like ingress where the type itself exists in the core spec, but in order to have get any behavior out of it, you need to install a controller that will reconcile it for you. So I think everyone is agreement that it's gonna work very much like ingress in that respect. So you'll need to install like a reference grid compatible controller. And one of the other things that's really interesting about the design here is there probably will end up being multiple reference grant controllers in the cluster. Some of them might be a gateway API one. Some of them might be a storage one. There might be some other ones. And they're all gonna need to have some way to interact. And also then some standard way of feeding back whether or not your reference grant is in use. That is probably one of our biggest areas of upcoming work is how do we make it clear to you, the user, that the reference grant that you have created is actually correctly configured and is being used correctly. Or more importantly, if you wanna go and delete this reference grant, how do you know if 100 people are using it or if nobody's using it? Like that seems really important to me too. That yeah, you wouldn't wanna delete the wrong reference grant and have like 100 people be like, oh my God, yeah, my TLS site just went down because you deleted the, you effectively deleted the key pair, the TLS key pair, that would suck. So then having some feedback available to people that lets that stuff be sorted out would be good. So I have talked much faster than I anticipated. So you guys are all gonna get heaps of time for questions. But here's my takeaways. So cross-name space of reference are hard, really hard. It's really, really important to do them correctly, but it's really, really easy to get them wrong. And so one of the things I wanted to do with this talk was to sort of have a way to sort of tell people like, hey, the key thing here is just that agreement between the two parties. Making sure that you have the agreement between the two parties is the right thing to do here. Ah! Sorry. And then so multiple patterns are definitely possible to do this, to do this sort of crossing trust domain relationship. So we've already got two examples today. The gateway HTTP route, mapping, and then reference grant itself. So yeah, as I said, that was a lot faster than it was when I practiced. I think I'm talking much faster today. So we have a lot of time for questions. Really sorry about that, but please feel free to hit me up. Yeah. Also, I would argue that the thing that you are using is gonna have to read Kubernetes resources in order to be able to reconcile the reference grant objects. That makes it a controller, right? Like you are building a controller that is gonna maintain like some sort of custom reference to this API key secret. So the thing that you will have to build to do that is gonna have to be a controller. Like you're gonna have to have something that watches for reference grants, knows about API key secrets, knows like which ones are relevant ones and how you would grant them and then allows the thing that you want to be able to use that secret to use it. Most of what we've done here is about if you have a Kubernetes object that needs to reference another Kubernetes object, not like a service that needs to reference a Kubernetes object. In the case that you're talking about where probably you'd want, yeah, if it's an API key or something like that, usually you'd want to mount that into the pod as a volume is usually the way that you would consume an API key like that. And so you might want to be able, if you want to be able to have something like that, you can absolutely can do it using a reference grant, but you would need then a custom controller to sort of manage that. How do you get the secret to the right place? Probably if you're spending that effort, you'd almost be better off building a like a CSI plugin to handle the secret, to handle the secret. So you can build a secret store plugin that will provide you a virtual file on disk that when you access it will reach out via some web call to somewhere and give the contents back in a standard way. So there's a few ones that we'll talk to Vault or the various key management stores of clouds and stuff like that. So you can effectively mount a secret straight from some other key store into your pod. And then every time the pod accesses it, it gets the current value. So yeah, I think, I see what you're saying, but yeah, if you did build something that wanted to do that sort of cross-name source reference, you're building a controller. Like, yeah, it's gonna have to reconcile the reference grants because again, if you delete the reference grant, the access needs to go away. You need to revoke it. Is that? Yeah. Yeah. Feel free to argue with me. Like I'm not saying the only one is right here. Like, yo, yeah, yep. Yes, yes, exactly. Yeah, and so that's to prevent exactly this sort of thing because if the reference grant can live in a different namespace to the thing it's granting access to, then you're gonna need a reference grant for the reference grant, right? Like, that doesn't seem like a good idea for anybody. Like, so that's why it was much simpler to make it that. And also it helps with the notion of ownership, that if the, you, that the person who owns the object should own the reference grant. You know, it should be the same person. It's actually one of the things that came up in the CEP review was that the single author of reviewers would like us to mandate some sort of RBAC check that if you're creating a reference grant that allows access to a secret that you as the user have access to that secret. So that one is actually a pretty interesting problem of actually implementing that check. And so like, yeah, we'll need to do, the controller that implemented would need to do like subject access review for the person creating the thing as like validating webhook or something. So yeah, that's pretty interesting design that I'm looking forward to talking to other people more about. Yeah, so again, cool, awesome, thanks. Yeah, so I think that, so the question was with the, bringing a reference grant into core, what's gonna happen with the allowed routes and stuff. I think we'll probably will keep that the same because it allows sort of a really clear thing for people who don't necessarily need to go off and learn about reference grant. Like it's a very clear relationship. Sorry, too much talking. Made it? Yeah, yeah, yeah, yeah, totally, yeah. I mean, practically I think that we'll end up sort of owning the definition anyway, even once it moves into core. Yeah, so yeah, like I said, I think that the level of work that we've got to do is like, yeah, super interesting. So yeah, does anyone else have other questions? If not, well, like maybe I'll pull up that cap and walk you through a couple of things because we still got ages. Yeah? Okay, let me pull up that cap. I hope we can get this good at the PR. Okay, so here's the cap. Most of what is in there, thank you very much, man. Most of what is in there is what I sort of went over already. One of the things, the phrases that we did come up is something that I do like. So, as usual for a cap, you sort of go through risk and mitigations and stuff, like no default implementation. As I mentioned, that's one of the things that you'll need to provide your own implementation. I mean, it is a pretty big risk that allowing any cross namespace references sort of does weaken the idea that the namespace is your fundamental unit. I would argue that this is weakening in a very controlled, careful way and that's the best that we can hope for. But yeah, like the thing, so the reference-growing object is half of a handshake. That's one of the most important things that I would like you to take away from this, is you gotta have the handshake and the thing that we're talking about here, it's only half. The other half is that something has to make the reference and there needs to be a way for that thing to make the reference. Yeah, and so you can see here that we've sort of ended up needing to bring in the thing that you need to have, read access at least to the things that you're granting access to. So yeah, part of implementing control for this will be doing a subject access review of the person who's created that object and making sure that that person has access to the thing they're granting access to. Yeah, this one is one that I was a bit sad about. In the Gateway API reference grant, we chose to use kind rather than resource. So who here knows about the distinction between kind and resource? Okay, one person, yeah. Most of the time, this doesn't matter, but kind is a singular object, a singular name, capitalized, it's what you see at the top of your most general files, but it does not uniquely identify an object, like an object type. A resource is actually the portion of the rest URL that does uniquely identify a resource type. So because this API is gonna end up being very generic, we can't get away with using the sort of may not be unique kind, even though using it would be much easier for people to understand. And so practically what it means is that instead of doing something like this, where you're gonna be like kind gateway, you will need to be resource gateways. And so the resource is actually the one that you see in Q-Kettle and stuff like that. If you tab complete and you get like gateways, in the case of this it will be gateways.gateway.networking.cubinities.io is the name of the resource, fully qualified name. And so that's why we have to use the name that you can use for the fully qualified name. Unfortunately, as Tim Hawkins said, it kind of sucks that we have to do this, but here we are, we can't change it now. Yeah, we've got the revocation behavior that I mentioned, the deletion of a reference grant means that the granted access is revoked. One of the things here is it's like you need to remove any config generated, but it's kind of up to you exactly what that means. So for the storage use case that we talked about before, they're actually saying if the reference grant exists when you make the reference and the position of volume is provisioned, that's okay, that's enough. If the reference grant is later revoked, you don't like lose access to the volume because that would be pretty bad. Whereas in the case of gateway API, it's kind of expected that if the TLS secret goes away, then you can't serve, you shouldn't be serving traffic out of that gateway anymore. So it's a slightly different thing because it's a slightly different usage. And so it's one of the things that's a bit tricky about writing this is that we have to have wording like some actions that have been enabled, can't be undone, but no future action should be allowed. One of the hardest things about writing this sort of standard. So we had some examples here. I would definitely recommend that if you are interested in this, have a look at this cap. Obviously it's going to be important later. We will keep you all posted as this sort of makes into actual core. I would imagine there'll be blog posts in the future. As you can see, you end up needing to put quite a lot of yo-text around these sort of things. Writing API specs turns out you need to be, I have a lot more sympathy, I would say for people who write RFCs than I did before I started writing API specs. I used to read RFCs and was like, oh, how could you possibly write something so dry? And I'm like, that's because if it's not dry and boring, then it contains ambiguity. And that means that engineers will take great delight in telling you all the ways in which it contains ambiguity and we'll make your day living hell until you remove the ambiguity. So, yeah. But what about if you do this edge case? Oh yes, okay, we better cover that too. So yeah, I think one of the other things that people have had an objection to is the use of from and to as the names. I think as this is a more generic API than the original gateway API one, it kind of makes a bit more sense to have you know, something like subject from, subject origin, subject object, like I was like, you could use subject object, that's technically correct, but it also means that you need to grammatically explain to people the difference between a subject and an object. You know, and people are generally pretty bad at that one. So yeah, we look like we're gonna be having a good old bike shooting session about the names there, but yeah. So I feel like I'm starting to be a bit boring. So I will sort of stop here that one of the things, like I said, that we really need a lot of design work on and I would love to hear people's opinions on is how best to surface information about how this thing is being used. The naive answer is, oh, I have a status on the reference grant. The problem then is that if you have 10 controllers reconciling different types of reference grant, every single one of them is gonna need to write status to every reference grant to say whether or not they're using it. And so how do you coordinate everybody writing into the one sub-resource is really, really hard. And ads can produce a lot of fun race conditions and eventual consistency bullshit. You know, that basically makes it really hard. So yeah, I'm really interested in like spending a lot of time thinking about that sort of stuff, but yeah. Sorry, yeah, go. Exactly, yeah, yeah. Yeah, yeah, so you need to, so either you need to be like, hey, you are consuming reference grants in your resource. Your resource needs to have something that says the reference grant has been consumed because you know what the thing is, but then the owner of the reference grant has no way of knowing what possible resources could be consuming it aside from what they have allowed. So yeah, exactly, right? So I mean, there's a real interesting design space problem there about how do you communicate the intent back to the user? How do you do that without creating massive fan-out problems for the API server where updating what object means you then need to go and update the status for like 100 other objects and things like that. There's a real risk in this sort of design. So yeah, there's a bunch of interesting, really interesting sort of design work there for this API, but I think that, you know, as you can see, like it has a lot of potential. I think that making, being able to make this sort of cross-name space more secure in like a standard way could be really game-changing for lots of different use cases. So yeah, with that, I've probably taken up enough of your time. If you have any other questions, feel free to grab me here. Catch me on Kubernetes Slack at Youngnick or grab me anywhere around today. So thanks very much, everyone, for your time. Thank you.