Policy Enforcement using OPA

Reading Time: 3 minutes


Hi Guys, In this blog we are going to explore OPA and will run the sample policy on OPA server.
The OPA(Open Policy Agent) is an open source, general-purpose policy engine that unifies policy enforcement across the stack. OPA provides declarative language Rego which let us write policy for decision making of micro services. We use OPA for enforcing policies in microservices, kubernetes, API gateways etc.
Basically, we use OPA for authorization purpose. Don’t get confused b/w authentication and authorization. The authentication will determine whether the person is valid user or not, on the other hand the authorization will determine What permission do users have? means how much resources a role can access, where role can be anything like admin, payer etc.

Working of OPA

OPA generates decision on input JSON data(Request) against the policy and data. The Data could be anything like – static data or dynamic data (Mysql).
As per diagram-

This image has an empty alt attribute; its file name is untitled-diagram-5.png

Here,User Alice sends request to access /getAllCustomer endpoint then the application will ask OPA that Alice is allowed to access /getAllCustomer if OPA responds “NO” then Alice can’t access /getAllCustomer endpoint. The decision wholly depends on rego policy.

Rego policy

OPA use Rego for defining policy that is easy to read and write.
example.rego

    package authz
    default allow = false
    allow {
        role:=roles_for_user
        required_roles[role]
    }
    roles_for_user= r {
        r := user_roles[input.user][_]
    }
    required_roles[role] {
        perm := role_perms[role][_]
        perm.method = input.method
        perm.path = input.path
    }
    
    user_roles = {
        "alice": ["guest"],
        "bob": ["admin"]
    }
    
    role_perms = {
        "guest": [
             {"method": "GET",  "path": "/productpage"},
             {"method": "GET",  "path": "/getAllCustomer"}
        ],
        "admin": [
            {"method": "POST",  "path": "/productpage"},
            {"method": "GET",  "path": "/api/v1/products"}
        ],
    }

OPA take input requests as JSON format, for this policy the input request can be curl –user alice:password -i http://productpage and the request components changed into JSON format, will look like as –

input.json

{
  "method" : "GET",
    "path" : "/getAllCustomer",
    "user" : "alice"
}

Now let’s understand the components of this policy –

  • Here we are using role based authorization ,where user_roles defines two roles guest and admin.
  • role_perms specifies that which role can access which endpoint of micro-service. /productpage is accessible to both roles but guest role can only see the productpage because the input method is GET ,where as for admin role the method is POST.
  • roles_for_user is user defined function whose input is none and output can be guest or admin depends on the input.user value.
  • required_roles is rule which takes a role as object and return the object as output.It will also match the input.path and input.method.
  • The policy decision depends on allow variable value, we have set default allow = false, it means that no one can access anything until required_roles will be true, so it’s safe to set default values.

OPA RUN

OPA includes a REPL (Read-Eval-Print-Loop). We can use the REPL to experiment with policies. Let’s run above policy in REPL. Download the OPA from here .

  • First save the above policy in a rego file and run
    >> ./opa run file_name.rego.
  • After starting the REPL you need to enter your rego file package name
    >>package authz
  • Then, we will provide input data in JSON format like –
    >>input := {“method”: “GET”, “path”:”/api/v1/products”, “user”:”alice”}
  • Now check the allow rule status as the allow is still false because according to policy alice is not allowed to access /api/v1/products endpoint.
  • Let’s change the input JSON data
    >>input := {“method”: “GET”, “path”:”/getAllCustomer”, “user”:”alice”}
  • As you can see the allow rule is true because alice is allowed to access /getAllCustomer.
This image has an empty alt attribute; its file name is blog_final.png

Wrap Up

I hope you get some insights about OPA and how OPA works. Here are some key Points:

  • Rego is the policy language not programming language which lets you write policy about multiple stacks.
  • we supply JSON data as input to OPA for making decisions.
  • Rego logic is all about queries. queries will find value that makes the condition true.

You can play around this policy here in Rego playground.
https://play.openpolicyagent.org/p/XHnJ4Fg6zH
So this is how OPA policy works.

NOTE:
I’ll post more blogs on OPA soon. Stay Tuned.

Thanks for Reading!!!
For more reference you can refer here.

This image has an empty alt attribute; its file name is footer-2.jpg

Written by 

Lokesh Aggarwal is a software Consultant trainee with 6 months of experience at Knoldus Inc.

Discover more from Knoldus Blogs

Subscribe now to keep reading and get access to the full archive.

Continue reading