Skip to content

Commit

Permalink
rework handling of Terraform providers so ResourceType has provider type
Browse files Browse the repository at this point in the history
  • Loading branch information
Larry Hitchon committed Jun 15, 2018
1 parent cc2ea9c commit 62323d0
Show file tree
Hide file tree
Showing 11 changed files with 54 additions and 18 deletions.
1 change: 1 addition & 0 deletions assertion/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func CheckRule(rule Rule, resource Resource, e ExternalRuleInvoker) (string, []V
RuleID: rule.ID,
ResourceID: resource.ID,
ResourceType: resource.Type,
Category: resource.Category,
Status: expressionResult.Status,
RuleMessage: rule.Message,
AssertionMessage: expressionResult.Message,
Expand Down
1 change: 1 addition & 0 deletions assertion/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type (
RuleID string
ResourceID string
ResourceType string
Category string
Status string
RuleMessage string
AssertionMessage string
Expand Down
5 changes: 0 additions & 5 deletions linter/common.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
package linter

import (
"fmt"
"github.com/ghodss/yaml"
"github.com/stelligent/config-lint/assertion"
"io/ioutil"
"os"
"path/filepath"
)

func loadYAML(filename string) ([]interface{}, error) {
empty := []interface{}{}
content, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Fprintln(os.Stderr, filename, err.Error())
return empty, err
}

var yamlData interface{}
err = yaml.Unmarshal(content, &yamlData)
if err != nil {
fmt.Fprintln(os.Stderr, filename, err.Error())
return empty, err
}
m := yamlData.(map[string]interface{})
Expand All @@ -32,7 +28,6 @@ func getResourceIDFromFilename(filename string) string {
return resourceID
}

// FIXME move this to the assertion package (along with test)
// CombineValidationReports merges results from two separate Validate runs
func CombineValidationReports(r1, r2 assertion.ValidationReport) assertion.ValidationReport {
return assertion.ValidationReport{
Expand Down
3 changes: 2 additions & 1 deletion linter/file_linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import (
)

type (
// Variable contains a key value pair for expressions in a Terraform configuration file
Variable struct {
Name string
Value interface{}
}
// FileResources contains the variables and resources loaded from a collection of files
FileResources struct {
Resources []assertion.Resource
Variables []Variable
Expand Down Expand Up @@ -48,7 +50,6 @@ func (fl FileLinter) Validate(ruleSet assertion.RuleSet, options Options) (asser
filesScanned = append(filesScanned, filename)
loaded, err := fl.Loader.Load(filename)
if err != nil {
fmt.Printf("Error loading %s: %s\n", filename, err)
loadViolations = append(loadViolations, makeLoadViolation(filename, err))
continue
}
Expand Down
1 change: 1 addition & 0 deletions linter/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (l KubernetesResourceLoader) Load(filename string) (FileResources, error) {
return loaded, nil
}

// PostLoad does no additional processing for a KubernetesLoader
func (l KubernetesResourceLoader) PostLoad(r FileResources) ([]assertion.Resource, error) {
return r.Resources, nil
}
1 change: 1 addition & 0 deletions linter/rules_resource_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func (l RulesResourceLoader) Load(filename string) (FileResources, error) {
return loaded, nil
}

// PostLoad does no additional processinfr for a RulesResourceLoader
func (l RulesResourceLoader) PostLoad(r FileResources) ([]assertion.Resource, error) {
return r.Resources, nil
}
36 changes: 30 additions & 6 deletions linter/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package linter

import (
"encoding/json"
"fmt"
"github.com/ghodss/yaml"
"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
Expand Down Expand Up @@ -87,7 +88,7 @@ func loadVariables(data interface{}) []Variable {

func extractDefault(value interface{}) interface{} {
list := value.([]interface{})
var defaultValue interface{} = ""
var defaultValue interface{}
for _, entry := range list {
m := entry.(map[string]interface{})
defaultValue = m["default"]
Expand Down Expand Up @@ -117,15 +118,37 @@ func (l TerraformResourceLoader) Load(filename string) (FileResources, error) {
loaded.Variables = result.Variables
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, result.Resources, "resource")...)
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, result.Data, "data")...)
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, normalizeProviders(result.Providers), "provider")...)
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, addIDToProviders(result.Providers), "provider")...)
return loaded, nil
}

func normalizeProviders(provider []interface{}) []interface{} {
wrappedProvider := map[string]interface{}{
"provider": provider,
// Providers do not have an name, so generate one to make the data format the same as resources

func addIDToProviders(providers []interface{}) []interface{} {
resources := []interface{}{}
for _, provider := range providers {
resources = append(resources, addIDToProvider(provider))
}
return resources
}

func addIDToProvider(provider interface{}) interface{} {
m := provider.(map[string]interface{})
for providerType, value := range m {
m[providerType] = addIDToProviderValue(value)
}
return []interface{}{wrappedProvider}
return m
}

// Counter used to generate an ID for providers
var Counter = 0

func addIDToProviderValue(value interface{}) interface{} {
Counter++
m := map[string]interface{}{}
key := fmt.Sprintf("%d", Counter)
m[key] = value
return []interface{}{m}
}

func getResources(filename string, ast *ast.File, objects []interface{}, category string) []assertion.Resource {
Expand Down Expand Up @@ -154,6 +177,7 @@ func getResources(filename string, ast *ast.File, objects []interface{}, categor
return resources
}

// PostLoad resolves variable expressions
func (l TerraformResourceLoader) PostLoad(fr FileResources) ([]assertion.Resource, error) {
for _, resource := range fr.Resources {
resource.Properties = replaceVariables(resource.Properties, fr.Variables)
Expand Down
5 changes: 2 additions & 3 deletions linter/terraform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ func TestTerraformProvider(t *testing.T) {
if err != nil {
t.Error("Expecting TestTerraformProvider to not return an error:" + err.Error())
}
if len(report.Violations) != 0 {
t.Errorf("TestTerraformProvider returned %d violations, expecting 0", len(report.Violations))
if len(report.Violations) != 1 {
t.Errorf("TestTerraformProvider returned %d violations, expecting 1", len(report.Violations))
t.Errorf("Violations: %v", report.Violations)
}
}
Expand All @@ -201,7 +201,6 @@ func TestTerraformParseError(t *testing.T) {
RuleIDs: []string{},
}
filenames := []string{
"./testdata/resources/terraform_provider.tf",
"./testdata/resources/terraform_syntax_error.tf",
}
linter := FileLinter{Filenames: filenames, ValueSource: TestingValueSource{}, Loader: TerraformResourceLoader{}}
Expand Down
4 changes: 3 additions & 1 deletion linter/testdata/resources/terraform_provider.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
provider "aws" {
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
region = "us-east-1"
}

provider "safe" {
}
14 changes: 12 additions & 2 deletions linter/testdata/rules/terraform_provider.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@ files:
- "*.tf"
rules:

- id: TEST_1
- id: AWS_PROVIDER
message: Testing
resource: provider
resource: aws
category: provider
assertions:
- key: access_key
op: present
- key: secret_key
op: present
- key: region
op: present

- id: SAFE_PROVIDER
message: Testing
resource: safe
category: provider
assertions:
- key: password
op: absent

1 change: 1 addition & 0 deletions linter/yaml_resource_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func (l YAMLResourceLoader) Load(filename string) (FileResources, error) {
return loaded, nil
}

// PostLoad does no additional processing fro a YAMLResourceLoader
func (l YAMLResourceLoader) PostLoad(r FileResources) ([]assertion.Resource, error) {
return r.Resources, nil
}

0 comments on commit 62323d0

Please sign in to comment.