tfGuard

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 31, 2024 License: GPL-3.0 Imports: 9 Imported by: 0

README

latest build latest release Go Reference

tf-guard

A package for writing Terraform Resource evaluation rules in native Golang.

A problem I've encountered with other Terraform security tools is the lack of control caused (most often) by the abstractions imposed by Domain Specific Languages (DSLs) used to make writing the rules themselves easier.

This causes headaches when trying to write more complicated logic around resources that DSLs may not have support for, or may cause conflicts with other resources during evaluation. Additionally the overhead of having to learn an additional DSL to support these tools can be cumbersome and time consuming when you already know full coding languages.

This package serves as my solution to that problem, allowing the flexibility of the full Golang language to allow users to write their own custom logic and rules for their resources within a provided Terraform plan.

This package intakes your Terraform plan (in JSON formatting) and your own defined resource rules (as functions extending the Rule type) and returns a simple ordered evaluation of those rules against the resources defined within your plan.

By removing the overhead of having to dig through the resources and their attributes in your plan files, you can instead focus on writing rules to evaluate your resources and take appropriate actions based on the results.

Usage

The package requires that a JSON formatted Terraform plan file be collected containing the resources that are to be evaluated. This can be accomplished with 2 Terraform commands:

terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > myplanfile.json

This JSON formatted plan file is fed into the package via the Deployment struct to parse its contents.

d := Deployment{
    PlanFile: "./myplanfile.json",
    ...
}

Additionally, if utilizing modules, a ModulesFile can be provided as the path to the modules.json file for the deployment that is used to link the underlying resources being created from within a module, to its parent and children addresses. If not provided, a best effort is made to identify the file in the execution directory.

d := Deployment{
    PlanFile: "./myplanfile.json",
    ModulesFile: "./.terraform/modules.json",
    ...
}

Next, the functions to be executed against the resources must be provided. These functions must satisfy the Rule type and can be provided into the Rules parameter of the Deployment.

d := Deployment{
    PlanFile: "./myplanfile.json",
    ModulesFile: "./.terraform/modules.json",
    Rules: []Rule{
        ...
    },
    ...
}

By providing a simple function type, the package allows custom functions to be written with full access to each Terraform resource's configuration values.

type Rule func(tfresources.Resource) Result

An example Rule declaration to showing access to Terraform module attributes as well as resource values:

func main(){
    d := Deployment{
        PlanFile: "./myplanfile.json",
        ModulesFile: "./.terraform/modules.json",
        Rules: []Rule{
            MyCustomTRule
        },
    }
    ...
}

func MyCustomTFRule(r tfresources.Resource) tfGuard.Result {
    moduleReference := r.Module.Version           // Immutable versioning for the module linked to this resource
    attributeValues := r.Planned.AttributeValues  // map[string]interface{} Containing resource attribute values
    resourceType := r.Planned.Type                // A Terraform resource type - like aws_s3_bucket
    ...
    return tfGuard.Result {               // A Result struct must be returned for each Rule type
        Name: "This is my custom rule.",  // A simple name for this rule
        Valid: true,                      // A boolean Valid argument for rule validity
        ...                               // Other attributes can be defined if required - see Result struct
    }
}

Finally the Scan method can be executed to parse the resources, evaluate each rule against them, and return the results as StdOut string text, or in JSON formatting for programmatic parsing.

func main(){
    d := Deployment{
        ...
    }
    d.Scan()                    // Results are written to StdOut unless Disabled

    fmt.Println(d.ResultsJson)  // JSON output can be written to a file if desired, or parsed directly
}
TF Guard Rule Evaluation for Resources:

[ ✅ ]  Rule: S3 buckets must be tagged at all times.
	Valid: true
	Severity: Minor
	Resource: aws_s3_bucket.default
	Type: aws_s3_bucket

[ ❌ ]  Rule: All resources must include an Owner tag.
	Valid: false
	Severity: Major
	Resource: aws_s3_bucket.default
	Type: aws_s3_bucket

[ ✅ ]  Rule: S3 Bucket Objects must always be tagged.
	Valid: true
	Severity: Minor
	Resource: aws_s3_object.obj
	Type: aws_s3_object

[ ❌ ]  Rule: All resources must include an Owner tag.
	Valid: false
	Severity: Major
	Resource: aws_s3_object.obj
	Type: aws_s3_object

Overall Resource Score: 50%

Check out the examples on how you can integrate this package into your own codebase.

Author

This codebase is created and maintained by Dave Streng.

License

GNU General Public License v3.0 or later

See LICENSE to see the full text.

Documentation

Overview

A package that will parse a Terraform plan file and execute a set of functions against the underlying resources that can be used to gate or control how Terraform resources are being provisioned into your environment.

This package can be utilized to build your own infrastructure scanning rules with the ability to leverage the capabilities of a full language instead of being limited by Domain Specific Languages (DSLs).

Index

Constants

This section is empty.

Variables

View Source
var (
	Severity = struct {
		Minor    string
		Major    string
		Critical string
	}{
		Minor:    "Minor",
		Major:    "Major",
		Critical: "Critical",
	}
)

Some default values for Severities that can be easily leveraged if desired, if not, you can provide your own severity values/structures based on your needs.

Functions

This section is empty.

Types

type Deployment

type Deployment struct {
	// The filesystem path to your JSON formatting terraform plan
	// file.
	PlanFile string

	// The filesystem path to your JSON modules file. If not provided
	// a best effort is made to locate the file in its appropriate
	// directory within the execution directory.
	ModulesFile string

	// A Resource slice holding all resources parsed out of the
	// provided Terraform plan file, used to execute the rules.
	Resources []tfresources.Resource

	// A Rule slice used to contain all Rule type functions that
	// are to be executed against ALL resources within the Terraform
	// plan file.
	Rules []Rule

	// A Result slice containing all compiled results of the
	// execution of each Rule against each Resource.
	Results []Result

	// A simple string output of the results of the execution
	// outputted to StdOut by default but also accessible to
	// write to a file if desired.
	ResultsStdOut string

	// An organized JSON representation of the results of the
	// execution, organized by Resource and Rule and also providing
	// the overall score that can be used to programmatically take
	// actions based on results.
	ResultsJson []byte

	// A simple toggle allowing the default StdOut results output
	// to be disabled if the results are being assessed via other
	// means.
	DisableStdOut bool

	// A simple Debug logging toggle for troubleshooting.
	Debug bool

	// A Logger container used to output the debug logging (if
	// enabled).
	Logger *logrus.Logger
}

A Deployment contains all the relevant attributes for a given Terraform plan execution. It contains references to Plan and Modules files, as well as the list of Rules to be evaluated against each resource, as lastly the results of the evaluation both in string-based StdOut format and JSON (to alloow for programmatic parsing).

func (*Deployment) Scan

func (d *Deployment) Scan()

The primary Scan method intakes the specified Plan and Modules file paths and utilizes the tfresources project to parse out the underlying Terraform resources and link them to any declared modules.

Once parsed, the resources are fed into the rule engine to begin the execution of each rule onto each resource and the results aggregated into StdOut and JSON formatting.

Debug logging can be enabled if desired to assist with writing Rules. Additionall the default StdOut text can be disabled if using the JSON output for programmatic control over the results.

type Result

type Result struct {
	// A simple name for this result. This name will be provided
	// in the aggregated results to identify the rule executed.
	Name string

	// A validity boolean - ths is the primary mechanism to report
	// a rule execution as successful or unsuccessful.
	Valid bool

	// A simple Severity toggle - defaults to `Minor` and is fully
	// configurable if you have different Severity constructs.
	Severity string

	// The underlying resource attributes this result was executed
	// against. This is automatically populated at execution to
	// allow you to identify the resource being evaluated.
	Resource tfresources.Resource

	// A simple Not Applicable boolean toggle, used to flag
	// resources that a particular rule execution does not apply
	// to. Any results with this toggled to `true` will be ignored
	// in the overall results aggregation.
	NotApplicable bool
}

A Result is a data structure used to hold the evaluation results for a Rule (as defined above). A Rule type function must return a valid Result.

type Rule

type Rule func(tfresources.Resource) Result

A Rule function definition - this function type must be satisfied in order for the provided function to be executed against the planned resources.

The input is a Resource type that extends the terraform-json project's StateResource struct by linking any resources created from modules back to their parent and children addresses. The output is a Result struct as defined below.

Check out the [terraform-json](https://github.com/hashicorp/terraform-json/blob/main/state.go#L124) project for more details on how you can access different resource values.

Additionally check out the [terraform-resources](https://pkg.go.dev/github.com/S7R4nG3/terraform-resources) project for more details on how you can utilize Module attributes to identify the exact source where a resources is defined.

Directories

Path Synopsis
examples
complex command
simple command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL