<?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: Andrew Wright</title>
    <description>The latest articles on DEV Community by Andrew Wright (@andrewwright).</description>
    <link>https://dev.to/andrewwright</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%2F325904%2F8b35d979-f7d0-4530-9adc-1aa2b658cea6.jpeg</url>
      <title>DEV Community: Andrew Wright</title>
      <link>https://dev.to/andrewwright</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andrewwright"/>
    <language>en</language>
    <item>
      <title>Regula: Validate Terraform for Policy Compliance with Open Policy Agent</title>
      <dc:creator>Andrew Wright</dc:creator>
      <pubDate>Wed, 05 Feb 2020 17:36:44 +0000</pubDate>
      <link>https://dev.to/andrewwright/regula-validate-terraform-for-policy-compliance-with-open-policy-agent-37lg</link>
      <guid>https://dev.to/andrewwright/regula-validate-terraform-for-policy-compliance-with-open-policy-agent-37lg</guid>
      <description>&lt;h1&gt;
  
  
  Regula
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;  Introduction
&lt;/li&gt;
&lt;li&gt;  How does Regula work?
&lt;/li&gt;
&lt;li&gt;  Running Regula locally
&lt;/li&gt;
&lt;li&gt;  Regula rules

&lt;ul&gt;
&lt;li&gt;  Simple rules
&lt;/li&gt;
&lt;li&gt;  Advanced rules
&lt;/li&gt;
&lt;li&gt;  Rule library
&lt;/li&gt;
&lt;li&gt;  Rule examples
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Compliance controls vs. rules

&lt;ul&gt;
&lt;li&gt;  Specifying compliance controls
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Interpreting the results

&lt;ul&gt;
&lt;li&gt;  Summary
&lt;/li&gt;
&lt;li&gt;  Controls
&lt;/li&gt;
&lt;li&gt;  Rules
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Running Regula in CI
&lt;/li&gt;

&lt;li&gt;  Development

&lt;ul&gt;
&lt;li&gt;  Directory structure
&lt;/li&gt;
&lt;li&gt;  Adding a test
&lt;/li&gt;
&lt;li&gt;  Debugging a rule with fregot
&lt;/li&gt;
&lt;li&gt;  Locally producing a report
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Regula is a tool that evaluates Terraform infrastructure-as-code for potential security misconfigurations and compliance violations prior to deployment.&lt;/p&gt;

&lt;p&gt;Regula includes a library of rules written in Rego, the policy language used by the Open Policy Agent (&lt;a href="https://www.openpolicyagent.org/" rel="noopener noreferrer"&gt;opa&lt;/a&gt;) project. Regula works with your favorite CI/CD tools such as Jenkins, Circle CI, and AWS CodePipeline; we’ve included a &lt;a href="https://github.com/fugue/regula-action" rel="noopener noreferrer"&gt;GitHub Actions example&lt;/a&gt; so you can get started quickly. Where relevant, we’ve mapped Regula policies to the CIS AWS Foundations Benchmark so you can assess your compliance posture. We'll be adding more rules in the coming weeks, sourced from &lt;a href="https://fugue.co" rel="noopener noreferrer"&gt;Fugue&lt;/a&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  How does Regula work?
&lt;/h2&gt;

