terraform: Unmark provisioner arguments
If provisioner configuration or connection info includes sensitive values, we need to unmark them before calling the provisioner. Failing to do so causes serialization to error. Unlike resources, we do not need to capture marked paths here, so we just discard the marks.
This commit is contained in:
parent
31033001a8
commit
9c580335e3
|
@ -12052,3 +12052,58 @@ output "out" {
|
||||||
t.Fatalf("wrong result\ngot: %#v\nwant: %#v", got, want)
|
t.Fatalf("wrong result\ngot: %#v\nwant: %#v", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContext2Apply_provisionerSensitive(t *testing.T) {
|
||||||
|
m := testModule(t, "apply-provisioner-sensitive")
|
||||||
|
p := testProvider("aws")
|
||||||
|
pr := testProvisioner()
|
||||||
|
pr.ProvisionResourceFn = func(req provisioners.ProvisionResourceRequest) (resp provisioners.ProvisionResourceResponse) {
|
||||||
|
if req.Config.ContainsMarked() {
|
||||||
|
t.Fatalf("unexpectedly marked config value: %#v", req.Config)
|
||||||
|
}
|
||||||
|
command := req.Config.GetAttr("command")
|
||||||
|
if command.IsMarked() {
|
||||||
|
t.Fatalf("unexpectedly marked command argument: %#v", command.Marks())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.ApplyResourceChangeFn = testApplyFn
|
||||||
|
p.PlanResourceChangeFn = testDiffFn
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Config: m,
|
||||||
|
Providers: map[addrs.Provider]providers.Factory{
|
||||||
|
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
Provisioners: map[string]ProvisionerFactory{
|
||||||
|
"shell": testProvisionerFuncFixed(pr),
|
||||||
|
},
|
||||||
|
Variables: InputValues{
|
||||||
|
"password": &InputValue{
|
||||||
|
Value: cty.StringVal("secret"),
|
||||||
|
SourceType: ValueFromCaller,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if _, diags := ctx.Plan(); diags.HasErrors() {
|
||||||
|
logDiagnostics(t, diags)
|
||||||
|
t.Fatal("plan failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
state, diags := ctx.Apply()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
logDiagnostics(t, diags)
|
||||||
|
t.Fatal("apply failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(state.String())
|
||||||
|
expected := strings.TrimSpace(testTerraformApplyProvisionerSensitiveStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify apply was invoked
|
||||||
|
if !pr.ProvisionResourceCalled {
|
||||||
|
t.Fatalf("provisioner was not called on apply")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -683,10 +683,17 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If our config or connection info contains any marked values, ensure
|
||||||
|
// those are stripped out before sending to the provisioner. Unlike
|
||||||
|
// resources, we have no need to capture the marked paths and reapply
|
||||||
|
// later.
|
||||||
|
unmarkedConfig, _ := config.UnmarkDeep()
|
||||||
|
unmarkedConnInfo, _ := connInfo.UnmarkDeep()
|
||||||
|
|
||||||
output := CallbackUIOutput{OutputFn: outputFn}
|
output := CallbackUIOutput{OutputFn: outputFn}
|
||||||
resp := provisioner.ProvisionResource(provisioners.ProvisionResourceRequest{
|
resp := provisioner.ProvisionResource(provisioners.ProvisionResourceRequest{
|
||||||
Config: config,
|
Config: unmarkedConfig,
|
||||||
Connection: connInfo,
|
Connection: unmarkedConnInfo,
|
||||||
UIOutput: &output,
|
UIOutput: &output,
|
||||||
})
|
})
|
||||||
applyDiags := resp.Diagnostics.InConfigBody(prov.Config)
|
applyDiags := resp.Diagnostics.InConfigBody(prov.Config)
|
||||||
|
|
|
@ -866,6 +866,13 @@ aws_instance.bar:
|
||||||
type = aws_instance
|
type = aws_instance
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testTerraformApplyProvisionerSensitiveStr = `
|
||||||
|
aws_instance.foo:
|
||||||
|
ID = foo
|
||||||
|
provider = provider["registry.terraform.io/hashicorp/aws"]
|
||||||
|
type = aws_instance
|
||||||
|
`
|
||||||
|
|
||||||
const testTerraformApplyDestroyStr = `
|
const testTerraformApplyDestroyStr = `
|
||||||
<no state>
|
<no state>
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
variable "password" {
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "foo" {
|
||||||
|
connection {
|
||||||
|
host = "localhost"
|
||||||
|
type = "telnet"
|
||||||
|
user = "superuser"
|
||||||
|
port = 2222
|
||||||
|
password = var.password
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "shell" {
|
||||||
|
command = "echo ${var.password} > secrets"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue