Protecting Your Code and Infrastructure: The Importance of Linting and Scanning for Security Vulnerabilities
What is a linter?
A linter is a tool for checking your code for potential errors, inconsistencies, and other issues that could cause problems. Linting can be performed by using specialized tools known as "linters" that analyze your code and flag any potential issues.
For example with Terraform I have been using a tool called tflint
to run this process. With Azure Bicep I have done this by using Github Actions or with built in flags such as validate
& what-if
in the command-line. An example could be running these commands before submitting your code for review or have them run in Github Actions:
az deployment sub validate -l <location> -f <path to template-file>
az deployment sub what-if -l <location> -f <path to template-file>
They are similar to how Terraform has terraform validate
& terraform plan
Later in this post I will show you how to install tflint
& tfsec
Some benefits to "linting":
- Linting can help improve the overall quality of your code by identifying and flagging potential errors, inconsistencies, and bad coding practices. This can help you catch and fix issues before they become major problems, leading to more stable and reliable code.
- Linting can also help ensure that your code is consistent in terms of style, formatting, and other conventions. It makes it easier to read and work with the code
- Linting can also help improve collaboration among team members by providing a shared set of guidelines and standards for writing code, everyone is working in the in the same way delivering consistency.
For example, you have several variables in your configuration file but they are never used or you are storing sensitive information such as passwords in variables in plain text, this would generate errors and/or warnings with your linter.
Install tooling
Let us set up our workstation. I will show you the commands I ran to install tflint
& tfsec
on my workstation on Windows but also for Linux. I use WSL (Windows Subsystem for Linux) sometimes and would like to have the tooling there as well.
Windows
- Pre-req: Install Chocolatey (Package manager):
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
- Install tooling
choco install tfsec
choco install tflint
Linux
- Install
tfsec
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash
- Install
tflint
curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash
Note, I had some issues with the above command, it could not download & extract the file properly. This is the workaround I used that fixed it should you have the same problem:
curl -LO https://github.com/terraform-linters/tflint/releases/latest/download/tflint_linux_amd64.zip
unzip tflint_linux_amd64.zip
sudo mv tflint /usr/local/bin/
Use the tooling
This is pretty straight forward. When you are inside a project you can simply run the commands shown here.
Lint
tflint
Or to include subfolders & files:
tflint --recursive
In my test directory I received the following output from the command:
2 issue(s) found:
Warning: terraform "required_version" attribute is required (terraform_required_version)
on line 0:
(source code not available)
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.2.2/docs/rules/terraform_required_version.md
Warning: Missing version constraint for provider "aws" in "required_providers" (terraform_required_providers)
on main.tf line 3:
3: provider "aws" {
Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.2.2/docs/rules/terraform_required_providers.md
Scan for security issues
A great thing to do in addition to using linters is to run some security scanning on your code as well:
tfsec
In my test directory I received the following output from the command:
Result #1 CRITICAL Security group rule allows ingress from public internet.
────────────────────────────────────────────────────────────────────────────────
C:\Github\terraformAssociate\110_modules\terraform-aws-apache-example\main.tf:35
via main.tf:7-14 (module.apache)
────────────────────────────────────────────────────────────────────────────────
25 resource "aws_security_group" "sg_my_server" {
..
35 [ cidr_blocks = ["0.0.0.0/0"]
..
56 }
────────────────────────────────────────────────────────────────────────────────
ID aws-ec2-no-public-ingress-sgr
Impact Your port exposed to the internet
Resolution Set a more restrictive cidr range
More Information
- https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/ec2/no-public-ingress-sgr/
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule#cidr_blocks
────────────────────────────────────────────────────────────────────────────────
Result #2 CRITICAL Security group rule allows egress to multiple public internet addresses.
────────────────────────────────────────────────────────────────────────────────
C:\Github\terraformAssociate\110_modules\terraform-aws-apache-example\main.tf:52
via main.tf:7-14 (module.apache)
────────────────────────────────────────────────────────────────────────────────
25 resource "aws_security_group" "sg_my_server" {
..
52 [ cidr_blocks = ["0.0.0.0/0"]
..
56 }
────────────────────────────────────────────────────────────────────────────────
ID aws-ec2-no-public-egress-sgr
Impact Your port is egressing data to the internet
Resolution Set a more restrictive cidr range
More Information
- https://aquasecurity.github.io/tfsec/v1.28.1/checks/aws/ec2/no-public-egress-sgr/
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
────────────────────────────────────────────────────────────────────────────────
(AND SO FORTH.....)
7 passed, 6 potential problem(s) detected.
As you can see I have some critical issues that needs fixing before this can go to production. In this case it is only a demo so I should be fine!
Conclusion
These are great tools to use when writing infrastructure as code configuration files, or any type of code for that matter. They are great to use on your own to ensure you are not stepping into common pitfalls when styling, formatting and writing your code to ensure you are following best practices.
However they really come into effect when you also use them to boost your code reviews & pull requests when working as a team. You can use automated actions that will automatically lint and scan your code so you can have more confidence when submitting your code for review that it will pass, and your submission will be merged into the main codebase.
References
About the author
