configs: Fix provider requirements panics

When parsing provider requirements we should check the type of the
source and version attributes rather than assuming that they are
strings. Otherwise an invalid attribute value will cause a panic.
This commit is contained in:
Alisdair McDiarmid 2020-06-24 10:09:12 -04:00
parent be510e53bc
commit 9a9f4e2696
2 changed files with 72 additions and 25 deletions

View File

@ -4,6 +4,7 @@ import (
version "github.com/hashicorp/go-version"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/terraform/addrs"
"github.com/zclconf/go-cty/cty"
)
// RequiredProvider represents a declaration of a dependency on a particular
@ -55,7 +56,16 @@ func decodeRequiredProvidersBlock(block *hcl.Block) (*RequiredProviders, hcl.Dia
vc := VersionConstraint{
DeclRange: attr.Range,
}
constraintStr := expr.GetAttr("version").AsString()
constraint := expr.GetAttr("version")
if !constraint.Type().Equals(cty.String) || constraint.IsNull() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid version constraint",
Detail: "Version must be specified as a string.",
Subject: attr.Expr.Range().Ptr(),
})
} else {
constraintStr := constraint.AsString()
constraints, err := version.NewConstraint(constraintStr)
if err != nil {
// NewConstraint doesn't return user-friendly errors, so we'll just
@ -71,8 +81,18 @@ func decodeRequiredProvidersBlock(block *hcl.Block) (*RequiredProviders, hcl.Dia
rp.Requirement = vc
}
}
}
if expr.Type().HasAttribute("source") {
rp.Source = expr.GetAttr("source").AsString()
source := expr.GetAttr("source")
if !source.Type().Equals(cty.String) || source.IsNull() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid source",
Detail: "Source must be specified as a string.",
Subject: attr.Expr.Range().Ptr(),
})
} else {
rp.Source = source.AsString()
fqn, sourceDiags := addrs.ParseProviderSourceString(rp.Source)
@ -92,6 +112,7 @@ func decodeRequiredProvidersBlock(block *hcl.Block) (*RequiredProviders, hcl.Dia
rp.Type = fqn
}
}
}
default:
// should not happen

View File

@ -306,6 +306,32 @@ func TestDecodeRequiredProvidersBlock(t *testing.T) {
},
Error: "Invalid required_providers syntax",
},
"invalid source attribute type": {
Block: &hcl.Block{
Type: "required_providers",
Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcl.Attributes{
"my-test": {
Name: "my-test",
Expr: hcltest.MockExprLiteral(cty.ObjectVal(map[string]cty.Value{
"source": cty.DynamicVal,
})),
},
},
}),
DefRange: blockRange,
},
Want: &RequiredProviders{
RequiredProviders: map[string]*RequiredProvider{
"my-test": {
Name: "my-test",
DeclRange: mockRange,
},
},
DeclRange: blockRange,
},
Error: "Invalid source",
},
}
for name, test := range tests {