Skip to main content

OPAL Scopes

OPAL Scopes allows OPAL to serve different policies and data sources, serving them to multiple clients. Every scope contains its own policy and data sources. All clients using the same Scope ID will get the same policy and data.

Scopes are an easy way to use OPAL with multiple Git repositories (or other sources of policy), and are a core feature to enable using OPAL itself as a multi-tenant service.

Scopes are dynamic, and can be created on the fly through the scopes API (/scopes)

Setting up scopes​

Prerequisites​

Scopes are supported in OPAL 0.2.0 and above. Use the provided docker compose example to quickly get started.

The server must be started with the environment variable OPAL_SCOPES=1.

The scope clones are kept under OPAL_BASE_DIR, which two running servers must not share: at each start, the pre-fork scope preload removes the lock files and partial packs in every clone there, whichever server's git op left them.

Use a REST API call to create or change a scope​

In this scenario, we create two different scopes (internal and external), that, for example, can be used for an internal and external facing app. The internal scope uses policies located in the internal directory, and external uses policies defined in the external directory. We can set different directories, different branches, different repositories, and any other setting.

The authorization used in this example are GitHub Personal Access Tokens that can be generated here.

curl --request PUT 'http://opal_server/scopes'
--header 'Content-Type: application/json'
--header 'Authorization: $OPAL_TOKEN'
--data-raw '{
"scope_id": "internal",
"policy": {
"source_type": "git",
"url": "https://github.com/company/policy",
"auth": {
"auth_type": "github_token",
"token": "github_token"
},
"directories": [
"internal"
],
"extensions": [
".rego",
".json"
],
"manifest": ".manifest",
"poll_updates": true,
"branch": "main"
},
"data": {
"entries": []
}
}'
curl --request PUT 'http://opal_server/scopes'
--header 'Content-Type: application/json'
--header 'Authorization: $OPAL_TOKEN'
--data-raw '{
"scope_id": "external",
"policy": {
"source_type": "git",
"url": "https://github.com/company/policy",
"auth": {
"auth_type": "github_token",
"token": "github_token"
},
"directories": [
"external"
],
"extensions": [
".rego",
".json"
],
"manifest": ".manifest",
"poll_updates": true,
"branch": "main"
},
"data": {
"entries": []
}
}'

PUT /scopes refuses, with 422, a branch name git can't fetch (such as x~1 or an empty name), since such a scope can't follow a branch. A scope stored with such a name before this release keeps being served as it was until it is changed. A scope whose branch is not on the remote gets no policy (GET /scopes/<scope_id>/policy answers 409), and the server logs Did not find target branch on remote: <branch> (<url>) at ERROR; a sync pass logs it once for each branch of each clone.

Launch OPAL Client with a scope​

docker run -it \
--env OPAL_CLIENT_TOKEN \
--env OPAL_SERVER_URL \
--env OPAL_DATA_TOPICS \
--env OPAL_SCOPE_ID=internal \
-p 7766:7000 \
-p 8181:8181 \
permitio/opal-client