Skip to content

Releases: StyraInc/regal

v0.11.0

19 Oct 05:50
2dded6a
Compare
Choose a tag to compare

Regal goes to v0.11.0! This release constitutes a milestone for the project, as we now ship with 50 built-in rules in total!

Regal now provides a GitHub Action for easily integrating Regal into your CI pipeline. Thanks @charlieegan3 for your work on this!

The v0.11.0 release contains six new rules, and a number of improvements and fixes.

New rule: import-after-rule

Category: imports

While certainly not common, Rego allows including imports after rule declarations, i.e.

allow if admin in input.user.roles

import data.roles.admin

The new import-after-rule rule does not allow that.

For more information, see the docs on import-after-rule.

New rule: import-shadows-builtin

Category: imports

The new import-shadows-builtin rule prevents importing a package that shadows a built-in function, or the "namespace" of a built-in function, like http in http.send:

# Forbidden, as it prevents calling `http.send` in this file
import data.features.http

For more information, see the docs on import-shadows-builtin.

New rule: prefer-set-or-object-rule

Category: idiomatic

Prefer set or object-generating rules over using top-level comprehensions.

# Avoid
deny := {reason |
    # ...
}

# Prefer
deny contains reason {
    # ...
}

For more information, see the docs on prefer-set-or-object-rule.

New rule: equals-pattern-matching

Category: idiomatic

Prefer using pattern matching in function arguments over equals comparison in head or body.

# Avoid
to_string(n) := "one" if n == 1
to_string(n) := "two" if n == 2

# Prefer
to_string(1) := "one"
to_string(2) := "two"

For more information, see the docs on equals-pattern-matching.

New rule: zero-arity-function

Category: bugs

Zero arity functions, or functions with no arguments, are problematic in Rego and should be replaced by rules.

# Avoid
first_user() := data.users[0]

# Prefer
first_user := data.users[0]

For more information, see the docs on zero-arity-function.

New rule: prefer-value-in-head

Category: custom

This is an opinonated rule and not a general recommendation. As such it is placed in the custom category and disabled by default.
Still, this is a coding style some teams or organizations may want to standardize on.

# Avoid
deny contains message if {
    # ... conditions
    message := "anonymous user not allowed"
}

# Prefer
deny contains "anonymous user not allowed" if {
    # ... conditions
}

For more information, see the docs on prefer-value-in-head.

Other improvements

  • Windows support now on par with Mac and Linux, and the project is now built and tested on Windows as part of our CI pipeline.
  • The unconditional-assignment rule now also considers partial, or multi-value, rules.
  • The no-whitespace-comment rule now allows configuring exceptions that should be allowed.
  • A --pprof flag has been added to the lint and test commands for profiling Regal. Thanks @srenatus!

Bugs fixed

Community

Changelog

v0.10.1

06 Oct 11:21
0fe50d1
Compare
Choose a tag to compare

This is a minor release to support the new setup-regal GitHub Action. This release improves the --format github output so that it no longer only reports violations in the form of annotations in the PR, but also prints the --format pretty table to the actions console, allowing you to quickly identify issues in either of the views.

As an added bonus, this release also features new documentation for the aggregate rule rule type introduced in v0.10.0, so that custom rule authors now may try them out.

Changelog

v0.10.0

03 Oct 12:07
e4fb086
Compare
Choose a tag to compare

This release brings a new type of linter rule to Regal — aggregate rules. v0.10.0 also brings a number of new rules, new features, performance improvements and bug fixes.

Aggregate rules

Aggregate rules evaluate input not just from a single Rego policy at a time, but collect, or aggregate, data from all files included for linting. A second evaluation step is then performed where the data collected is used to determine if a linter rule violation occured. Aggregate rules help solve issues at the level of a project rather than individual files, and could for example be used to ensure that at least one package is annotated with an authors attribute, or that no import point to a package that doesn't exist in the repo. Since aggregate rules require input from several files, they are disabled by default when linting a single policy file.

Huge thanks to @sesponda (Atlassian) who helped both in the design and implementation of this feature!

While the feature is considered stable, there are still some things to work out for the next release in terms of configuration options and documentation for custom aggregate rules. Join us in the #regal channel if you'd like to be an early adopter!

New rule: prefer-package-imports

Category: imports

The first built-in rule to make use of the new aggregate system is prefer-package-imports. The Rego Style Guide has long since advocated the use of package level imports over importing rules and functions directly, and now there is a Regal rule to enforce that!

For more information, see the docs on prefer-package-imports.

New rule: no-defined-entrypoint

Category: idiomatic

The next aggregate rule to ship with Regal is no-defined-entrypoint. Annotating at least one package or rule as an entrypoint is a good practice for documenting your project. And not only that — using an entrypoint annotation unlocks several programmatic capabilities for compilation to other formats, like Wasm, or IR.

