{"id":119045,"date":"2026-07-06T10:47:16","date_gmt":"2026-07-06T05:17:16","guid":{"rendered":"https:\/\/www.guvi.in\/blog\/?p=119045"},"modified":"2026-07-06T10:47:18","modified_gmt":"2026-07-06T05:17:18","slug":"opa-open-policy-agent-tutorial","status":"publish","type":"post","link":"https:\/\/www.guvi.in\/blog\/opa-open-policy-agent-tutorial\/","title":{"rendered":"OPA (Open Policy Agent) Tutorial: Policy as Code Made Simple"},"content":{"rendered":"\n<p>Every app needs rules. Who can delete a record? Which containers are allowed to run? Can this Terraform plan deploy a public S3 bucket? Without OPA, those rules live scattered across application code and config files with no central audit trail. This OPA (Open Policy Agent) tutorial shows you how to centralise all of that into one place using policy as code. By the end, you will have OPA installed, a Rego policy written, and a clear picture of where it fits in a real system.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>TL;DR Summary<\/strong><\/h2>\n\n\n\n<ul>\n<li>This OPA (Open Policy Agent) tutorial shows you how to install OPA, write your first Rego policy, and evaluate it against real input.<\/li>\n\n\n\n<li>OPA decouples policy decisions from your application code so you never hardcode authorization logic again.<\/li>\n\n\n\n<li>Policies are written in Rego, a declarative language that reads almost like plain English once you know the basics.<\/li>\n\n\n\n<li>OPA is free, open-source, and a CNCF graduated project used by Netflix, Pinterest, and Atlassian.<\/li>\n\n\n\n<li>You can run OPA as a CLI tool locally or as a REST API server that your apps query for decisions.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What is OPA?<\/strong><\/h2>\n\n\n\n<p>OPA (Open Policy Agent) is a free, open-source policy engine that separates the question &#8220;is this allowed?&#8221; from the application code that enforces the answer.<\/p>\n\n\n\n<p>Your application sends a JSON input to OPA, such as the user&#8217;s role and the action they want to perform. OPA evaluates that input against your Rego policies and returns a decision, typically <strong>allow: true<\/strong> or <strong>allow: false<\/strong>. Your application enforces it. OPA only decides, never enforces. This means you update policies without touching application code, test them independently, and audit every decision from one place.<\/p>\n\n\n\n<p>Policy as code sits at the intersection of DevOps, security, and platform engineering, one of the highest-growth skill clusters in 2026. HCL GUVI&#8217;s<a href=\"https:\/\/www.guvi.in\/zen-class\/devops-course\/?utm_source=blog&amp;utm_medium=hyperlink&amp;utm_campaign=opa-open-policy-agent-tutorial\" target=\"_blank\" rel=\"noreferrer noopener\"> DevOps Course<\/a> covers CI\/CD, infrastructure automation, and security integration with real-world projects and NSDC certification.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>OPA (Open Policy Agent) Tutorial: Installation<\/strong><\/h2>\n\n\n\n<p>OPA ships as a single binary with no runtime dependencies.<\/p>\n\n\n\n<ul>\n<li><strong>macOS:<\/strong> <strong>brew install opa<\/strong><\/li>\n\n\n\n<li><strong>Linux:<\/strong> <strong>curl -L -o opa https:\/\/openpolicyagent.org\/downloads\/latest\/opa_linux_amd64_static &amp;&amp; chmod +x opa &amp;&amp; sudo mv opa \/usr\/local\/bin\/<\/strong><\/li>\n\n\n\n<li><strong>Windows:<\/strong> Download the binary from the official OPA releases page on GitHub and add it to your PATH.<\/li>\n\n\n\n<li><strong>Docker:<\/strong> <strong>docker pull openpolicyagent\/opa<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Confirm it worked by running <strong>opa version<\/strong>, which prints the current version number.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Understanding Rego in 2 Minutes<\/strong><\/h2>\n\n\n\n<p>Rego (pronounced &#8220;ray-go&#8221;) is OPA&#8217;s policy language. It is declarative, meaning you describe what should be true, not how to compute it.<\/p>\n\n\n\n<p>Three things to know before writing your first policy:<\/p>\n\n\n\n<ul>\n<li><strong>Everything is data.<\/strong> Both your input and your policy logic work with JSON objects.<\/li>\n\n\n\n<li><strong>Rules evaluate to true or false.<\/strong> A rule like <strong>allow<\/strong> is true only when all its conditions are met.<\/li>\n\n\n\n<li><strong>Undefined means denied by default.<\/strong> If OPA cannot prove a rule is true, it treats it as false.<\/li>\n<\/ul>\n\n\n\n<p>That last point is important. OPA follows a closed-world assumption: if you have not explicitly allowed something, it is denied. You opt into permission, never out of it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Writing Your First Policy<\/strong><\/h2>\n\n\n\n<p>Create a file called <strong>policy.rego<\/strong> with the following content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package authz\n\nimport rego.v1\n\ndefault allow := false\n\nallow if {\n    input.user.role == \"admin\"\n}\n<\/code><\/pre>\n\n\n\n<p>This policy does one thing. It denies everything by default, then allows the request only if the user&#8217;s role is &#8220;admin.&#8221; Simple, readable, and completely separate from any application code.<\/p>\n\n\n\n<p>Now create an input file called <strong>input.json<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"user\": {\n    \"name\": \"alice\",\n    \"role\": \"admin\"\n  },\n  \"action\": \"delete\"\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Evaluating a Policy with the CLI<\/strong><\/h2>\n\n\n\n<p>This is the core of any OPA (Open Policy Agent) tutorial: actually running a policy evaluation.<\/p>\n\n\n\n<p>Run this command in your terminal:<\/p>\n\n\n\n<p><strong>opa eval -d policy.rego -i input.json &#8220;data.authz.allow&#8221;<\/strong><\/p>\n\n\n\n<p>OPA returns:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"result\": &#91;\n    {\n      \"expressions\": &#91;\n        {\n          \"value\": true,\n          \"text\": \"data.authz.allow\"\n        }\n      ]\n    }\n  ]\n}\n<\/code><\/pre>\n\n\n\n<p>The value is <strong>true<\/strong> because the input user has the role &#8220;admin.&#8221; Change the role to &#8220;viewer&#8221; and run it again. The result becomes <strong>false<\/strong> immediately, with no code change needed anywhere else in your system.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Running OPA as a Server<\/strong><\/h2>\n\n\n\n<p>For real applications, OPA runs as a REST API server your services query over HTTP.<\/p>\n\n\n\n<p>Start it with: <strong>opa run &#8211;server policy.rego<\/strong><\/p>\n\n\n\n<p>OPA listens on port 8181. Query it with:<\/p>\n\n\n\n<p><strong>curl -X POST http:\/\/localhost:8181\/v1\/data\/authz\/allow &#8211;data &#8216;{&#8220;input&#8221;: {&#8220;user&#8221;: {&#8220;role&#8221;: &#8220;admin&#8221;}, &#8220;action&#8221;: &#8220;delete&#8221;}}&#8217;<\/strong><\/p>\n\n\n\n<p>OPA responds with <strong>{&#8220;result&#8221;: true}<\/strong>. Your application reads the result and enforces it. Policy logic lives entirely in Rego. Application code stays clean.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Where OPA Fits in Your Stack<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Use Case<\/strong><\/td><td><strong>What OPA Checks<\/strong><\/td><\/tr><tr><td>API authorization<\/td><td>Can this user call this endpoint?<\/td><\/tr><tr><td>Kubernetes admission<\/td><td>Does this pod spec meet security policies?<\/td><\/tr><tr><td>Terraform validation<\/td><td>Does this plan violate compliance rules?<\/td><\/tr><tr><td><a href=\"https:\/\/www.guvi.in\/blog\/understanding-ci-cd\/\" target=\"_blank\" rel=\"noreferrer noopener\">CI\/CD<\/a> pipelines<\/td><td>Does this container image come from an approved registry?<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<div style=\"background-color: #099f4e; border: 3px solid #110053; border-radius: 12px; padding: 18px 22px; color: #FFFFFF; font-size: 18px; font-family: Montserrat, Helvetica, sans-serif; line-height: 1.6; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); max-width: 750px; margin: 22px auto;\">\n  <h3 style=\"margin-top: 0; font-size: 22px; font-weight: 700; color: #ffffff;\">\ud83d\udca1 Did You Know?<\/h3>\n  <ul style=\"padding-left: 20px; margin: 10px 0;\">\n    <li>OPA is a CNCF graduate project.<\/li>\n    <li>Netflix was one of the earliest adopters, using OPA to enforce authorization across thousands of microservices.<\/li>\n  <\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Common Mistakes to Avoid<\/strong><\/h2>\n\n\n\n<ul>\n<li><strong>Forgetting that undefined means denied.<\/strong> Always set <strong>default allow := false<\/strong> explicitly, then build the conditions that make it true. Without this, valid requests get silently blocked and beginners cannot tell why.<\/li>\n\n\n\n<li><strong>Not writing tests for your policies.<\/strong> OPA has a built-in test framework. Run <strong>opa test policy_test.rego<\/strong> before deploying. Untested policy changes can silently break access for real users.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>This OPA (Open Policy Agent) tutorial walks you through the full beginner workflow: installing OPA, understanding how Rego works, writing a real policy, evaluating it against input, and running OPA as a server your applications can query. The core shift OPA enables is simple but powerful: policy logic moves out of scattered application code and into one testable, auditable, version-controlled place.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>FAQs<\/strong><\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1782366492428\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>1. Is OPA free to use?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. OPA is fully open-source under Apache 2.0. Everything in this OPA (Open Policy Agent) tutorial requires no paid account.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782366512010\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>2. What language are OPA policies written in?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Rego (pronounced &#8220;ray-go&#8221;), a declarative language built specifically for expressing policy logic over JSON data.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782366533603\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>3. Is OPA only for Kubernetes?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. OPA works with any system that sends JSON over HTTP, including API authorization, Terraform validation, and CI\/CD pipeline checks.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782366550176\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>4. What happens when OPA cannot evaluate a rule?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>It is treated as undefined, which defaults to denied. Always set <strong>default allow := false<\/strong> explicitly and build conditions that make it true.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782366569243\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>5. Can I run OPA in GitHub Actions?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. Use <strong>open-policy-agent\/setup-opa<\/strong> and run <strong>opa test<\/strong> on every pull request to catch policy regressions automatically.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every app needs rules. Who can delete a record? Which containers are allowed to run? Can this Terraform plan deploy a public S3 bucket? Without OPA, those rules live scattered across application code and config files with no central audit trail. This OPA (Open Policy Agent) tutorial shows you how to centralise all of that [&hellip;]<\/p>\n","protected":false},"author":65,"featured_media":120908,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[621],"tags":[],"views":"50","authorinfo":{"name":"Jebasta","url":"https:\/\/www.guvi.in\/blog\/author\/jebasta\/"},"thumbnailURL":"https:\/\/www.guvi.in\/blog\/wp-content\/uploads\/2026\/06\/OPA-Open-Policy-Agent-Tutorial-300x116.webp","_links":{"self":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/119045"}],"collection":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/users\/65"}],"replies":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/comments?post=119045"}],"version-history":[{"count":2,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/119045\/revisions"}],"predecessor-version":[{"id":120919,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/119045\/revisions\/120919"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media\/120908"}],"wp:attachment":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media?parent=119045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/categories?post=119045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/tags?post=119045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}