mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-23 07:33:32 -06:00
Handle static variable secret flag (#2045)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
parent
8638b815dc
commit
0d1e6cd5f0
@ -1,8 +1,18 @@
|
||||
variable "passphrase" {
|
||||
type = string
|
||||
default = "26281afb-83f1-47ec-9b2d-2aebf6417167"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
locals {
|
||||
key_length = sensitive(32)
|
||||
}
|
||||
|
||||
terraform {
|
||||
encryption {
|
||||
key_provider "pbkdf2" "basic" {
|
||||
passphrase = "26281afb-83f1-47ec-9b2d-2aebf6417167"
|
||||
key_length = 32
|
||||
passphrase = var.passphrase
|
||||
key_length = local.key_length
|
||||
iterations = 200000
|
||||
hash_function = "sha512"
|
||||
salt_length = 12
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/lang"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
@ -62,6 +63,15 @@ func (b *Backend) Hash(schema *configschema.Block) (int, hcl.Diagnostics) {
|
||||
val = cty.UnknownVal(schema.ImpliedType())
|
||||
}
|
||||
|
||||
if marks.Contains(val, marks.Sensitive) {
|
||||
return -1, diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Backend config contains sensitive values",
|
||||
Detail: "The backend configuration is stored in .terraform/terraform.tfstate as well as plan files. It is recommended to instead supply sensitive credentials via backend specific environment variables",
|
||||
Subject: b.DeclRange.Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
toHash := cty.TupleVal([]cty.Value{
|
||||
cty.StringVal(b.Type),
|
||||
val,
|
||||
|
@ -6,11 +6,14 @@
|
||||
package configs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/gohcl"
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/lang"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
@ -90,21 +93,21 @@ func (s StaticEvaluator) Evaluate(expr hcl.Expression, ident StaticIdentifier) (
|
||||
}
|
||||
|
||||
func (s StaticEvaluator) DecodeExpression(expr hcl.Expression, ident StaticIdentifier, val any) hcl.Diagnostics {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
refs, refsDiags := lang.ReferencesInExpr(addrs.ParseRef, expr)
|
||||
diags = append(diags, refsDiags.ToHCL()...)
|
||||
srcVal, diags := s.Evaluate(expr, ident)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
ctx, ctxDiags := s.scope(ident).EvalContext(refs)
|
||||
diags = append(diags, ctxDiags.ToHCL()...)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
if marks.Contains(srcVal, marks.Sensitive) {
|
||||
return diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Sensitive value not allowed",
|
||||
Detail: fmt.Sprintf("Sensitive values, or values derived from sensitive values, cannot be used as %s.", ident.String()),
|
||||
Subject: expr.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
return gohcl.DecodeExpression(expr, ctx, val)
|
||||
return diags.Extend(gohcl.DecodeValue(srcVal, expr.StartRange(), expr.Range(), val))
|
||||
}
|
||||
|
||||
func (s StaticEvaluator) DecodeBlock(body hcl.Body, spec hcldec.Spec, ident StaticIdentifier) (cty.Value, hcl.Diagnostics) {
|
||||
|
@ -321,8 +321,11 @@ func TestStaticEvaluator_DecodeExpression(t *testing.T) {
|
||||
}{{
|
||||
expr: `"static"`,
|
||||
}, {
|
||||
expr: `count`,
|
||||
diags: []string{`eval.tf:1,1-6: Invalid reference; The "count" object cannot be accessed directly. Instead, access one of its attributes.`},
|
||||
expr: `count`,
|
||||
diags: []string{
|
||||
`eval.tf:1,1-6: Invalid reference; The "count" object cannot be accessed directly. Instead, access one of its attributes.`,
|
||||
`:0,0-0: Dynamic value in static context; Unable to use count. in static context, which is required by local.test`,
|
||||
},
|
||||
}, {
|
||||
expr: `module.foo.bar`,
|
||||
diags: []string{`eval.tf:1,1-15: Module output not supported in static context; Unable to use module.foo.bar in static context, which is required by local.test`},
|
||||
@ -372,8 +375,28 @@ terraform {
|
||||
}
|
||||
}`,
|
||||
diags: []string{`eval.tf:4,11-25: Module output not supported in static context; Unable to use module.foo.bar in static context, which is required by backend.badeval`},
|
||||
}, {
|
||||
ident: "sensitive",
|
||||
body: `
|
||||
locals {
|
||||
sens = sensitive("magic")
|
||||
}
|
||||
terraform {
|
||||
backend "sensitive" {
|
||||
thing = local.sens
|
||||
}
|
||||
}`,
|
||||
diags: []string{`eval.tf:6,2-21: Backend config contains sensitive values; The backend configuration is stored in .terraform/terraform.tfstate as well as plan files. It is recommended to instead supply sensitive credentials via backend specific environment variables`},
|
||||
}}
|
||||
|
||||
schema := &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"thing": &configschema.Attribute{
|
||||
Type: cty.String,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.ident, func(t *testing.T) {
|
||||
parser := testParser(map[string]string{"eval.tf": tc.body})
|
||||
@ -383,13 +406,14 @@ terraform {
|
||||
}
|
||||
|
||||
mod, _ := NewModule([]*File{file}, nil, RootModuleCallForTesting(), "dir", SelectiveLoadAll)
|
||||
_, diags := mod.Backend.Decode(&configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"thing": &configschema.Attribute{
|
||||
Type: cty.String,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
_, diags := mod.Backend.Hash(schema)
|
||||
if diags.HasErrors() {
|
||||
assertExactDiagnostics(t, diags, tc.diags)
|
||||
return
|
||||
}
|
||||
|
||||
_, diags = mod.Backend.Decode(schema)
|
||||
|
||||
assertExactDiagnostics(t, diags, tc.diags)
|
||||
})
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/didyoumean"
|
||||
"github.com/opentofu/opentofu/internal/lang"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
@ -256,6 +257,9 @@ func (s staticScopeData) GetInputVariable(ident addrs.InputVariable, rng tfdiags
|
||||
}
|
||||
|
||||
val, valDiags := s.eval.call.vars(variable)
|
||||
if variable.Sensitive {
|
||||
val = val.Mark(marks.Sensitive)
|
||||
}
|
||||
return val, s.enhanceDiagnostics(id, diags.Append(valDiags))
|
||||
}
|
||||
|
||||
|
5
internal/configs/testdata/error-files/module-sensitive.tf
vendored
Normal file
5
internal/configs/testdata/error-files/module-sensitive.tf
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
module "test" {
|
||||
source = sensitive("hostname/namespace/name/system") # ERROR: Sensitive value not allowed
|
||||
version = sensitive("1.0.0") # ERROR: Invalid version constraint
|
||||
}
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
version "github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/convert"
|
||||
)
|
||||
@ -37,6 +38,15 @@ func decodeVersionConstraintValue(attr *hcl.Attribute, val cty.Value) (VersionCo
|
||||
DeclRange: attr.Range,
|
||||
}
|
||||
|
||||
if val.HasMark(marks.Sensitive) {
|
||||
return ret, diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid version constraint",
|
||||
Detail: fmt.Sprintf("Sensitive values, or values derived from sensitive values, cannot be used as %s arguments.", attr.Name),
|
||||
Subject: attr.Expr.Range().Ptr(),
|
||||
})
|
||||
}
|
||||
|
||||
var err error
|
||||
val, err = convert.Convert(val, cty.String)
|
||||
if err != nil {
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/encryption/config"
|
||||
"github.com/opentofu/opentofu/internal/lang"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/gohcl"
|
||||
@ -187,6 +188,14 @@ func (e *targetBuilder) setupKeyProvider(cfg config.KeyProviderConfig, stack []c
|
||||
return diags
|
||||
}
|
||||
|
||||
// gohcl does not handle marks, we need to remove the sensitive marks from any input variables
|
||||
// We assume that the entire configuration in the encryption block should be treated as sensitive
|
||||
for key, sv := range evalCtx.Variables {
|
||||
if marks.Contains(sv, marks.Sensitive) {
|
||||
evalCtx.Variables[key], _ = sv.UnmarkDeep()
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the Key Provider
|
||||
decodeDiags := gohcl.DecodeBody(cfg.Body, evalCtx, keyProviderConfig)
|
||||
diags = append(diags, decodeDiags...)
|
||||
|
Loading…
Reference in New Issue
Block a user