Skip to content

Commit

Permalink
Send marked values over the wire
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 committed Mar 19, 2023
1 parent 7b23e20 commit 18f94f9
Show file tree
Hide file tree
Showing 9 changed files with 1,039 additions and 500 deletions.
42 changes: 40 additions & 2 deletions plugin/fromproto/fromproto.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/plugin/proto"
"github.com/terraform-linters/tflint-plugin-sdk/terraform/lang/marks"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/msgpack"
Expand Down Expand Up @@ -161,7 +162,7 @@ func Expression(expr *proto.Expression) (hcl.Expression, hcl.Diagnostics) {
return nil, diags
}
if expr.Value != nil {
val, err := msgpack.Unmarshal(expr.Value, cty.DynamicPseudoType)
val, err := Value(expr.Value, cty.DynamicPseudoType, expr.ValueMarks)
if err != nil {
panic(fmt.Errorf("cannot unmarshal the bound expr: %w", err))
}
Expand Down Expand Up @@ -210,6 +211,43 @@ func Pos(pos *proto.Range_Pos) hcl.Pos {
}
}

// Value converts msgpack and []proto.ValueMark to cty.Value
func Value(value []byte, ty cty.Type, valueMarks []*proto.ValueMark) (cty.Value, error) {
val, err := msgpack.Unmarshal(value, ty)
if err != nil {
return cty.NilVal, err
}

pvm := make([]cty.PathValueMarks, len(valueMarks))
for idx, mark := range valueMarks {
pvm[idx] = cty.PathValueMarks{
Path: AttributePath(mark.Path),
}
if mark.Sensitive {
pvm[idx].Marks = cty.NewValueMarks(marks.Sensitive)
}
}

return val.MarkWithPaths(pvm), nil
}

// AttributePath converts proto.AttributePath to cty.Path
func AttributePath(path *proto.AttributePath) cty.Path {
ret := cty.Path{}

for _, step := range path.Steps {
switch s := step.Selector.(type) {
case *proto.AttributePath_Step_ElementKeyString:
ret = ret.IndexString(s.ElementKeyString)
case *proto.AttributePath_Step_ElementKeyInt:
ret = ret.IndexInt(int(s.ElementKeyInt))
case *proto.AttributePath_Step_AttributeName:
ret = ret.GetAttr(s.AttributeName)
}
}
return ret
}

// Config converts proto.ApplyGlobalConfig_Config to tflint.Config
func Config(config *proto.ApplyGlobalConfig_Config) *tflint.Config {
if config == nil {
Expand Down Expand Up @@ -313,7 +351,7 @@ func Error(err error) error {
case proto.ErrorCode_ERROR_CODE_UNEVALUABLE:
return fmt.Errorf("%s%w", st.Message(), tflint.ErrUnevaluable)
case proto.ErrorCode_ERROR_CODE_SENSITIVE:
return fmt.Errorf("%s%w", st.Message(), tflint.ErrSensitive)
return tflint.ErrSensitive
}
}

Expand Down
9 changes: 6 additions & 3 deletions plugin/plugin2host/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
"github.com/zclconf/go-cty/cty/json"
"github.com/zclconf/go-cty/cty/msgpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand Down Expand Up @@ -327,7 +326,7 @@ func (c *GRPCClient) EvaluateExpr(expr hcl.Expression, ret interface{}, opts *tf
return fromproto.Error(err)
}

val, err := msgpack.Unmarshal(resp.Value, ty)
val, err := fromproto.Value(resp.Value, ty, resp.Marks)
if err != nil {
return err
}
Expand All @@ -336,7 +335,7 @@ func (c *GRPCClient) EvaluateExpr(expr hcl.Expression, ret interface{}, opts *tf
return gocty.FromCtyValue(val, ret)
}