For more information, see the docs on no-defined-entrypoint.

New rule: default-over-else

Category: style

The next rule is not an aggregate one, but no less useful! In the style category, the default-over-else rule will flag "fallback else" conditions in favor of default assignment.

Avoid

package policy

import future.keywords.if

permisisions := ["read", "write"] if {
    input.user == "admin"
} else := ["read"]

Prefer

package policy

import future.keywords.if

default permisisions := ["read"]

permisisions := ["read", "write"] if {
    input.user == "admin"
}

A configuration option allows setting default functions (recently introduced in OPA) as a preference as well.

For more information, see the docs on default-over-else.

New rule: rule-length

Category: style

Thanks to some improvements to the OPA AST contributed upstream by @charlieegan3, one class of rules has been made much simpler to implement. One such rule is rule-length, which similarly to file-length flags when too much is going on in a single location, and in this case a rule or a function body. The default limit is 30 lines, but this can be changed in the configuration to your liking.

For more information, see the docs on rule-length.

Feature: regal lint --enable-print

The regal lint command now accepts an --enable-print flag to simply allow print statements without printing other debugging information.

Feature: regal lint --profile

Similarly to the profiling capabilities in OPA, Regal now provides a --profile flag to help collect and report profiling data, helping policy authors and Regal developers to see where most of the time is spent in evaluation.

Experimental: Wasm/Wasi compilation

Friend of Regal @srenatus has contributed some experimental code to compile Regal to Wasm/Wasi. See the development docs if you're curious to try it out!

Performance improvements

  • Regal now uses a custom algorithm to filter out files ignored, up to 30X faster than previously.
  • OPA dependency bumped to point to main which includes performance improvements to walk and arithmetic operations.

Other improvements

  • The regal new rule command now adds both a documentation page and an entry in the README table. Thanks @Ronnie-personal for contributing!
  • A non-breakable-word-threshold option has been added to the line-length rule, which allows tolerating single words that exceed the line length if they can't be broken up into several parts, like URLs. Thanks @iamleot for requesting this!
  • The top-level-iteration incorrectly identified constants and other parameters as iteration. This was identified and fixed by @zregvart. Thanks!

Great to see so many old and new faces in the list of contributors. Thank you all!

Changelog

v0.9.0

19 Sep 11:04
83f22ee
Compare
Choose a tag to compare

This release brings three new rules to Regal, a new Rego-based build system, and improvements to the Go API. Plus a number of improvements, features and bugfixes.

The v0.9.0 release also coincides with some exciting news from our community — users of the Rego Playground now experience Regal integrated in the tool, and have linter violations reported directly in the UI!

New rule: dubious-print-sprintf

Category: testing

This new rule will flag the use of print together with sprintf in it's argument list. The print function takes any number of arguments as it is, and using sprintf negates the benefits of the print functions special handling of undefined values.

For more information, see the docs on dubious-print-sprintf.

Thank you @Ronnie-personal for contributing this rule! 👏

New rule: forbidden-function-call

Category: custom

In the custom category, the new forbidden-function-call rule will allow you to configure a list of built-in functions that should be flagged by Regal if encountered. This could for example be http.send calls, or JWT decoding using HMAC rather than assymetric crypto.

For more information, see the docs on forbidden-function-call.

New rule: chained-rule-body

Category: style

The new chained-rule-body rule will have Regal flag rules where the body is "chained", as this style isn't recommended any more.

For more information, see the docs on chained-rule-body.

Regal in the Rego Playground!

Regal is now integrated in the Rego Playground, and provides users with information on linter violations as they work on their policies!

Thanks @charlieegan3 for your work on this!

Go API (experimental)

While integrations using the Go API is still not recommended, several steps were taken in this release in order to move it closer to a stable state. This work was done in order to get Regal integrated into the Rego Playground.

Documentation

A new page on the Regal's architecture has been added to the docs, which should be helpful for people looking to contribute to Regal, or those curious to learn more about how Regal works.

Using Rego to build Rego that lints Rego!

Regal now uses Rego — via @charlesdaniels eminent rq tool — as a "build tool" of sorts. See this LinkedIn post for more details, and a link to our new build definition file. The development docs have been updated with instructions for using this tool.

While we're on that topic — the new do.rq pr task will run all the formatting, testing and linter steps required to prepare a PR. Make sure to use it when contributing!

Thanks to @srenatus for leading the way on this one!

Other improvements and fixes

  • Custom configuration for a rule is no longer required to provide a level attribute. If not provided, the level will be inherited from the default configuration for that rule.
  • The walk built-in function is now by default excepted by the function-arg-return rule. See the rule documentation for details.
  • The regal lint command now accepts a --metrics flag, which will provide helpful information on where Regal spends most of the time evaluating a project.

