<?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: StackGuardian</title>
    <description>The latest articles on DEV Community by StackGuardian (stackguardian).</description>
    <link>https://dev.to/stackguardian</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.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F15000%2Fe30c2d0c-de13-4f27-bf04-f777fa111d50.jpeg</url>
      <title>DEV Community: StackGuardian</title>
      <link>https://dev.to/stackguardian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stackguardian"/>
    <language>en</language>
    <item>
      <title>3 Terraform policies to start with: tags, ingress, instance types</title>
      <dc:creator>Diana Loomis</dc:creator>
      <pubDate>Wed, 14 Oct 2026 11:03:01 +0000</pubDate>
      <link>https://dev.to/stackguardian/3-terraform-policies-to-start-with-tags-ingress-instance-types-mo8</link>
      <guid>https://dev.to/stackguardian/3-terraform-policies-to-start-with-tags-ingress-instance-types-mo8</guid>
      <description>&lt;p&gt;Most teams agree they need guardrails on Terraform changes. Fewer agree on which policy to write first. Here are three starter checks you can run with Tirith, the open-source policy engine from StackGuardian, against the JSON plan your pipeline already produces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Tirith
&lt;/h2&gt;

&lt;p&gt;Tirith needs Python 3.8 or newer. Install it from the pinned Git tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"git+https://github.com/StackGuardian/tirith.git@1.2.1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Tirith is not on PyPI. &lt;code&gt;pip install tirith&lt;/code&gt; installs an unrelated project.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  The three policies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Environment tag.&lt;/strong&gt; Every resource must carry an &lt;code&gt;Environment&lt;/code&gt; tag set to &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt; or &lt;code&gt;prod&lt;/code&gt;. A resource with no tag fails instead of slipping through.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No public ingress.&lt;/strong&gt; No inline &lt;code&gt;ingress&lt;/code&gt; rule on an &lt;code&gt;aws_security_group&lt;/code&gt; may allow &lt;code&gt;0.0.0.0/0&lt;/code&gt;. Rules defined as separate resources need their own check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approved instance types.&lt;/strong&gt; Every &lt;code&gt;aws_instance&lt;/code&gt; must use a type from your allowlist. One oversized instance fails the check.&lt;/p&gt;

&lt;p&gt;All three fit in one policy file, &lt;code&gt;starter.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"required_provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stackguardian/terraform_plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"starter-guardrails"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Starter guardrails"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evaluators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"environment_tag_is_valid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"provider_args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"operation_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attribute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terraform_resource_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terraform_resource_attribute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tags.Environment"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RegexMatch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^(dev|staging|prod)$"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no_public_cidr_in_ingress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"provider_args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"operation_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attribute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terraform_resource_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws_security_group"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terraform_resource_attribute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ingress.*.cidr_blocks"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NotContains"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"instance_type_is_approved"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"provider_args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"operation_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attribute"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terraform_resource_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws_instance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"terraform_resource_attribute"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"instance_type"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ContainedIn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"t3.small"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"t3.medium"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"eval_expression"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"environment_tag_is_valid &amp;amp;&amp;amp; no_public_cidr_in_ingress &amp;amp;&amp;amp; instance_type_is_approved"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Run it against your plan
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan &lt;span class="nt"&gt;-out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tfplan &lt;span class="nt"&gt;-input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;terraform show &lt;span class="nt"&gt;-json&lt;/span&gt; tfplan &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; plan.json
tirith lint starter.json
tirith &lt;span class="nt"&gt;--fail-on-error&lt;/span&gt; &lt;span class="nt"&gt;-policy-path&lt;/span&gt; starter.json &lt;span class="nt"&gt;-input-path&lt;/span&gt; plan.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;tirith lint&lt;/code&gt; catches policy mistakes before they reach CI. With &lt;code&gt;--fail-on-error&lt;/code&gt;, a failing policy exits with code &lt;code&gt;3&lt;/code&gt; and fails the pipeline step. Without that flag, Tirith exits &lt;code&gt;0&lt;/code&gt; even when a check fails.&lt;/p&gt;

