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

Add is_valid and compare SemVer built-ins #2538

Merged
merged 1 commit into from
Jul 15, 2020
Merged

Add is_valid and compare SemVer built-ins #2538

merged 1 commit into from
Jul 15, 2020

Conversation

charlieegan3
Copy link
Contributor

@charlieegan3 charlieegan3 commented Jul 13, 2020

I recently wrote a gist to compare Semantic Version strings as a proof of concept for something I was working on. Given the domains that OPA is commonly used in, I thought this might be a useful built-in. Especially after learning that it was hardly trivial in Rego alone (see gist).

Our use case was comparing installed software with recommended/insecure versions of the same applications.

Here is an example of what the functions look like:

> semver.is_valid("1.0.0")
true
> semver.is_valid(1)
false
> semver.compare("1.0.0", "2.0.0")
-1
> semver.compare("2.0.0", "1.0.0")
1
> semver.compare("1.0.0", "1.0.0")
0
> semver.compare("1.0.0", "1")
1 error occurred: semver.compare("1.0.0", "1"): eval_builtin_error: semver.compare: operand 2: string "1" is not a valid SemVer
> semver.compare("1.0.0", 1)
1 error occurred: 1:1: rego_type_error: semver.compare: invalid argument(s)
        have: (string, number)
        want: (string, string, number)

I apologise in advance for not raising an issue first to discuss the idea - I found myself with some time today and took the opportunity. I won't be offended if you feel this is too specific 😸

Copy link
Contributor

@patrick-east patrick-east left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the builtin definitions and implementation this looks great. The only thing I am hesitant about is taking the dependency on golang/x/mod. Thats a lot of code just for them, and we try very hard to keep the dependency requirements for OPA as small as possible to make it easier to embed in other go applications.

I would suggest that we grab something minimal and laser focused on semvers like https://github.com/coreos/go-semver/blob/master/semver/semver.go plus its supporting helpers/tests as needed: https://github.com/coreos/go-semver/tree/master/semver . Then add them to a new package like ./internal/semver in OPA (so no new golang module dependency, we're hard vendoring them as an internal package). Preserve the original licensing info and all that, we did something similar for ./internal/jwx as a reference.

The reasoning is that this type of helper library doesn't change much, if ever. Semvers are a pretty static thing, the spec isn't constantly changing and that code shouldn't need updates frequently. It's worth the extra cost of maintaining an internal fork to prevent any new dependencies on OPA for cases like this.

Edit: To clarify, it doesn't have to be that one I linked, we can even take the implementation from golang/x/mod if its small and assuming the license is compatible.

@charlieegan3
Copy link
Contributor Author

Hey Patrick, thanks for the review - makes sense. I will have a look at making that change over the next day or two.

@charlieegan3
Copy link
Contributor Author

I've had another go at this. I opted to use the coreos package since it uses the same license.

In cdec628302ef71971686d4f1d593de20216f1e5f I opted to remove unused parts of the vendored package rather than explaining what they did to please the linter.

If you'd rather not have these edits, and think that the go mod license is compatible then vendoring the go mod semver package might fare better with the linter and require fewer changes to the vendored code.

Let me know what you'd prefer.

Copy link
Contributor

@patrick-east patrick-east left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In cdec628 I opted to remove unused parts of the vendored package rather than explaining what they did to please the linter.

Perfect! 😄 No reason for us to keep code around that isn't used anyway.

Just one nit for the new files and then assuming the CI checks are all good go ahead and squash the changes.

@@ -0,0 +1,56 @@
package topdown
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please add the OPA copyright header to these new files in topdown

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, should be all present and correct now.

These built-ins will allow policies to more easily make comparisons on
semantic version strings.

I am doing this because I recently needed to write policy concerning
versions of installed software in Kubernetes environments.

I feel this is a better solution than implementing such a feature in
Rego: https://gist.github.com/charlieegan3/76dbec05c65164ac98dfec74b1381c5a

is_valid is to allow users to gate access to the compare function which
fails if the input is not a valid version string.

The semver functionality is vendored from the coreos package based on
the discussion here:
#2538 (review)

Signed-off-by: Charlie Egan <charlieegan3@users.noreply.github.com>
@charlieegan3
Copy link
Contributor Author

charlieegan3 commented Jul 15, 2020

Hopefully ready to go. I've squashed the commits too.

I also made a last minute update to the docs. The functions in the coreos package don't expect the v prefix in version strings. I think this is probably my preference anyway. The prefix v was only there because of the go package's implementation anyway.

@patrick-east patrick-east merged commit 8d321f0 into open-policy-agent:master Jul 15, 2020
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

Successfully merging this pull request may close these issues.

2 participants