diff --git a/pkg/scanners/terraform/parser/evaluator.go b/pkg/scanners/terraform/parser/evaluator.go index c425f7ea7..f49b3be0e 100644 --- a/pkg/scanners/terraform/parser/evaluator.go +++ b/pkg/scanners/terraform/parser/evaluator.go @@ -347,7 +347,7 @@ func (e *evaluator) evaluateVariable(b *terraform.Block) (cty.Value, error) { return cty.NilVal, fmt.Errorf("cannot resolve variable with no attributes") } if def, exists := attributes["default"]; exists { - return def.Value(), nil + return def.NullableValue(), nil } return cty.NilVal, fmt.Errorf("no value found") } diff --git a/pkg/scanners/terraform/parser/parser_test.go b/pkg/scanners/terraform/parser/parser_test.go index 23f05079a..1b623a66c 100644 --- a/pkg/scanners/terraform/parser/parser_test.go +++ b/pkg/scanners/terraform/parser/parser_test.go @@ -633,3 +633,36 @@ module "registry" { require.NoError(t, err) require.Len(t, modules, 2) } + +func Test_NullDefaultValueForVar(t *testing.T) { + fs := testutil.CreateFS(t, map[string]string{ + "test.tf": ` +variable "bucket_name" { + type = string + default = null +} + +resource "aws_s3_bucket" "default" { + bucket = var.bucket_name != null ? var.bucket_name : "default" +} +`, + }) + + parser := New(fs, "", OptionStopOnHCLError(true)) + if err := parser.ParseFS(context.TODO(), "."); err != nil { + t.Fatal(err) + } + modules, _, err := parser.EvaluateAll(context.TODO()) + require.NoError(t, err) + require.Len(t, modules, 1) + + rootModule := modules[0] + + blocks := rootModule.GetResourcesByType("aws_s3_bucket") + require.Len(t, blocks, 1) + block := blocks[0] + + attr := block.GetAttribute("bucket") + require.NotNil(t, attr) + assert.Equal(t, "default", attr.Value().AsString()) +} diff --git a/pkg/terraform/attribute.go b/pkg/terraform/attribute.go index f967914bb..a1b27bfa6 100644 --- a/pkg/terraform/attribute.go +++ b/pkg/terraform/attribute.go @@ -253,6 +253,23 @@ func (a *Attribute) Value() (ctyVal cty.Value) { return ctyVal } +// Allows a null value for a variable https://developer.hashicorp.com/terraform/language/expressions/types#null +func (a *Attribute) NullableValue() (ctyVal cty.Value) { + if a == nil { + return cty.NilVal + } + defer func() { + if err := recover(); err != nil { + ctyVal = cty.NilVal + } + }() + ctyVal, _ = a.hclAttribute.Expr.Value(a.ctx.Inner()) + if !ctyVal.IsKnown() { + return cty.NilVal + } + return ctyVal +} + func (a *Attribute) Name() string { if a == nil { return ""