&lt;p&gt;Each result names the resource and attribute (output trimmed):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Check: environment_tag_is_valid
  FAILED
    2. FAILED: [aws_instance.batch (create)] tags.Environment: `"production"` does not match regex pattern `"^(dev|staging|prod)$"`

Check: no_public_cidr_in_ingress
  FAILED
    2. FAILED: [aws_security_group.web (create)] ingress.1.cidr_blocks: Found `"0.0.0.0/0"` inside `["0.0.0.0/0"]`

Check: instance_type_is_approved
  FAILED
    2. FAILED: [aws_instance.batch (create)] instance_type: Failed to find `"m5.24xlarge"` inside `["t3.medium", "t3.micro", "t3.small"]`

Passed: 0 Failed: 3 Skipped: 0
✘ Failed final evaluation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; With &lt;code&gt;"*"&lt;/code&gt;, resources that can't take tags, such as &lt;code&gt;aws_iam_role_policy_attachment&lt;/code&gt;, also fail. Adding &lt;code&gt;"error_tolerance": 2&lt;/code&gt; to the condition stops those failures, but it also lets a taggable resource with no &lt;code&gt;Environment&lt;/code&gt; tag pass. If that trade-off doesn't suit you, add one evaluator per resource type instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Start with these three, see what they catch on real pull requests, then extend from the &lt;a href="https://stackguardian.github.io/tirith/docs/tirith-policies/tirith-policy-cookbook/" rel="noopener noreferrer"&gt;policy cookbook&lt;/a&gt;. To try Tirith on your own plans:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/StackGuardian" rel="noopener noreferrer"&gt;
        StackGuardian
      &lt;/a&gt; / &lt;a href="https://github.com/StackGuardian/tirith" rel="noopener noreferrer"&gt;
        tirith
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Plug IaC governance into any IaC pipeline. Evaluate plans with Tirith, protect sensitive values, enforce centralised policies, and surface actionable results before infrastructure changes are applied.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a href="https://github.com/StackGuardian/tirith/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b29de0acdfd19013f1f02689b15c933e4a6c145be9efa718288f88ba3280b1c5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d417061636865253230322e302d626c75652e737667" alt="License"&gt;&lt;/a&gt;
&lt;a href="https://github.com/StackGuardian/tirith/CODE_OF_CONDUCT.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4ae39ae593b602cf0ae07972b61c73728b77ec8e2cf40f579a2441948208036b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f6e7472696275746f72253230436f76656e616e742d322e312d3462616161612e737667" alt="Contributor Covenant"&gt;&lt;/a&gt;
&lt;a href="https://github.com/psf/black" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7019b88be88468d6b83fcbf59d2c06bfa4992bafa7d129f9b89ab29f8c7c1acb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d626c61636b2d3030303030302e737667" alt="Code style: black"&gt;&lt;/a&gt;
&lt;a href="https://join.slack.com/t/stackguardian-ol78820/shared_invite/zt-2ksag36j9-OjmXqQmyXudgYrV6FmesIQ" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/28edab52068e19592d957d96845ade6c7b996a9e20bceea4eca1946ff449ec3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536c61636b2d3441313534423f7374796c653d666f722d7468652d6261646765266c6f676f3d736c61636b266c6f676f436f6c6f723d7768697465" alt="Slack"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/gh/StackGuardian/tirith" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/097058ee0ec62fd7db9157313f97cc4697b607ff0fd9d092cc5b4650ae355bbf/68747470733a2f2f636f6465636f762e696f2f67682f537461636b477561726469616e2f7469726974682f6272616e63682f6d61696e2f67726170682f62616467652e737667" alt="codecov"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Tirith — IaC Governance plugin&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New — &lt;code&gt;tirith ui&lt;/code&gt;, an interactive interface. In beta, and we want your input.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Explore a failing evaluation down to the resource that caused it, assemble policies from a
form, and experiment in a playground with worked examples. Try it with
&lt;code&gt;pip install 'py-tirith[tui] @ git+https://github.com/StackGuardian/tirith.git'&lt;/code&gt;, then
&lt;code&gt;tirith ui&lt;/code&gt; — see
&lt;a href="https://github.com/StackGuardian/tirith#the-interactive-interface" rel="noopener noreferrer"&gt;The interactive interface&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is new, so the rough edges are still being found. Tell us what is confusing, what is
missing, or what you would rather it did
&lt;a href="https://github.com/StackGuardian/tirith/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; or say so in
&lt;a href="https://join.slack.com/t/stackguardian-ol78820/shared_invite/zt-2ksag36j9-OjmXqQmyXudgYrV6FmesIQ" rel="nofollow noopener noreferrer"&gt;Slack&lt;/a&gt;
Nothing about the existing CLI changes: same flags, same &lt;code&gt;--json&lt;/code&gt; output, same exit codes.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Plugin IaC Governance for any pipeline, running anywhere.&lt;/strong&gt; Evaluate plans with Tirith, protect
sensitive values, enforce centralised governance, and surface actionable results before
infrastructure changes are applied.&lt;/p&gt;
&lt;p&gt;Tirith reads the plan your pipeline already produces — the output…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/StackGuardian/tirith" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>terraform</category>
      <category>devops</category>
      <category>opensource</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Checkov and Tirith: Governing Your Own Rules in Every IaC Pipeline</title>
      <dc:creator>Diana Loomis</dc:creator>
      <pubDate>Fri, 09 Oct 2026 15:59:51 +0000</pubDate>
      <link>https://dev.to/stackguardian/checkov-and-tirith-governing-your-own-rules-in-every-iac-pipeline-56fn</link>
      <guid>https://dev.to/stackguardian/checkov-and-tirith-governing-your-own-rules-in-every-iac-pipeline-56fn</guid>
      <description>&lt;p&gt;Your pipeline already runs Checkov, and the scan passes. An encrypted, private bucket can still be missing the owner tag your incident process depends on, and a valid plan can still go over the monthly cost limit finance agreed to. Checkov checks that resources are secure. Rules like these come from how your organization operates, so they need their own owner and a way to be enforced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rules that come from your organization
