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 aim is to make sure that the proper particular person has acceptable entry to the related useful resource. On this article, we’ll talk about find out how to allow the Position-based entry management (RBAC) authorization mannequin in 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 assets in pc programs. RBAC assigns permissions to customers based mostly on their function inside a company. In RBAC, roles are outlined based mostly on the capabilities 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 function may need permission to create and replace API assets, whereas an end-user function would possibly solely have permission to learn or execute API assets.
Principally, RBAC assigns permissions based mostly on person roles, whereas ABAC assigns permissions based mostly on attributes related to customers and assets.
In RBAC, a coverage is outlined by the mixture of a person’s assigned function, the actions they’re licensed to carry out, and the assets 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 method to coverage enforcement throughout a complete distributed system. It lets you outline, handle, and implement insurance policies centrally from a single level. By defining insurance policies as code, OPA allows straightforward evaluate, enhancing, 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. Once you request a coverage choice from OPA, it makes use of the principles and information that you’ve supplied in a .rego
file to judge the question and produce a response. The question result’s then despatched again to you because the coverage choice. OPA shops all of the insurance policies and the info it wants in its in-memory cache. In consequence, OPA returns outcomes shortly. Right here is an instance of a easy OPA Rego file:
bundle instance
default enable = false
enable
enter.methodology == "GET"
enter.path =="/api/useful resource"
enter.person.function == "admin"
On this instance, we’ve a bundle known as “instance” that defines a rule known as “enable”. The “enable” rule specifies that the request is allowed if the enter methodology is “GET”, the requested path is /api/useful resource
, and the person’s function is “admin”. If these circumstances are met, then the “enable” 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. Then again, OPA provides an authorization layer and decouples the coverage from the code by creating a definite profit for authorization. With this mixture, you’ll be able to add permissions for an API useful resource to a job. Customers is likely to be related to a number of person roles. Every person function defines a set of permissions (GET, PUT, DELETE) on RBAC assets (outlined by URI paths). Within the subsequent part, let’s discover ways to obtain RBAC utilizing these two.

Easy methods to Implement RBAC With OPA and Apache APISIX
In Apache APISIX, you’ll be able to configure routes and plugins to outline the conduct of your API. You should utilize the APISIX opa plugin to implement RBAC insurance policies by forwarding requests to OPA for decision-making. Then OPA makes an authorization choice based mostly on customers’ roles and permissions in real-time.
Assume that we’ve Conference API the place you’ll be able to retrieve/edit occasion classes, matters, and speaker info. A speaker can solely learn their very own classes and matters whereas the admin can add/edit extra classes and matters. Or attendees can go away their suggestions concerning 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:

- API client requests a route on the API Gateway with its credential resembling a JWT token within the authorization header.
- API Gateway sends client information with a JWT header to the OPA engine.
- 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.
- If the OPA choice is allowed, then the request will probably 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 also use instruments resembling Postman to work together with the API.
Step 1: Set up Apache APISIX
APISIX may 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 have to 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 '
"identify":"Conferences API upstream",
"desc":"Register Conferences API because the upstream",
"kind":"roundrobin",
"scheme":"https",
"nodes":
"conferenceapi.azurewebsites.internet:443":1
'
Step 3: Create an API Shopper
Subsequent, we create a client (a brand new speaker) with the username jack
in Apache APISIX. It units up the jwt-auth plugin for the buyer with the required key and secret. It will enable 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 have to arrange a brand new Route that generates and indicators the token utilizing the public-api plugin. On this situation, API Gateway acts as an id supplier server to create and confirm the token with our client jack’s key. The id supplier may be additionally some other third-party companies resembling 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 Shopper
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 function, and permission within the payload.
curl -G --data-urlencode 'payload="function":"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 includes 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.internet"
'
- The
proxy-rewrite
plugin is configured to proxy requests to theconferenceapi.azurewebsites.internet
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 info to OPA. We are going to add this coverage .
rego
file within the Opa configuration part.
Step 7: Create a Route for Convention Classes
The ultimate step is to create a brand new route for Conferences API speaker classes:
curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
"identify":"Conferences API speaker classes route",
"desc":"Create a brand new route in APISIX for the Conferences API speaker classes",
"strategies": ["GET", "POST"],
"uris": ["/speaker/*/topics","/speaker/*/sessions"],
"upstream_id":"1",
"plugin_config_id":1
'
The payload accommodates details about the route, resembling its identify, 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 completely different URIs, /speaker/matters
and /speaker/classes
. 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: Take a look at the Setup With out OPA
To date, we’ve arrange all the mandatory configurations for APISIX to direct incoming requests to Convention API endpoints, solely permitting licensed API customers. Now, every time an API client needs to entry an endpoint, they have to present a JWT token to retrieve information from the Convention backend service. You’ll be able to confirm this by hitting the endpoint and the area handle 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 most recent model. It creates a brand new container on the present APISIX community apisix-quickstart-net
with the identify opa
and exposes port 8181
. So, APISIX can ship coverage test requests to OPA straight utilizing the handle [http://opa:8181](http://opa:8181)
Be aware 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 is advisable outline the insurance policies that will probably be used to manage entry to API assets. 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 based mostly on these attributes. For instance, within the beneath configuration, we’re saying to OPA, test the user_roles
desk to seek out the function for jack
. This info is shipped by APISIX inside enter.client.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"] # Position 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 job and permission token = "payload": payload [_, payload, _] := io.jwt.decode(bearer_token) # Logic that implements RBAC default enable = falseenable # Lookup the record of roles for the person roles := user_roles[input.consumer.username] # For every function in that record r := roles[_] # Lookup the permissions record for function r permissions := role_permissions[r] # For every permission p := permissions[_] # Test if the permission granted to r matches the customers request p == "permission": token.payload.permission '
Step 11: Replace the Present 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: Take a look at the Setup With OPA
Now we will check all setups we did with OPA insurance policies. In case you 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 client and JWT token information to OPA to confirm the function and permission because the authorization course of. Any request with out a JWT token in place or allowed roles will probably be denied.
curl -i http://127.0.0.1:9080/speaker/1/matters -H 'Authorization: API_CONSUMER_TOKEN'
Conclusion
On this article, we discovered 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 based mostly on our API client’s function and permissions. Additionally, this tutorial demonstrated how we will extract API consumer-related info within the coverage file from the JWT token payload or client object despatched by APISIX.