Part 4: Scanning Terraform Code with Checkov
📘 This post is part of the DevSecOps for Java series:
🛠️ Why Infrastructure Code Needs Scanning
We’ve secured:
-
✅ Our libraries with Snyk (SCA)
-
✅ Our application code with SonarQube (SAST)
But what about the Terraform code we use to provision our cloud resources?
If we accidentally expose a public IP, open all ports, or skip encryption, it can create massive security holes — before our app is even live.
That’s why we scan our infrastructure as code (IaC).
🔍 What Is Checkov?
Checkov is an open-source tool from Bridgecrew that scans Terraform (and other IaC formats) for security and compliance risks.
It checks for things like:
-
Publicly accessible resources
-
Missing encryption on storage
-
Overly permissive IAM roles
-
Open security groups or NSGs
-
Hardcoded secrets or access keys
Think of it like Snyk — but for your Terraform instead of your Java code.
⚡ Getting Started with Checkov
To test it locally:
Plain textANTLR4BashCC#CSSCoffeeScriptCMakeDartDjangoDockerEJSErlangGitGoGraphQLGroovyHTMLJavaJavaScriptJSONJSXKotlinLaTeXLessLuaMakefileMarkdownMATLABMarkupObjective-CPerlPHPPowerShell.propertiesProtocol BuffersPythonRRubySass (Sass)Sass (Scss)SchemeSQLShellSwiftSVGTSXTypeScriptWebAssemblyYAMLXML bashCopyEditpip install checkov checkov -d ./terraform
That’s it. It will scan all .tf files in the ./terraform directory and give you a nice CLI report.
✅ Integrate Checkov into Azure DevOps Pipeline
Let’s add Checkov as a separate stage in your Azure Pipeline.
Step 1: Make Sure Python is Available
Use a VM image with Python pre-installed:
Plain textANTLR4BashCC#CSSCoffeeScriptCMakeDartDjangoDockerEJSErlangGitGoGraphQLGroovyHTMLJavaJavaScriptJSONJSXKotlinLaTeXLessLuaMakefileMarkdownMATLABMarkupObjective-CPerlPHPPowerShell.propertiesProtocol BuffersPythonRRubySass (Sass)Sass (Scss)SchemeSQLShellSwiftSVGTSXTypeScriptWebAssemblyYAMLXML yamlCopyEditpool: vmImage: 'ubuntu-latest'
Step 2: Add the Checkov Stage to Your YAML
Plain textANTLR4BashCC#CSSCoffeeScriptCMakeDartDjangoDockerEJSErlangGitGoGraphQLGroovyHTMLJavaJavaScriptJSONJSXKotlinLaTeXLessLuaMakefileMarkdownMATLABMarkupObjective-CPerlPHPPowerShell.propertiesProtocol BuffersPythonRRubySass (Sass)Sass (Scss)SchemeSQLShellSwiftSVGTSXTypeScriptWebAssemblyYAMLXML yamlCopyEdit- stage: IaCScan displayName: 'Scan Terraform with Checkov' dependsOn: SAST jobs: - job: checkov displayName: 'Run Checkov Scan' pool: vmImage: 'ubuntu-latest' steps: - checkout: self - script: | pip install checkov checkov -d terraform/ --quiet --soft-fail displayName: 'Checkov Terraform Scan'
What That Does
-
Installs Checkov
-
Scans all .tf files in the terraform/ folder
-
The –soft-fail flag means: don’t fail the pipeline yet — just report findings
Once your team is comfortable, you can remove –soft-fail to enforce blocking.
✅ What Will It Catch?
Let’s say you have a VNet with a public IP:
Plain textANTLR4BashCC#CSSCoffeeScriptCMakeDartDjangoDockerEJSErlangGitGoGraphQLGroovyHTMLJavaJavaScriptJSONJSXKotlinLaTeXLessLuaMakefileMarkdownMATLABMarkupObjective-CPerlPHPPowerShell.propertiesProtocol BuffersPythonRRubySass (Sass)Sass (Scss)SchemeSQLShellSwiftSVGTSXTypeScriptWebAssemblyYAMLXML hclCopyEditresource "azurerm_public_ip" "example" { allocation_method = "Static" sku = "Standard" }
Checkov will warn you:“Public IPs should be avoided unless absolutely necessary”
Or maybe an NSG allows all traffic:
Plain textANTLR4BashCC#CSSCoffeeScriptCMakeDartDjangoDockerEJSErlangGitGoGraphQLGroovyHTMLJavaJavaScriptJSONJSXKotlinLaTeXLessLuaMakefileMarkdownMATLABMarkupObjective-CPerlPHPPowerShell.propertiesProtocol BuffersPythonRRubySass (Sass)Sass (Scss)SchemeSQLShellSwiftSVGTSXTypeScriptWebAssemblyYAMLXML hclCopyEditaccess = "Allow" destination_port_range = "*" source_address_prefix = "*"
Checkov will catch that too. It uses hundreds of built-in policies (based on CIS Benchmarks, AWS/Azure/GCP security best practices, etc.)
🔐 Why This Is Essential
Even the most secure app can be exposed if:
-
A storage account is open to the internet
-
A Function app has no authentication
-
A key vault is public
-
You hardcode secrets in Terraform
Checkov helps you catch all of that before terraform apply.
✅ Bonus: Use terraform validate too
Before scanning, you can also validate the syntax:
- script: |
terraform init
terraform validate
displayName: 'Terraform Syntax Check'
This ensures your Terraform is even parseable before Checkov analyzes it.
⏭️ What’s Next?
We’ve now secured:
-
✅ Dependencies (Snyk)
-
✅ App code (SonarQube)
-
✅ Infrastructure code (Checkov)
Next up?We apply that infrastructure using Terraform and deploy our app — the next stage in bringing our secure Java app to life.
👉 Continue to Part 5 – Deploying Infrastructure with Terraform in Azure Pipelines