During a recent audit of a mid-sized Indian FinTech firm, I discovered over 40 public-facing RDS instances that were deployed via a legacy Terraform module. The root cause was not a lack of intent, but a lack of visibility. Developers were moving fast to meet DPDP Act 2023 compliance deadlines, but their Infrastructure as Code (IaC) templates hadn't been updated to reflect modern security baselines.
Manual code reviews are no longer viable when dealing with thousands of lines of HashiCorp Configuration Language (HCL). We need automated gates that can parse these files before they ever hit a terraform apply.
What is Infrastructure as Code (IaC) Scanning?
IaC scanning is the process of performing static analysis on configuration files like Terraform, CloudFormation, Kubernetes manifests, and ARM templates. Unlike traditional DAST (Dynamic Application Security Testing), IaC scanning happens before the infrastructure is provisioned. I treat it as a pre-flight check for the cloud.
We are looking for misconfigurations such as:
- Hardcoded secrets in
.tffiles or environment variables. - Unencrypted storage volumes (EBS, S3, RDS).
- Overly permissive Security Group rules (e.g., ingress from
0.0.0.0/0on port 22), which often violate the OWASP Top 10 standards for secure configuration. - Lack of logging and versioning on critical buckets.
- Missing tags required for cost allocation and compliance tracking.
The Role of Security in the DevOps Lifecycle
In a standard CI/CD pipeline, security often acts as a friction point. By integrating IaC scanning, we shift security to the "left"—the earliest possible stage of development. I've found that catching a misconfiguration on a developer's local machine costs roughly 100x less than fixing a live data breach in the ap-south-1 region.
We don't want security to be a gatekeeper that stops the build every Friday afternoon. Instead, we want to provide developers with the same feedback loop they get from a linter or a unit test. If the code is insecure, the scan fails, and the developer gets a clear explanation of how to fix it.
Why Manual Code Reviews Aren't Enough
Manual reviews are prone to "reviewer fatigue." After looking at the tenth pull request of the day, a reviewer might miss a subtle change in an IAM policy that grants iam:PassRole permissions to an EC2 instance.
Automated tools like Snyk or Checkov don't get tired. They use a database of thousands of known misconfigurations and best practices to evaluate every single line of code. In the Indian context, where many teams are scaling rapidly, automation is the only way to maintain a consistent security posture, similar to how organizations are hardening NGINX against MCP integration flaws to prevent unauthorized access.
Early Detection of Security Misconfigurations
The primary benefit of IaC scanning is immediate feedback. When I run a scan locally, I get a report in seconds. This allows me to iterate on my infrastructure design without waiting for a security architect's approval.
For example, if I accidentally define an S3 bucket without server-side encryption, the scanner will flag it immediately. I can fix the HCL, re-run the scan, and ensure the code is clean before I even commit it to Git.
Ensuring Compliance with Frameworks (SOC2, HIPAA, PCI-DSS)
For Indian startups looking to expand globally, compliance with international standards is mandatory. IaC scanners often come with pre-built policy sets for SOC2, ISO 27001, and PCI-DSS.
Under the DPDP Act 2023, Indian companies must implement "reasonable security safeguards." Using an automated scanner to enforce encryption and access control is a strong piece of evidence for auditors. It demonstrates that you have a repeatable, documented process for securing personal data at the infrastructure layer. For teams looking to build these skills internally, professional cybersecurity training and courses can bridge the gap between DevOps and compliance.
Reducing Cost and Effort of Post-Deployment Remediation
Remediating a live environment is risky. Changing an IAM role or a Security Group on a production database can cause unexpected downtime. I've seen teams spend weeks trying to "harden" a live AWS account, only to break critical internal services.
By fixing these issues in the code, we ensure that the infrastructure is "secure by design." When the terraform apply command runs, the resulting environment is already compliant. This eliminates the need for "security debt" sprints where teams have to backtrack and fix months of sloppy configuration.
Top Open-Source Tools: Checkov, Tfsec, and Terrascan
If you are just starting, open-source tools offer significant value.
- Checkov: Written in Python, it supports a wide range of platforms and allows for custom policies using Python or YAML. It's excellent for complex environments.
- Tfsec: A Go-based scanner that is incredibly fast. It focuses specifically on Terraform and is known for its clear, concise output.
- Terrascan: Built on the Open Policy Agent (OPA) engine, it uses Rego for policy definitions, making it highly extensible for enterprise-grade policy-as-code.
Enterprise-Grade Solutions: Snyk, Bridgecrew, and Prisma Cloud
While open-source tools are great for CLI usage, enterprise solutions offer better reporting, integration, and vulnerability databases that sync with the NIST NVD for real-time threat intelligence.
- Snyk: I prefer Snyk for its "developer-first" approach. It doesn't just find the bug; it often provides the exact code snippet needed to fix it. It also integrates deeply with Git providers and CI/CD tools.
- Bridgecrew: Now part of Prisma Cloud, it offers a very polished UI and deep integration with cloud service providers to track "drift" between code and reality.
Comparison Criteria: Language Support and Integration
When choosing a tool, I look for three things:
- Platform Coverage: Does it support Terraform, K8s, and Dockerfiles?
- Integration: Can I run it in a GitHub Action, a GitLab runner, and locally?
- Actionability: Are the results easy to understand, or do they require a security degree to interpret?
Prerequisites: Setting Up Your Development Environment
Before we run a scan, ensure you have the following installed:
- Terraform (v1.0.0+)
- Node.js (for Snyk CLI installation)
- An active Snyk account (the free tier works for this tutorial)
Installing Your Scanning Tool (CLI Guide)
I use the Snyk CLI because it provides a unified experience for both software vulnerabilities and IaC misconfigurations. To install it on a Linux or macOS machine, run:
Install Snyk CLI via NPM
npm install -g snyk
Authenticate the CLI with your Snyk account
snyk auth
Once authenticated, you will see a confirmation message in your browser. This links your local CLI to your Snyk dashboard for centralized reporting.
Executing a Scan on Terraform Manifests
Let's assume you have a directory named ./terraform/environments/prod/ containing your HCL files. To scan this directory for high-severity issues, execute:
snyk iac test ./terraform/environments/prod/ --severity-threshold=high
If you want to scan a specific Terraform plan (which is more accurate as it includes variables and modules), you can use the following workflow:
Generate a plan file
terraform plan -out=tfplan.binary
Convert the plan to JSON
terraform show -json tfplan.binary > tfplan.json
Scan the JSON plan
snyk iac test tfplan.json
Interpreting Scan Results and Severity Levels
Snyk categorizes findings into four levels:
- Critical: Immediate risk of data exposure (e.g., public database).
- High: Significant misconfiguration (e.g., unencrypted S3 bucket).
- Medium: Best practice violation (e.g., missing resource tags).
- Low: Minor hardening suggestions.
The output will look something like this:
Testing tfplan.json...
Infrastructure as code issues found: ✗ S3 bucket should likely have public access blocks (Medium) [SNYK-CC-TF-AWS-430] in S3 introduced by resource > aws_s3_bucket.data_storage
✗ S3 bucket should have versioning enabled (Low) [SNYK-CC-TF-AWS-429] in S3 introduced by resource > aws_s3_bucket.data_storage
Remediating Unencrypted S3 Buckets
A common finding is an unencrypted S3 bucket. In AWS, this is often identified by the absence of the server_side_encryption_configuration block.
Insecure HCL:
resource "aws_s3_bucket" "insecure_bucket" { bucket = "my-sensitive-data-in-mumbai" }
Secure HCL:
resource "aws_s3_bucket" "secure_bucket" { bucket = "my-sensitive-data-in-mumbai" }
resource "aws_s3_bucket_server_side_encryption_configuration" "example" { bucket = aws_s3_bucket.secure_bucket.id
rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } } }
Restricting Overly Permissive IAM Roles
I frequently see Action = "*" in IAM policies. This violates the principle of least privilege. Snyk will flag these as high-severity issues.
Bad Practice: Full S3 Access
resource "aws_iam_policy" "too_permissive" { name = "full_access" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "s3:" Effect = "Allow" Resource = "" }, ] }) }
Instead, scope the policy to specific buckets and specific actions like s3:GetObject and s3:PutObject.
Securing Security Group Ingress and Egress Rules
Opening port 22 (SSH) to the entire world (0.0.0.0/0) is a recipe for a brute-force attack. I've observed that in Indian enterprise networks, it's better to restrict SSH to a specific VPN CIDR block or, better yet, utilize a browser based SSH client to manage access without exposing ports to the public internet.
resource "aws_security_group" "allow_ssh" { name = "allow_ssh" description = "Allow SSH inbound traffic"
ingress { description = "SSH from Office" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["10.0.0.0/16"] # Restricted to Internal Network } }
Automating Scans with GitHub Actions
To ensure that no insecure infrastructure is ever merged into the main branch, I integrate Snyk into the GitHub Actions pipeline. This creates a "Security Gate."
name: Snyk IaC Security Gate on: [push, pull_request]
jobs: security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install Snyk CLI run: npm install -g snyk
- name: Snyk Auth run: snyk auth ${{ secrets.SNYK_TOKEN }}
- name: Snyk IaC Test run: snyk iac test ./terraform/ --severity-threshold=medium --json > snyk_results.json # We set continue-on-error to false to fail the build on findings continue-on-error: false
- name: Upload Results uses: actions/upload-artifact@v3 if: always() with: name: snyk-reports path: snyk_results.json
Setting Up 'Fail-Build' Policies for High-Risk Findings
In the YAML above, the continue-on-error: false directive is crucial. If Snyk finds a vulnerability that meets the medium threshold, the exit code will be non-zero, and GitHub Actions will stop the deployment.
This forces the developer to address the issue before the code can be merged. I recommend starting with --severity-threshold=high to avoid overwhelming the team, then moving to medium as the codebase matures.
Generating and Archiving Security Reports
The --json flag allows us to export the results into a machine-readable format. This is vital for compliance audits. In the Indian EdTech sector, where I've worked extensively, these JSON reports serve as proof of "reasonable security practices" during annual security reviews or due diligence processes for funding rounds.
Implementing Policy as Code (PaC) with OPA and Rego
For advanced users, standard rules might not be enough. You might want to enforce Indian-specific residency requirements—for example, ensuring that all RDS instances are located in ap-south-1 (Mumbai) or ap-south-2 (Hyderabad).
Using Open Policy Agent (OPA), you can write custom Rego policies to enforce these business-specific rules.
Example Rego policy to enforce Mumbai region
package terraform
deny[msg] { resource := input.resource_changes[_] resource.type == "aws_instance" region := resource.change.after.availability_zone not startswith(region, "ap-south-1") msg := sprintf("Resource %v is not in Mumbai region", [resource.address]) }
Handling False Positives and Suppressing Alerts
No tool is perfect. Sometimes a "misconfiguration" is intentional. For instance, a public S3 bucket might be necessary for hosting a static website's frontend.
Snyk allows you to ignore specific issues using a .snyk policy file or via the CLI:
Ignore a specific issue for 30 days
snyk iac ignore SNYK-CC-TF-AWS-430 --expiry=2024-12-31 --reason="Static website public bucket"
Be careful with suppresses. I always require a mandatory reason field and an expiration date to ensure that "temporary" ignores don't become permanent security holes.
Scanning Multi-Cloud Environments Consistently
If you are running a hybrid cloud with AWS and Azure (common for disaster recovery in Indian banking), you can use the Snyk CLI to describe your current cloud state and compare it against your IaC.
Detect drift between AWS and Terraform state
snyk iac describe --org=${SNYK_ORG_ID} --platform=aws
This command identifies resources that were created manually in the AWS console (Shadow IT) and are not managed by Terraform. This is often where the most dangerous vulnerabilities hide.
Shifting Security Left: Developer-First Workflows
The most successful security implementations I've seen are those where developers own the security of their code. This requires training. Don't just hand them a list of 500 errors; sit down with them and show how to use the CLI.
I recommend installing the Snyk IDE extension (available for VS Code and IntelliJ). This provides real-time feedback as the developer types their HCL. It underlines insecure code in red, just like a syntax error.
Regularly Updating Scanning Rules and Plugins
Cloud providers release new services and features every week. Your scanner must be updated to recognize these new resources. I've encountered cases where a new AWS service was used, but because the scanner was six months old, it ignored the resource entirely, leading to a false sense of security.
Keep Snyk CLI updated
npm update -g snyk
Continuous Monitoring of Deployed Infrastructure
IaC scanning is a point-in-time check. It doesn't account for someone logging into the AWS console and changing a setting manually. This is why we combine IaC scanning with Cloud Security Posture Management (CSPM).
Use the snyk iac describe command mentioned earlier as part of a weekly cron job to detect "drift." If the live environment deviates from the scanned HCL code, it should trigger an alert for the security team.
To get a deeper look at your current AWS environment's security posture, try running:
snyk iac test --report --project-name='Mumbai-Edge-Cluster' --remote-repo-url=https://github.com/warnhack/infra
