 All right, so this talk is about delivering complex software with open component model and flux in the context of high security and with the potential of zero connectivity. So starting with a little intro here, who am I? I'm Dan Small. I'm an expert software engineer at SAP. Been with them for about three years. I've been in the industry for about 27 years, mostly big companies, Symantec, IBM and now SAP. Worked in the dev tool space, the GRC space, and worked on a lot of internal CIC-CD type projects. I've got a little mini agenda here. We're gonna talk about some challenges with delivering complex software products across security boundaries and clouds while painting compliance, a little bit of theory. So we'll have an intro to the open component model and the OCM tool set, the integration with flux and this term we're throwing out called get ops localization. And then we'll have a little demo where we transport a simple software component, or describe, transfer and deploy a simple software component using OCM, well using the elements that we just saw up above. All right, so challenge. How do you deliver cloud native apps everywhere without jeopardizing security and while dealing potentially with zero connectivity? So true cloud native apps are cloud native everywhere. Software providers like SAP need to describe, transport and deploy complex apps too, public cloud, private cloud, sovereign cloud and government clouds. Now these last three are the key reason for us having this talk because with those usually you have policies in place that prevent you from just pulling whatever you want from wherever you want. So for example, Nginx, maybe you can't get that from Docker Hub but instead you have to get it from some internal private registry. So to kind of summarize the need of the challenge here, you need the ability to describe a software component in a way that lets you gather up all of the deployable bits, then transport them into another environment and then once they're there, any of your deployment descriptors, anything that refers to those deployment bits, they need to be fixed up. And this process of fixing it up, we're referring to that as get ops localization. And once that's done, then of course you wanna use normal get ops methodologies for getting your software deployed. And of course this all can apply to on-prem and hybrid cloud as well. But it's not just about deploying the bits. You also wanna bring over all your tools, processes and standards into the new environment. For example, any orchestrated deployment processes you need those to keep working. In addition, you wanna be able to secure your supply chain while doing this as if you were in your previous environment. So, kinda summarize what's needed here. After transport, you need to be able to check the integrity of what was transported and you also wanna be able to verify the provenance of it. Is it what I in fact expected it to be? Also, once it's been transported, you may need to perform some sort of locale specific compliance checks, maybe a particular type of antivirus scan or something in that new environment. All right, so the solution we're presenting is bringing this all together with the open component model. So, bringing together the component description, the deployment resources themselves and any signatures that were acquired along the way. Bringing that all into one thing, the open component model. And this comes about because folks at Weaverworks and SAP kind of realized that what they really were needing was a consistent way to refer to describe a software component, a way that was machine readable. And then with this, it would be easy to implement tooling that would let you transport the bits, the deployable bits from one environment to another. And for anything that's going to need to look at those bits, again, any sort of vulnerability scanners or what have you, they'd have what they need in order to do their job. So we'll look here at the open component model, an example of it. So this is just, it's a YAML-like syntax or YAML-based syntax. So every component has a unique name and a version, and then a set of resources. Now, thing to note with the items in the resource list or the one item that you see here is that how you identify the resource and how you locate the resource, they've been made separate. So instead of just having like a URI to some sort of OCI image and then you're done, no, we're keeping it separate. That's gonna facilitate this GitOps localization because you can just adjust, once you move your model from one environment to the next, you just adjust the location and everything else can key off of that new location. Now, this whole thing is focused on delivery artifacts. So we're throwing out also this term, software bill of delivery as a way of describing what this provides. Oh, one other thing before I move away from this, it's also supporting nesting. So one component can actually be comprised, not just of resources like a Docker image and a Helm chart or what have you, but it also can be comprised of other components. So you can have a dependency chain represented by this. All right, so use cases. So your normal build process, if it were just to do what it does today, but then produce a one of these OCI component descriptors with that, then you'd have one way to refer to your artifacts. You could say, rather than to say, well, I've got my Helm chart over there and I've got my Docker image over there, you would say, okay, well, I've got my component and then that can say, well, in it in a standard way, there's this resources, that resource, they're bringing it all together in a standard way. And of course, you could have one artifact or one component referring to another component. You could group them into an even bigger set. And with this OCI usage, now all your tooling can have one way to refer, one common name to refer to any single component, rather than it's, well, it's a big bag of, there's that, there's that, there's that. You could say, hey, refer to the one software component in the inside there in a standard way. You've got your enumeration of all your resources. Any process that needs the bits, if you're using open component model, though any process that needs a bit can go find the bits because the component descriptor says where the bits are. And of course, dependency relationships are now visible to any tooling that cares. So for example, if your compliance group is saying, well, we wanna know everyone that is using log4j because that has some vulnerability. Well, if that's been modeled as a component, they can see in the chain, you can, your tooling can say, well, hey, here's all the things that are using that. And of course, if all the signatures gather in one place, you don't have to, if you're saying like, say your vulnerability scanner or your AV scanner, whatever, those tools are putting signatures on the component to denote this has been passed this process. Now you've got all the signatures gathered in one spot. And with all that, okay, you can also then have your transport work, right? Because as we said, you've got a component that says here's where all the bits are. And you can have tooling and say, all right, well now we're gonna move all those bits over here and update the descriptors to say, well, in this new environment, this is where the bits are. And of course, in the new environment, you can kind of, you have all the same benefits. So any additional verification or anything has to happen in the new environment. If you're using this model, it's easy to implement. All right, so how do we automate this? Now this is a Kubernetes, GitOps, Flux integration kind of talk. So we're gonna just focus on the Flux Ocm integration. So there's basically four parts to this integration with Flux. There's the Ocm CLI, and that is taking a component descriptor and then putting into a OCI repository that you have picked, putting all those resources and the descriptor in there. We've referred to that as an Ocm repository, but it's really just an OCI repository with specific stuff in it. So that's one piece. There's a custom resource type or set of custom resource types that live in Kubernetes that kind of realize these components in Kubernetes. And then there's an Ocm controller, which is responsible for taking what it sees in Kubernetes, the custom resource instances that are in there and taking the information that's in the Ocm repository and putting that into an OCI repository that it creates and that it makes Flux aware of so that Flux can then you can just use your normal reconciliation from that OCI repository that's been populated by the Ocm controller. And we'll get a sense of this when we get into the demo. Oh, right, one other bit of automation, localization. So there's this OCI registry that the controller is populating and you're making visible to Flux. The resources that are put in there are localized with whatever localization rules you've provided. And again, we'll see that in the demo. Okay, so the demo. So in this demo, we're going to describe or look at the activities of describing simple software component, transporting it across a boundary and then on the other side of that boundary, we'll have it deployed using the GitOps localization. We'll do this twice. We can see the process is repeatable. V1, V2, we'll get them rolled out. Now we're creating our boundary by using two orgs in a GitT repository or a GitT server. This isn't really air gapped, but that doesn't matter. Ocm is capable of storing any number of component versions into a tar file, which you could then put into a USB fob, transport into a secure location and then upload from that tar file into an Ocm repository that's waiting in the secure location. So you can just take that and insert it in the middle of what I'm showing here and you'd be covering the air gap scenario. Now for this demo, I've pre-created a few resources just for expediency's sake. In the public org, we've already got our Docker images. We've got one of our two component versions and then a myriad bit of source code. And then our private org, we have all the boilerplate customized files that are required to actually make the deploy happen. Before I move away from this slide and actually get into the demo, I wanna call out that not visible on here is the CLI, but there is an Ocm CLI. And we can see here in these images that we have represented the component, the product, and it has references to the Docker image. And so when we do the transfer, we wanna transfer our component from the one org to the next. And in the new location, it's gonna be referring to Docker images that are local in that new location. All right, so here. And hopefully this is, okay, so, right. Before we do that, we're gonna go, right. So the first thing we're gonna do is we're gonna look at those resources starting with this deployment descriptor. So the thing of note here is the image field is actually just having some placeholder value in it. And that's because the GitOps localization will actually fill that in after the transfer is complete. Now here we have a component descriptor and you'll recognize a couple of the elements from one of the previous slides. So we've got our unique name in our version and we've got a resource list. Now unlike before, we don't have any composition aggregation happening here. So this is just a really simple resource list. What we do have is a nearby directory that has some manifests in it. The deployment YAML was one of those. We have a config and we'll get to that in a minute. And I guess it'd be worthwhile to make note of the name of that config and then also the next resource, which is our actual OCI image, the Docker image that has our code in it, make note of the name of that image there because we're gonna see that as well. Anyway this is just a simple descriptor. We've got a resource list in here and you can see again the identification of each resource is separate from where it is. So now moving on to this config YAML. So I mentioned before about localization rules. So here we have an example of localization rules. So you can see we're saying what's gonna be localized, the deployment YAML file that we looked at before. So then something that's in the component and then how it's gonna be localized. Well it's got a reference to the field in the YAML file that needs to be adjusted. So that's the image spec. And then okay the value that is gonna be stored in that field is the location of the image resource. So here where that name there image is referring to the name of the resource in the component descriptor before. Before we leave the browser, we'll just look into the private org OCI repositories. Repositories, right now there aren't any. I'll just do a refresh here. And that's gonna get filled in when we do our transfer. Okay so now going to, the first thing we're gonna do is we're gonna take that component descriptor YAML that we had and we're gonna make a component archive. So the component descriptor is really just for machines and for people to work with to describe a component but it's not the actual component. Component archive content or what you would have in an OCI repository, that would be actual component. So we're gonna produce a component archive and then we'll also just kinda show what's in there. So you see here we ran a couple commands. The first was this add component versions. That's actually making our archive and you can see something about what went into the archive. And the next thing we did was we just enumerated the resources in the archive just to see okay yes and what we wanted in there is in there. All right now the next thing we're gonna do is we're gonna sign this and then we'll run the verification on that. So you can see here the signature command was run or the sign command was made run and then it printed out a bunch of digest for the various things that are in there in the component archive and it gave a thumbs up. And then we did a verify which the output looks very similar. It spit out some digest of what was in the archive and it gave a thumbs up. Now the next thing we'll be doing is we're going to transfer this component archive into the public OCI repository. So we're gonna put that v2 into our public repo. And we're also after we're done with that, so this actually ran two commands. One was the transfer so we took what was the component archive that was local, transferred that into the OCI repository of the public org and then we actually did a verify and you can see the tail end of the command there where we're saying hey, we're targeting this repo we're not just doing something local. Next, all right so the next thing we're gonna do is we're going to transfer version one of our component from the public org to the private org and then we'll verify that. We'll verify that the bits landed appropriately. So here this is running. Now this takes a little bit more time and we can see here, we can see here the transfer command here, it took longer and the reason why is we use this copy resources switch. We didn't use that before. So because we use the copy resources switch, the component version that was stored in the private org actually has in it the Docker image that's part of our component. So before we didn't actually transfer the component basically the components versions that we put into our public org, all they have is basically pointers to wherever the Docker image is. They didn't actually bundle the Docker image in the component version itself. But this time with copy resources that's happening. So that's where we get our transfer happening. And then at the end there, the second command we did a verify. This time though we're looking at the private org where we transferred our component to and it's verifying that hey, the signature is still valid for the bits wherever they landed. If we go here, I believe and we refresh this, oops, refresh this, we see okay in our private org, now we've got that first OCI repository which is it's an OCI repository which means it has particular content in it, the component version descriptors, et cetera in there. And then we also have our Docker image which has been transferred over. While we're here, we'll go to here. Okay, so of the resources that we have in our private Git repo which is hooked up with Flux, we've got some files relevant to this whole process. So first we'll take a look at the component version YAML. Okay, so this custom resource here is making our component visible within Kubernetes that the OCM controller can do its magic. And in here at the bottom, we can see that we're telling it, hey, you're supposed to be verifying things, making sure it's signed by Alice. So that verification that we did before from the command line while we're transporting bits, okay, that's all good. At least in this case, it's a bit redundant because the OCM controller has been told, hey, anything that you're dealing with, it has to be signed. This is like an automated securing of our supply chain here. And then we will look at localization. So this is, this custom resource is telling the OCM controller, hey, you've got localization rules to apply. So that config YAML that we mentioned before, that's going to be named in here. Yeah, rather unimaginative name at the bottom config. But anyway, this is telling OCM controller, hey, you've got to localize things using the localization rules we mentioned or we showed before. And it's gonna put it, like I said, into an OCI repository that Flex will be looking at. So that repository is named there. So this is just a plain Jane Flex customization file, really. The only thing it's significant about it is that it's pointing to the OCI repository that the OCM controller is producing and filling in with localized data. Okay, so I think that's all we wanna look at there. And then if we go here. Okay, so we have now, we see there's a deployment that's running. It's been running for about four minutes for about as long as I've been yacking about this thing. And if we take a look at the deployment descriptor, we can see that the image has been fixed up, that GitOps localization took place, right? It's pointing to our private repo and it's version one. It's specifically, it's the version we transferred over. And then if we do this. So here we're, now we're transferring over the V2 of our component. And we take a look again. Now we see we have version two. So we can see how with OCM and the tooling around it and the GitOps, sorry, the Flex integration, we can automate this whole process of transferring and localizing our deployments on PowerPoint. Don't fail me now. So the takeaways. OCM as a uniform component model enables automated standard and secure supply chain processes. OCM is really a software bill of delivery and the Flex OCM based GitOps localization provides GitOps automation for complex software product deliveries and deployments. And in case I didn't mention already, we have a website OCM software where there's getting started guides, links to the spec, documentation, and contact info if you want to learn more about OCM and or potentially contribute to it. And I guess on the contribute part, I forgot to mention. OCM isn't just about deploying Docker images. It's been designed with the intent that it would work with other things as well. So RPMs or whatever kind of packaging you need to deal with. We're just showcasing the Docker container support because that's what this show is really about. So I think that's it. If anyone has any questions or anything, I'm here and I'll be around for a couple of hours after as well. Thank you.