&lt;/h2&gt;

&lt;p&gt;Most platform teams need to know who owns each resource, whether a change fits the budget, and whether every repository enforces the same version of a rule.&lt;/p&gt;

&lt;p&gt;That last one is where things slip. A team can run the right checks in one repository while another repository runs a copy of the policy that was last updated a year ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing those rules as Tirith policies
&lt;/h2&gt;

&lt;p&gt;Tirith is StackGuardian's open-source policy engine. It runs as an additional step in the pipeline you already have, so Checkov and your other checks keep running as they are.&lt;/p&gt;

&lt;p&gt;A Tirith policy is declarative JSON with one consistent structure: you choose a provider, select the value or operation, then state the condition. Providers exist for Terraform plans, Infracost estimates, Kubernetes manifests and workflow files, so an owner-tag rule and a cost rule are written the same way, and reviewers read them the same way.&lt;/p&gt;

&lt;p&gt;To connect a pipeline, you add one step after &lt;code&gt;terraform plan&lt;/code&gt;: the Tirith GitHub Action, the Tirith GitLab CI/CD component or a Tirith step in Bitbucket Pipelines. Your apply jobs stay where they are.&lt;/p&gt;

&lt;p&gt;To install Tirith, use the pinned release from GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"git+https://github.com/StackGuardian/tirith.git@1.2.1"&lt;/span&gt;
tirith &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; &lt;code&gt;pip install tirith&lt;/code&gt; installs a different, unrelated package with the same name on PyPI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Keeping every pipeline on the same policy
&lt;/h2&gt;

