Skip to content
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
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
[![godoc](https://pkg.go.dev/badge/github.com/coder/preview.svg)](https://pkg.go.dev/github.com/coder/preview)
[![Go Report Card](https://goreportcard.com/badge/github.com/coder/preview)](https://goreportcard.com/report/github.com/coder/preview)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9511/badge)](https://www.bestpractices.dev/projects/9511)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/coder/preview/badge)](https://scorecard.dev/viewer/?uri=github.com%2Fcoder%2Fpreview)
[![license](https://img.shields.io/github/license/coder/preview)](./LICENSE)

</div>
Expand Down
2 changes: 1 addition & 1 deletion owner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"golang.org/x/xerrors"
)

func WorkspaceOwnerHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) {
func workspaceOwnerHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) {
if input.Owner.Groups == nil {
input.Owner.Groups = []string{}
}
Expand Down
2 changes: 1 addition & 1 deletion parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/coder/preview/types"
)

func RichParameters(modules terraform.Modules) ([]types.Parameter, hcl.Diagnostics) {
func parameters(modules terraform.Modules) ([]types.Parameter, hcl.Diagnostics) {
diags := make(hcl.Diagnostics, 0)
params := make([]types.Parameter, 0)
exists := make(map[string][]types.Parameter)
Expand Down
4 changes: 2 additions & 2 deletions paramhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"github.com/coder/preview/hclext"
)

// ParameterContextsEvalHook is called in a loop, so if parameters affect
// parameterContextsEvalHook is called in a loop, so if parameters affect
// other parameters, this can solve the problem 1 "evaluation" at a time.
//
// Omitting to set a default value is OK, as long as at least 1 parameter
// is resolvable. The resolvable parameter will be accessible on the next
// iteration.
func ParameterContextsEvalHook(input Input) func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) {
func parameterContextsEvalHook(input Input) func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) {
return func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value) {
data := blocks.OfType("data")
for _, block := range data {
Expand Down
22 changes: 4 additions & 18 deletions plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"slices"
"strings"

"github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson/parser"
"github.com/aquasecurity/trivy/pkg/iac/terraform"
tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context"
tfjson "github.com/hashicorp/terraform-json"
Expand All @@ -20,7 +19,7 @@ import (
"github.com/coder/preview/hclext"
)

func PlanJSONHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) {
func planJSONHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks terraform.Blocks, inputVars map[string]cty.Value), error) {
var contents io.Reader = bytes.NewReader(input.PlanJSON)
// Also accept `{}` as an empty plan. If this is stored in postgres or another json
// type, then `{}` is the "empty" value.
Expand All @@ -36,7 +35,7 @@ func PlanJSONHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks t
}
}

plan, err := ParsePlanJSON(contents)
plan, err := parsePlanJSON(contents)
if err != nil {
return nil, fmt.Errorf("unable to parse plan JSON: %w", err)
}
Expand Down Expand Up @@ -216,28 +215,15 @@ func toCtyValue(a any) (cty.Value, error) {
}
}

// ParsePlanJSON can parse the JSON output of a Terraform plan.
// parsePlanJSON can parse the JSON output of a Terraform plan.
// terraform plan out.plan
// terraform show -json out.plan
func ParsePlanJSON(reader io.Reader) (*tfjson.Plan, error) {
func parsePlanJSON(reader io.Reader) (*tfjson.Plan, error) {
plan := new(tfjson.Plan)
plan.FormatVersion = tfjson.PlanFormatVersionConstraints
return plan, json.NewDecoder(reader).Decode(plan)
}

// ParsePlanJSON can parse the JSON output of a Terraform plan.
// terraform plan out.plan
// terraform show -json out.plan
func TrivyParsePlanJSON(reader io.Reader) (*tfjson.Plan, error) {
p := parser.New()
plan, err := p.Parse(reader)
var _ = plan

plan.ToFS()

return nil, err
}

func keyMatcher(key cty.Value) func(to any) bool {
switch {
case key.Type().Equals(cty.Number):
Expand Down
49 changes: 35 additions & 14 deletions preview.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ import (
"encoding/json"
"fmt"
"io/fs"
"log/slog"
"os"
"path/filepath"

"github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"

Expand All @@ -28,16 +25,40 @@ type Input struct {
}

type Output struct {
ModuleOutput cty.Value
// ModuleOutput is any 'output' values from the terraform files. This has 0
// effect on the parameters, tags, etc. It can be helpful for debugging, as it
// allows exporting some terraform values to the caller to review.
ModuleOutput cty.Value

Parameters []types.Parameter
WorkspaceTags types.TagBlocks
Files map[string]*hcl.File
// Files is included for printing diagnostics.
// TODO: Is the memory impact of this too much? Should we render diagnostic source code
// into the diagnostics up front? and remove this?
Files map[string]*hcl.File
}

func Preview(ctx context.Context, input Input, dir fs.FS) (*Output, hcl.Diagnostics) {
// TODO: FIX LOGGING
slog.SetLogLoggerLevel(slog.LevelDebug)
slog.SetDefault(slog.New(log.NewHandler(os.Stderr, nil)))
func Preview(ctx context.Context, input Input, dir fs.FS) (output *Output, diagnostics hcl.Diagnostics) {
// The trivy package works with `github.com/zclconf/go-cty`. This package is
// similar to `reflect` in its usage. This package can panic if types are
// misused. To protect the caller, a general `recover` is used to catch any
// mistakes. If this happens, there is a developer bug that needs to be resolved.
defer func() {
if r := recover(); r != nil {
diagnostics = hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "Panic occurred in preview. This should not happen, please report this to Coder.",
Detail: fmt.Sprintf("panic in preview: %+v", r),
},
}
}
}()

// TODO: Fix logging. There is no way to pass in an instanced logger to
// the parser.
//slog.SetLogLoggerLevel(slog.LevelDebug)
//slog.SetDefault(slog.New(log.NewHandler(os.Stderr, nil)))

varFiles, err := tfVarFiles("", dir)
if err != nil {
Expand All @@ -50,7 +71,7 @@ func Preview(ctx context.Context, input Input, dir fs.FS) (*Output, hcl.Diagnost
}
}

planHook, err := PlanJSONHook(dir, input)
planHook, err := planJSONHook(dir, input)
if err != nil {
return nil, hcl.Diagnostics{
{
Expand All @@ -61,7 +82,7 @@ func Preview(ctx context.Context, input Input, dir fs.FS) (*Output, hcl.Diagnost
}
}

ownerHook, err := WorkspaceOwnerHook(dir, input)
ownerHook, err := workspaceOwnerHook(dir, input)
if err != nil {
return nil, hcl.Diagnostics{
{
Expand All @@ -81,7 +102,7 @@ func Preview(ctx context.Context, input Input, dir fs.FS) (*Output, hcl.Diagnost
parser.OptionWithTFVarsPaths(varFiles...),
parser.OptionWithEvalHook(planHook),
parser.OptionWithEvalHook(ownerHook),
parser.OptionWithEvalHook(ParameterContextsEvalHook(input)),
parser.OptionWithEvalHook(parameterContextsEvalHook(input)),
)

err = p.ParseFS(ctx, ".")
Expand All @@ -107,8 +128,8 @@ func Preview(ctx context.Context, input Input, dir fs.FS) (*Output, hcl.Diagnost
}

diags := make(hcl.Diagnostics, 0)
rp, rpDiags := RichParameters(modules)
tags, tagDiags := WorkspaceTags(modules, p.Files())
rp, rpDiags := parameters(modules)
tags, tagDiags := workspaceTags(modules, p.Files())

// Add warnings
diags = diags.Extend(warnings(modules))
Expand Down
10 changes: 5 additions & 5 deletions workspacetags.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/coder/preview/types"
)

func WorkspaceTags(modules terraform.Modules, files map[string]*hcl.File) (types.TagBlocks, hcl.Diagnostics) {
func workspaceTags(modules terraform.Modules, files map[string]*hcl.File) (types.TagBlocks, hcl.Diagnostics) {
diags := make(hcl.Diagnostics, 0)
tagBlocks := make(types.TagBlocks, 0)

Expand Down Expand Up @@ -65,7 +65,7 @@ func WorkspaceTags(modules terraform.Modules, files map[string]*hcl.File) (types
var tags []types.Tag
tagsValue.ForEachElement(func(key cty.Value, val cty.Value) (stop bool) {
r := tagsAttr.HCLAttribute().Expr.Range()
tag, tagDiag := NewTag(&r, files, key, val)
tag, tagDiag := newTag(&r, files, key, val)
if tagDiag != nil {
diags = diags.Append(tagDiag)
return false
Expand All @@ -76,7 +76,7 @@ func WorkspaceTags(modules terraform.Modules, files map[string]*hcl.File) (types
return false
})
//for _, item := range tagsObj.Items {
// tag, tagDiag := NewTag(tagsObj, files, item, evCtx)
// tag, tagDiag := newTag(tagsObj, files, item, evCtx)
// if tagDiag != nil {
// diags = diags.Append(tagDiag)
// continue
Expand All @@ -94,8 +94,8 @@ func WorkspaceTags(modules terraform.Modules, files map[string]*hcl.File) (types
return tagBlocks, diags
}

// NewTag creates a workspace tag from its hcl expression.
func NewTag(srcRange *hcl.Range, files map[string]*hcl.File, key, val cty.Value) (types.Tag, *hcl.Diagnostic) {
// newTag creates a workspace tag from its hcl expression.
func newTag(srcRange *hcl.Range, files map[string]*hcl.File, key, val cty.Value) (types.Tag, *hcl.Diagnostic) {
//key, kdiags := expr.KeyExpr.Value(evCtx)
//val, vdiags := expr.ValueExpr.Value(evCtx)

Expand Down
Loading