Credits

Thank you all who contributed to this release! Special thanks goes out to first time contributors:

You rock! 👏

Changelog

v0.8.0

04 Sep 11:29
6253cae
Compare
Choose a tag to compare

This is the most feature-packed release to date, adding a new output format, four new rules, and many improvements across the board!

New GitHub output format

The regal lint command now accepts a new --format option named github. This is ideal for when Regal is run in CI/CD scenarios using GitHub Actions. This format will emit annotations for any violation, which will be visible in the pull request file view.

annotation

In addition to this, the GitHub output format will also create a linter report visible in the "Checks" tab:

report

This report summarizes the result of linting, with links provided to the documentation for any violation.

New rule: use-some-for-output-vars

Category: idiomatic

Using some to declare output variables used in iteration (and elsewhere) has long been considered a best practice. Regal can now identify places where variables are introduced without some and treat these as errros:

allow {
    userinfo := data.users[id]
    # ...
}

Unless the id variable in the above example is declared elsewhere in the policy, it should be declared using some:

allow {
    some id
    userinfo := data.users[id]
    # ...
}

# alternatively, and arguably more idiomatic:
allow {
    some id, userinfo in data.users
    # ...
}

For more information, see the docs on use-some-for-output-vars.

New rule: prefer-some-in-iteration

Category: style

Similarly, the new prefer-some-in-iteration rule will have Regal warn when using the "old" style of iteration which could be replaced in favor of some ... in:

engineers[employee] {
    employee := data.employees[_]
    employee.role in engineering_roles
}

# Prefer some .. in

engineers[employee] {
    some employee in data.employees
    employee.role in engineering_roles
}

An exception to this rule may deeply nested iteration, where the shorter syntax is often preferable. Regal thus allows configuring the rule to allow exceptions from any given nesting level.

For more information, see the docs on prefer-some-in-iteration.

New rule: metasyntactic-variable

Category: testing

Using rule and variable names like "foo", "bar" or "baz" might be convenient in examples, but rarely has a place in production policy. The new metasyntactic-variable rule will flag any occurences of these names. The ignore directive may of course be used to e.g. allow these type of variables in tests or other legitimate locations.

For more information, see the docs on metasyntactic-variable.

New rule: file-length

Category: style

Having policy files span several hundred lines of code is often a signal to consider refactoring the code into smaller units, and to modularize properly using packages and imports. The new file-length rule by default flags any file with more than 500 lines. This number can be changed via the rule's configuration.

For more information, see the docs on file-length.

Other improvements

In addition to the above features, this release comes with many smaller improvements to code, documentation and the pre-commit-hooks — not to mention a bunch of bugs that got fixed. Thanks to everyone who contributed to this release!

Changelog

v0.7.0

11 Aug 08:54
6f91381
Compare
Choose a tag to compare

This release adds a new custom category to the built-in rules, which allows users to easily define the most common organizational requirements, like naming conventions, by simply editing their Regal configuration. This release also brings a new frontend for the Regal docs, which are now published to docs.styra.com/regal.

New custom category, and naming-convention rule

The custom category of rules allows teams and organizations to define their own conventions for their Rego projects, without having to write custom linter policies. Naming conventions are likely the most common requirement, which is also what the new naming-convention rule helps solve by allowing users to specify their conventions in the Regal configuration using regex patterns.

An example configuration leveraging the naming-convention rule could look like below:

rules:
  custom:
    naming-convention:
      # one of "error", "warning", "ignore"
      level: error
      conventions:
          # allow only "private" rules and functions, i.e. those starting with
          # underscore, or rules named "deny" or "allow"
        - pattern: '^_[a-z]+$|^deny$|^allow$'
          # one of "package", "rule", "function", "variable"
          targets:
            - rule
            - function
        # any number of naming rules may be added
        # package names must start with "acmecorp" or "system"
        - pattern: '^acmecorp|^system'
          targets:
            - package

Note that all rules in the "custom" category are disabled by default (i.e. level "ignore") as some configuration needs to be provided by the user (i.e. you!) in order for them to be useful.

Docs published to docs.styra.com

While GitHub renders markdown well, the file browser doesn't lend itself too well for exploring all the rules available in Regal. From this release, docs are now published to to docs.styra.com/regal, and this page will be used in links found in the reports emitted by regal lint. If you prefer navigating GitHub, the markdown files are still there too.

Changelog

v0.6.0

08 Aug 11:44
44cd7de
Compare
Choose a tag to compare

This release brings a new command for quickly generating new (custom or built-in) rules, a new linter rule, and some improvements around tooling.

