For the complete documentation index, see llms.txt. This page is also available as Markdown.
Custom Rules Quickstart
ORL Rules are YAML-like files that drive the orl engine to modify files within a workspace.
Step 1. Clone Rattleback
Rattleback includes some sample code that can be used to run checks against. We will use it for this example.
gitclonegit@github.com:Gomboc-AI/rattleback.git
Step 2. Create a Rule
Next, let's create a simple rule that ensures aws_s3_bucket Terraform resources are tagged. Don't worry too much about the details at this point, we'll explain it below.
Create a ./rules directory and write the following as ./rules/enforce_aws_s3_bucket_tagging.orl.
type:Rulesetversion:v1metadata:annotations:purpose:taggingpriority:100name:ensure-s3-buckets-are-taggeddisplay_name:Ensure S3 Buckets are taggeddescription:| ## Description All buckets have to be tagged according to the source of truth.spec:template:language:terraformaudit_language:astrules:-name:ensure-tag-existsaudit:| {{ aResource("aws_s3_bucket", aMissingAttribute("tags")) }}remediation:-command:insert_afterpath:bodyflags:prefix:"\n\n"indent:""value:| tags = { source = "rattleback" }
Step 3: Remediate
The ORL engine is provided as a Docker container. It can be executed with the appropriate mount points to load the rules and remediate files.
After running the command, main.tf is modified to include a tags attribute for the uut resource with source = "rattleback", just as specified by the rule. The resulting git diff would look like this:
orl remediate supports a --dry-run option which will write the changed files to the terminal instead of disk. This can help in developing rules as you don't need to run git restore to undo the changes and try again.
# There are five ORL types: Rule, Ruleset, Variables, Test, and Report.
# Type and version tell ORL how and when to process the file.
# "Ruleset" tells ORL it is a collection of rules that have to be executed
# as a group.
type: Ruleset
version: v1
# Metadata defines various details which control how the rule executes
# as well as provides context for reports
metadata:
# Name uniquely identifies the rule, while display_name is copied into the
# report and is meant as a more human readable name.
name: ensure-s3-buckets-are-tagged
display_name: Ensure S3 Buckets are tagged
# Description is a markdown string that describes the purpose of the rule.
# It is copied into the report.
description: |
## Description
All buckets have to be tagged according to the source of truth.
# Priority defines the order of when rules are run. Rules are run from the
# smallest number to the largest. Two rules with the same priority are
# run based on sorted names.
priority: 100
# Annotations are a map of string key/value pairs. They can be anything,
# and are blindly copied into the ORL report.
annotations:
purpose: tagging
# The spec depends on the types. This is the spec for a "Ruleset", which is an
# array of Rules.
spec:
# These settings are shared with each rule below
template:
# The ORL language can be used to get a list of the languages
# Only rules that match `orl remediate --language <language>` are loaded.
language: terraform
# This determines what form of parsing ORL uses. Currently only AST is
# supported.
audit_language: ast
# Array of the actual rules
rules:
# All rules in a ruleset should be uniquely named. This name is included
# in the report metadata.
- name: ensure-tag-exists
# `audit` is the search query to perform. In this case, it uses template
# helpers that generate the actual S-expression. The list of helpers can
# be seen via `orl language <language>`
audit: |
{{ aResource("aws_s3_bucket", aMissingAttribute("tags")) }}
# A list of remediation steps to perform on each finding
remediation:
# The command to run on each finding. `insert_after` sets the cursor
# right after the last character of the named match defined by `path`.
# The other commands are:
# `audit` - Don't change any files, just log a message to the report
# `create` - Add value to the bottom of a file only if no named match was found
# `insert_before` - Insert value before the named match
# `replace` - Replace the contents of the named match
# `remove` - Remove the named match
- command: insert_after
# The `aResource` helper provides many named matches in the AST
# structure. "body" is all the text exclusively between the curly
# braces.
path: body
flags:
prefix: "\n\n" # Append an empty line before `value`
indent: " " # Add in front of every line of `value`
value: |
tags = {
source = "rattleback"
}