### Example Directory Structure for Policies Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/directory-package-mismatch This example illustrates a project structure where directories mirror the package paths of Rego policies. It shows how `authorization.rbac.roles` corresponds to the `bundle/authorization/rbac/roles` directory. ```text # Directory structure # Package path . ├── README.md └── bundle └── authorization ├── main.rego # authorization └── rbac ├── data.json # authorization.rbac ├── roles │   └── roles.rego # authorization.rbac.roles │   └── roles_test.rego # authorization.rbac.roles_test └── users ├── customers.rego # authorization.rbac.users ├── customers_test.rego # authorization.rbac.users_test ├── internal.rego # authorization.rbac.users └── internal_test.rego # authorization.rbac.users_test ``` -------------------------------- ### Simplest Policy Example Source: https://www.openpolicyagent.org/projects/regal/custom-rules This is the most basic Rego policy, containing only a package declaration. It serves as a starting point for understanding AST generation. ```rego package policy ``` -------------------------------- ### Linter Configuration Example Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/prefer-set-or-object-rule This snippet shows an example configuration for the prefer-set-or-object-rule linter, specifying the 'error' level. ```yaml rules: idiomatic: prefer-set-or-object-rule: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Write a Rego Policy Source: https://www.openpolicyagent.org/projects/regal Example of a basic Rego policy file for authorization. ```rego package authz default allow = false allow if { isEmployee "developer" in input.user.roles } isEmployee if regex.match("@acmecorp\.com$", input.user.email) ``` -------------------------------- ### Example Directory Structure with exclude-test-suffix=false Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/directory-package-mismatch This example demonstrates the directory structure when the `exclude-test-suffix` configuration option is set to `false`. In this configuration, test files must also reside in directories with a `_test` suffix, matching their package path. ```text # Directory structure # Package path . ├── README.md └── bundle └── authorization ├── main.rego # authorization └── rbac ├── data.json # authorization.rbac ├── roles │   └── roles.rego # authorization.rbac.roles ├── roles_test │   └── roles_test.rego # authorization.rbac.roles_test ├── users │   ├── customers.rego # authorization.rbac.users │   └── internal.rego # authorization.rbac.users └── users_test ├── customers_test.rego # authorization.rbac.users_test └── internal_test.rego # authorization.rbac.users_test ``` -------------------------------- ### Regal Configuration File Example Source: https://www.openpolicyagent.org/projects/regal/configuration Use a YAML file (e.g., .regal/config.yaml) to override default Regal configurations. This example shows how to set rule levels (ignore, warning, error), configure specific rule options like max-line-length, ignore files for rules, define custom naming conventions, specify OPA engine version, and set project roots. ```yaml rules: style: todo-comment: # don't report on todo comments level: ignore line-length: # custom rule configuration max-line-length: 100 # warn on too long lines, but don't fail level: warning opa-fmt: # not needed as error is the default, but # being explicit won't hurt level: error # files can be ignored for any individual rule # in this example, test files are ignored ignore: files: - "*_test.rego" custom: # custom rule configuration naming-convention: level: error conventions: # ensure all package names start with "acmecorp" or "system" - pattern: '^acmecorp\.[a-z_\.]+$|^system\.[a-z_\.]+$' targets: - package capabilities: from: # optionally configure Regal to target a specific version of OPA # this will disable rules that has dependencies to e.g. built-in # functions or features not supported by the given version # # if not provided, Regal will use the capabilities of the latest # version of OPA available at the time of the Regal release engine: opa version: v0.58.0 ignore: # files can be excluded from all lint rules according to glob-patterns files: - file1.rego - "*_tmp.rego" project: roots: # declares the 'main' and 'lib/jwt' directories as project roots - main - lib/jwt # may also be provided as an object with additional options - path: lib/legacy rego-version: 0 ``` -------------------------------- ### Install Regal with mise Source: https://www.openpolicyagent.org/projects/regal Install the latest version of Regal using the mise polyglot tool version manager. ```bash mise use -g regal@latest ``` -------------------------------- ### Example todo-test Policy Source: https://www.openpolicyagent.org/projects/regal/rules/testing/todo-test This is an example of a test case prefixed with 'todo_' in Rego. Such tests are intended for development tracking and should be removed before submission. ```rego package policy_test import data.policy # Make sure this passes todo_test_allow_if_admin { policy.allow with input as {"user": {"roles": ["admin"]}} } ``` -------------------------------- ### Package with Metadata Source: https://www.openpolicyagent.org/projects/regal/rules/custom/missing-metadata This example demonstrates a package declaration with metadata annotations for description and scope. This adheres to the missing-metadata rule. ```rego # METADATA # description: The `acmecorp.authz` module provides authorization logic for the AcmeCorp application. package acmecorp.authz # METADATA # description: Provides a set of all authorized users given the conditions in `input`. # scope: document authorized_users contains user if { # logic to determine authorized users } ``` -------------------------------- ### Regal Linter Configuration Example Source: https://www.openpolicyagent.org/projects/regal/rules/style/avoid-get-and-list-prefix Shows how to configure the `avoid-get-and-list-prefix` linter rule in Regal, specifying the severity level. ```yaml rules: style: avoid-get-and-list-prefix: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Rego Linter Configuration for `use-some-for-output-vars` Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/use-some-for-output-vars Example configuration for the `use-some-for-output-vars` linter rule, specifying the severity level. ```yaml rules: idiomatic: use-some-for-output-vars: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Verify Regal Installation (macOS/Linux) Source: https://www.openpolicyagent.org/projects/regal Check if the Regal installation was successful by running the version command. ```bash regal version ``` -------------------------------- ### Prefer Importing Packages Source: https://www.openpolicyagent.org/projects/regal/rules/imports/prefer-package-imports This example demonstrates the 'Prefer' case where an entire package is imported. This approach makes it obvious where imported data originates from, enhancing code readability. ```rego package policy # Package imported rather than rule import data.users has_waldo if { # Obvious where "first_names" comes from "Waldo" in users.first_names } ``` -------------------------------- ### Prefer concise rule structure Source: https://www.openpolicyagent.org/projects/regal/rules/custom/prefer-value-in-head This example demonstrates the preferred, more concise structure where the assignment is moved to the rule head. This is the recommended pattern. ```rego package policy pin_as_number := to_number(input.pin_code) if is_number(input.pin_code) deny contains "user attribute missing from input" if not input.user ``` -------------------------------- ### Rego Unification Example: `data.users` Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/use-some-for-output-vars Illustrates how Rego's unification allows variables like `name` to be treated as outputs, binding to keys in a map. ```json { "jane": {"email": "jane@acmecorp.com", "firstname": "Jane", "lastname": "Doe"}, "joe": {"email": "joe@example.com", "firstname": "Joe", "lastname": "Bloggs"}, "john": {"email": "john@opa.org", "firstname": "John", "lastname": "Smith"} } ``` ```rego usernames contains name if { data.users[name] } ``` -------------------------------- ### OPA Argument Evaluation Example Source: https://www.openpolicyagent.org/projects/regal/rules/custom/narrow-argument This example illustrates how OPA evaluates function arguments before calling the function, especially when negation is involved. If 'user.phone' is undefined, the 'has_phone' function is never called. ```rego not has_phone(user.phone) ``` ```rego arg1 := user.phone not has_phone(arg1) ``` -------------------------------- ### Prefer Unique Rules in Policy Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/duplicate-rule This example demonstrates the preferred way to write policies, with each rule being unique. This avoids the 'duplicate-rule' linter warning. ```rego package policy allow if user.is_admin allow if user.is_developer ``` -------------------------------- ### Install Regal with Homebrew Source: https://www.openpolicyagent.org/projects/regal Use Homebrew to install the Regal binary on macOS. This method supports both ARM64 and AMD64 architectures. ```bash brew install regal ``` -------------------------------- ### Extending Set Generating Rules Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/prefer-set-or-object-rule This example demonstrates how set generating rules can be extended from multiple sources, including input and data, and how to unconditionally add items. ```rego package policy # Getting developers from input developers contains developer if { some user in input.users "developer" in user.roles developer := user.name } # *Also* getting developers from data developers contains developer if { some user in data.users "developer" in user.roles developer := user.name } # Unconditionally adding a developer to the set developers contains "Hackerman" ``` -------------------------------- ### Simplify Boolean Rules with Pattern Matching Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/equals-pattern-matching This example demonstrates how rules that evaluate to true can be simplified by moving equality checks to function arguments, making the intent clearer. ```rego package policy is_admin(role) if role == "admin" is_admin(role) if role == "administrator" is_admin(role) if role == "root" ``` -------------------------------- ### Avoid Tests in Same Package Source: https://www.openpolicyagent.org/projects/regal/rules/testing/test-outside-test-package This example shows a policy and its test within the same package. It is recommended to avoid this structure for better separation. ```rego package policy allow if { "admin" in input.user.roles } # Tests in same package as policy test_allow_if_admin { allow with input as {"user": {"roles": ["admin"]}} } ``` -------------------------------- ### Example of print call in OPA policy Source: https://www.openpolicyagent.org/projects/regal/rules/testing/print-or-trace-call This snippet demonstrates how a `print` call might appear within an OPA policy. It is useful for debugging but should be removed before production. ```rego package policy reasons contains sprintf("%q is a dog!", [user.name]) if { some user in input.users user.species == "canine" # Useful for debugging, but leave out before committing print("user:", user) } ``` -------------------------------- ### Prefer: Narrowed Email Argument Source: https://www.openpolicyagent.org/projects/regal/rules/custom/narrow-argument This example demonstrates the preferred approach where the function directly accepts the 'email' string, making it more reusable. ```rego package policy valid_email(email) if endswith(email, "acmecorp.com") valid_email(email) if endswith(email, "acmecorp.org") ``` -------------------------------- ### Avoid Import Shadows Rule Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/import-shadows-rule This example demonstrates a rule that shadows an imported identifier. Avoid this pattern to prevent unreachable code. ```rego package policy import data.resources # 'resources' shadowed by import resources contains resource if { # ... } ``` -------------------------------- ### Unification operator without unification Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/prefer-equals-comparison Shows how the previous example would be written without using the unification operator, requiring explicit comparison and assignment. ```rego user_id := id if { count(input.path) == 2 input.path[0] == "users" id := input.path[1] } ``` -------------------------------- ### Interchangeable Use of '=' and ':=' Source: https://www.openpolicyagent.org/projects/regal/rules/style/use-assignment-operator This example shows cases where '=' and ':=' can be used interchangeably for assignment, though ':=' is still recommended for consistency and clarity. ```Rego first_name(full_name) = split(full_name, " ")[0] # same as first_name(full_name) := split(full_name, " ")[0] ``` -------------------------------- ### Package without Metadata Source: https://www.openpolicyagent.org/projects/regal/rules/custom/missing-metadata This example shows a package declaration without any metadata annotations. The missing-metadata rule flags this as a violation. ```rego package acmecorp.authz authorized_users contains user if { # logic to determine authorized users } ``` -------------------------------- ### Prefer Consistent Function Argument Names Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/inconsistent-args This example demonstrates the preferred way to declare functions with consistent argument names. This practice helps prevent bugs. ```rego package policy find_vars(rule, node) if node in rule find_vars(rule, node) if { walk(rule, [path, value]) # ... } ``` -------------------------------- ### Sample Rego File Source: https://www.openpolicyagent.org/projects/regal/editor-support A basic Rego file used for demonstrating diagnostics. This serves as an example input for testing Regal integration. ```rego package test default allowRbac := true ``` -------------------------------- ### Avoid Circular Imports: Original Code Source: https://www.openpolicyagent.org/projects/regal/rules/imports/circular-import This example demonstrates a circular import between 'authz.rego' and 'shared.rego'. Avoid this pattern. ```rego # authz.rego package authz import data.shared admins := { "anna", "bob", } allow if { input.role in shared.roles } allow if { input.user in admins } ``` ```rego # shared.rego package shared import data.authz # circular import! roles := { "admin", "editor", "viewer" } users := authz.admins | { "chloe", "dave", } ``` -------------------------------- ### Annotate Incremental Rule Definitions Explicitly Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/ambiguous-scope This example demonstrates annotating each incremental rule definition with its own metadata and scope when they have different descriptions. ```rego package policy # METADATA # description: allow is true if the user is admin allow if user_is_admin # METADATA # description: allow is true if the requested resource is public allow if public_resource ``` -------------------------------- ### Prefer Attached Metadata Annotation Source: https://www.openpolicyagent.org/projects/regal/rules/style/detached-metadata This example demonstrates the preferred style where the metadata annotation is placed directly above the package declaration, improving readability. ```rego package authz # METADATA # description: allow any requests by admin users allow if { "admin" in input.user.roles } ``` -------------------------------- ### Prefer Tests in Separate Package Source: https://www.openpolicyagent.org/projects/regal/rules/testing/test-outside-test-package This example demonstrates the preferred method of placing tests in a separate package named 'policy_test' with a '_test' suffix, importing the main policy package. ```rego # Tests in separate package with _test suffix package policy_test import data.policy test_allow_if_admin { policy.allow with input as {"user": {"roles": ["admin"]}} } ``` -------------------------------- ### Caveat with default functions and undefined arguments Source: https://www.openpolicyagent.org/projects/regal/rules/style/default-over-else This example demonstrates that a default value for a function is not guaranteed if arguments passed to the function are undefined. ```rego # undefined if `input.name` is undefined fname := first_name(input.name) ``` -------------------------------- ### Avoid: Broad User Argument Source: https://www.openpolicyagent.org/projects/regal/rules/custom/narrow-argument This example shows a function that accepts a broad 'user' object. Prefer to narrow arguments to specific fields like 'email' when possible. ```rego package policy valid_user(user) if endswith(user.email, "acmecorp.com") valid_user(user) if endswith(user.email, "acmecorp.org") ``` -------------------------------- ### Regal Linter Configuration Example Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/equals-pattern-matching This configuration snippet shows how to set the severity level for the 'equals-pattern-matching' linter rule. ```yaml rules: idiomatic: equals-pattern-matching: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Iterating over map keys in Rego Source: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-some-in-iteration This example shows two ways to iterate over map keys. The 'some .. in' version is preferred for its clarity and to avoid potential conflicts with rule names. ```rego package policy key_traversal if { map[key] # do something with key } key_traversal if { some key in object.keys(map) # do something with key } ``` -------------------------------- ### Regal Linter Configuration Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/in-wildcard-key Example configuration for the 'in-wildcard-key' linter rule, specifying the severity level for detected issues. ```yaml rules: idiomatic: in-wildcard-key: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Prefer Functions with Arguments Only in OPA Source: https://www.openpolicyagent.org/projects/regal/rules/style/external-reference This example shows a preferred function design where dependencies are passed as arguments, making the function more reusable and testable. ```rego package policy # Depends only on function arguments is_preferred_login_method(method, user, all_login_methods) if { preferred_login_methods := {login_method | some login_method in all_login_methods login_method in user.login_methods } method in preferred_login_methods } ``` -------------------------------- ### Prefer Pattern Matching on Function Arguments Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/equals-pattern-matching This example shows the preferred method of using pattern matching directly on function arguments for equality checks, leading to more idiomatic Rego. ```rego package policy readable_number(1) := "one" readable_number(2) := "two" ``` -------------------------------- ### Avoid Duplicate Rules in Policy Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/duplicate-rule This example shows a policy with a duplicated 'allow' rule. The linter flags this as a bug. Ensure each rule is unique to avoid potential mistakes. ```rego package policy allow if user.is_admin allow if user.is_developer # we already covered this! allow if user.is_admin ``` -------------------------------- ### Avoid direct iteration in Rego Source: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-some-in-iteration This example shows the 'avoid' pattern where direct iteration is used, which can be ambiguous. Use 'some .. in' for clearer intent. ```rego package policy engineering_roles := {"engineer", "dba", "developer"} engineers contains employee if { employee := data.employees[_] employee.role in engineering_roles } ``` -------------------------------- ### Prefer 'some .. in' for iteration in Rego Source: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-some-in-iteration This example demonstrates the preferred 'some .. in' construct for iterating over collections, improving clarity and reducing ambiguity. ```rego package policy engineering_roles := {"engineer", "dba", "developer"} engineers contains employee if { some employee in data.employees employee.role in engineering_roles } ``` -------------------------------- ### Deeply nested iteration comparison in Rego Source: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-some-in-iteration This example compares a deeply nested iteration using direct indexing with the 'some .. in' approach, showing that the compact form can be more readable in such cases. ```rego package policy # These rules are equivalent, but the more compact form is arguably easier to read any_user_is_admin if { some user in input.users some attribute in user.attributes some role in attribute.roles role == "admin" } any_user_is_admin if { input.users[_].attributes[_].roles[_] == "admin" } # Using "if", we may even omit the brackets for single line rules any_user_is_admin if input.users[_].attributes[_].roles[_] == "admin" ``` -------------------------------- ### Prefer Grouped Incremental Rules Source: https://www.openpolicyagent.org/projects/regal/rules/style/messy-rule This example demonstrates the preferred way to define incremental rules by grouping their heads together. This enhances readability and allows for better tooling support. ```rego package policy allow if something allow if something_else unrelated_rule if { # ... } ``` -------------------------------- ### Policy with Entrypoint Annotation Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/no-defined-entrypoint This example demonstrates a Rego policy with an entrypoint annotation. Adding metadata like 'entrypoint: true' and a description improves policy clarity and enables advanced features for tooling. ```rego package policy default allow := false # METADATA # description: Allow only admins, or reading public resources # entrypoint: true allow if user_is_admin allow if public_resource_read user_is_admin if { some role in input.user.roles role in data.permissions.admin_roles } public_resource_read if { input.request.method == "GET" input.request.path[0] == "public" } ``` -------------------------------- ### Custom Regal Naming Rule Example Source: https://www.openpolicyagent.org/projects/regal/custom-rules This is an example of a custom Regal rule that checks for specific package naming conventions. It reports a violation if the package name does not start with 'acme.corp' or 'system.log'. Ensure the package name follows the `custom.regal.rules.[""]` format. ```rego package custom.regal.rules.naming["acme-corp-package"] import data.regal.result report contains violation if { not acme_corp_package not system_log_package violation := result.fail(rego.metadata.chain(), result.location(input.package.path[1])) } acme_corp_package if { input.package.path[1].value == "acme" input.package.path[2].value == "corp" } system_log_package if { input.package.path[1].value == "system" input.package.path[2].value == "log" } ``` -------------------------------- ### Avoid Implicit Future Keywords Import Source: https://www.openpolicyagent.org/projects/regal/rules/imports/implicit-future-keywords This example demonstrates the 'Avoid' pattern, which uses the catch-all 'future.keywords' import. This can lead to unexpected behavior and conflicts with future OPA keywords. ```rego package policy import future.keywords report contains violation if { not "developer" in input.user.roles violation := "Required role 'developer' missing" } ``` -------------------------------- ### Regal Linting Output with Skipped Rule Source: https://www.openpolicyagent.org/projects/regal/rules/imports/use-rego-v1 This is an example of the output from running `regal lint bundle` when the `use-rego-v1` rule is skipped due to missing capabilities for the targeted OPA version. ```bash $ regal lint bundle 131 files linted. No violations found. 1 rule skipped: - use-rego-v1: Missing capability for `import rego.v1` ``` -------------------------------- ### Ambiguity in iteration vs. membership check Source: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-some-in-iteration This example highlights how direct iteration can be ambiguous, making it unclear whether iteration or a membership check is intended without further context. ```rego some_condition if { other_rule[user] # ... } ``` -------------------------------- ### Avoid Importing Rules Directly Source: https://www.openpolicyagent.org/projects/regal/rules/imports/prefer-package-imports This example shows the 'Avoid' case where individual rules are imported directly. This can make it unclear where imported data originates from, especially in larger policies. ```rego package policy # Rule imported directly import data.users.first_names has_waldo if { # Not obvious where "first_names" comes from "Waldo" in first_names } ``` -------------------------------- ### Prefer Different Package Names or Aliases Source: https://www.openpolicyagent.org/projects/regal/rules/imports/import-shadows-builtin This example shows preferred ways to handle imports to avoid shadowing built-in functions. Use distinct package names or import aliases to prevent conflicts. ```rego package policy # Using a different package name import data.printer # Using an alias import input.attributes.http as http_attributes ``` -------------------------------- ### Prefer using rego.v1 import Source: https://www.openpolicyagent.org/projects/regal/rules/imports/use-rego-v1 This code shows the recommended way to import `rego.v1`, which prepares policies for OPA 1.0 by enabling future keywords and syntax by default. For OPA 1.0 and later, this import is unnecessary. ```rego package policy # with OPA v0.59.0 and later, use import rego.v1 instead # with OPA v1.0 and later, this import is unnecessary import rego.v1 report contains item if { # ... } ``` -------------------------------- ### Avoid Ambiguous Metadata Scope Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/ambiguous-scope This example demonstrates an ambiguous metadata scope where the description applies to multiple incremental rule definitions without explicit scope. ```rego package policy # METADATA # description: allow is true if the user is admin, or the requested resource is public allow if user_is_admin allow if public_resource ``` -------------------------------- ### Regal Update Notification Example Source: https://www.openpolicyagent.org/projects/regal/remote-features This is an example of the message displayed when a new version of Regal is available. No user data is sent to GitHub. ```text A new version of Regal is available (v0.23.1). You are running v0.23.0. See https://github.com/open-policy-agent/regal/releases/tag/v0.23.1 for the latest release. ``` -------------------------------- ### Load Rego Files from Paths Source: https://www.openpolicyagent.org/projects/regal/integration Use `InputFromPaths` to load Rego modules from a list of file paths. Ensure proper error handling for file access issues. ```go paths := []string{"foo.rego", "bar.rego"} input, err := rules.InputFromPaths(paths) if err != nil { // handle error } ``` -------------------------------- ### Regal Lint Violation Examples Source: https://www.openpolicyagent.org/projects/regal Examples of linting violations reported by Regal, including rule name, description, location, and the problematic text. ```text Rule: non-raw-regex-pattern Description: Use raw strings for regex patterns Category: idiomatic Location: policy/authz.rego:12:27 Text: isEmployee if regex.match("@acmecorp\.com$", input.user.email) Documentation: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/non-raw-regex-pattern Rule: use-assignment-operator Description: Prefer := over = for assignment Category: style Location: policy/authz.rego:5:1 Text: default allow = false Documentation: https://www.openpolicyagent.org/projects/regal/rules/style/use-assignment-operator Rule: prefer-snake-case Description: Prefer snake_case for names Category: style Location: policy/authz.rego:12:1 Text: isEmployee if regex.match("@acmecorp\.com$", input.user.email) Documentation: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-snake-case 1 file linted. 3 violations found. ``` -------------------------------- ### Prefer Renamed Rule to Avoid Import Shadows Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/import-shadows-rule This example shows how to avoid import shadowing by renaming the local rule to a different name, ensuring clarity and reachability. ```rego package policy import data.resources # using a different name for the rule report contains resource if { # ... } ``` -------------------------------- ### Nesting level example in Rego Source: https://www.openpolicyagent.org/projects/regal/rules/style/prefer-some-in-iteration This example demonstrates a nesting level of 1, where only one variable is bound in iteration, which is not considered deep nesting by the linter rule. ```rego package policy example_users contains user if { domain := "example.com" user := input.sites[domain].users[_] } ``` -------------------------------- ### Prefer Document Scope for Metadata Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/ambiguous-scope This example shows the preferred way to define metadata scope using '# scope: document' when a description applies to all incremental rule definitions. ```rego package policy # METADATA # description: allow is true if the user is admin, or the requested resource is public # scope: document allow if user_is_admin allow if public_resource ``` -------------------------------- ### Prefer Aliased Import to Avoid Import Shadows Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/import-shadows-rule This example demonstrates using an alias for an imported identifier to prevent it from shadowing a local rule, thus avoiding conflicts. ```rego package policy # using an alias to avoid shadowing 'resources' rule import data.resources as inventory resources contains resource if { # ... } ``` -------------------------------- ### Example of sprintf argument mismatch during evaluation Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/sprintf-arguments-mismatch This example demonstrates the output when `sprintf` encounters an argument mismatch during evaluation. The function returns a string indicating the missing argument rather than failing. ```bash > opa eval -f pretty 'sprintf("%v %d", [1])' "1 %!d(MISSING)" ``` -------------------------------- ### Regal Linter Configuration Source: https://www.openpolicyagent.org/projects/regal/rules/testing/test-outside-test-package Example configuration for the 'test-outside-test-package' linter rule, setting its level to 'error'. ```yaml rules: testing: test-outside-test-package: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Internal vs. External Rule References Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/leaked-internal-reference This example contrasts a public rule 'allow' that can be referenced externally with an internal rule '_user_is_developer' that should not be. The underscore prefix conventionally denotes internal use. ```rego # `allow` may be referenced from outside the package allow if _user_is_developer # `_user_is_developer` should not be referenced from outside the package _user_is_developer if "developer" in input.users.roles ``` -------------------------------- ### GitHub Actions: Lint Rego Policies with Regal Source: https://www.openpolicyagent.org/projects/regal/cicd Use the `setup-regal` action to lint Rego policies in GitHub Actions. Specify a version for production workflows. ```yaml name: Regal Lint on: pull_request: jobs: lint-rego: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: open-policy-agent/setup-regal@v2 with: # For production workflows, use a specific version, like v0.22.0 version: latest - name: Lint run: regal lint --format=github ./policy ``` -------------------------------- ### Prefer '==' for equality comparison Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/prefer-equals-comparison This example demonstrates the preferred usage of the '==' operator for equality comparison in Rego. ```rego package policy allow if { input.request.method == "GET" # .. more conditions .. } ``` -------------------------------- ### Avoid Shadowing Built-ins with Imports Source: https://www.openpolicyagent.org/projects/regal/rules/imports/import-shadows-builtin This example demonstrates how importing packages with names that conflict with built-in OPA functions can shadow them. Avoid using names like 'print' or 'http' for your own packages if they conflict with built-ins. ```rego package policy # Shadows the built-in `print` function import data.print # Shadows the built-in `http.send` function import input.attributes.http ``` -------------------------------- ### Illustrate Potential Use of an Argument Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/argument-always-wildcard This example shows a scenario where an argument, initially defined as a wildcard, might be intended for use in one of the function's definitions. It highlights the importance of checking argument usage across all function clauses. ```rego package policy default authorized(_, _) := false authorized(user, _) if { # some logic to determine if authorized } # or authorized(_, request) if { # some further logic to determine if authorized } ``` -------------------------------- ### Regal Linter Configuration for dubious-print-sprintf Source: https://www.openpolicyagent.org/projects/regal/rules/testing/dubious-print-sprintf Configuration for the dubious-print-sprintf rule within the Regal linter. This example sets the rule level to 'error'. ```yaml rules: testing: dubious-print-sprintf: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Prefer Explicit Future Keywords Imports Source: https://www.openpolicyagent.org/projects/regal/rules/imports/implicit-future-keywords This example demonstrates the 'Prefer' pattern, using explicit imports for 'future.keywords.contains', 'future.keywords.if', and 'future.keywords.in'. This approach prevents potential conflicts with future OPA keywords. ```rego package policy import future.keywords.contains import future.keywords.if import future.keywords.in report contains violation if { not "developer" in input.user.roles violation := "Required role 'developer' missing" } ``` -------------------------------- ### Explicit Rule Scope for Incremental Definitions Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/ambiguous-scope This example explicitly sets the scope to 'rule' for each incremental rule definition when they have different descriptions. ```rego package policy # METADATA # description: allow is true if the user is admin # scope: rule allow if user_is_admin allow if public_resource ``` -------------------------------- ### Configuration for prefer-package-imports Rule Source: https://www.openpolicyagent.org/projects/regal/rules/imports/prefer-package-imports This configuration snippet shows how to set the level for the 'prefer-package-imports' rule and how to specify 'ignore-import-paths' for exceptions. ```yaml rules: imports: prefer-package-imports: # one of "error", "warning", "ignore" level: error ignore-import-paths: # Make an exception for some specific import paths - data.permissions.admin.users ``` -------------------------------- ### Avoid complex rule structure Source: https://www.openpolicyagent.org/projects/regal/rules/custom/prefer-value-in-head This example shows a rule structure that can be simplified by moving the assignment to the rule head. It is flagged by the linter. ```rego package policy pin_as_number := val if { is_number(input.pin_code) val := to_number(input.pin_code) } deny contains message if { not input.user message := "user attribute missing from input" } ``` -------------------------------- ### Perform Linting with Regal Source: https://www.openpolicyagent.org/projects/regal/integration Create a Regal linter instance, configure it with input modules, and call the `Lint` method. Handle any errors during the linting process and return the report. ```go regalInstance := linter.NewLinter().WithInputModules(&input) lintingReport, err := regalInstance.Lint(r.Context()) if err != nil { response.ErrorMessage = err.Error() writeJSON(w, http.StatusOK, response) return } ``` -------------------------------- ### Performance comparison: count vs. direct comparison Source: https://www.openpolicyagent.org/projects/regal/rules/performance/equals-over-count Illustrates the function calls involved in checking collection emptiness using `count` versus direct comparison, highlighting the performance difference. ```rego a := count(deny) > 0 # calls `count` and `gt` (`>`) b := count(input.roles) != 0 # calls `count` and `neq` (`!=`) c := count(data.users) == 0 # calls `count` and `equal` (`==`) ``` ```rego a := deny != set() # calls only `neq` (`!=`) b := input.roles != [] # calls only `neq` (`!=`) c := data.users == [] # calls only `equal` (`==`) ``` -------------------------------- ### Download Regal Binary for Linux (AMD64) Source: https://www.openpolicyagent.org/projects/regal Manually download the Regal binary for Linux on AMD64 architecture. ```bash curl -L -o regal https://github.com/open-policy-agent/regal/releases/latest/download/regal_Linux_x86_64 ``` -------------------------------- ### Policy without Entrypoint Annotation Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/no-defined-entrypoint This example shows a Rego policy that lacks an explicit entrypoint annotation. It is recommended to add metadata to clearly define entrypoints for better documentation and programmatic access. ```rego package policy default allow := false # Nothing wrong with this rule, but an # entrypoint should be documented as such allow if user_is_admin allow if public_resource_read user_is_admin if { some role in input.user.roles role in data.permissions.admin_roles } public_resource_read if { input.request.method == "GET" input.request.path[0] == "public" } ``` -------------------------------- ### Avoid unification operator for equality comparison Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/prefer-equals-comparison This example shows the incorrect usage of the unification operator for equality comparison. Prefer '==' for clarity. ```rego package policy allow if { input.request.method = "GET" # .. more conditions .. } ``` -------------------------------- ### Download Regal Binary for Linux (ARM64) Source: https://www.openpolicyagent.org/projects/regal Manually download the Regal binary for Linux on ARM64 architecture. ```bash curl -L -o regal https://github.com/open-policy-agent/regal/releases/latest/download/regal_Linux_arm64 ``` -------------------------------- ### Import Capabilities from File Source: https://www.openpolicyagent.org/projects/regal/configuration/capabilities Load capabilities from a local JSON file. This is useful for managing a complex set of capabilities or sharing them across projects. ```yaml capabilities: from: file: build/capabilities.json ``` -------------------------------- ### Avoid Detached Metadata Annotation Source: https://www.openpolicyagent.org/projects/regal/rules/style/detached-metadata This example shows a metadata annotation placed with extra newlines above the package declaration, which is considered a detached metadata style. ```rego package authz # METADATA # description: allow any requests by admin users allow if { "admin" in input.user.roles } ``` -------------------------------- ### Not flagging function calls with only-scalars enabled Source: https://www.openpolicyagent.org/projects/regal/rules/custom/prefer-value-in-head This example is not flagged when 'only-scalars' is true because the value assigned to 'message' is the result of a function call, not a direct scalar. ```rego deny contains message if { not input.user # value returned from a function call, not suggested if `only-scalars` is set to `true` message := sprintf("user attribute missing from input: %v", [input]) } ``` -------------------------------- ### Flagging scalar values with only-scalars enabled Source: https://www.openpolicyagent.org/projects/regal/rules/custom/prefer-value-in-head When the 'only-scalars' option is true, this example would be flagged because 'message' is assigned a scalar string value directly. ```rego deny contains message if { not input.user # value is a scalar message := "user attribute missing from input" } ``` -------------------------------- ### Configure Regal in nvim-lspconfig Source: https://www.openpolicyagent.org/projects/regal/editor-support Use this configuration to set up Regal as a language server within Neovim using the nvim-lspconfig plugin. Ensure Regal is installed separately. ```lua require('lspconfig').regal.setup() ``` -------------------------------- ### Prefer walk() with wildcard path Source: https://www.openpolicyagent.org/projects/regal/rules/performance/walk-no-path This snippet demonstrates the 'prefer' case where a wildcard variable (_) is used for the path argument in walk(), optimizing performance by avoiding unnecessary allocations. ```rego package policy allow if { # replacing `path` with a wildcard variable tells the evaluator that it won't # have to build the path array for each node `walk` traverses, thereby avoiding # unnecessary allocations walk(user.permissions, [_, value]) value.type == "role" value.name == "admin" } ``` -------------------------------- ### Regal Linter Configuration Example Source: https://www.openpolicyagent.org/projects/regal/rules/style/function-arg-return This configuration snippet shows how to set the level for the 'function-arg-return' rule and specify functions to be excepted from it. The `walk` function is excepted by default. ```yaml rules: style: function-arg-return: # one of "error", "warning", "ignore" level: error # list of function names to ignore # * by default, walk is excepted from this rule # * note that `print` is always ignored as it does not return a value except-functions: - walk ``` -------------------------------- ### Avoid External References in OPA Functions Source: https://www.openpolicyagent.org/projects/regal/rules/style/external-reference This example demonstrates a function that depends on 'input' and 'data', which are considered external references. Prefer functions that only depend on their arguments. ```rego package policy # Depends on both `input` and `data` is_preferred_login_method(method) if { preferred_login_methods := {login_method | some login_method in data.authentication.all_login_methods login_method in input.user.login_methods } method in preferred_login_methods } ``` -------------------------------- ### Avoid Messy Incremental Rules Source: https://www.openpolicyagent.org/projects/regal/rules/style/messy-rule This example shows a 'messy' rule where incremental definitions are separated. Grouping these definitions improves code clarity and editor tooling. ```rego package policy allow if something unrelated_rule if { # <--- this rule is breaking up allow # ... } allow if something_else # <--- should be with the first allow ``` -------------------------------- ### Regal Linter Configuration Source: https://www.openpolicyagent.org/projects/regal/rules/imports/import-shadows-builtin This example shows how to configure the import-shadows-builtin linter rule in Regal. You can set the 'level' to 'error', 'warning', or 'ignore' to control how violations are reported. ```yaml rules: imports: import-shadows-builtin: # one of "error", "warning", "ignore" level: error ``` -------------------------------- ### Example: Country Code Function Source: https://www.openpolicyagent.org/projects/regal/rules/custom/narrow-argument Illustrates a function that depends on a specific field ('user.country') within a larger object. The rule suggests narrowing the argument to just 'country'. ```rego package policy country_code(user) := 61 if user.country == "Australia" country_code(user) := 81 if user.country == "Japan" ``` -------------------------------- ### Reference Prefix Narrowing: Internal User Source: https://www.openpolicyagent.org/projects/regal/rules/custom/narrow-argument This example shows how the 'narrow-argument' rule can identify a common prefix ('context.user') across different references within a function and suggest narrowing the argument to that prefix. ```rego package policy internal_user(context) if endswith(context.user.email, "@acmecorp.com") internal_user(context) if "staff" in context.user.roles ``` -------------------------------- ### Refactor Function using Pattern Matching Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/equals-pattern-matching This example shows the refactored version of the 'normalize_role' function, utilizing pattern matching on arguments to achieve the same result more concisely. ```rego package policy normalize_role("administrator") := "admin" normalize_role("root") := "admin" ``` -------------------------------- ### Prefer Correct Metadata Attribute Structure Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/invalid-metadata-attribute This example demonstrates the correct way to define custom metadata attributes. Place them under the '# custom:' key, which acts as a map for arbitrary key-value pairs, ensuring they are recognized as metadata annotations. ```rego # METADATA # title: Main policy routing requests to other policies based on input # custom: # category: Routing package router ``` -------------------------------- ### Avoid Equality Checks in Rule Body Source: https://www.openpolicyagent.org/projects/regal/rules/idiomatic/equals-pattern-matching This example demonstrates the anti-pattern of using equality checks within the rule body, which can be simplified using pattern matching. ```rego package policy readable_number(x) := "one" if x == 1 readable_number(x) := "two" if x == 2 ``` -------------------------------- ### Prefer Deferring Assignment - Rego Source: https://www.openpolicyagent.org/projects/regal/rules/performance/defer-assignment This example demonstrates the preferred way to structure assignments. The assignment `resp := http.send(...)` is placed after the check `input.user.name in allowed_users`, which does not depend on `resp`. This ensures the potentially expensive HTTP request is only made when necessary, improving performance and readability. ```rego package policy allow if { input.user.name in allowed_users # the next expression *does* depend on `resp` resp := http.send({"method": "GET", "url": "http://example.com"}) resp.status_code == 200 # more done with response here } ``` -------------------------------- ### Verify Regal Binary Checksum Source: https://www.openpolicyagent.org/projects/regal Verify the integrity of a downloaded Regal binary using its SHA256 checksum. This example demonstrates verification for the macOS ARM64 binary. ```bash BINARY_NAME=regal_Darwin_arm64 curl -L -O https://github.com/open-policy-agent/regal/releases/latest/download/$BINARY_NAME curl -L -O https://github.com/open-policy-agent/regal/releases/latest/download/$BINARY_NAME.sha256 shasum -c $BINARY_NAME.sha256 ``` -------------------------------- ### Avoid Invalid Metadata Attribute Source: https://www.openpolicyagent.org/projects/regal/rules/bugs/invalid-metadata-attribute This example shows an incorrect way to define metadata attributes. Custom attributes like 'category' should not be placed directly under '# METADATA'. ```rego # METADATA # title: Main policy routing requests to other policies based on input # category: Routing package router ``` -------------------------------- ### Avoid `with` for Mocking in Production Policies Source: https://www.openpolicyagent.org/projects/regal/rules/performance/with-outside-test-context This example demonstrates the incorrect use of `with` outside of a test context. The `allowed_user` rule, which involves an expensive JWT verification, will be re-evaluated for each user because of the `with` clause, preventing OPA's caching mechanism from being effective. ```rego package policy allow if { some user in data.users # mock input to pass data to `allowed_user` rule allowed_user with input as {"user": user} } verified := io.jwt.verify_rs256(input.token, data.keys.verification_key) allowed_user := input.user if { # this expensive rule will be evaluated for each user! verified "admin" in input.user.roles } ```