RBAC With API Gateway and Open Coverage Agent (OPA)

With varied entry management fashions and implementation strategies accessible, developing an authorization system for backend service APIs can nonetheless be difficult. Nonetheless, the final word purpose is to make sure that the proper particular person has applicable entry to the related useful resource. On this article, we’ll talk about find out how to allow the Function-based entry management (RBAC) authorization mannequin to your API with open-source API Gateway Apache APISIX and Open Policy Agent (OPA).

What Is RBAC?

Role-based access control (RBAC)and attribute-based access control (ABAC) are two generally used entry management fashions used to handle permissions and management entry to sources in laptop programs. RBAC assigns permissions to customers primarily based on their position inside a company. In RBAC, roles are outlined primarily based on the features or tasks of customers, and permissions are assigned to these roles. Customers are then assigned to a number of roles, they usually inherit the permissions related to these roles. Within the API context, for instance, a developer position might need permission to create and replace API sources, whereas an end-user position may solely have permission to learn or execute API sources.

Mainly, RBAC assigns permissions primarily based on person roles, whereas ABAC assigns permissions primarily based on attributes related to customers and sources.

In RBAC, a coverage is outlined by the mix of a person’s assigned position, the actions they’re approved to carry out, and the sources on which they will carry out these actions.

What Is OPA?

OPA (Open Policy Agent) is a coverage engine and a set of instruments that present a unified strategy to coverage enforcement throughout a whole distributed system. It lets you outline, handle, and implement insurance policies centrally from a single level. By defining insurance policies as code, OPA permits simple assessment, modifying, and roll-back of insurance policies, facilitating environment friendly coverage administration.


OPA offers a declarative language known as Rego, which lets you create and implement insurance policies all through your stack. Whenever you request a coverage resolution from OPA, it makes use of the foundations and knowledge that you’ve got offered in a .rego file to judge the question and produce a response. The question result’s then despatched again to you because the coverage resolution. OPA shops all of the insurance policies and the information it wants in its in-memory cache. Consequently, OPA returns outcomes rapidly. Right here is an instance of a easy OPA Rego file:

bundle instance

default permit = false
permit 
    enter.methodology == "GET"
    enter.path =="/api/useful resource"
    enter.person.position == "admin"

On this instance, we’ve got a bundle known as “instance” that defines a rule known as “permit”. The “permit” rule specifies that the request is allowed if the enter methodology is “GET”, the requested path is /api/useful resource, and the person’s position is “admin”. If these circumstances are met, then the “permit” rule will consider as “true”, permitting the request to proceed.

Why Use OPA and API Gateway for RBAC?

API Gateway offers a centralized location to configure and handle API, and API customers. It may be used as a centralized authentication gateway by avoiding having every particular person service implement authentication logic contained in the service itself. However, OPA provides an authorization layer and decouples the coverage from the code by creating a definite profit for authorization. With this mix, you possibly can add permissions for an API useful resource to a task. Customers may be related to a number of person roles. Every person position defines a set of permissions (GET, PUT, DELETE) on RBAC sources (outlined by URI paths). Within the subsequent part, let’s discover ways to obtain RBAC utilizing these two.

Learn how to Implement RBAC With OPA and Apache APISIX

In Apache APISIX, you possibly can configure routes and plugins to outline the conduct of your API. You need to use the APISIX opa plugin to implement RBAC insurance policies by forwarding requests to OPA for decision-making. Then OPA makes an authorization resolution primarily based on customers’ roles and permissions in real-time.

Assume that we’ve got Conference API the place you possibly can retrieve/edit occasion periods, matters, and speaker data. A speaker can solely learn their very own periods and matters whereas the admin can add/edit extra periods and matters. Or attendees can depart their suggestions in regards to the speaker’s session through a POST request to /speaker/speakerId/session/suggestions and the speaker can solely see by requesting the GET methodology of the identical URI. The beneath diagram illustrates the entire situation:


  1. API shopper requests a route on the API Gateway with its credential reminiscent of a JWT token within the authorization header.
  2. API Gateway sends shopper knowledge with a JWT header to the OPA engine.
  3. OPA evaluates if the buyer has a proper to entry the useful resource by utilizing insurance policies (roles and permissions) we specify within the .rego file.
  4. If the OPA resolution is allowed, then the request might be forwarded to the upstream Convention service.

Subsequent, we set up, configure APISIX, and outline insurance policies in OPA.

Stipulations

  • Docker is used to putting in the containerized etcd and APISIX.
  • curl is used to ship requests to APISIX Admin API. You may as well use instruments reminiscent of Postman to work together with the API.

Step 1: Set up Apache APISIX

APISIX could be simply put in and began with the next quickstart script:

curl -sL https://run.api7.ai/apisix/quickstart | sh

Step 2: Configure the Backend Service (Upstream)

To route requests to the backend service for the Convention API, you’ll must configure it by including an upstream server in Apache APISIX through the Admin API.

curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -X PUT -d '

   "title":"Conferences API upstream",
   "desc":"Register Conferences API because the upstream",
   "sort":"roundrobin",
   "scheme":"https",
   "nodes":
      "conferenceapi.azurewebsites.web:443":1
   
'

Step 3: Create an API Client

Subsequent, we create a shopper (a brand new speaker) with the username jack in Apache APISIX. It units up the jwt-auth plugin for the buyer with the desired key and secret. This may permit the buyer to authenticate utilizing a JSON Web Token (JWT).

curl http://127.0.0.1:9180/apisix/admin/customers -X PUT -d '

    "username": "jack",
    "plugins": 
        "jwt-auth": 
            "key": "user-key",
            "secret": "my-secret-key"
        
    
'

Step 4: Create a Public Endpoint to Generate a JWT Token

You additionally must arrange a brand new Route that generates and indicators the token utilizing the public-api plugin. On this situation, API Gateway acts as an identification supplier server to create and confirm the token with our shopper jack’s key. The identification supplier could be additionally every other third-party companies reminiscent of Google, Okta, Keycloak, and Ory Hydra.

curl http://127.0.0.1:9180/apisix/admin/routes/jas -X PUT -d '

    "uri": "/apisix/plugin/jwt/signal",
    "plugins": 
        "public-api": 
    
'

Step 5: Declare a New JWT Token for the API Client

Now we will get a brand new token for our speaker Jack from the API Gateway utilizing the general public endpoint we created. The next curl command generates a brand new token with Jack’s credentials and assigns position, and permission within the payload.

curl -G --data-urlencode 'payload="position":"speaker","permission":"learn"' http://127.0.0.1:9080/apisix/plugin/jwt/signal?key=user-key -i

After you run the above command, you’ll obtain a token as a response. Save this token someplace — later we’re going to use this token to entry our new API Gateway endpoint.

Step 6: Create a New Plugin Config

This step entails configuring APISIX’s 3 plugins: proxy-rewrite, jwt-auth, and opa plugins.

curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PUT -d '

   "plugins":
      "jwt-auth":
      ,
      "proxy-rewrite":
         "host":"conferenceapi.azurewebsites.web"
      
   
'
  • The proxy-rewrite plugin is configured to proxy requests to the conferenceapi.azurewebsites.web host.
  • OPA authentication plugin is configured to make use of the OPA coverage engine operating at http://localhost:8181/v1/data/rbacExample. Additionally, APISIX sends all consumer-related data to OPA. We are going to add this coverage .rego file within the Opa configuration part.

Step 7: Create a Route for Convention Periods

The ultimate step is to create a brand new route for Conferences API speaker periods:

curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '

    "title":"Conferences API speaker periods route",
    "desc":"Create a brand new route in APISIX for the Conferences API speaker periods",
    "strategies": ["GET", "POST"],
    "uris": ["/speaker/*/topics","/speaker/*/sessions"],
    "upstream_id":"1",
    "plugin_config_id":1
'

The payload accommodates details about the route, reminiscent of its title, description, strategies, URIs, upstream ID, and plugin configuration ID. On this case, the route is configured to deal with GET and POST requests for 2 totally different URIs, /speaker/matters and /speaker/periods. The “upstream_id” discipline specifies the ID of the upstream service that can deal with incoming requests for this route, whereas the “plugin_config_id” discipline specifies the ID of the plugin configuration for use for this route.

