diff --git a/lang/funcs/filesystem.go b/lang/funcs/filesystem.go index 4b899cbc4..eb4921de1 100644 --- a/lang/funcs/filesystem.go +++ b/lang/funcs/filesystem.go @@ -100,6 +100,20 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Fun Variables: varsVal.AsValueMap(), } + // We require all of the variables to be valid HCL identifiers, because + // otherwise there would be no way to refer to them in the template + // anyway. Rejecting this here gives better feedback to the user + // than a syntax error somewhere in the template itself. + for n := range ctx.Variables { + if !hclsyntax.ValidIdentifier(n) { + // This error message intentionally doesn't describe _all_ of + // the different permutations that are technically valid as an + // HCL identifier, but rather focuses on what we might + // consider to be an "idiomatic" variable name. + return cty.DynamicVal, function.NewArgErrorf(1, "invalid template variable name %q: must start with a letter, followed by zero or more letters, digits, and underscores", n) + } + } + // We'll pre-check references in the template here so we can give a // more specialized error message than HCL would by default, so it's // clearer that this problem is coming from a templatefile call. diff --git a/lang/funcs/filesystem_test.go b/lang/funcs/filesystem_test.go index 341e616cf..12e58523e 100644 --- a/lang/funcs/filesystem_test.go +++ b/lang/funcs/filesystem_test.go @@ -86,6 +86,14 @@ func TestTemplateFile(t *testing.T) { cty.StringVal("Hello, Jodie!"), ``, }, + { + cty.StringVal("testdata/hello.tmpl"), + cty.MapVal(map[string]cty.Value{ + "name!": cty.StringVal("Jodie"), + }), + cty.NilVal, + `invalid template variable name "name!": must start with a letter, followed by zero or more letters, digits, and underscores`, + }, { cty.StringVal("testdata/hello.tmpl"), cty.ObjectVal(map[string]cty.Value{ diff --git a/website/docs/configuration/functions/templatefile.html.md b/website/docs/configuration/functions/templatefile.html.md index 77cf80df8..55756bed9 100644 --- a/website/docs/configuration/functions/templatefile.html.md +++ b/website/docs/configuration/functions/templatefile.html.md @@ -29,7 +29,9 @@ into a separate file for readability. The "vars" argument must be a map. Within the template file, each of the keys in the map is available as a variable for interpolation. The template may also use any other function available in the Terraform language, except that -recursive calls to `templatefile` are not permitted. +recursive calls to `templatefile` are not permitted. Variable names must +each start with a letter, followed by zero or more letters, digits, or +underscores. Strings in the Terraform language are sequences of Unicode characters, so this function will interpret the file contents as UTF-8 encoded text and