Skip to content

magodo/hclgrep

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hclgrep

workflow

Search for HCL(v2) using syntax tree.

The idea is heavily inspired by https://github.com/mvdan/gogrep.

Install

go install github.com/magodo/hclgrep@latest

Usage

usage: hclgrep [options] commands [FILE...]

An option is one of the following:

-H                  prefix the filename and byte offset of a match

A command is one of the following:

-x  pattern         find all nodes matching a pattern
-g  pattern         discard nodes not matching a pattern
-v  pattern         discard nodes matching a pattern
-p  number          navigate up a number of node parents
-rx name="regexp"   filter nodes by regexp against wildcard value of "name"
-w  name            print the wildcard node only (must be the last command)

A pattern is a piece of HCL code which may include wildcards. It can be:

  • A body (zero or more attributes, and zero or more blocks)
  • An expression

There are two types of wildcards can be used in a pattern, depending on the scope it resides in:

  • Attribute wildcard ("@"): represents an attribute, a block, or an object element
  • Expression wildcard ("$"): represents an expression or a place that a string is accepted (i.e. as a block type, block label)

The wildcards are followed by a name. Each wildcard with the same name must match the same node/string, excluding "_". Example:

$x.$_ = $x # assignment of self to a field in self

The wildcard name is only recorded for "-x" command or "-g" command (the first match in DFS).

If "*" is before the name, it will match any number of nodes. Example:

[$*_] # any number of elements in a tuple

resource foo "name" {
    @*_  # any number of attributes/blocks inside the resource block body
}

Example

  • Grep dynamic blocks used in Terraform config

      $ hclgrep -x 'dynamic $_ {@*_}' main.tf
    
  • Grep potential mis-used "count" in Terraform config

      $ hclgrep -x 'var.$_[count.index]' main.tf
    
  • Grep module source addresses in Terraform config

      $ hclgrep -x 'module $_ {@*_}' \
          -x 'source = $addr' \
          -w addr main.tf
    
  • Grep AzureRM Terraform network security rule resource which allows 22 port for inbound traffic

      $ hclgrep -x 'resource azurerm_network_security_rule $_ {@*_}' \
      -g 'direction = "Inbound"' \
      -g 'access = "Allow"' \
      -g 'destination_port_range = $port' \
      -rx 'port="22|\*"' \
      main.tf
    
  • Grep for the evaluated Terraform configurations, run following command in the root module (given there is no output variables defined)

      $ terraform show -no-color | sed --expression 's;(sensitive value);"";' | hclgrep -x '<pattern>'
    

Limitation

  • The any expression wildcard ($*) doesn't work inside a traversal.
  • The any wildcard doesn't remember the matched wildcard name.