New command to help develop new rules

The regal new rule command may now be used to quickly get started developing your own rules, wether custom ones for your organization, or built-in rules for inclusion in Regal.

regal new rule --category naming --name foo-bar-baz

The above command will create two new files under .regal/rules/naming (all directories created if not exists since before) where one is a policy for the new rule, and another is a test for the same rule. See the updated documentation for custom rules development for more details.

New rule: non-raw-regex-pattern

Using raw string literals for regex pattern has since long been a best practice, and is recommended both by the OPA docs as well as the Rego Style Guide.. The new non-raw-regex-pattern rule (in the idiomatic category) will now help enforce this convention.

Pre-Commit Hooks

Regal now provides pre-commit hooks for easily running Regal as part of your development workflow. Very useful if you want to ensure regal lint is run before you commit any changes to policy files. See the docs on pre-commit hooks for more information. Thanks @adam-moss and @c-wygoda for your contributions to this feature.

Other notable changes

  • The use-in-operator rule has been moved from the style category to idiomatic. Thanks @Parsifal-M!
  • The documentation for all rules now includes a footer linking to the Regal channel in the Styra Community Slack.
  • OPA version bumped from v0.54.0 to v0.55.0

Changelog

v0.5.0

21 Jul 14:13
6fdb963
Compare
Choose a tag to compare

This release brings improvements and new features to improve the experience of authoring custom rules, as well as new, granular capabilities for ignoring files. Most of these improvements are directly based on feedback — and in some cases contributions — from Regal users, which is particularly exciting!

New functionality for ignoring files at a global level and rule level

In addition to setting the severity level of a rule in the Regal configuration file, it is now possible to have the linter ignore files based on their name (or a pattern). This configuration can be applied either globally for all rules, or per rule. An example of this could be wanting to allow the use of the print function in files with a _test.rego suffix, but not in any other files.

Example .regal/config.yaml

ignore:
  files:
    # ignore this file for all rules
    - sketch.rego
rules:
  testing:
    print-or-trace-call:
      level: error
      ignore:
        files:
          # ignore the print-or-trace-call rule in tests
          - "*_test.rego"

See the configuration section of the docs for more details. Thanks @kristiansvalland for this excellent contribution!

Custom rules authoring improvements

Based on feedback we got from users starting to write their own custom rules, we've made several updates to the docs on this topic, fixing the parts people found confusing, and added more examples show e.g. the directory structure of a policy repo using custom Regal rules. Apart from documentation, we've also made it possible have custom rules without a related_resources attribute in the metadata, as some might prefer to document their rules in code, or by other means.

Enhanced type checking of the input AST

This improves the authoring experience for both builtin and custom rules. The regal test command, which is commonly used when developing and testing new rules, now makes use of a schema for the input attribute, i.e. the AST. This allows the command to fail directly when unknown attributes on input are encountered in linter rules, due to typos or other mistakes.

To use this schema in custom rules, add a schemas attribute to the package annotation, using schema.regal.ast for the input:

# METADATA
# description: All packages must use "acme.corp" base name
# schemas:
# - input: schema.regal.ast
package custom.regal.rules.naming["acme-corp-package"]

import future.keywords.contains
import future.keywords.if

report contains violation if {
    # this will fail at compile time, as there is no 'functions' attribute
    # in the input AST
    some function in input.functions

    # ...
}

The schema is applied automatically for builtin rules.

Community

On the community side, we're excited to have @kristiansvalland join us as a maintainer!

Changelog

v0.4.0

04 Jul 09:05
cb516a4
Compare
Choose a tag to compare

This release brings three new rules related to comments and metadata annotations:

  • invalid-metadata-attribute (bugs category) flags custom attributes in metadata annotations not placed under the custom attribute.
  • detached-metadata (style category) flags metadata annotations that are "detached" by whitespace from their package or rule.
  • no-whitespace-comment (style category) simply flags comments where the first character following the # is not whitespace.

Additionally, new end-to-end tests exposed a few mistakes in a previous refactoring, which have been fixed. This mistake meant that v0.3.0 failed to correctly run the line-length and function-arg-return rules... so if you started from that release you're really getting five new rules with v0.4.0... good thing we're keeping a fast paced release cadence! Thanks to @kristiansvalland for reporting on this regression.

Changelog

v0.3.0

27 Jun 13:39
6dcc15e
Compare
Choose a tag to compare

This release improves the use-assignment-operator rule to include many more cases than previously reported.

Additionally, this release fixes a number of issues uncovered when running Regal against some large real-world policy libraries. A few of these were false positives, i.e. where Regal would report issues where there were none, and a few were cases that Regal previously missed.

On the community side, a link to the blog about the ideas behind Regal was added to the README.

Changelog