About a month ago, I whipped up simple shell script that would download some puppet modules and then generate a valid snippet of code you could insert into your Puppetfile. This was helpful when you wanted to add a single module but it had dependencies, and then those dependencies had dependencies, and then 30 minutes go by and you have no idea what it was you set out to do in the beginning. As I started using it, I realized this was only half the battle – I might already have some of those dependencies in my Puppetfile and adding the same modules again doesn’t work.
So I started adding to the script and quickly realized a shell script was not sufficient. About three weeks ago, I decided to convert it to a ruby program and add cli arguments to support all the new features I wanted and that some users were requesting. I had a few problems I knew I needed to solve, namely how to parse an existing Puppetfile and pull out the existing forge modules, how to combine that and any non-forge module data with the new module list and generate a new file, and how to generate a .fixtures.yml file. I also ended up with a boatload of problems that I didn’t know I needed to solve.
Security isn’t about being secure.
That’s a bold, but honest statement. Sure, you want to be secure, but it’s not a realistic end goal. No matter how much you “practice” security, it never “makes perfect.” Someone always has more time or resources to throw at attacking you than you have to defend yourself, whether we are talking about physical or cyber security. Burglars have just as much relatively overwhelming capability as nation sponsored and endorsed hackers. This has held true for centuries (16-17th century pirates were often state sponsored!) and we should expect that to hold true for the foreseeable future as well.
Accepting this premise leaves us with a bit of a quandary. If security is not about being secure, what is it about?
Security is about reducing the risk and scope of vulnerabilities. The risk is the likelihood of any given vulnerability to be exploited. Storing everyone’s passwords in the clear but having restrictions on people and applications that can access it may have a lower risk than encrypted passwords that are exposed on GitHub. Scope is the range of impact the vulnerability would have, direct and indirect. A full 100% cleartext passwords would be available to exploit immediately, a much larger scope than encrypted passwords that would take time to exploit and likely never reach 100% availability.
When designing and implementing security, stop believing that you will build a “secure” product, whatever that is. Analyze potential vulnerabilities by risk and scope and make informed decisions about how to address them. The aim is to reduce both risk and scope to acceptable and reasonable levels given your outstanding technical debt, your available resources, your regulatory environment, and your user base. This means you will inevitably have to decide between compromising the security or the usability of the systems you design. The analysis you’ve already performed will give you confidence to make the correct decision in your circumstances and give you an understanding of the limitations of that decision.
Revisit your vulnerability analysis on a regular basis so your security posture can be improved over time. You can’t afford to make your home as secure as Fort Knox, and most of our employers can’t afford to do the same either, but you can get closer every day. This is the true practice of security.
Inspired in part by Eric Wright’s recent article Thinking Like the Bad Actors and Prioritizing Security