Infrastructure as Code (IaC) is the cloud-computing practice of putting the provisioning and configuring your cloud resources into machine-readable code.
Rather than manually configuring each server, container, database, or API gateway (to name just a few of the resources that can be managed using IaC), only to repeat that process when you need to update the settings or deploy another instance, all your requirements and settings are recorded in code (typically YAML or JSON files) which you can apply as many times as you need.
Defining your infrastructure in software with IaC makes replicating your virtual machines, containers, and services efficient and consistent. Because of this, IaC is a key enabler of a fully automated DevOps process.
By putting environment configuration and deployment logic into code, you can automatically refresh a pre-production environment before running automated tests on the latest build of your application and create multiple identical testing and staging environments for an automated CI/CD pipeline.
Programming infrastructure allows you to make the most of cloud-hosted resources because you can provision new services with minimal effort. For example, suppose you’re managing a containerized deployment with Kubernetes or Docker Swarm. In that case, putting your configuration into code means you can scale up your cluster with minimal effort, knowing that each new node will be provisioned consistently.
Furthermore, storing IaC configuration files in source control means you can easily revert to an earlier version when needed and ensures you have an audit log of all changes to your infrastructure setup.
Tools such as AWS CloudFormation, Hashicorp’s Terraform, and Microsoft’s Azure Resource Manager allow you to use Infrastructure as Code to automate provisioning and configuration of cloud-hosted infrastructures, such as Amazon EC2 instances, Microsoft Azure resources, or Docker containers.
As more and more organizations turn to cloud-based infrastructure to host their systems and services, Infrastructure as Code (IaC) is being used more and more widely. But for all the advantages of Infrastructure as Code, it can also present risks.
Misconfigurations or failing to change the default behavior of cloud resources can introduce security vulnerabilities and expose your organization to cyberattacks. Multi-cloud setups increase the complexity of systems, making it a challenge to maintain a comprehensive understanding of your computing estate and the impact that a change will have, increasing the likelihood of unintended consequences.
The following are some of the most common security risk areas for Infrastructure as Code.
Storing the credentials or private keys required to connect to particular services directly in your IaC configuration files is a severe security failing which unfortunately happens far too often. It usually occurs because authentication details have been hard-coded as a “temporary” solution while the code was still in development, only to be forgotten.
The result is that secrets remain visible in the configuration files, which are then added to source control. Even with access controls to your source code, this is too risky a place to store credentials. You’re effectively handing the keys to any hacker wishing to gain access to your systems.
As with authentication secrets, it’s not uncommon for developers to grant root privileges to services in the early phases of development simply because it’s quicker than creating a role that only has the required permissions.
However, granting more permissions than are needed to the resources you create means that a malicious actor who has gained access to your system can more easily start using and modifying your system for their needs.
Suppose you’re using existing templates to create cloud resources such as VMs or containers. In that case, there is a high chance that the template will include insecure default configurations, such as public SSH ports or unencrypted data. Use templates from trusted sources and always check that the settings are what you need before using them as the basis for your infrastructure.
Several IaC management tools use a centralized controller that communicates with multiple nodes to configure resources. In these cases, it’s essential to secure the communications between the control plane and worker nodes using SSL/TLS to prevent them from being visible to anyone who cares to look.
In addition to securing data in transit, your IaC configuration should ensure that any sensitive data is encrypted at rest. Even if access is secured, it’s prudent to have multiple layers of security just in case one of your defenses is breached.
Configuration drift refers to discrepancies between defining the infrastructure in code and what is deployed. It usually results from manual changes to resources directly rather than updating the code and deploying the changes as part of an automated IaC process.
Bypassing the normal process usually means your changes have not gone through your standard automated tests and security checks (more on that below), increasing the likelihood that a security flaw will be introduced.
Adopting IaC ensures that your infrastructure is always configured consistently and means you can easily audit your settings to ensure they meet your requirements. As long as you apply security best practices to your configuration files, using infrastructure as code will improve your security posture by reducing the likelihood of security flaws in your infrastructure.
On the other hand, failing to apply security best practices to IaC means any security flaws will propagate through your estate, creating multiple opportunities for an attacker. Let’s look at some key security practices for IaC.
Infrastructure as Code is a DevOps practice that applies software development techniques to operations tasks; defining your infrastructure in software, putting it through a series of automated tests, and automatically deploying it provides you with frequent opportunities for rapid feedback on the changes you’ve made to your resources so that you can address any issues as early as possible.
DevSecOps extends this approach to security considerations. Tools such as Static Analysis Security Testing (SAST) allow you to check IaC files for known vulnerabilities as you write them so that you can address issues immediately.
Having checked the static code, you can put your IaC changes through an automated CI/CD pipeline and use Dynamic Analysis tools (DAST) to test the code at runtime and get rapid feedback before changes are deployed. Building security testing into the development process for IaC significantly reduces the likelihood of security issues in production.
Rather than hardcoding secrets in your configuration files, use a secure storage mechanism such as AWS Secrets Manager or Microsoft’s Azure Key Vault and reference these from your IaC files. IDE security plugins for IaC can check for insecurely stored secrets and remind developers to move credentials out of the code and into a secret vault.
Applying the principle of least privilege means granting only the permissions that are required and no more. For example, you might only assign read permissions if you need a resource to retrieve values from a database. Setting broader permissions than are required – such as write or delete – might be easier, but it also provides opportunities for malicious actors that have gained access to your system to misuse resources.
Applying least privilege also means de-provisioning accounts when they are no longer needed. Creating an automated onboarding and offboarding process helps ensure that developer accounts no longer in use do not remain available for someone to hijack.
Automatically tagging all your cloud resources as they are created not only ensures that you can identify the owner of each VM, container, database, file share, or gateway if an issue arises but also reduces the likelihood of unmanaged ghost resources. Untagged resources can make managing costs difficult and present a security risk.
Any misuse – such as cryptocurrency mining – can easily go undetected for weeks. When you spot potentially suspicious activity, tracking down the team owning the resource will take much longer to confirm whether the resource should be terminated.
If your organization must adhere to particular standards – such as HIPAA, GDPR, or ISO27001 – use policy guardrails for auditing your configuration for compliance as part of your automated pre-deployment checks.
Having developed an automated pipeline that checks for security flaws such as hardcoded secrets and validates that your infrastructure complies with relevant policies, it’s vital to ensure that the process is never bypassed.
When changes need to be made urgently, it’s safer to put them through the pipeline to verify them before deployment than to make a manual change that may introduce unexpected issues.
Furthermore, because IaC is version controlled in the same way as application code, avoiding manual configuration ensures you always have an audit log of all changes and can roll back to an earlier version if needed.
Finally, collecting and analyzing log files from your cloud resources in real-time will allow you to monitor your infrastructure and identify issues in production as they emerge.
Building security into the development process for IaC reduces the likelihood of vulnerabilities in your production system and, therefore, the potential for attacks. This leaves operations teams more capacity to check the production infrastructure for security issues and address emerging vulnerabilities.
When changes need to be made, having an automated process that checks your IaC for security flaws means you can deploy updates quickly and consistently while minimizing the risk of further issues.
For organizations required to comply with particular regulations – for example, on handling personally identifiable information or health data – building security into the pipeline enables you to demonstrate continuous compliance with relevant policies with little manual effort.
An essential part of securing your infrastructure as code is using tools that can alert you to security flaws. You can choose between individual tools to target particular areas described below or platforms designed to address multiple stages of the IaC lifecycle, such as Bridgecrew and Tenable CS.
IDE plugins provide you with feedback on your code while you’re developing. Addressing issues while you’re writing the changes is more efficient than waiting until later in the development cycle, so it’s good practice to use plugins that check for known security issues as part of your development process. Tools such as TFLint, Docker Linter, Checkov, Snyk, and Cycode integrate with the developer workflow to provide rapid feedback on IaC configurations.
Finally, Cloud Security Posture Management (CSPM) tools provide security checks at runtime by continuously checking your cloud deployments for misconfigurations. Some also check for drift detection to alert you when changes have been made to resources without going through the normal IaC pipeline. Tools such as CloudGuard, Falcon Horizon, and Cloud One Conformity.
Infrastructure as code offers many advantages, but it’s important to understand your cloud systems and security protections. If you’re using templates, ensure they don’t introduce vulnerabilities. Using security tools and automated tests will help to guard against misconfigurations and identify flaws early, reducing opportunities for malicious actors to attack your system.