66 "io"
77 "io/fs"
88 "log"
9+ "reflect"
910 "strings"
1011
1112 "github.com/aquasecurity/trivy/pkg/iac/scanners/terraformplan/tfjson/parser"
@@ -45,11 +46,11 @@ func PlanJSONHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks t
4546 continue
4647 }
4748
48- if parts [0 ] == "data" && ! strings .Contains (resource . Type , "coder" ) {
49+ if parts [0 ] != "data" || strings .Contains (parts [ 1 ] , "coder" ) {
4950 continue
5051 }
5152
52- val , err := attributeCtyVal (resource .AttributeValues )
53+ val , err := toCtyValue (resource .AttributeValues )
5354 if err != nil {
5455 // TODO: Remove log
5556 log .Printf ("unable to determine value of resource %q: %v" , resource .Address , err )
@@ -62,21 +63,49 @@ func PlanJSONHook(dfs fs.FS, input Input) (func(ctx *tfcontext.Context, blocks t
6263 }, nil
6364}
6465
65- func attributeCtyVal (attr map [string ]interface {}) (cty.Value , error ) {
66- mv := make (map [string ]cty.Value )
67- for k , v := range attr {
68- ty , err := gocty .ImpliedType (v )
66+ func toCtyValue (a any ) (cty.Value , error ) {
67+ if a == nil {
68+ return cty .NilVal , nil
69+ }
70+ av := reflect .ValueOf (a )
71+ switch av .Type ().Kind () {
72+ case reflect .Slice , reflect .Array :
73+ sv := make ([]cty.Value , 0 , av .Len ())
74+ for i := 0 ; i < av .Len (); i ++ {
75+ v , err := toCtyValue (av .Index (i ).Interface ())
76+ if err != nil {
77+ return cty .NilVal , fmt .Errorf ("slice value %d: %w" , i , err )
78+ }
79+ sv = append (sv , v )
80+ }
81+ return cty .ListVal (sv ), nil
82+ case reflect .Map :
83+ if av .Type ().Key ().Kind () != reflect .String {
84+ return cty .NilVal , fmt .Errorf ("map keys must be string, found %q" , av .Type ().Key ().Kind ())
85+ }
86+
87+ mv := make (map [string ]cty.Value )
88+ var err error
89+ for _ , k := range av .MapKeys () {
90+ v := av .MapIndex (k )
91+ mv [k .String ()], err = toCtyValue (v .Interface ())
92+ if err != nil {
93+ return cty .NilVal , fmt .Errorf ("map value %q: %w" , k .String (), err )
94+ }
95+ }
96+ return cty .ObjectVal (mv ), nil
97+ default :
98+ ty , err := gocty .ImpliedType (a )
6999 if err != nil {
70- return cty .NilVal , fmt .Errorf ("implied type for %q : %w" , k , err )
100+ return cty .NilVal , fmt .Errorf ("implied type: %w" , err )
71101 }
72102
73- mv [ k ] , err = gocty .ToCtyValue (v , ty )
103+ cv , err : = gocty .ToCtyValue (a , ty )
74104 if err != nil {
75- return cty .NilVal , fmt .Errorf ("implied value for %q : %w" , k , err )
105+ return cty .NilVal , fmt .Errorf ("implied value: %w" , err )
76106 }
107+ return cv , nil
77108 }
78-
79- return cty .ObjectVal (mv ), nil
80109}
81110
82111// ParsePlanJSON can parse the JSON output of a Terraform plan.
0 commit comments