&lt;p&gt;There are two parts to Regula. The first is a &lt;a href="https://github.com/fugue/regula/blob/master/bin/regula" rel="noopener noreferrer"&gt;shell script&lt;/a&gt;&lt;br&gt;
that generates a &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;terraform&lt;/a&gt; plan in JSON format, ready for consumption by&lt;br&gt;
&lt;a href="https://www.openpolicyagent.org/" rel="noopener noreferrer"&gt;opa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The second part is a Rego framework that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Merges resource info from &lt;code&gt;planned_values&lt;/code&gt; and &lt;code&gt;configuration&lt;/code&gt; in the
Terraform plan into a more conveniently accessible format.&lt;/li&gt;
&lt;li&gt;  Walks through the imported Terraform modules and merges them into a flat
format.&lt;/li&gt;
&lt;li&gt;  Looks for rules and executes them.&lt;/li&gt;
&lt;li&gt;  Creates a report with the results of all rules and a
control mapping in the output.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Running Regula locally
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./bin/regula [TERRAFORM_PATH] [REGO_PATHS...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;TERRAFORM_PATH&lt;/code&gt; is the directory where your Terraform configuration files are&lt;br&gt;
located.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;REGO_PATHS&lt;/code&gt; are the directories that need to be searched for Rego code.  This&lt;br&gt;
should at least include &lt;code&gt;lib/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;./bin/regula ../my-tf-infra .&lt;/code&gt;: conveniently check &lt;code&gt;../my-tf-infra&lt;/code&gt; against
all rules in this main repository.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;./bin/regula ../my-tf-infra lib examples/aws/t2_only.rego&lt;/code&gt;: run Regula
using only the specified rule.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;./bin/regula ../my-tf-infra lib ../custom-rules&lt;/code&gt;: run Regula using a
directory of custom rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is also possible to set the name of the &lt;code&gt;terraform&lt;/code&gt; executable, which is&lt;br&gt;
useful if you have several versions installed:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env TERRAFORM=terraform-v0.12.18 ./bin/regula ../regula-ci-example/ lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Regula rules
&lt;/h2&gt;

&lt;p&gt;Regula rules are written in standard &lt;a href="https://www.openpolicyagent.org/docs/latest/policy-language/" rel="noopener noreferrer"&gt;Rego&lt;/a&gt; and use a similar format to&lt;br&gt;
&lt;a href="https://docs.fugue.co/rules.html" rel="noopener noreferrer"&gt;Fugue Custom Rules&lt;/a&gt;. This means there are (currently) two kinds of rules:&lt;br&gt;
simple rules and advanced rules.&lt;/p&gt;
&lt;h3&gt;
  
  
  Simple rules
&lt;/h3&gt;

&lt;p&gt;Simple rules are useful when the policy applies to a single resource type only,&lt;br&gt;
and you want to make simple yes/no decision.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rules must always be located right below the `rules` package.&lt;/span&gt;
&lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;my_simple_rule&lt;/span&gt;

&lt;span class="c1"&gt;# Simple rules must specify the resource type they will police.&lt;/span&gt;
&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aws_ebs_volume"&lt;/span&gt;

&lt;span class="c1"&gt;# Simple rules must specify `allow` or `deny`.  For this example, we use&lt;/span&gt;
&lt;span class="c1"&gt;# an `allow` rule to check that the EBS volume is encrypted.&lt;/span&gt;
&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced rules
&lt;/h3&gt;

&lt;p&gt;Advanced rules are harder to write, but more powerful. They allow you to&lt;br&gt;
observe different kinds of resource types and decide which specific resources&lt;br&gt;
are valid or invalid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rules still must be located in the `rules` package.&lt;/span&gt;
&lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_attached_policy&lt;/span&gt;

&lt;span class="c1"&gt;# Advanced rules typically use functions from the `fugue` library.&lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fugue&lt;/span&gt;

&lt;span class="c1"&gt;# We mark an advanced rule by setting `resource_type` to `MULTIPLE`.&lt;/span&gt;
&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MULTIPLE"&lt;/span&gt;

&lt;span class="c1"&gt;# `fugue.resources` is a function that allows querying for resources of a&lt;/span&gt;
&lt;span class="c1"&gt;# specific type.  In our case, we are just going to ask for the EBS volumes&lt;/span&gt;
&lt;span class="c1"&gt;# again.&lt;/span&gt;
&lt;span class="n"&gt;ebs_volumes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fugue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"aws_ebs_volume"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Auxiliary function.&lt;/span&gt;
&lt;span class="n"&gt;is_encrypted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Regula expects advanced rules to contain a `policy` rule that holds a set&lt;/span&gt;
&lt;span class="c1"&gt;# of _judgements_.&lt;/span&gt;
&lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ebs_volumes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;is_encrypted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fugue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allow_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ebs_volumes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_encrypted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fugue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deny_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;fugue&lt;/code&gt; API consists of four functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;fugue.resources(resource_type)&lt;/code&gt; returns an object with all resources of
the requested type.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;fugue.allow_resource(resource)&lt;/code&gt; marks a resource as valid.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;fugue.deny_resource(resource)&lt;/code&gt; marks a resource as invalid.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;fugue.missing_resource(resource_type)&lt;/code&gt; marks a resource as &lt;strong&gt;missing&lt;/strong&gt;.
This is useful if you for example &lt;em&gt;require&lt;/em&gt; a log group to be present.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rule library
&lt;/h3&gt;

&lt;p&gt;See &lt;a href="https://github.com/fugue/regula/tree/master/rules" rel="noopener noreferrer"&gt;rules&lt;/a&gt; directory.  Fugue is currently working on open sourcing more rules from &lt;a href="https://www.fugue.co/" rel="noopener noreferrer"&gt;our product&lt;/a&gt; to Regula.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Rule Name&lt;/th&gt;
&lt;th&gt;Rule Summary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;CloudTrail&lt;/td&gt;
&lt;td&gt;cloudtrail_log_file_validation&lt;/td&gt;
&lt;td&gt;CloudTrail log file validation should be enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;EBS&lt;/td&gt;
&lt;td&gt;ebs_volume_encrypted&lt;/td&gt;
&lt;td&gt;EBS volume encryption should be enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;IAM&lt;/td&gt;
&lt;td&gt;iam_admin_policy&lt;/td&gt;
&lt;td&gt;IAM policies should not have full "&lt;em&gt;:&lt;/em&gt;" administrative privileges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;IAM&lt;/td&gt;
&lt;td&gt;iam_user_attached_policy&lt;/td&gt;
&lt;td&gt;IAM policies should not be attached directly to users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;KMS&lt;/td&gt;
&lt;td&gt;kms_rotate&lt;/td&gt;
&lt;td&gt;KMS CMK rotation should be enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;VPC&lt;/td&gt;
&lt;td&gt;security_group_ingress_anywhere&lt;/td&gt;
&lt;td&gt;VPC security group rules should not permit ingress from '0.0.0.0/0' except to ports 80 and 443&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;VPC&lt;/td&gt;
&lt;td&gt;security_group_ingress_anywhere_rdp&lt;/td&gt;
&lt;td&gt;VPC security group rules should not permit ingress from '0.0.0.0/0' to port 3389 (Remote Desktop Protocol)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;VPC&lt;/td&gt;
&lt;td&gt;security_group_ingress_anywhere_ssh&lt;/td&gt;
&lt;td&gt;VPC security group rules should not permit ingress from '0.0.0.0/0' to port 22 (SSH)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;VPC&lt;/td&gt;
&lt;td&gt;vpc_flow_log&lt;/td&gt;
&lt;td&gt;VPC flow logging should be enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Rule examples
&lt;/h3&gt;

&lt;p&gt;Whereas the rules included in the Regula rules library are generally applicable, we've built rule &lt;a href="https://github.com/fugue/regula/tree/master/examples" rel="noopener noreferrer"&gt;examples&lt;/a&gt; that look at tags, region restrictions, and EC2 instance usage that should be modified to fit user/organization policies.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Rule Name&lt;/th&gt;
&lt;th&gt;Rule Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;EC2&lt;/td&gt;
&lt;td&gt;ec2_t2_only&lt;/td&gt;
&lt;td&gt;Restricts instances to a whitelist of instance types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;Tags&lt;/td&gt;
&lt;td&gt;tag_all_resources&lt;/td&gt;
&lt;td&gt;Checks whether resources that are taggable have at least one tag with a minimum of 6 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;Regions&lt;/td&gt;
&lt;td&gt;useast1_only&lt;/td&gt;
&lt;td&gt;Restricts resources to a given AWS region&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Compliance controls vs. rules
&lt;/h2&gt;

&lt;p&gt;What's the difference between controls and rules? A &lt;strong&gt;control&lt;/strong&gt; represents an individual recommendation within a compliance standard, such as "IAM policies should not have full &lt;code&gt;"*:*"&lt;/code&gt; administrative privileges" (CIS AWS Foundations Benchmark 1-22).&lt;/p&gt;

&lt;p&gt;In Regula, a &lt;strong&gt;rule&lt;/strong&gt; is a Rego policy that validates whether a cloud resource violates a control (or multiple controls). One example of a rule is &lt;a href="https://github.com/fugue/regula/blob/master/rules/aws/iam_admin_policy.rego" rel="noopener noreferrer"&gt;&lt;code&gt;iam_admin_policy&lt;/code&gt;&lt;/a&gt;, which checks whether an IAM policy in a Terraform file has &lt;code&gt;"*:*"&lt;/code&gt; privileges. If it does not, the resource fails validation.&lt;/p&gt;

&lt;p&gt;Controls map to sets of rules, and rules can map to multiple controls. For example, control &lt;code&gt;CIS_1-22&lt;/code&gt; and &lt;code&gt;REGULA_R00002&lt;/code&gt; &lt;a href="https://github.com/fugue/regula/blob/master/rules/aws/iam_admin_policy.rego#L7" rel="noopener noreferrer"&gt;both map to&lt;/a&gt; the rule &lt;code&gt;iam_admin_policy&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specifying compliance controls
&lt;/h3&gt;

&lt;p&gt;Controls can be specified within the rules: just add a &lt;code&gt;controls&lt;/code&gt; set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Rules must always be located right below the `rules` package.&lt;/span&gt;
&lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;my_simple_rule&lt;/span&gt;

&lt;span class="c1"&gt;# Simple rules must specify the resource type they will police.&lt;/span&gt;
&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"aws_ebs_volume"&lt;/span&gt;

&lt;span class="c1"&gt;# Controls.&lt;/span&gt;
&lt;span class="n"&gt;controls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"CIS_1-16"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Rule logic&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interpreting the results
&lt;/h2&gt;

&lt;p&gt;Here's a snippet of test results from a Regula report. The output is from an example &lt;a href="https://github.com/fugue/regula-ci-example/runs/389223751#step:4:12" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "result": [
    {
      "expressions": [
        {
          "value": {
            "controls": {
              "CIS_1-22": {
                "rules": [
                  "iam_admin_policy"
                ],
                "valid": false
              },
            },
            "rules": {
              "iam_admin_policy": {
                "resources": {
                  "aws_iam_policy.basically_allow_all": {
                    "id": "aws_iam_policy.basically_allow_all",
                    "message": "invalid",
                    "type": "aws_iam_policy",
                    "valid": false
                  },
                  "aws_iam_policy.basically_deny_all": {
                    "id": "aws_iam_policy.basically_deny_all",
                    "message": "",
                    "type": "aws_iam_policy",
                    "valid": true
                  }
                },
                "valid": false
              },
            "summary": {
              "controls_failed": 2,
              "controls_passed": 12,
              "rules_failed": 2,
              "rules_passed": 8,
              "valid": false
            }
          },
          "text": "data.fugue.regula.report",
          "location": {
            "row": 1,
            "col": 1
          }
        }
      ]
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;These are the important bits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;li&gt;Controls&lt;/li&gt;
&lt;li&gt;Rules&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;summary&lt;/code&gt; block contains a breakdown of the compliance state of your Terraform files. In the output above, the Terraform violated 2 rules and 2 controls, so the test as a whole failed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controls
&lt;/h3&gt;

&lt;p&gt;Regula shows you compliance results for both controls and rules, in addition to which specific resources failed. Above, in the &lt;code&gt;controls&lt;/code&gt; block, you can see that the Terraform in the example is noncompliant with &lt;code&gt;CIS_1-22&lt;/code&gt;, and the mapped rules that failed are listed underneath (in this case, &lt;code&gt;iam_admin_policy&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules
&lt;/h3&gt;

&lt;p&gt;In the &lt;code&gt;rules&lt;/code&gt; block further down from &lt;code&gt;controls&lt;/code&gt;, each rule lists the resources that failed. Above, you'll see that the resource &lt;code&gt;aws_iam_policy.basically_allow_all&lt;/code&gt; was the one that failed the mapped rule -- as noted by &lt;code&gt;"valid": false&lt;/code&gt;. In contrast, &lt;code&gt;aws_iam_policy.basically_deny_all&lt;/code&gt; passed.&lt;/p&gt;

&lt;p&gt;You can see the full example report in this &lt;a href="https://github.com/fugue/regula-ci-example/runs/389223751#step:4:12" rel="noopener noreferrer"&gt;GitHub Action log&lt;/a&gt;. For a detailed explanation of the report, see the &lt;a href="https://github.com/fugue/regula-ci-example" rel="noopener noreferrer"&gt;regula-ci-example README&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Regula in CI
&lt;/h2&gt;

&lt;p&gt;Regula is designed to be easy to run in CI.  We provide a GitHub Action that can&lt;br&gt;
be easily added to your repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fugue/regula-action" rel="noopener noreferrer"&gt;https://github.com/fugue/regula-action&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up Regula with different CI/CD solutions such as Jenkins, CodePipeline,&lt;br&gt;
CircleCI, TravisCI, and others would follow a similar pattern.  This repository&lt;br&gt;
contains an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fugue/regula-ci-example" rel="noopener noreferrer"&gt;https://github.com/fugue/regula-ci-example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Directory structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;bin/&lt;/code&gt;: the main Regula script that calls &lt;code&gt;terraform&lt;/code&gt; &amp;amp; &lt;code&gt;opa&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;lib/&lt;/code&gt;: the OPA library code to evaluate rules and mangle input.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;rules/&lt;/code&gt;: a collection of rules.  We may split this up further as the number
of rules increases.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;examples/&lt;/code&gt;: a collection of example rules that you can use as inspiration
 for your own rules.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;scripts/&lt;/code&gt;: scripts for development; currently only a script to generate
test input.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;tests/&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;tests/lib&lt;/code&gt;: internal tests for the library.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;tests/rules/&lt;/code&gt;: tests for the various rules.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;tests/rules/inputs&lt;/code&gt;: terraform files that can be used to generate Rego
 files.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;tests/examples/&lt;/code&gt;: tests for the example rules.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;tests/examples/inputs&lt;/code&gt;: input files for the example rules.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding a test
&lt;/h3&gt;

&lt;p&gt;If you would like to add a rule, we recommend starting with a test.&lt;br&gt;
Put your terraform code in a file in &lt;code&gt;tests/rules/&amp;lt;provider&amp;gt;/inputs&lt;/code&gt;; for example&lt;br&gt;
&lt;a href="https://github.com/fugue/regula/blob/master/tests/rules/aws/inputs/kms_rotate_infra.tf" rel="noopener noreferrer"&gt;tests/rules/aws/inputs/kms_rotate_infra.tf&lt;/a&gt;.&lt;br&gt;
From this, you can generate a mock input by running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash scripts/generate-test-inputs.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The mock input will then be placed in a &lt;code&gt;.rego&lt;/code&gt; file with the same name,&lt;br&gt;
in our case &lt;a href="https://github.com/fugue/regula/blob/master/tests/rules/aws/inputs/kms_rotate_infra.rego" rel="noopener noreferrer"&gt;tests/rules/aws/inputs/kms_rotate_infra.rego&lt;/a&gt;.&lt;br&gt;
It is then customary to add the actual tests in a file with the same name (appended with &lt;code&gt;_test&lt;/code&gt; instead of &lt;code&gt;_infra&lt;/code&gt;),&lt;br&gt;
but outside of the &lt;code&gt;inputs/&lt;/code&gt; subdirectory.  In this case, that would be&lt;br&gt;
&lt;a href="https://github.com/fugue/regula/blob/master/tests/rules/aws/kms_rotate_test.rego" rel="noopener noreferrer"&gt;tests/rules/aws/kms_rotate_test.rego&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging a rule with fregot
&lt;/h3&gt;

&lt;p&gt;Once you have generated the mock input, it is easy to debug a rule with&lt;br&gt;
&lt;a href="https://github.com/fugue/fregot" rel="noopener noreferrer"&gt;fregot&lt;/a&gt;.  Fire up &lt;code&gt;fregot&lt;/code&gt; with the right directories and set a breakpoint on&lt;br&gt;
the rule you are trying to debug:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ fregot repl lib rules tests
F u g u e   R E G O   T o o l k i t
fregot v0.7.2 repl - use :help for usage info
repl% :break data.rules.t2_only.allow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, we can just evaluate the entire report with the mock input.  If your rule&lt;br&gt;
is triggered, that will drop you into a debug prompt:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;repl% data.fugue.regula.report with input as data.tests.rules.t2_only.mock_input
19|   valid_instance_types[input.instance_type]
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From here, you can evaluate anything in context; such as &lt;code&gt;input&lt;/code&gt; to look at the&lt;br&gt;
resource, or any other auxiliary rules such as &lt;code&gt;valid_instance_types&lt;/code&gt; in this&lt;br&gt;
example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Locally producing a report
&lt;/h3&gt;

&lt;p&gt;In some cases, you may want to produce the steps that Regula performs manually.&lt;br&gt;
If that is something you want to step through, this section is for you.&lt;/p&gt;

&lt;p&gt;We first need to obtain a JSON-formatted terraform plan.  In order to do get&lt;br&gt;
that, you can use:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
terraform plan -refresh=false -out=plan.tfplan
terraform show -json plan.tfplan &amp;gt;input.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This gives you &lt;code&gt;input.json&lt;/code&gt;.  Now you can test this input against the rules by&lt;br&gt;
evaluating &lt;code&gt;data.fugue.regula.report&lt;/code&gt; with OPA.  In order to do that, point OPA&lt;br&gt;
to the input file, and the regula project directory.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;opa eval -d /path/to/regula --input input.json 'data.fugue.regula.report'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or using &lt;code&gt;fregot&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fregot eval --input input.json 'data.fugue.regula.report' . | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If all goes well, you should now see the results for each rule.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