&lt;p&gt;Every route works in local mode first, evaluating the policy files committed to the repository. Copy the same file into fifty repositories, though, and over time you have fifty versions. Platform mode is optional: the same step evaluates plans against the policies your StackGuardian organization enforces, so policy owners change a rule once and every connected pipeline picks it up on its next run.&lt;/p&gt;

&lt;p&gt;Depending on your plan and setup, StackGuardian can also run Tirith and Checkov on your plans, keep every result linked to the run that produced it for audit, and report the pipelines that skip the checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Start with a rule your engineers still check by hand and try it in one pipeline. The full guide has a minimal owner-tag policy and the exact plan, check, apply sequence. It also covers what reviewers see in each CI system when a policy fails, how a finding becomes a reviewed and tested Tirith policy, and which features are in Tirith 1.2.1 and which are still in development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.stackguardian.io/post/checkov-and-tirith-where-each-fits" rel="noopener noreferrer"&gt;Read the full guide: Checkov and Tirith: Governing Every IaC Pipeline With StackGuardian&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>Meet Tirith, StackGuardian's Open-Source Policy Engine</title>
      <dc:creator>Diana Loomis</dc:creator>
      <pubDate>Mon, 05 Oct 2026 09:13:31 +0000</pubDate>
      <link>https://dev.to/stackguardian/meet-tirith-stackguardians-open-source-policy-engine-1c42</link>
      <guid>https://dev.to/stackguardian/meet-tirith-stackguardians-open-source-policy-engine-1c42</guid>
      <description>&lt;p&gt;Tirith (GitHub: &lt;a href="https://github.com/StackGuardian/tirith" rel="noopener noreferrer"&gt;https://github.com/StackGuardian/tirith&lt;/a&gt;) is StackGuardian's open-source policy as code framework. It reads the JSON your pipeline already produces, such as the output of terraform show -json, and checks it against policies stored as JSON files. Each rule passes, fails, or is skipped, and the result names the resource and value behind it. Tirith is licensed under Apache 2.0, needs no account, and runs on your own machine or CI runner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Tirith?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is no new policy language to learn. You pick a provider, an operation, and a condition such as Equals, ContainedIn, or RegexMatch, then combine checks with &amp;amp;&amp;amp;, ||, and !. &lt;/p&gt;

&lt;p&gt;Built-in providers cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Terraform plans&lt;/li&gt;
&lt;li&gt;Infracost cost estimates&lt;/li&gt;
&lt;li&gt;Kubernetes manifests&lt;/li&gt;
&lt;li&gt;StackGuardian workflow configurations&lt;/li&gt;
&lt;li&gt;Any JSON document&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That means one framework can block a public S3 bucket, cap EC2 spend at 100 USD a month, and require liveness probes on every pod.&lt;br&gt;
Because policies live in your repository, the same files gate a GitHub Actions job, a GitLab pipeline, and a local run. With --fail-on-error, Tirith exits with code 3 on a violation, so a non-compliant change never reaches apply. Two recent additions help while you write policies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tirith lint catches broken policies in pre-commit hooks.&lt;/li&gt;
&lt;li&gt;tirith ui, currently in beta, is a terminal interface for exploring results and building policies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Who is it for?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tirith is for DevSecOps, platform, and cloud teams that need infrastructure guardrails without building their own policy engine. Tirith is also the engine behind StackGuardian's policy checks, and StackGuardian users can run tirith platform check to test a plan against their organization's central policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get Started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tirith is not on PyPI, so install it from GitHub:&lt;br&gt;
pip install git+&lt;a href="https://github.com/StackGuardian/tirith.git" rel="noopener noreferrer"&gt;https://github.com/StackGuardian/tirith.git&lt;/a&gt;&lt;br&gt;
Then evaluate a plan:&lt;br&gt;
tirith -policy-path policy.json -input-path plan.json&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to contribute?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project welcomes new providers, evaluators, bug fixes, and pull request reviews. Read the contributing guide (&lt;a href="https://github.com/StackGuardian/tirith/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;https://github.com/StackGuardian/tirith/blob/main/CONTRIBUTING.md&lt;/a&gt;), open an issue to get one assigned. And if you have questions, drop them in the StackGuardian Slack community (&lt;a href="https://join.slack.com/t/stackguardian-ol78820/shared_invite/zt-2ksag36j9-OjmXqQmyXudgYrV6FmesIQ" rel="noopener noreferrer"&gt;https://join.slack.com/t/stackguardian-ol78820/shared_invite/zt-2ksag36j9-OjmXqQmyXudgYrV6FmesIQ&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>hacktoberfest</category>
      <category>policyascode</category>
    </item>
    <item>
      <title>A Guide to Getting Started with StackGuardian</title>
      <dc:creator>Diana Loomis</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:23:09 +0000</pubDate>
      <link>https://dev.to/stackguardian/a-guide-to-getting-started-with-stackguardian-40cm</link>
      <guid>https://dev.to/stackguardian/a-guide-to-getting-started-with-stackguardian-40cm</guid>
      <description>&lt;p&gt;If you run Terraform or OpenTofu across several teams, you know the pain: hand-built CI pipelines, credentials in pipeline variables, scattered state files, and compliance checks after deployment. StackGuardian is an infrastructure as code (IaC) automation and governance platform that brings execution, credentials, state, and policy as code into one place, so every infrastructure change follows one trusted standard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you need&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A StackGuardian account, a Git repo with a small Terraform project, an AWS, Azure, or GCP sandbox, and permission to create an IAM role or equivalent. For GitHub, you also need organization admin rights to install the StackGuardian GitHub App.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect Git and your cloud&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On first sign-in, choose GitOps for IaC and name your organization. If you signed up with GitHub, onboarding asks you to install the GitHub App, which becomes your first VCS connector, so don't create it again. Instead of projects, StackGuardian organizes workflows into Workflow Groups, usually mapped to environments or teams. Connect GitHub, GitLab, Bitbucket, or Azure DevOps to trigger runs on pull requests, pushes, or tags. For AWS, use OIDC federation: runs get temporary credentials, and no long-lived secrets are stored. Azure and GCP have their own connectors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a Workflow Group, create a Terraform or OpenTofu workflow pointing to your repo, branch, and working directory. Add parameters, and reference secrets from the StackGuardian vault or a supported external vault so they never appear in your configuration. Select your cloud connector, keep the managed backend on for versioned state, and enable approvals. Use a private runner if executions must stay in an environment you control. Beyond built-in types like Ansible, Kubernetes, and CloudFormation, custom workflows bring any toolset onto the platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan, review, apply&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click Create Run. StackGuardian plans, evaluates policies, and pauses for approval. The summary shows resource changes and Infracost estimates, using a built-in key or your own. Approve, and the apply runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a guardrail&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Policies use Tirith, StackGuardian's open-source policy as code framework, and you can bring existing Open Policy Agent (OPA) and Checkov policies (see supported policy types). Start from 250+ marketplace templates or a no-code builder. For example, a rule allowing only t3.micro for aws_instance stops non-compliant plans before they reach your cloud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to go next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add PR-triggered plans and Stacks for multi-layer infrastructure. To catch changes made outside Terraform, ask the StackGuardian team to enable drift detection. For resources never written as code, SGCode discovers them and generates code for review, then opens a pull request and runs a plan. The managed runtime supports Terraform up to 1.5.7; for newer versions, use OpenTofu or a custom runtime image.&lt;br&gt;
Check out &lt;a href="https://www.stackguardian.io/" rel="noopener noreferrer"&gt;https://www.stackguardian.io/&lt;/a&gt; for more details.&lt;/p&gt;

</description>
      <category>infrastructureascode</category>
      <category>terraform</category>
      <category>infrastructure</category>
      <category>infrastructuregovernance</category>
    </item>
  </channel>
</rss>
