PageSourceSearch

https://www.openpolicyagent.org/assets/js/c8f5dfe7.6a12a604.js

js openpolicyagent.org collected 2026-09-24 08:28:36 UTC 6,456 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkopa_website=self.webpackChunkopa_website||[]).push([[9495],{28453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var r=n(96540);const i={},o=r.createContext(i);function s(e){const t=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(o.Provider,{value:t},e.children)}},85576:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"architecture","title":"architecture","description":"Architecture | Regal","source":"@site/projects/regal/architecture.md","sourceDirName":".","slug":"/architecture","permalink":"/projects/regal/architecture","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"sidebar_position":4,"sidebar_label":"Architecture"},"sidebar":"autoSidebar","previous":{"title":"Fixing Violations","permalink":"/projects/regal/fixing"},"next":{"title":"CLI","permalink":"/projects/regal/cli"}}');var i=n(74848),o=n(28453);const s={sidebar_position:4,sidebar_label:"Architecture"},l="Architecture",a={},c=[{value:"High-level Overview",id:"high-level-overview",level:2},{value:"Rego Rules Evaluation",id:"rego-rules-evaluation",level:2}];function h(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.R)(),...e.components},{Head:n}=t;return n||function(e,t){throw new Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Head",!0),(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n,{children:(0,i.jsx)("title",{children:"Architecture | Regal"})}),"\n",(0,i.jsx)(t.header,{children:(0,i.jsx)(t.h1,{id:"architecture",children:"Architecture"})}),"\n",(0,i.jsx)(t.p,{children:'Or "How does Regal work?"'}),"\n",(0,i.jsxs)(t.p,{children:["As you might have\n",(0,i.jsx)(t.a,{href:"https://web.archive.org/web/https://www.styra.com/blog/guarding-the-guardrails-introducing-regal-the-rego-linter/",children:"read"}),",\nRegal ",(0,i.jsx)(t.a,{href:"https://web.archive.org/web/https://www.styra.com/blog/linting-rego-with-rego/",children:"uses Rego for linting Rego"})," \u2014 or rather,\nRego policies turned into a JSON representation of their abstract syntax tree (AST)."]}),"\n",(0,i.jsx)(t.h2,{id:"high-level-overview",children:"High-level Overview"}),"\n",(0,i.jsxs)(t.p,{children:["When running Regal against a directory, like ",(0,i.jsx)(t.code,{children:"regal lint my-policies/"}),", Regal does the following:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:["For each source file provided for linting, Regal parses the Rego into its AST representation. This AST representation\nis then turned into JSON and provided as the ",(0,i.jsx)(t.strong,{children:"input"})," variable to the linter rules."]}),"\n",(0,i.jsxs)(t.li,{children:["Each linter rule (and there are almost 40 of them at the time of writing this) uses the ",(0,i.jsx)(t.strong,{children:"input"}),", which contains\ninformation such as the package name, what imports are used, and all the rules and the expressions they contain, to\ndetermine whether the Rego policy linted contains any violations against the rule. An example could be a rule that\n",(0,i.jsx)(t.a,{href:"https://www.openpolicyagent.org/projects/regal/rules/bugs/rule-shadows-builtin",children:"forbids shadowing"}),"\n(i.e. using the same name as) built-in functions and operators."]}),"\n",(0,i.jsxs)(t.li,{children:["Since rule bodies aren\u2019t necessarily flat, but may contain nested bodies of constructs such as\n",(0,i.jsx)(t.a,{href:"https://www.openpolicyagent.org/docs/policy-language/#comprehensions",children:"comprehensions"})," or\n",(0,i.jsx)(t.a,{href:"https://www.openpolicyagent.org/docs/policy-language/#every-keyword",children:"every"})," blocks, many linter rules need to\ntraverse all expressions in order to find what they are looking for. This is normally done with the help of the\nbuilt-in ",(0,i.jsx)(t.a,{href:"https://www.openpolicyagent.org/docs/policy-reference/#graph",children:"walk"})," function."]}),"\n",(0,i.jsx)(t.li,{children:"Traversing huge AST structures \u2014 and some policies contain millions of AST nodes! \u2014 takes time. This isn\u2019t noticeable\nwhen linting a single file, but for some of the largest policy repositories out there, with several thousands of\npolicy files and tests, the cost may be prohibitive. To alleviate this, Regal is implemented to process files\nconcurrently to minimize the impact of IO bound tasks, and to make use of multiple cores when available."}),"\n",(0,i.jsxs)(t.li,{children:["The result of linting each file is eventually collected and compiled into a linter report, which is presented to the\nuser in one of the available ",(0,i.jsx)(t.a,{href:"https://www.openpolicyagent.org/projects/regal#output-formats",children:"output formats"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"rego-rules-evaluation",children:"Rego Rules Evaluation"}),"\n",(0,i.jsxs)(t.p,{children:["The main entrypoint for Rego rule evaluation is unsurprisingly found in\n",(0,i.jsx)(t.a,{href:"https://github.com/open-policy-agent/regal/blob/main/bundle/regal/main/main.rego",children:"main.rego"}),", in which we query the ",(0,i.jsx)(t.code,{children:"report"}),"\nrule from the ",(0,i.jsx)(t.a,{href:"https://github.com/open-policy-agent/regal/blob/main/pkg/linter/linter.go",children:"Go"})," application."]}),"\n",(0,i.jsxs)(t.p,{children:["The ",(0,i.jsx)(t.code,{children:"report"})," rule in turn uses\n",(0,i.jsx)(t.a,{href:"https://web.archive.org/web/https://www.styra.com/blog/dynamic-policy-composition-for-opa/",children:"dynamic policy composition"}),"\nto query all rules named\n",(0,i.jsx)(t.code,{children:"report"})," under ",(0,i.jsx)(t.code,{children:"data.regal.rules[category][title]"})," for built-in rules, and ",(0,i.jsx)(t.code,{children:"data.custom.regal.rules[category][title]"}),"\nfor custom rules. The violations reported from each rule is added to the ",(0,i.jsx)(t.code,{children:"report"})," set and sent back to the application,\nwhich will compile a final report and present it to the user."]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.