Skip to content

Set intersection, difference, length, and union operators #2124

@luxas

Description

@luxas

Category

Cedar language or syntax features/changes

Describe the feature you'd like to request

This issue tracks the interest in common operations on sets: intersection, difference, length, and union.
I asked @emina about these before, and she mentioned that they are analyzable, but avoided so far for performance reasons. She told that sets in SMT are unbounded, and can thus have infinite length, so to expose a length field in Cedar, one would need to perform expensive conversions back and forth. In addition, execution of a Cedar policy cannot yield a value that is bigger or smaller than what is given as input, but the intersection, difference and union operators could change that.

I guess that some optimizations could be done to e.g. evaluate set operations lazily instead of eagerly (eventually all usage of sets turn into a boolean through contains* or similar), but it's a fair point.

For the Kubernetes use-case, authorization of updates get both the old (already in storage) and new (request) objects, and in such cases, you naturally care about differences, e.g. (object.finalizers - oldobject.finalizers).isEmpty() || (object.finalizers - oldobject.finalizers) == ["allowed-value"] instead of something like (copied from upbound/kubernetes-cedar-authorizer#13)

  // if (new finalizers >= old finalizers), verify either equality or one added finalizer
  (if resource.request.metadata.finalizers.unorderedSet.containsAll(resource.stored.metadata.finalizers.unorderedSet) then
    (resource.stored.metadata.finalizers.unorderedSet.containsAll(resource.request.metadata.finalizers.unorderedSet)
    || (resource.request.metadata.finalizers.unorderedSet.contains("my-controller-finalizer") && 
        resource.request.metadata.finalizers.length == resource.stored.metadata.finalizers.length + 1))
  // There was at least one old finalizer not in the new set, verify new finalizers < old, and that the difference is "my-controller-finalizer"
  else
    (resource.stored.metadata.finalizers.unorderedSet.containsAll(resource.request.metadata.finalizers.unorderedSet &&
     resource.stored.metadata.finalizers.unorderedSet.contains("my-controller-finalizer") &&
     resource.request.metadata.finalizers.length == resource.stored.metadata.finalizers.length - 1)
  )

that'd you'd need to do today.

I'm not asking for this to be implemented right away, but I just wanted to open this issue to gauge interest in this feature.

Describe alternatives you've considered

Users can expose the set and the length separately, but that can produce symcc false positives.
Some of the operations could maybe technically be emulated using existing operations, but it's quite a lot of work for users and error-prone.

Additional context

No response

Is this something that you'd be interested in working on?

  • 👋 I may be able to implement this feature request
  • ⚠️ This feature might incur a breaking change

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestThis issue requets a substantial new featurepending-triageThe cedar maintainers haven't looked at this yet. Automicaly added to all new issues.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions