Skip to content

Commit

Permalink
Add custom map value function (#847)
Browse files Browse the repository at this point in the history
- support passing a function into the mapvalue of Contains function
  • Loading branch information
owenrumney authored Jul 9, 2021
1 parent ac78d78 commit 715c2d4
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 3 deletions.
9 changes: 9 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
{
"version": "0.2.0",
"configurations": [

{
"name": "Basic tfsec",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/tfsec/main.go",
"args": ["${workspaceFolder}/example"]
},
{
"name": "custom_functions test",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/tfsec/main.go",
"args": ["${workspaceFolder}/example/custom_functions"]
}
]
}
22 changes: 22 additions & 0 deletions example/custom_functions/.tfsec/functions_tfchecks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
checks:
- code: TAG_custom
description: Custom check to ensure the Environment tag is applied
errorMessage: The required Environment tag was missing or invalid
matchSpec:
action: contains
name: tags
value:
Environment:
action: isAny
value:
- production
- test
- dev
- staging

requiredTypes:
- resource
severity: ERROR
requiredLabels:
- aws_lb
6 changes: 6 additions & 0 deletions example/custom_functions/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resource "aws_lb" "test_lb" {

tags = {
Environment = "uat"
}
}
4 changes: 1 addition & 3 deletions internal/app/tfsec/block/hclattribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,11 @@ func (attr *HCLAttribute) listContains(val cty.Value, stringToLookFor string, ig
func (attr *HCLAttribute) mapContains(checkValue interface{}, val cty.Value) bool {
switch t := checkValue.(type) {
case map[interface{}]interface{}:

for k, v := range t {

valueMap := val.AsValueMap()
for key, value := range valueMap {
rawValue := getRawValue(value)
if key == k && rawValue == v {
if key == k && evaluate(v, rawValue) {
return true
}
}
Expand Down
42 changes: 42 additions & 0 deletions internal/app/tfsec/block/value_functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package block

const (
functionNameKey = "action"
valueNameKey = "value"
)

var functions = map[string]func(interface{}, interface{}) bool{
"isAny": isAny,
"isNone": isNone,
}

func evaluate(criteriaValue interface{}, testValue interface{}) bool {
switch t := criteriaValue.(type) {
case map[interface{}]interface{}:
if t[functionNameKey] != nil {
functionName := t[functionNameKey].(string)
if functions[functionName] != nil {
return functions[functionName](t[valueNameKey], testValue)
}
}
default:
return t == testValue
}
return false
}

func isAny(criteriaValues interface{}, testValue interface{}) bool {
switch t := criteriaValues.(type) {
case []interface{}:
for _, v := range t {
if v == testValue {
return true
}
}
}
return false
}

func isNone(criteriaValues interface{}, testValue interface{}) bool {
return !isAny(criteriaValues, testValue)
}

0 comments on commit 715c2d4

Please sign in to comment.