<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jacky Ho</title>
    <description>The latest articles on DEV Community by Jacky Ho (@jackyho).</description>
    <link>https://dev.to/jackyho</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3637503%2F7cbae232-5c97-46ac-989a-4e40c790c47b.png</url>
      <title>DEV Community: Jacky Ho</title>
      <link>https://dev.to/jackyho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jackyho"/>
    <language>en</language>
    <item>
      <title>Building a DevSecOps Terraform Review Loop with Checkov, Infracost, and AI</title>
      <dc:creator>Jacky Ho</dc:creator>
      <pubDate>Tue, 16 Dec 2025 07:22:30 +0000</pubDate>
      <link>https://dev.to/jackyho/building-a-devsecops-terraform-review-loop-with-checkov-infracost-and-ai-35h2</link>
      <guid>https://dev.to/jackyho/building-a-devsecops-terraform-review-loop-with-checkov-infracost-and-ai-35h2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When I design Terraform pipelines, I am rarely satisfied with a simple “terraform plan succeeded.” A green plan tells me that syntax is valid and providers are reachable—but it says nothing about whether I am about to merge a security misconfiguration, introduce unnecessary cost, or miss an architectural concern that will only surface after deployment.&lt;/p&gt;

&lt;p&gt;What I want instead is immediate, structured feedback at pull-request time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security misconfigurations identified before human review,&lt;/li&gt;
&lt;li&gt;Cost impact quantified before merge, and&lt;/li&gt;
&lt;li&gt;Actionable guidance delivered directly where engineers already collaborate—the PR itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is my attempt to codify that expectation into a repeatable DevSecOps pattern for Terraform. The reference implementation uses Amazon EKS purely to keep the example concrete, but the workflow itself is infrastructure-agnostic. Whether the stack provisions VPCs, databases, or serverless components, the same review loop applies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70r3uzi1h2mw45twvkkl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70r3uzi1h2mw45twvkkl.png" alt=" " width="758" height="1120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Checkov and Infracost?
&lt;/h2&gt;

&lt;p&gt;Terraform is intentionally declarative and provider-focused. That is its strength—but it also means Terraform has no native awareness of security policy or financial impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Context with Checkov
&lt;/h2&gt;

&lt;p&gt;Without an external scanner, Terraform will happily apply configurations such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;security groups open to 0.0.0.0/0,&lt;/li&gt;
&lt;li&gt;EKS clusters without secrets encryption etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Checkov addresses this gap by scanning Terraform code against predefined and custom policies. Every pull request triggers a scan and produces structured JSON output (checkov.json) containing rule IDs, affected resources, and file locations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6adhh9p0whkebwjnb22w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6adhh9p0whkebwjnb22w.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Awareness with Infracost
&lt;/h2&gt;

&lt;p&gt;Cost is the other blind spot in most Terraform workflows. Small configuration changes can translate into significant monthly spend, yet the impact often remains invisible until after deployment.&lt;/p&gt;

&lt;p&gt;Infracost analyzes the Terraform plan and produces a machine-readable cost diff (infracost.json). Before merging, reviewers can clearly see estimated monthly deltas and which resources drive them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3af24x2qb0upc6lltryy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3af24x2qb0upc6lltryy.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Together, Checkov and Infracost ensure that both security and financial considerations enter the review process at the same time as functional correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI Fits
&lt;/h2&gt;

&lt;p&gt;The AI component of this project is intentionally narrow in scope. I did not want a conversational summary or a vague “best practices” bot. Instead, the goal was deterministic, structured assistance.&lt;/p&gt;

&lt;p&gt;The AI reviewer ingests three inputs simultaneously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checkov findings (checkov.json),&lt;/li&gt;
&lt;li&gt;Terraform plan JSON (plan.json),&lt;/li&gt;
&lt;li&gt;Infracost cost data (infracost.json).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using a tightly scoped prompt (llm/review_prompt.md) and a strict response schema (llm/review_schema.json), the model is required to return JSON only. Wherever possible, it includes concrete Terraform HCL snippets that resolve the identified issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7xmrvluzfc5bvgaebc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7xmrvluzfc5bvgaebc5.png" alt=" " width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, when Checkov flags a missing EKS encryption configuration (e.g., CKV_AWS_58), the AI response includes the exact encryption_config block that can be pasted directly into the module. Cost deltas above a defined threshold (for example, $20 or 10%) are explicitly highlighted, along with any assumptions made during estimation.&lt;/p&gt;

&lt;p&gt;Because the output is structured, it becomes composable. Today it renders as a rich pull-request comment; tomorrow it could just as easily drive Jira tickets, Slack notifications, or even automated patch proposals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Terraform modules under /modules&lt;/li&gt;
&lt;li&gt;EKS cluster and node groups&lt;/li&gt;
&lt;li&gt;S3 backend bucket&lt;/li&gt;
&lt;li&gt;GitHub OIDC IAM role&lt;/li&gt;
&lt;li&gt;Bootstrap layer (infra/bootstrap): Provisions the S3 backend and IAM role. State keys follow state//terraform.tfstate.&lt;/li&gt;
&lt;li&gt;GitHub Actions workflow: .github/workflows/terraform-eks-devsecops.yml, running on a self-hosted Ubuntu runner with Node.js, Python, Terraform, Checkov, and supporting CLI tools.&lt;/li&gt;
&lt;li&gt;Authentication: AWS access via GitHub OIDC (aws-actions/configure-aws-credentials@v4).&lt;/li&gt;
&lt;li&gt;Artifacts: checkov.json, plan.json, infracost.json, and ai_output.json uploaded for traceability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Workflow Walkthrough
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Format and validate Terraform code with terraform fmt and terraform validate.&lt;/li&gt;
&lt;li&gt;Run Checkov and capture policy violations without blocking iteration.&lt;/li&gt;
&lt;li&gt;Initialize backend and generate plan, exporting plan.json.&lt;/li&gt;
&lt;li&gt;Run Infracost to calculate cost deltas.&lt;/li&gt;
&lt;li&gt;Build AI input payload using jq.&lt;/li&gt;
&lt;li&gt;Invoke AI reviewer via scripts/call_llm.py.&lt;/li&gt;
&lt;li&gt;Post structured PR comment with findings, cost overview, and HCL fixes.&lt;/li&gt;
&lt;li&gt;Upload artifacts for auditability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn922lb5q536qxp7e7xhn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn922lb5q536qxp7e7xhn.png" alt=" " width="449" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;Source code available on GitHub Repository:&lt;br&gt;
&lt;a href="https://github.com/JackyHOz/Building-a-DevSecOps-Terraform-Review-Loop/" rel="noopener noreferrer"&gt;https://github.com/JackyHOz/Building-a-DevSecOps-Terraform-Review-Loop/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;This project demonstrates that Terraform reviews can go far beyond syntax validation. By integrating policy-as-code, cost estimation, and narrowly scoped AI assistance, infrastructure reviews become faster, more informative, and easier to audit.&lt;/p&gt;

&lt;p&gt;EKS is simply the demo surface. The real value is the repeatable review loop: security insight, cost visibility, and concrete remediation guidance—delivered before infrastructure ever reaches production.&lt;/p&gt;

</description>
      <category>devsecops</category>
      <category>terraform</category>
      <category>finops</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