// Returns an error if the value cannot be decoded to a Go value (e.g. unknown value, null).
// Returns an error if the value cannot be decoded to a Go value (e.g. unknown, null, sensitive).
// This allows the caller to handle the value by the errors package.
err = cty.Walk(val, func(path cty.Path, v cty.Value) (bool, error) {
if !v.IsKnown() {
Expand All @@ -347,6 +346,10 @@ func (c *GRPCClient) EvaluateExpr(expr hcl.Expression, ret interface{}, opts *tf
logger.Debug(fmt.Sprintf("null value found in %s", expr.Range()))
return false, tflint.ErrNullValue
}
if v.IsMarked() {
logger.Debug(fmt.Sprintf("sensitive value found in %s", expr.Range()))
return false, tflint.ErrSensitive
}
return true, nil
})
if err != nil {
Expand Down
93 changes: 93 additions & 0 deletions plugin/plugin2host/plugin2host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/plugin/proto"
"github.com/terraform-linters/tflint-plugin-sdk/terraform/addrs"
"github.com/terraform-linters/tflint-plugin-sdk/terraform/lang/marks"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/zclconf/go-cty/cty"
"google.golang.org/grpc"
Expand Down Expand Up @@ -1855,6 +1856,98 @@ func TestEvaluateExpr(t *testing.T) {
return !errors.Is(err, tflint.ErrNullValue)
},
},
{
Name: "sensitive",
Expr: hclExpr(`var.foo`),
TargetType: reflect.TypeOf(""),
ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) {
return evalExpr(expr, &hcl.EvalContext{
Variables: map[string]cty.Value{
"var": cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("bar").Mark(marks.Sensitive),
}),
},
})
},
Want: "",
GetFileImpl: fileExists,
ErrCheck: func(err error) bool {
return !errors.Is(err, tflint.ErrSensitive)
},
},
{
Name: "sensitive as cty.Value",
Expr: hclExpr(`var.foo`),
TargetType: reflect.TypeOf(cty.Value{}),
ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) {
return evalExpr(expr, &hcl.EvalContext{
Variables: map[string]cty.Value{
"var": cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("bar").Mark(marks.Sensitive),
}),
},
})
},
Want: cty.StringVal("bar").Mark(marks.Sensitive),
GetFileImpl: fileExists,
ErrCheck: neverHappend,
},
{
Name: "sensitive in object",
Expr: hclExpr(`{ value = var.foo }`),
TargetType: reflect.TypeOf(map[string]string{}),
ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) {
return evalExpr(expr, &hcl.EvalContext{
Variables: map[string]cty.Value{
"var": cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("bar").Mark(marks.Sensitive),
}),
},
})
},
Want: (map[string]string)(nil),
GetFileImpl: fileExists,
ErrCheck: func(err error) bool {
return !errors.Is(err, tflint.ErrSensitive)
},
},
{
Name: "sensitive object as cty.Value",
Expr: hclExpr(`var.foo`),
TargetType: reflect.TypeOf(cty.Value{}),
ServerImpl: func(expr hcl.Expression, opts tflint.EvaluateExprOption) (cty.Value, error) {
return evalExpr(expr, &hcl.EvalContext{
Variables: map[string]cty.Value{
"var": cty.MapVal(map[string]cty.Value{
"foo": cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("barval").Mark(marks.Sensitive),
"baz": cty.ListVal([]cty.Value{cty.NumberIntVal(1).Mark(marks.Sensitive)}),
"qux": cty.TupleVal([]cty.Value{cty.StringVal("quxval").Mark(marks.Sensitive)}),
"quux": cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("fooval").Mark(marks.Sensitive),
}),
"corge": cty.ObjectVal(map[string]cty.Value{
"bar": cty.NumberIntVal(2).Mark(marks.Sensitive),
}),
}),
}),
},
})
},
Want: cty.ObjectVal(map[string]cty.Value{
"bar": cty.StringVal("barval").Mark(marks.Sensitive),
"baz": cty.ListVal([]cty.Value{cty.NumberIntVal(1).Mark(marks.Sensitive)}),
"qux": cty.TupleVal([]cty.Value{cty.StringVal("quxval").Mark(marks.Sensitive)}),
"quux": cty.MapVal(map[string]cty.Value{
"foo": cty.StringVal("fooval").Mark(marks.Sensitive),
}),
"corge": cty.ObjectVal(map[string]cty.Value{
"bar": cty.NumberIntVal(2).Mark(marks.Sensitive),
}),
}),
GetFileImpl: fileExists,
ErrCheck: neverHappend,
},
}

for _, test := range tests {
Expand Down
5 changes: 2 additions & 3 deletions plugin/plugin2host/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/json"
"github.com/zclconf/go-cty/cty/msgpack"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand Down Expand Up @@ -156,12 +155,12 @@ func (s *GRPCServer) EvaluateExpr(ctx context.Context, req *proto.EvaluateExpr_R
if err != nil {
return nil, toproto.Error(codes.FailedPrecondition, err)
}
val, err := msgpack.Marshal(value, ty)
val, marks, err := toproto.Value(value, ty)
if err != nil {
return nil, toproto.Error(codes.FailedPrecondition, err)
}

return &proto.EvaluateExpr_Response{Value: val}, nil
return &proto.EvaluateExpr_Response{Value: val, Marks: marks}, nil
}

// EmitIssue emits the issue with the passed rule, message, location
Expand Down
Loading

0 comments on commit 18f94f9

Please sign in to comment.