Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend type system with 'marker' functionality #1042

Open
saracen opened this issue Oct 17, 2024 · 2 comments
Open

Extend type system with 'marker' functionality #1042

saracen opened this issue Oct 17, 2024 · 2 comments

Comments

@saracen
Copy link

saracen commented Oct 17, 2024

Change

Terraform expressions support a feature where values can be deemed sensitive. Using a sensitive value propagates, tainting values that are derived from them.

It has 2 built-in functions: sensitive() which makes a regular value sensitive, and nonsensitive() which can make a value non-sensitive. For example, the expression sha256_sum(sensitive_value) would return a sensitive value, but nonsensitive(sha256_sum(sensitive_value) would make it non-sensitive.

The way this is achieved is by Terraform/HCL2's underlying expression type system (go-cty) supporting markers: https://github.com/zclconf/go-cty/blob/v1.15.0/cty/marks.go.

With Terraform, any operation that produces a new value from one with markers has the markers copied. Functions (such as nonsensitive()) can add or remove these markers. Terraform has several of these markers for various reasons, but I think sensitive is probably the one most users are familiar with.

Cel-go is extremely extendable, and whilst I'm new to using it, I couldn't find a good way of mimicking this behaviour.

I'm wondering if existing types, or a new wrapper type, implementing a "marker"-esque system could be added so that it plays nicely with the existing types and functions?

Alternatives considered

I've tried to implement this using a custom SensitiveType that wraps cel-go values:

type SensitiveType struct {
	ref.Val
}

But stumbled across a couple of problems:

  • Without implementing a sensitive type per cel-type, my wrapper has to implement traits that the underlying type might not have:

      func (s SensitiveType) Add(other ref.Val) ref.Val {
          return SensitiveType{s.Val.(traits.Adder).Add(other)}
      }
  • Using Add() like this allows the expression sensitive_value + 1234, but doesn't allow 1234 + sensitive_value. I tried looking into function overloading to support this, however, it looks like overriding/extending default operations like this is not allowed by design (singleton function incompatible with specialized overloads: _+_).

@TristonianJones
Copy link
Collaborator

An open question is whether this is actually a type or if it's just bookkeeping. As a type, supporting this in CEL would mean having sensitive copies of all types, or perhaps just annotated copies of all types if we want to make this general purpose. Annotated values can certainly be useful, but there might be other ways to approach this.

Is it sufficient to indicate in the output details that the output value is sensitive or sensitive derived?

@saracen
Copy link
Author

saracen commented Oct 22, 2024

Is it sufficient to indicate in the output details that the output value is sensitive or sensitive derived?

@TristonianJones I think that would be fine, providing a function could also nonsensitive()-ize values as they're being used.

but there might be other ways to approach this

Is there any you can think I might want to experiment with trying, especially if it means not touching cel-go internals? Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants