 Hi, I'm Carolyn Vance, like a principal software engineer at Microsoft. Today, I want to think through how we can have our cake and eat it too. Namely, I want to install software quickly and securely. Now, I have to admit that I'm kind of a sucker for running an installation script by using curlpipe bash. I mean, I know I shouldn't, but it's just so easy and I'm so lazy. Now, this laziness extends beyond just installing dev tools on my laptop. A lot of cloud-native software could benefit from having a more straightforward installation process. Common Wisdom says that curling a script, piping it to bash, isn't safe. So what can we do to make this work instead? What if we could make installers that are as easy to use as curlpipe bash, but were a whole lot safer? First, let's talk about what curlpipe bash really is. So this is what it looks like. That's when you copy and paste a command that looks like the one right here. Now, we all use scripts like this because they install quickly and it helps you a software that you aren't familiar with. Curl downloads a script and then the script contents are piped to bash and they're immediately executed. Personally, I really like installation scripts. I can copy-paste my way to victory with just a single command. They require little to no knowledge of the installation logic or tooling. And yeah, I really do believe that the project maintainers can automate the installation way better than me on the first try. So let's review why curlpipe bash is a security risk. What if someone on the internet offered to help install an application that you really wanted and they would do it for you? All you need is to hand over your laptop for five seconds and they'll type super fast and boom, it's installed. Now, I don't know about you, but I don't hand over my laptop to my husband and I trust him mostly. When we think about handing over your laptop to a stranger, it's easy to see why it's risky. They would have access to everything on there, documents, pictures, environment variables with security tokens and passwords. You're logged into a bunch of sites, maybe even your work VPN. It's clear that they could do anything with your laptop that you could do. And that doesn't change when you switch from a physical laptop to a quick copy-paste of an installation script. When you use magic installation scripts, you are giving the script full access to your laptop and anything your laptop has access to. Oops. So okay, what if you read the script first and then run it? You open the script in your browser, you look it over and go, yep, this looks like how I expected. And then you run the script. So here's a fun fact. A web server can detect that you are piping that web request to bash. A malicious server can detect that you are piping to bash and then decide to give you a different file. Not that file that you just read in your browser, but whatever it wants. And then you're right back to where you started, letting Rando's run amok on your computer. Instead of using that handy one liner, here's a safer way to run an installation script. First, download the script. Then if they provided a checksum of the script, match against it and make sure you've downloaded the right file. Now, read the script, figure out if it is legit, if it's what you want to be running, and then, you know, run it. My frustration with this is that the copy paste experience from that one liner is completely lost. No one really wants to read bash. And depending on the complexity of the script, even after reading it, you may not completely be sure what it's going to do. Most importantly, when you do finally run the script, it's executing as you. And again, it can still do anything that you can do. Alright, so we aren't supposed to curl pipe bash, but what if I really want to anyways? Have you ever wanted to try out some software? And the installation instructions are like 15 steps where you have to install three CLIs, copy your credentials into more environment variables. You're gonna forget about them and leave them around forever. And you know, it requires a database that you don't feel like figuring out how to set up. And really, now that you think about it, maybe you'll just try out this some other time, because this is just one more act to shave, and you have work to do. You know who could really benefit from a one liner? Cloud native deployments. Often they're complex with dependencies, dedicated CLIs, magic configuration credentials. Most of us don't want to read a series of docs and install extra tools just to try something out. We really don't want to figure out how to script coordinating all these tools. For example, creating a database, and then passing the connection string as a helm chart value. Just a little example, but I don't want to do it. Lots of potential users stop there and decide this is more than they're willing to invest, especially when they're just figuring out, is this software they want to use? And they're installing a couple and trying them out to see how they work. So I know that I just said we shouldn't curlpipe bash, but if we could just provide our users a great experience to quickly set up and try out our software, that would be great, right? So let's flip the reflexive, you can't do that, that's not safe, to how can we make it safe? What would we need to do to make that happen? We need to isolate the installer, only giving access to what it needs, instead of being able to read God knows what, that is hiding on my laptop. We want something that does the boring stuff, like checking signatures or digest for us. We also want reliable insight into what is actually in the installer so that they don't have to read the source. There are a couple of tools out there that can meet most of our requirements here. Now, one of them is the CNCF Sandbox project, Porter. Let's see how close we can get to making a safer installation experience for our users. Porter is a command line tool that makes cloud installers. It packages your application, which could be a website, a microservice, an IoT app, whatever, with all the necessary tools, configuration, and deployment logic necessary to properly install your application. The bundle is versioned, it's distributed by OCI registries, and it can be installed with a single command. Now, it doesn't replace any of your existing tools, and Porter works with any tooling or stack. You can use VMs, serverless, IoT, bare metal, whatever you can script, it all goes in the bundle. Porter provides packaging, distribution, a layer of security around what you already use today. Let's say that I have a nifty app that I'd like to share with the world. TabiCats Tracker. TabiCats is a browser extension that shows you a different cute cat like you see here on each new tab that you open. TabiCats Tracker is an app that lets you save your favorites and share your top TabiCats with your friends. TabiTracker runs on Kubernetes and it's installed with a Helm chart. And because I was resume padding a bit, it uses the cloud database to save your Tabis too, so it's got everything in it. Now, let's use Porter to install TabiTracker safely. No curl pipe bash for us. For unfamiliar bundles, you can use Porter Explain to learn how to install it. Bundles have metadata that describes what the bundle is, its version, the credentials it needs to install, and any parameters that you can use to customize the installation. Explain gives you enough information to know what you need to pass to the Porter install command, or later to the upgrade command. Now, looking over my bundle, I see that I need an Azure service principle. I can pick which region to use, though it'll default to my favorite central US. I can also see that the bundle uses Terraform and Helm. And based on the outputs, it's going to create a Kubernetes cluster and a database. All right, that makes me feel a bit more comfortable running this bundle, since I can see exactly what credentials and tools the bundle will use. Next, I'm going to tell Porter, where can look up any credentials that the bundle needs? In this case, an Azure service principle. Instead of storing them in environment variables on my computer, I'm going to put them into a secret store. Here, I have Azure Key Vault set up with secrets for the service principle. I'm using Azure, but I could have used any secret store, like Hashicorp Vault. Porter has something called credential sets, which is a mapping between the credentials used by the bundle, and where Porter can look up those credentials. When the bundle is run, Porter looks up the credentials just in time and injects them into the bundle. This is great because it keeps sensitive values off my Dev NCI server. Now, I'm going to run Porter credentials generate to make a credential set and pass it to my bundle. Porter is going to walk through each credential and prompt for where that value is stored. Now, mine are all in a secret store, so I can just enter in the key name for each value, and this tells Porter where to get my credentials when it needs it later. Now, I realize this is an extra step installing something that you wouldn't have to do with curlpipe bash. But remember that one of our goals was isolating the installation script from our local computer. We don't want the installer to be able to snoop around and find juicy environment variables with tokens and credentials in them. When Porter runs a bundle, the bundle executes inside a Docker container. Any credentials that the bundle needs must be explicitly passed in. A credential set lets me store a hint for Porter on how to find my credentials, maybe I have one for my Azure credentials, another for AWS or GitHub. I can define this once, and then when I run a bundle that needs access, I can give the bundle that credential set without having to specify each time how to read them out of a secret store. Now that all this security stuff is out of the way, here's the one liner to replace our curlpipe bash. I can run Porter install, give it my credentials, and the bundle to install, that's it. So even though the bundle is using Helm and Terraform, I don't have to have those installed on my laptop because the bundle, remember a Docker container has the right versions of the CLI installed alongside with my Terraform files and Helm charts. Everything my app needs to install is inside that bundle. It doesn't matter what I'm installing, it's the same Porter install command. Now that my app is installed, let's check it out. The Porter list command lets me see everything that I've installed with Porter, and I can see more details about that installation with Porter show. So I can see when it was installed, if it was successful, and if I had specified any custom parameters when I installed it, they would show up here too. What I'm looking for next is the URL of Tabbycat's tracker that I installed. I'm going to look for the outputs generated by the bundle with Porter with installation outputs list. So the bundle saved all sorts of useful things and the connection string for the database, a Kube config, Terraform state, and here's what I was looking for, the endpoint for my app. Now you're going to see that I'm kind of an inspiring web designer, but hopefully the Kube Tabbycats make up for my CSS skills. Seriously, even if you aren't into Porter at this point, I hope that I've tricked you into installing the Tabbycats browser plugin at the very least. Now let's go look at the cluster that it made for me. I'm going to save the Kube config, and then I'm going to use it with Kube CTL and see what was deployed. Here I want to call out just two things. First, the image used by my deployment uses a digest, not a tag. That's something that Porter can help you manage so that you aren't copying digest around, you know, because it's not quite as easy to work with as tags. And I'll show you in a minute just how Porter does that. The other thing that you can see is that Porter injected the connection string for the database that the installation script created. Now let's go see the source for the bundle and how it was made. A bundle is defined by a porter.yaml file. This manifest contains basic information about the bundle and also has all the data that you saw from Porter explain. Here you can see that I declared that we need an Azure service principle and also a region parameter. Keep going. Let's look around a bit. It also declares what tools are inside the bundle by declaring mixins. Mixins are building blocks for bundles and they help you use existing tools inside of a bundle and have it work the way you'd expect. Mixins install the tools inside the bundle's Docker image and map between the yaml that you see here and the final commands executed inside the bundle when it's run. Mixins can make it easier to write the bundle. For example, since we are using Helm inside of the install action, it will automatically use the Helm install command. Mixins help you extract data from a step and pass it into the next step of your installation. Here Terraform created a cluster and a database and I'm grabbing those out of that step and making them available to the Helm chart which I'm running right next here. Normally this type of stuff is all done with a bit of glue work inside of bash and you could still do that if you wanted to. The mixins just make it easier to focus on the deployment logic. So pretty much everything you see here helps you create a bundle with just one file and the YAML kind of helps you piece everything together. You don't have to do this like quite honestly you could keep the bash script you wrote today, put in the bundle and go but for a lot of people this extra metadata and structured view of passing data between steps can be really helpful. So did we hit the mark? If I'm looking for a safer way to quickly install Rando software from the internet, does Porter meet our requirements? Now we wanted to isolate the installer, automatically check signatures and digest and we wanted insight into what the installer was actually going to do. Bundles really just borrow security features from existing tools. We can check off isolated installer, they run in a container and they only have access to what we explicitly provide like cloud credentials. Bundles are distributed over OCI you know docker registries and this existing infrastructure that we already know how to run, we can scan it for vulnerabilities, we can check digest and Porter can help do this for you. So we, Porter, we're also working on signing bundles with Notary so that Porter can check the bundle signature and verify that it was created by a trusted publisher. So that checks off our first two security concerns. So for the rest with Porter explain we can see what's in the bundle and how to run it which is way better in my opinion than reading bash. Great so it's safer than curl pipe bash but is this the experience what we were originally aiming for? Full disclosure it isn't always a one-liner. The first time you run a new bundle you're going to run Porter explain to see what credentials it needs and then create a credential set with the creds it needs if you don't have one set up already but for any bundle that you've worked with before it's just that one command Porter install. I mean I'm calling it close enough it's always the same command just Porter install regardless of the tech stack tucked away inside the bundle so I think we're doing pretty good here and finally what we really wanted all along was a magic installer someone with no experience with the app or any of its deployment tools they can run install and get a working installation of software in very little time I mean kind of magic so I mean there you go it's a safer curl pipe bash for cloud native deployments we should have accomplished I said that this is a safer curl pipe bash originally but there was a there's a little qualifier on the end of that which is I said for the cloud Porter isn't really intended to install just say a command line tool on your local dev machine what bundles can help with and make safer and easier would be things like quick starts for your application you're trying to help someone get your software set up for the first time so they can try it out or customer installations you're not a sass you're shipping something that the customer needs to install so in addition to writing an installation guide you can give them the installer that helps them get up get set up really the first time but it also tracks upgrades over time so that you can manage additional operational concerns from day to day like a bundle could help you do troubleshooting for the status see what's up or down or do a backup even your own internal applications just like an external customer would kind of appreciate a little help setting up and running your software you know the same applies to the people on your team the people managing your software in production aren't always the developers who wrote it being able to upgrade to a new patch quickly flip a parameter and like crank the log level to 11 with just a single command I think is kind of useful teams can also share an installation of Porter so that when say someone stalls the app in a new environment on Monday another team member can see what was done and pick up where they left off without any explicit handoff you can also use bundles for a side project now I don't know about you but when I work on a project in a weekend you know I'll figure out how to set up all the infrastructure and like configure the secrets for my app and then I get distracted like life happens so I tear it all down because I don't want to be paying for it and then when I come back to it a few weeks later I don't know I've forgotten how to install the darn thing to be honest and this is where bundles are kind of cool I can capture all the logic for deploying this app that I was playing around with and when I come back to it later I can just run the bundle and I didn't lose any progress trying to re figure out what I did a couple weeks ago and I mean this is why I like bundles I can ship not just a binary or a docker image and if I'm really like going above and beyond giving someone an installation guide that's actually useful instead not instead but in addition to I can just ship an entire installer it has all the tools it needs it knows how to do a proper installation not just what was easiest to document and come on I mean you know there's a gap between the two what's in the docs and what's a real production installation you could put that real production installation in the bundle even if it's awkward and hard to describe here are some resources for getting started making your own installers the quick start walks you through how to use porter to install bundles or you know if you like videos or learning page as demos and talks that cover porter just in general and when you're ready to make your first bundle run porter create boom you're up and running then head over to our authoring bundles page for more details on what you can do inside of a bundle now if you have any questions our community page has links to slack our forums the mailing list you can ask questions and connect with other users thank you for going on a bit of a user experience journey with me asking ourselves an important question that I think is relevant to any software how can we make the tasks that people are going to do regardless no matter what you say how do we make that more secure rather than telling someone nope that's a bad thing you're a bad person for wanting to do it let's aim to understand why they want to do this task in the first place what were they really trying to accomplish and maybe there's an alternate user experience that we can provide and make it safe thanks everyone