Hands-on Example
This example shows how MagicFarmacia, a pharmacy management platform with multiple branches across different cities, might use Permguard to manage authorization and access control in a multi-tenant, multi-domain environment.
Each domain (patients, prescriptions, inventory, etc.) maintains its own ledger, ensuring isolation per branch, full traceability, and secure access decisions.
| Domain | Ledger | What it tracks |
|---|---|---|
| Branch Management | branch-management-ledger | Registration and configuration of pharmacy branches |
| Patients | patient-event-ledger | Patient data, profile updates, and consent changes |
| Prescriptions | prescription-event-ledger | Prescription creation and dispensing records |
| Inventory | inventory-transaction-ledger | Stock movements and restock triggers |
| Orders | order-event-ledger | Order lifecycle and refund operations |
| Appointments | appointment-ledger | Bookings and schedule changes |
| Notifications | notification-ledger | Sent messages and delivery results |
Before to start make sure che CLI is installed and the AuthZ server is running.
Check out the Playground
The first step is to check out the MagicFarmacia playground.
This example demonstrates Permguard in action and allows testing of its features.
git clone git@github.com:permguard/playground-server.git
cd playground-server/cedar/magicfarmacia/Create the Zone and Policy Store
The next step is to initialize the workspace then create a zone and the policy store.
Plese refer to the Command Line section for more information about the available commands.
permguard zones create --name demozoneHere’s what you’ll see.
895741663247: demozoneIt is important to note that the zoneid is required for the ledger creation and it is returned by the previous command.
permguard authz ledgers create --name magicfarmacia --zone-id 895741663247Displayed result.
809257ed202e40cab7e958218eecad20: magicfarmaciaSet Up the Workspace
In this step, you need set up the workspace and check out the policy store.
A workspace represents a local working space. Plese refer to the CodeOps Workspace section for more information about the workspace.
permguard init --authz-language cedar
permguard remote add origin localhost
permguard checkout origin/895741663247/magicfarmaciaCaptured output.
permguard remote add origin localhost
permguard checkout origin/895741663247/magicfarmacia
Initialized empty permguard ledger in '.'.
Remote origin has been added.
Ledger magicfarmacia has been added.
The local workspace is already fully up to date with the remote ledger.Apply the Policies
At this stage, since the playground already includes some sample policies, it is necessary to apply the changes.
A workspace represents a local working space. Plese refer to the CodeOps Coding section for more information about the workspace.
permguard applyIf everything is set up correctly, you should see the following output.
Initiating the planning process for ledger head/895741663247/809257ed202e40cab7e958218eecad20.
Planning process completed successfully.
The following changes have been identified and are ready to be applied:
+ 2e3d2306e5cae1146396a9c9bf5b1c03c80ede9057d7796f3189a569de4ca113 platform-administrator
+ 3da1ed56372b54f7c6e33b14f21ae3d53db06fe8701b65599c541cbbdf119fde platform-manager
+ b8c072aee9679efdbe86175b51c7305e88e7011e9e8f6f52186ab182b8d0cfa9 platform-auditor
+ f5918d66683fa021e104c8d66d6a9cef4a7a33a3a1d90b5c21043e3d5ece9aec platform-viewer
+ 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1 platform-creator
+ 0bc0aaefc5c96f1ca318c01fef32863273b83c2820ca7f3baf2ddafd73e6ce32 schema
unchanged 0, created 6, modified 0, deleted 0
Initiating the apply process for ledger head/895741663247/809257ed202e40cab7e958218eecad20.
Apply process completed successfully.
Your workspace is synchronized with the remote ledger: head/895741663247/809257ed202e40cab7e958218eecad20.Perform the Authorization Check
The final step is to perform the authorization check.
Plese refer to the Command Line section for more information about the available commands.
permguard authz check ./requests/ok_onlyone1.json -o jsonBelow a sample json for the authorization check.
{
"authorization_model": {
"zone_id": 895741663247,
"policy_store": {
"kind": "ledger",
"id": "809257ed202e40cab7e958218eecad20"
},
"principal": {
"type": "user",
"id": "amy.smith@acmecorp.com",
"source": "keycloak"
},
"entities": {
"schema": "cedar",
"items": [
{
"uid": {
"type": "MagicFarmacia::Platform::BranchInfo",
"id": "subscription"
},
"attrs": {
"active": true
},
"parents": []
}
]
}
},
"request_id": "abc1",
"subject": {
"type": "role-actor",
"id": "platform-creator",
"source": "keycloak",
"properties": {
"isSuperUser": true
}
},
"resource": {
"type": "MagicFarmacia::Platform::Subscription",
"id": "e3a786fd07e24bfa95ba4341d3695ae8",
"properties": {
"isEnabled": true
}
},
"action": {
"name": "MagicFarmacia::Platform::Action::create",
"properties": {
"isEnabled": true
}
},
"context": {
"time": "2025-01-23T16:17:46+00:00",
"isSubscriptionActive": true
}
}Here’s what gets returned.
{
"authorization_check": {
"request_id": "abc1",
"decision": true,
"context": {
"id": "94acbe8e1f224c6aa7a2e6353ed76869"
},
"evaluations": [
{
"request_id": "abc1",
"decision": true,
"context": {
"id": "94acbe8e1f224c6aa7a2e6353ed76869"
}
}
]
}
}Next Steps
This example demonstrates how to set up the MagicFarmacia playground and perform an authorization check.
To better understand Permguard, it is worth exploring the Policy Store, which is implemented as a Ledger. The Ledger uses a Git-like object storage system.
Plese refer to the Command Line Objects section for more information about the available commands.
Below is an example of how to list all objects in the workspace.
permguard objects --allOutput shown below.
Your workspace objects:
- 0bc0aaefc5c96f1ca318c01fef32863273b83c2820ca7f3baf2ddafd73e6ce32 blob schema
- 2e3d2306e5cae1146396a9c9bf5b1c03c80ede9057d7796f3189a569de4ca113 blob platform-administrator
- 3da1ed56372b54f7c6e33b14f21ae3d53db06fe8701b65599c541cbbdf119fde blob platform-manager
- 6a30289b571b09ba52d32b63ff92b745abc8bc8e816f0d585f5a133ee314f652 commit
- 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1 blob platform-creator
- b8c072aee9679efdbe86175b51c7305e88e7011e9e8f6f52186ab182b8d0cfa9 blob platform-auditor
- f5918d66683fa021e104c8d66d6a9cef4a7a33a3a1d90b5c21043e3d5ece9aec blob platform-viewer
- fb16aa66413ae45275e2063bcbdf6267be4689200b74c04ff8f2ad0f4b03127c tree
total 8, commit 1, tree 1, blob 6The following example shows how to display the content of the platform-creator object.
permguard objects cat 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1Displayed output.
Your workspace object 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1:
{"annotations":{"id":"platform-creator"},"effect":"permit","principal":{"op":"==","entity":{"type":"Permguard::IAM::RoleActor","id":"platform-creator"}},"action":{"op":"==","entity":{"type":"MagicFarmacia::Platform::Action","id":"create"}},"resource":{"op":"is","entity_type":"MagicFarmacia::Platform::Subscription"},"conditions":[{"kind":"when","body":{"\u0026\u0026":{"left":{"\u0026\u0026":{"left":{"==":{"left":{".":{"left":{"Var":"context"},"attr":"isSubscriptionActive"}},"right":{"Value":true}}},"right":{"==":{"left":{".":{"left":{"Var":"action"},"attr":"isEnabled"}},"right":{"Value":true}}}}},"right":{"==":{"left":{".":{"left":{"Var":"resource"},"attr":"isEnabled"}},"right":{"Value":true}}}}}},{"kind":"unless","body":{"==":{"left":{".":{"left":{"Var":"principal"},"attr":"isSuperUser"}},"right":{"Value":false}}}}]}
type blob, size 881, oname platform-creatorIt is also possible to specify the frontend option to display the object in a more readable format.
permguard objects cat 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1 --frontendHere’s the result.
Your workspace object 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1:
@id("platform-creator")
permit (
principal == Permguard::IAM::RoleActor::"platform-creator",
action == MagicFarmacia::Platform::Action::"create",
resource is MagicFarmacia::Platform::Subscription
)
when { context.isSubscriptionActive == true && action.isEnabled == true && resource.isEnabled == true }
unless { principal.isSuperUser == false };
type blob, size 881, oname platform-creatorIt is recommended to explore the Policy as Code section to learn more about the policy store and the policy language.
Plese refer to the DevOps section for more information about configuration and deployment.
Finally, it is worth considering how to deploy the AuthZ server.