Infrastructure as code (IaC) is the practice of managing and provisioning computing resources using configuration files or scripts rather than manual deployment and configuration processes. This enables developers and operations teams to collaborate more effectively, automate deployments, and improve consistency and reliability.
However, IaC also introduces new security challenges and risks that need to be comprehensively addressed at every stage of the DevOps software development lifecycle (SDLC).
In this blog post, we will break down every step of the DevOps lifecycle, from planning to post-deployment, and highlight the potential security risks associated with each stage. We will also provide best practices and recommendations for mitigating these risks and ensuring the security of your IaC infrastructure.
By following these guidelines, you can confidently adopt IaC in your DevOps processes without compromising the security of your applications and data.
Let's dive in and explore the security challenges and solutions of IaC in the DevOps SDLC!
The planning stage involves defining the requirements and design of the infrastructure, as well as identifying the potential threats and vulnerabilities that may affect it. At the planning stage, there are two main things you should be doing to secure your IaC:
- Threat modeling
- Establishing privileges
For threat modeling, it is common to use a standard framework or methodology, such as STRIDE or DREAD, to identify and prioritize the most critical risks in the design of your infrastructure. You can also use tools like Microsoft’s Threat Modeling Tool or OWASP Threat Dragon to assist you in threat modeling. Consider the use of encryption, hashing, and key management techniques to protect sensitive data and credentials both in transit and at rest. You should also have a plan for handling untrusted input. Additionally, consider how network controls like a WAF can improve your application’s security posture.
Always follow the principle of least privilege, which means granting only the minimum permissions and access levels required for each resource and account. For user accounts, implement segregation of duties by separating the responsibilities of different team members. Minimizing the power of individual credentials reduces the damage that can be done if a cybercriminal hijacks an account or credential.
The development or coding stage involves writing and updating the code or scripts that define the infrastructure. Some of the security best practices for this stage are:
- Security-based IDE plugins
- Pre-commit hooks
- Static analysis
- Secrets management
In DevOps, the culture is all about “shifting left,” which means it’s better to catch bugs and security issues sooner rather than later. As a developer, the quickest feedback you can get is right in your IDE while you are writing your IaC. There are various IDE plugins that are capable of identifying vulnerabilities in your code as you write it. A few examples are:
- TFLint – TerraForm linter with some security best-practice rules
- Checkov – misconfiguration scanner for multiple types of IaC
- Snyk – code, container, and IaC scanner that offers an IDE plugin
Pre-commit hooks automate the execution of static code analysis tools before the code is committed to your version control system. For example, remediating exposed secrets can get messy when the secret is already in the git history of your repository. If you set up a secret scanner as a pre-commit hook, it will catch secrets before they get committed and save you from some extra cleanup work later.
ggshield is a CLI application that runs in a local environment or in a CI environment to help detect more than 300 types of secrets, as well as other potential security vulnerabilities or policy breaks.
Once code has been committed to your version-controlled repository, you can scan the code with static code analysis tools. There are various scanning tools, depending on what you are trying to scan. Some popular IaC static analysis tools are:
- ggshield – yes, the GitGuardian CLI can also be used to scan for infrastructure as code vulnerabilities by running the command:
ggshield iac scan iac_repo
- Kube Bench – Kubernetes configuration scanner based on CIS Kubernetes Benchmark
- Coverity – static analysis platform similar to Snyk
Learn more about using ggshield to scan IaC misconfigurations:
Secrets management is a complex topic in and of itself, but it’s all about making sure your secrets are accessible in a secure way. If you want to learn more about how to be good at secret management, check out our Secrets Management Maturity Model.
Build and Test
In the building and testing phases, you have the opportunity to see what the infrastructure will look like and how it will behave. These are the key security practices you should be following in this phase of the DevSecOps pipeline:
- Separation of environments
- Dynamic testing
- Vulnerability scanning
- Container image scanning
- Artifact signing
Separation of environments
Use a dedicated testing environment that mimics the production environment as closely as possible but with isolated resources and data. Sharing things like databases between environments can lead to production data being put at risk when a vulnerability is introduced to a test environment.
Dynamic testing tools perform automated tests on the deployed infrastructure to check its configuration and behavior against the expected security policies and standards. A couple of popular IaC dynamic testing tools are InSpec and Terratest.
Container image scanning
When your applications use container images, it’s important to take inventory of the software that is baked into each image and look for vulnerable, outdated versions. You can scan a newly built image in your CI pipeline with a tool like Aqua or Snyk, but it’s also a good idea to scan your entire container registry on a regular basis to ensure that new vulnerabilities are being noticed when an image isn’t receiving updates. And don't forget about leaked secrets in images' layers!
When you sign build artifacts such as binaries and container images, you are ensuring the integrity of your services between the time they are built to the time they are deployed. To learn more about why supply chain security is important and how you can implement it, check out our blog on Supply Chain Security.
Deploying IaC happens automatically, so there isn’t much involvement from operations at this stage. However, there are still policies you’ll need to follow in your deployment pipeline to ensure that you are meeting best practices when it comes to securely deploying your assets:
- Inventory management
Once your infrastructure is deployed, you don’t want it to deviate from what is defined in your code. Post-deployment changes can introduce unintended bugs or vulnerabilities. Whenever a change is needed, you should first update your code and then follow the CI/CD process to redeploy the entire infrastructure. If possible, use policies or controls to prevent the modification of your infrastructure after it has been deployed.
Inventory management is a foundational part of most cybersecurity frameworks. When you commission and decommission assets, your IaC tools should be automatically updating your overall asset inventory so you have an accurate picture of your attack surface. Applying tags to assets is another practice that can help you organize and maintain your inventory. Tags improve your ability to identify configuration drift and deprecated systems that have not been decommissioned properly.
Post-deployment monitoring has historically been the bread-and-butter of security programs, but as deployment environments have changed and shifted to the cloud, there are some new approaches to securing IaC. Nonetheless, the two keys of security monitoring remain the same:
- Threat detection
When provisioning and configuring IaC resources, you should have audit and security logging in place to keep a record of the creation of and access to your infrastructure. Forwarding logs to a SIEM or analysis engine can help you identify anomalies like resources being spun up outside of the normal deployment cycle or configuration changes outside of provisioning (tying back to the importance of immutability).
Building runtime threat detection into your IaC is the best way to ensure that you are made aware when the infrastructure you have created is under attack. There are countless security tools to choose from depending on the type of infrastructure you are deploying. There are tools like Falco to detect anomalies in Kubernetes pods or EDR tools for traditional virtual machine infrastructure. You can also forward additional logs to a SIEM depending on what is needed to enable your detection strategy.
Summary: 15 Infrastructure as Code Best Practices
- Threat modeling: Use a framework to identify and prioritize risks in the infrastructure design. Consider encryption, hashing, key management techniques, and network controls.
- Establishing privileges: Follow the principle of least privilege and implement segregation of duties to minimize the power of individual credentials.
- Security-based IDE plugins: Use IDE plugins to catch bugs and security issues sooner rather than later, such as TFLint, Checkov, and Snyk.
- Pre-commit hooks: Automate the execution of static code analysis tools before code is committed to the version control system. Use ggshield to detect more than 350+ types of secrets.
- Static analysis: Scan code with static analysis tools like ggshield, Kube Bench, and Coverity.
- Secrets management: Securely manage secrets with appropriate tools. Use GitGuardian's Secrets Management Maturity Model if needed.
Build and Test
- Separation of environments: Use a dedicated testing environment that mimics the production environment as closely as possible but with isolated resources and data.
- Dynamic testing: Use automated tests to check infrastructure configuration and behavior against security policies and standards, such as InSpec and Terratest.
- Container image scanning: Take inventory of software that is baked into each image and look for vulnerable, outdated versions. Scan a newly built image in your CI pipeline with tools like Aqua and Snyk.
- Artifact signing: Sign build artifacts like binaries and container images to ensure their integrity.
- Immutability: Do not allow post-deployment changes that deviate from what is defined in the code. Use policies or controls to prevent modification of the infrastructure after it has been deployed.
- Inventory management: Commission and decommission assets, automatically update the asset inventory and apply tags to assets to organize and maintain the inventory.
- Logging: Provision and configure IaC resources with audit and security logging to keep a record of creation and access to the infrastructure. Forward logs to a SIEM or analysis engine to identify anomalies.
- Threat detection: Build runtime threat detection into IaC using tools like Falco or traditional EDR tools.
In this blog post, we have discussed some of the best practices and tools for securing IaC at each stage of the DevSecOps software development lifecycle. By following these steps and referencing the cheat sheet, you can improve the security, reliability, and consistency of your IaC throughout your DevOps pipeline.
If you're interested in diving deeper into infrastructure security with Terraform, be sure to check out our previous blog post. It offers a detailed exploration of Terraform security practices and techniques that you can use to enhance your IaC security further. Don't miss out on this valuable resource!