Skip to content
This repository has been archived by the owner on Jan 23, 2025. It is now read-only.

feat(terraform): Support tfvars files during scans #1294

Merged
merged 1 commit into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/detection/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func init() {

matchers[FileTypeTerraform] = func(name string, _ io.ReadSeeker) bool {
ext := filepath.Ext(filepath.Base(name))
return strings.EqualFold(ext, ".tf") || strings.EqualFold(ext, ".tf.json")
return strings.EqualFold(ext, ".tf") || strings.EqualFold(ext, ".tf.json") || strings.EqualFold(ext, ".tfvars")
}

matchers[FileTypeTerraformPlan] = func(name string, r io.ReadSeeker) bool {
Expand Down
32 changes: 4 additions & 28 deletions pkg/scanners/terraform/parser/load_vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io/fs"
"os"
"path/filepath"
"runtime"
"strings"

"github.com/hashicorp/hcl/v2"
Expand All @@ -14,23 +13,6 @@ import (
"github.com/zclconf/go-cty/cty"
)

func getAbsPath(inputPath string) (string, error) {
p, err := filepath.Abs(inputPath)
if err != nil {
return "", fmt.Errorf("unable to determine path: %w", err)
}
switch runtime.GOOS {
case "windows":
if volume := filepath.VolumeName(p); volume != "" {
p = strings.TrimPrefix(filepath.ToSlash(p), volume+"/")
return filepath.FromSlash(p), nil
}
return strings.TrimPrefix(filepath.Clean(p), fmt.Sprintf("%c", os.PathSeparator)), nil
default:
return strings.TrimPrefix(filepath.Clean(p), fmt.Sprintf("%c", os.PathSeparator)), nil
}
}

func loadTFVars(srcFS fs.FS, filenames []string) (map[string]cty.Value, error) {
combinedVars := make(map[string]cty.Value)

Expand Down Expand Up @@ -67,20 +49,14 @@ func loadTFVarsFile(srcFS fs.FS, filename string) (map[string]cty.Value, error)
return inputVars, nil
}

absPath, err := getAbsPath(filename)
if err != nil {
return nil, err
}
absPath = filepath.ToSlash(absPath) // in memory fs is only slash based

src, err := fs.ReadFile(srcFS, absPath)
src, err := fs.ReadFile(srcFS, filepath.ToSlash(filename))
if err != nil {
return nil, err
}

var attrs hcl.Attributes
if strings.HasSuffix(absPath, ".json") {
variableFile, err := hcljson.Parse(src, absPath)
if strings.HasSuffix(filename, ".json") {
variableFile, err := hcljson.Parse(src, filename)
if err != nil {
return nil, err
}
Expand All @@ -89,7 +65,7 @@ func loadTFVarsFile(srcFS fs.FS, filename string) (map[string]cty.Value, error)
return nil, err
}
} else {
variableFile, err := hclsyntax.ParseConfig(src, absPath, hcl.Pos{Line: 1, Column: 1})
variableFile, err := hclsyntax.ParseConfig(src, filename, hcl.Pos{Line: 1, Column: 1})
if err != nil {
return nil, err
}
Expand Down
24 changes: 21 additions & 3 deletions pkg/scanners/terraform/parser/load_vars_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,40 @@ package parser
import (
"testing"

"github.com/aquasecurity/defsec/test/testutil"

"github.com/zclconf/go-cty/cty"

"github.com/aquasecurity/defsec/pkg/extrafs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_TFVarsFile(t *testing.T) {
t.Run("tfvars file", func(t *testing.T) {
vars, err := loadTFVars(extrafs.OSDir("/"), []string{"testdata/tfvars/terraform.tfvars"})
fs := testutil.CreateFS(t, map[string]string{
"test.tfvars": `instance_type = "t2.large"`,
})

vars, err := loadTFVars(fs, []string{"test.tfvars"})
require.NoError(t, err)
assert.Equal(t, "t2.large", vars["instance_type"].AsString())
})

t.Run("tfvars json file", func(t *testing.T) {
vars, err := loadTFVars(extrafs.OSDir("/"), []string{"testdata/tfvars/terraform.tfvars.json"})
fs := testutil.CreateFS(t, map[string]string{
"test.tfvars.json": `{
"variable": {
"foo": {
"default": "bar"
},
"baz": "qux"
},
"foo2": true,
"foo3": 3
}`,
})

vars, err := loadTFVars(fs, []string{"test.tfvars.json"})
require.NoError(t, err)
assert.Equal(t, "bar", vars["variable"].GetAttr("foo").GetAttr("default").AsString())
assert.Equal(t, "qux", vars["variable"].GetAttr("baz").AsString())
Expand Down