From 611558e4ce61818330118684274534f26b1fda99 Mon Sep 17 00:00:00 2001 From: Alberto Donato Date: Fri, 8 Nov 2024 08:32:54 +0100 Subject: [PATCH] fix(terraform): set null value as fallback for missing variables (#7669) --- pkg/iac/scanners/terraform/parser/parser.go | 9 ++++++ .../scanners/terraform/parser/parser_test.go | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/pkg/iac/scanners/terraform/parser/parser.go b/pkg/iac/scanners/terraform/parser/parser.go index 695cbee4fb25..866835d5f8a5 100644 --- a/pkg/iac/scanners/terraform/parser/parser.go +++ b/pkg/iac/scanners/terraform/parser/parser.go @@ -217,6 +217,7 @@ func (p *Parser) Load(ctx context.Context) (*evaluator, error) { "Variable values was not found in the environment or variable files. Evaluating may not work correctly.", log.String("variables", strings.Join(missingVars, ", ")), ) + setNullMissingVariableValues(inputVars, missingVars) } } @@ -268,6 +269,14 @@ func missingVariableValues(blocks terraform.Blocks, inputVars map[string]cty.Val return missing } +// Set null values for missing variables, to allow expressions using them to be +// still be possibly evaluated to a value different than null. +func setNullMissingVariableValues(inputVars map[string]cty.Value, missingVars []string) { + for _, missingVar := range missingVars { + inputVars[missingVar] = cty.NullVal(cty.DynamicPseudoType) + } +} + func (p *Parser) EvaluateAll(ctx context.Context) (terraform.Modules, cty.Value, error) { e, err := p.Load(ctx) diff --git a/pkg/iac/scanners/terraform/parser/parser_test.go b/pkg/iac/scanners/terraform/parser/parser_test.go index 540338afb57f..9c62b958a212 100644 --- a/pkg/iac/scanners/terraform/parser/parser_test.go +++ b/pkg/iac/scanners/terraform/parser/parser_test.go @@ -1801,6 +1801,36 @@ resource "test" "fileset-func" { assert.Equal(t, []string{"a.py", "path/b.py"}, attr.GetRawValue()) } +func TestExprWithMissingVar(t *testing.T) { + files := map[string]string{ + "main.tf": ` +variable "v" { + type = string +} + +resource "test" "values" { + s = "foo-${var.v}" + l1 = ["foo", var.v] + l2 = concat(["foo"], [var.v]) + d1 = {foo = var.v} + d2 = merge({"foo": "bar"}, {"baz": var.v}) +} +`, + } + + resources := parse(t, files).GetResourcesByType("test") + require.Len(t, resources, 1) + + s_attr := resources[0].GetAttribute("s") + require.NotNil(t, s_attr) + assert.Equal(t, "foo-", s_attr.GetRawValue()) + + for _, name := range []string{"l1", "l2", "d1", "d2"} { + attr := resources[0].GetAttribute(name) + require.NotNil(t, attr) + } +} + func TestVarTypeShortcut(t *testing.T) { files := map[string]string{ "main.tf": `