Triggering Data Updates
OPAL allows for other components to notify it (and through it all the OPAL clients , and their next-door policy agents) of data updates, triggering each client [subscribed to the published topic] to fetch the data it needs.
What is this good for?
Let's try an example - say your application has a billing service, and you want to allow access only to users who have billing enabled (enforced via a policy agent). You now need changes to the state of the billing service to be propagated to each of the enforcement points/agents (and preferably instantly [Users who've paid - don't like to wait 😅 ]). With the OPAL's data-update-triggers feature the billing-service, another service monitoring it, or even a person can trigger updates as they need - knowing OPAL will take it from there to all the points that need it.
First, you need to obtain a data-source identity token (JWT)
Every service that publishes to OPAL needs a datasource
identity token.
Obtaining one is easy, but you need access to the corresponding OPAL Server master token.
Obtain a data source token with the cli:
opal-client obtain-token $OPAL_AUTH_MASTER_TOKEN --server-url=$YOUR_SERVERS_ADDRESS --type datasource
If you don't want to use the cli, you can obtain the JWT directly from the deployed OPAL server via its REST API:
curl --request POST 'https://opal.yourdomain.com/token' \
--header 'Authorization: Bearer MY_MASTER_TOKEN' \
--header 'Content-Type: application/json' \
--data-raw '{
"type": "datasource",
}'
The /token
API endpoint can receive more parameters, as documented here.
This example assumes that:
- You deployed OPAL server to
https://opal.yourdomain.com
- The master token of your deployment is
MY_MASTER_TOKEN
.- In real life, use a cryptographically secure secret. If you followed our tutorials while deploying OPAL, you probably generated one with
opal-server generate-secret
.
- In real life, use a cryptographically secure secret. If you followed our tutorials while deploying OPAL, you probably generated one with
How to trigger updates
There are a few ways to trigger updates:
Option 1: Trigger a data update with the CLI
Can be run both from opal-client and opal-server.
Example:
-
With
$token
being a JWT we generated in step 1. -
we publish a data-event regarding two topics
users
andbilling
pointing clients tohttp://mybillingserver.com/users
to obtain the data they need. we also provide the clients with the credentials they'll need to connect to the server (as HTTP authorization headers) -
opal-client publish-data-update $token --src-url http://mybillingserver.com/users -t users -t billing --src-config '{"headers":{"authorization":"bearer secret-token"}}'
-
(Yes... We did... We put authorization in your authorization 😜 😅 )
-
See this recording showing the command including getting the JWT for the server with the
obtain-token
command.
Option 2: Trigger a data update with OPAL Server REST API
- All the APIs in opal are OpenAPI / Swagger based (via FastAPI).
- Check out the API docs on your running OPAL-server -- this link assumes you have the server running on
http://localhost:7002
- You can also generate an API-client in the language of your choice using the OpenAPI spec provided by the server
Using PATCH save method
- There are two save methods of triggering data update, PUT and PATCH defined in the payload using the
save_method
field - Using PUT basically places(overrides if path exists) data at the specified
dst_path
- When using PATCH, the
data
field should conform to JSON patch schema according to RFC 6902 and this applies patch operation on the data as specified - Let's say the following is the
-
NOTE: OPA does not support
move
operation of JSON patch, refer discussion for the same and hence OPAL cannot supportmove
operation as well - Example: Consider this JSON data from the opal-example-policy-repo
- Let's say a user is deleted from the system and we would want that user details to be removed from the JSON, let's remove bob from the list, we can use the
remove
operation of JSON patch to achieve this - The following API request will remove
bob
from theusers
JSON
curl -X 'POST' \
'http://localhost:7002/data/config' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": "randomid",
"entries": [
{
"url": "",
"config": {},
"topics": [
"policy_data"
],
"dst_path": "/users",
"save_method": "PATCH",
"data": [
{
"op": "remove",
"path": "/bob"
}
]
}
],
"reason": "user bob is deleted from the system",
"callback": {
"callbacks": []
}
}'
The primariy way meant to do updates with OPAL is with the PUT
method; PATCH
is better used for light tweaks to the data.
While future versions of OPAL might have deeper support for PATCH, it is not currently the case.
To build complex data layouts - we recommend building data-updates into keys that do not intersect to build larger data-sets, and when they do intersect we’d recommend updating the entire entry.
If you want to use PATCH and have more control over its behavior you can implement a custom data fetcher that will handle the order of writing or dependencies.
Option 3: Write your own - import code from the OPAL's packages
- One of the great things about OPAL being written in Python is that you can easily reuse its code.
See the code for the
DataUpdate
model at opal_common/schemas/data.py and use it within your own code to send an update to the server