Skip to content

Commit

Permalink
Do not flow secretness on input values (#107)
Browse files Browse the repository at this point in the history
* Do not flow secretness on input values

Fixes #106

* Add a test for a mutating input

Details on what that means in `provider.go` in the added comment.
  • Loading branch information
iwahbe authored Aug 24, 2023
1 parent 68b2897 commit 16913d7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
13 changes: 11 additions & 2 deletions infer/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,9 @@ func markComputed(
return prop
}

func markSecret(field *field, prop resource.PropertyValue, inputs resource.PropertyMap) resource.PropertyValue {
func markSecret(
field *field, key resource.PropertyKey, prop resource.PropertyValue, inputs resource.PropertyMap,
) resource.PropertyValue {
// If we should never return a secret, ensure that the field *is not* marked as
// secret, then return.
if field.neverSecret {
Expand All @@ -313,6 +315,13 @@ func markSecret(field *field, prop resource.PropertyValue, inputs resource.Prope
return resource.MakeSecret(prop)
}

if input, ok := inputs[key]; ok && !input.IsSecret() && input.DeepEquals(prop) {
// prop might depend on a secret value, but the output mirrors a input in
// name and value. We don't make it secret since it will be public in the
// state anyway.
return prop
}

// Otherwise secretness is derived from dependencies: any dependency that is
// secret makes the field secret.
for _, k := range field.deps {
Expand All @@ -333,7 +342,7 @@ func markField(
prop = markComputed(field, key, prop, oldInputs, inputs, isCreate)
}

return markSecret(field, prop, inputs)
return markSecret(field, key, prop, inputs)

}

Expand Down
55 changes: 55 additions & 0 deletions infer/tests/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,61 @@ func TestCreate(t *testing.T) {
}, resp.Properties)
})

t.Run("unwired-secrets", func(t *testing.T) {
prov := provider()
sec := resource.MakeSecret
str := resource.NewStringProperty
resp, err := prov.Create(p.CreateRequest{
Urn: urn("Echo", "create"),
Properties: resource.PropertyMap{
"string": sec(str("my string")),
"int": resource.NewNumberProperty(7.0),
"strMap": resource.NewObjectProperty(resource.PropertyMap{
"fizz": sec(str("buzz")),
"foo": str("bar"),
}),
},
})

assert.NoError(t, err)
assert.Equal(t, "create-id", resp.ID)
assert.Equal(t, resource.PropertyMap{
"string": sec(str("my string")),
"int": resource.NewNumberProperty(7.0),
"strMap": resource.NewObjectProperty(resource.PropertyMap{
"fizz": sec(str("buzz")),
"foo": str("bar"),
}),
"nameOut": sec(str("create")),
"stringOut": sec(str("my string")),
"intOut": sec(resource.NewNumberProperty(7.0)),
"strMapOut": sec(resource.NewObjectProperty(resource.PropertyMap{
"fizz": str("buzz"),
"foo": str("bar"),
})),
}, resp.Properties)
})

t.Run("unwired-secrets-mutated-input", func(t *testing.T) {
prov := provider()
sec := resource.MakeSecret
num := resource.NewNumberProperty
resp, err := prov.Create(p.CreateRequest{
Urn: urn("Increment", "create"),
Properties: resource.PropertyMap{
"int": num(3.0),
"other": sec(num(0.0)),
},
})

assert.NoError(t, err)
assert.Equal(t, "id-3", resp.ID)
assert.Equal(t, resource.PropertyMap{
"int": sec(num(4.0)),
"other": sec(num(0.0)),
}, resp.Properties)
})

t.Run("wired-preview", func(t *testing.T) {
prov := provider()
c := resource.MakeComputed
Expand Down
17 changes: 17 additions & 0 deletions infer/tests/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ func urn(typ, name string) resource.URN {
tokens.Type("test:index:"+typ), tokens.QName(name))
}

// This type helps us test the highly suspicious behavior of naming an input the same as
// an output, while giving them different values. This should never be done in practice,
// but we need to accommodate the behavior while we allow it.
type Increment struct{}
type IncrementArgs struct {
Number int `pulumi:"int"`
Other int `pulumi:"other,optional"`
}

type IncrementOutput struct{ IncrementArgs }

func (*Increment) Create(ctx p.Context, name string, inputs IncrementArgs, preview bool) (string, IncrementOutput, error) {
output := IncrementOutput{IncrementArgs: IncrementArgs{Number: inputs.Number + 1}}
return fmt.Sprintf("id-%d", inputs.Number), output, nil
}

type Echo struct{}
type EchoInputs struct {
String string `pulumi:"string"`
Expand Down Expand Up @@ -163,6 +179,7 @@ func provider() integration.Server {
infer.Resource[*Echo, EchoInputs, EchoOutputs](),
infer.Resource[*Wired, WiredInputs, WiredOutputs](),
infer.Resource[*WiredPlus, WiredInputs, WiredPlusOutputs](),
infer.Resource[*Increment, IncrementArgs, IncrementOutput](),
},
ModuleMap: map[tokens.ModuleName]tokens.ModuleName{"tests": "index"},
})
Expand Down

0 comments on commit 16913d7

Please sign in to comment.