Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How to deploy Open Policy Agent for API authorization

April 13, 2023
Jorge Balderas
Related topics:
APIsCI/CDKubernetes
Related products:
Red Hat OpenShift

Share:

    In this article, we will demonstrate how to deploy Open Policy Agent in server mode into a Red Hat OpenShift cluster. We will then set up simple Rego policies to validate a JWT token and provide authorization to specific APIs.

    About Open Policy Agent

    Open Policy Agent (OPA) is a Cloud Native Computing Foundation (CNCF) graduated project. OPA is an open source policy agent ideal for decoupling authorization from cloud-native applications, APIs, Kubernetes resources, and CI/CD pipelines, along with other artifacts. OPA uses Rego, a declarative language, to define policies as code. Applications and services can use OPA to query, provide an input evaluated against predefined policies, and provide a policy decision, as shown in the Figure 1 diagram.

    A diagram depicting the flow for evaluating policies by Open Policy Agent.
    Figure 1: The flow for evaluating policies by Open Policy Agent.

    How to deploy OPA using REST API

    OPA provides 3 primary options of deploying OPA to evaluate policies:

    1. REST API: Deployed separate from your application or service.
    2. Go library: Requires Go to deploy as a side car alongside your application.
    3. WebAssembly (WASM): Deployed alongside your application regardless of the language.

    In this article, we will demonstrate the REST API option and focus on the use cases for leveraging OPA for API authorization. We will describe each step for deploying OPA, creating simple policies, and then evaluating the using the OPA REST API.

    Prerequisites

    To complete this demo you will need the following prerequisites:

    • Red Hat OpenShift cluster: For this demo, we use OCP 4.12. However, any 4.x version should work. Alternatively, you can use any Kubernetes cluster. The instructions in this demo are specific to OpenShift.
    • OpenShift CLI: You can download the OpenShift CLI (oc) from your cluster as specified in the OpenShift documentation.
    • Git bash or shell/bash terminal: Although not required, the commands presented in this article assume a Linux shell syntax.

    Deploying OPA in 2 steps

    To deploy OPA as a REST API, first create three Kubernetes resources.

    Step 1: Create Kubernetes definition files

    Create a file named deployment.yaml with the following content:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: opa
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: opa
      template:
        metadata:
          labels:
            app: opa
        spec:
          containers:
            - name: opa
              securityContext:
                capabilities:
                  drop: ["ALL"]
                runAsNonRoot: true
                allowPrivilegeEscalation: false
                seccompProfile:
                  type: "RuntimeDefault"
              image: openpolicyagent/opa:0.50.1-debug
              args:
                - "run"
                - "--watch"
                - "--ignore=.*"
                - "--server"
                - "--skip-version-check"
                - "--log-level"
                - "debug"
                - "--set=status.console=true"
                - "--set=decision_logs.console=true"
    

    Most of these parameters are optional, but we included them for higher verbosity level which is helpful for troubleshooting. You can view the purpose of these parameters in the documentation for the opa run command.

    Important observations:

    • We are using OPA version 0.50.1, the latest available at the time of writing. We are using the -debug version of the OPA image which includes a CLI that can be useful for inspecting the deployed files. However for a production release it is recommended that you use the -rootless version of this image.
    • The --server parameter is what tells OPA to run in server mode so that it can listen for REST API requests.

    Next, create a file named service.yaml which will expose OPA as a service within the cluster as follows:

    kind: Service
    apiVersion: v1
    metadata:
      labels:
        app: opa
      name: opa
    spec:
      selector:
        app: opa
      ports:
      - name: http
        protocol: TCP
        port: 80
        targetPort: 8181

    Finally, create a file named route.yaml which will expose OPA service as follows:

    kind: Route
    apiVersion: route.openshift.io/v1
    metadata:
      labels:
        app: opa
      name: opa
    spec:
      selector:
        matchLabels:
          app: opa
      to:
        kind: Service
        name: opa
      port:
        targetPort: http

    Note: We are using http for demo purposes. In a production environment, ensure that you are using https.

    Step 2: Deploy Kubernetes resources to OpenShift cluster

    First, log in to your OpenShift cluster by obtaining a token from your cluster using the OC CLI as follows:

    oc login --token=<sha256~token> --server=<your-openshift-cluster-api-url>

    Next, create a new project for this cluster. We export the NAMESPACE name as a variable so that it can be used in subsequent steps.

    NAMESPACE=opa
    oc new-project $NAMESPACE

    Then, create the resources using the files created previously as follows:

    oc apply -f deployment.yaml -n $NAMESPACE
    oc apply -f service.yaml -n $NAMESPACE
    oc apply -f route.yaml -n $NAMESPACE

    To get the route that was created, issue the following command:

    echo http://$(oc get route $NAMESPACE -o jsonpath='{.spec.host}')

    Navigate to the route in your browser to view the OPA home screen (Figure 2), which allows you to evaluate a policy.

    A screenshot of the OPA home screen.
    Figure 2: The OPA home screen.

    Policy evaluation 3-step demo

    Now, we need to define and load policies for demo purposes.

    Step 1: Create common JWT policy

    One of the nice features about Rego is that it provides several built-in functions. One set of functions that is particularly helpful is the one for JWT (JSON Web Token) token validation. The policy will decode a JWT token, and then validate it against the secret used to sign the token.

    We will use a shared secret for demo purposes. However, the JWT function can verify the token using JWKS (JSON Web Key Sets). Anybody familiar with the JWKS verification flow knows that it is not a trivial implementation. The built-in verify token functions will take care of retrieving KIDs (key ids) from the corresponding well known URL, and it even provides caching capabilities to speed up that process.

    First, create a file named jwt.regoas follows:

    package com.redhat.common.jwt
    
    import input
    import future.keywords.in
    
    valid_token(jwt) = token {
        [header, payload, sig]:= io.jwt.decode(jwt)
    
        valid := io.jwt.verify_hs256(jwt, 'secret')
        token := {"valid": valid,
                    "name": payload.name}
    }

    As you can see from this Rego file, it is primarily JSON, except for the import/package headers. Again, we are using a shared secret, which is done only for demo purposes.

    Next, load this policy using the create policy REST API from the OPA as follows:

    OPA_URL=http://$(oc get route $NAMESPACE -o jsonpath='{.spec.host}')
    cat jwt.rego | curl --location --request PUT "${OPA_URL}/v1/policies/com/redhat/common/jwt" --header 'Content-Type: text/plain' --data-binary '@-'

    Deconstructing this URL:

    • ${OPA_URL}: The base OPA URL.
    • v1/policies: The default location for policies.
    • com/redhat/common/jwt: This is how policies are retrieved. Notice that it matches the package name (i.e., com.redhat.common.jwt), but using a different character separator. There is no hard rule that these should match, but I have found it a good practice to follow to make it easier to organize policies.

    Step 2: Create API authorization policy

    In this step, we will create a policy that uses the common JWT policy loaded in step 1. Create a file named api.rego with the following content:

    package com.redhat.myapi
    
    import data.com.redhat.common.jwt.valid_token
    
    default allow := { #disallow requests by default
        "allowed": false,
        "reason": "unauthorized resource access"
    }
    
    allow := { "allowed": true } { #allow GET requests to viewer user
        input.method == "GET"
        input.path[1] == "policy"
        token := valid_token(input.identity)
        token.name == "viewer"
        token.valid
    }
    
    allow := { "allowed": true } { #allow POST requests to admin user 
        input.method == "POST"
        input.path[1] == "policy"
        token := valid_token(input.identity)
        token.name == "admin"
        token.valid
    }

    Notice the import to the valid_token function. It matches the package used previously, but it is prepended with data.

    Next, load this policy with a similar curl command as follows:

    cat api.rego | curl --location --request PUT "${OPA_URL}/v1/policies/com/redhat/myapi" --header 'Content-Type: text/plain' --data-binary '@-'

    Step 3: Evaluate the policy

    To evaluate the policy, we will need to get a valid JWT token. You can get one from jwt.io, the only requirement is that you enter the same secret from the jwt policy into the <your-256-bit-secret> in the Verify Signature section.

    Additionally, change the name in the Payload section to viewer and copy the generated token.

    Repeat these steps and enter admin as the name, and then save both tokens in a file from where you can copy values.

    Next, create a request to test a successful viewer request named viewer-allowed.json:

    {
        "input": {
            "identity": "<viewer token>",
            "path": "policy",
            "method": "GET"
        }
    }

    Execute the curl command (notice the url changes from policy to data):

    cat viewer-not-allowed.json | curl --location --request POST "${OPA_URL}/v1/data/com/redhat/myapi" --header 'Content-Type: application/json' --data-binary '@-'

    Expect an allowed true output similar to the following:

    {
        "result": {
            "allow": {
                "allowed": true
            }
        }
    }

    Next, create a request to test a not allowed viewer request named viewer-not-allowed.json by changing the method to POST.

    {
        "input": {
            "identity": "<viewer token>",
            "path": "policy",
            "method": "POST"
        }
    }

    Execute the following curl command and expect the output to include allowed false.

    cat viewer-not-allowed.json | curl --location --request POST "${OPA_URL}/v1/data/com/redhat/myapi" --header 'Content-Type: application/json' --data-binary '@-'
    
    {"result":{"allow":{"allowed":false,"reason":"unauthorized resource access"}}

    Next, create an admin-allowed.json file with the following request:

    {
        "input": {
            "identity": "<admin jwt token>",
            "path": "policy",
            "method": "POST"
        }
    }

    Execute the curl command and expect the output to include allowed true as follows:

    cat admin-allowed.json | curl --location --request POST "${OPA_URL}/v1/data/com/redhat/myapi" --header 'Content-Type: application/json' --data-binary '@-'

    Open Policy Agent easily deployed

    This article demonstrated how to easily deploy the Open Policy Agent into an OpenShift cluster and load a common JWT policy with an API policy. We also described how policy evaluation works within OPA. This demo showcased a small set of the capabilities and potential that OPA offers, providing an introduction to OPA and Rego policies.

    Last updated: September 19, 2023

    Related Posts

    • Create an Azure Red Hat OpenShift cluster in less than 5 minutes

    • Set up an OpenShift cluster to deploy an application in odo CLI

    • API login and JWT token generation using Keycloak

    • Authentication and authorization using the Keycloak REST API

    Recent Posts

    • Integrate Red Hat AI Inference Server & LangChain in agentic workflows

    • Streamline multi-cloud operations with Ansible and ServiceNow

    • Automate dynamic application security testing with RapiDAST

    • Assessing AI for OpenShift operations: Advanced configurations

    • OpenShift Lightspeed: Assessing AI for OpenShift operations

    What’s up next?

    Learn how to deploy an application on a cluster using Red Hat OpenShift Service on AWS. This learning path uses a pre-built application that will let you become more familiar with features of OpenShift and Kubernetes.

    Start learning
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue