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.

DomainLedgerWhat it tracks
Branch Managementbranch-management-ledgerRegistration and configuration of pharmacy branches
Patientspatient-event-ledgerPatient data, profile updates, and consent changes
Prescriptionsprescription-event-ledgerPrescription creation and dispensing records
Inventoryinventory-transaction-ledgerStock movements and restock triggers
Ordersorder-event-ledgerOrder lifecycle and refund operations
Appointmentsappointment-ledgerBookings and schedule changes
Notificationsnotification-ledgerSent 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 demozone

Here’s what you’ll see.

895741663247: demozone

It 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 895741663247

Displayed result.

809257ed202e40cab7e958218eecad20: magicfarmacia

Set 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/magicfarmacia

Captured 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 apply

If 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 json

Below 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 --all

Output 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 6

The following example shows how to display the content of the platform-creator object.

permguard objects cat 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1

Displayed 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-creator

It is also possible to specify the frontend option to display the object in a more readable format.

permguard objects cat 7fae1224aa4174473d445bb93255c592e66af184fee82956d5ef96a3c55192a1 --frontend

Here’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-creator

It 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.