Step 8: Check the Setup With out OPA

Thus far, we’ve got arrange all the required configurations for APISIX to direct incoming requests to Convention API endpoints, solely permitting approved API customers. Now, every time an API shopper needs to entry an endpoint, they have to present a JWT token to retrieve knowledge from the Convention backend service. You may confirm this by hitting the endpoint and the area deal with we’re requesting now could be our customized API Gateway however not an precise Convention service:

curl -i http://127.0.0.1:9080/speaker/1/matters -H 'Authorization: API_CONSUMER_TOKEN'

Step 9: Run OPA Service

The opposite two steps are we run the OPA service utilizing Docker and add our coverage definition utilizing its API which can be utilized to judge authorization insurance policies for incoming requests.

docker run -d --network=apisix-quickstart-net --name opa -p 8181:8181 openpolicyagent/opa:newest run -s

This Docker command runs a container of the OPA picture with the newest model. It creates a brand new container on the present APISIX community apisix-quickstart-netwith the title opaand exposes port 8181. So, APISIX can ship coverage examine requests to OPA instantly utilizing the deal with [http://opa:8181](http://opa:8181) Word that OPA and APISIX ought to run in the identical docker community.

Step 10: Outline and Register the Coverage

The second step on the OPA aspect is it’s essential outline the insurance policies that might be used to regulate entry to API sources. These insurance policies ought to outline the attributes required for entry (which customers have which roles) and the permission (which roles have which permissions) which are allowed or denied primarily based on these attributes. For instance, within the beneath configuration, we’re saying to OPA, examine the user_roles desk to seek out the position for jack. This data is distributed by APISIX inside enter.shopper.username. Additionally, we’re verifying the buyer’s permission by studying the JWT payload and extracting token.payload.permission from there. The feedback describe the steps clearly.

curl -X PUT '127.0.0.1:8181/v1/insurance policies/rbacExample' 
    -H 'Content material-Kind: textual content/plain' 
    -d 'bundle rbacExample

# Assigning person rolesuser_roles := 
    "jack": ["speaker"],
    "bobur":["admin"]


# Function permission assignments
role_permissions := 
    "speaker": ["permission": "read"],
    "admin":   ["permission": "read", "permission": "write"]


# Helper JWT Features
bearer_token := t 
 t := enter.request.headers.authorization


# Decode the authorization token to get a task and permission
token = "payload": payload 
 [_, payload, _] := io.jwt.decode(bearer_token)


# Logic that implements RBAC
default permit = falsepermit 
    # Lookup the listing of roles for the person
    roles := user_roles[input.consumer.username]    # For every position in that listing
    r := roles[_]    # Lookup the permissions listing for position r
    permissions := role_permissions[r]    # For every permission
    p := permissions[_]    # Verify if the permission granted to r matches the customers request
    p == "permission": token.payload.permission
'

Step 11: Replace the Current Plugin Config With the OPA Plugin

As soon as we outlined insurance policies on the OPA service, we have to replace the present plugin config for the route to make use of the OPA plugin. We specify within the coverage attribute of the OPA plugin.

curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PATCH -d '

   "plugins":
      "opa":
         "host":"http://opa:8181",
         "coverage":"rbacExample",
         "with_consumer":true
      
   
'

Step 12: Check the Setup With OPA

Now we will take a look at all setups we did with OPA insurance policies. If you happen to attempt to run the identical curl command to entry the API Gateway endpoint, it first checks the JWT token because the authentication course of and sends shopper and JWT token knowledge to OPA to confirm the position and permission because the authorization course of. Any request with out a JWT token in place or allowed roles might be denied.

curl -i http://127.0.0.1:9080/speaker/1/matters -H 'Authorization: API_CONSUMER_TOKEN'

Conclusion

On this article, we realized find out how to implement RBAC with OPA and Apache APISIX. We outlined a easy customized coverage logic to permit/disallow API useful resource entry primarily based on our API shopper’s position and permissions. Additionally, this tutorial demonstrated how we will extract API consumer-related data within the coverage file from the JWT token payload or shopper object despatched by APISIX.