Information security practice has evolved to be pretty good at granting and managing access to confidential information - by people. But automation is taking over. Applications, servers, even networks are not configured and deployed by hand anymore. This is great; our systems and delivery pipelines are becoming faster and more robust. Automation, however, requires a shift in how we think about securing our infrastructure and the applications that run on it. When delegating our authority to non-human actors, we want to make sure they can only do what we ask. Modern infrastructure is made of cattle, not pets. A VM or container may be running less than the time it takes to record their existence by hand. In this article, I will cover a few common steps in the modern development lifecycle and share best practices for securing them.
- Development - Keep secrets out of source, off filesystem. Make it easy for people to get what they need and audit it. Rotations should be handled.
- Continuous integration - Keep secrets out of job config. Give your jobs only the credentials they need, when they need them. Be careful about lax permissions on hosted CI.
- Deployment - Deploy system should be a separate unit than CI. Deployments should be logged to an audit with the credentials they needed to run the deploy. Deploy agents should be first-class citizens.
- Production - Really consider turning SSH off (shipping logs, debug containers). Don't send secrets to logs. Delegating authority to scripts/chatops should be specific and audited. Ship your audit logs to your same log aggregator and set alerts on suspicious behavior.