|
| 1 | +This tutorial is about how to install and use the [@solidlab/ucp](https://github.com/SolidLabResearch/user-managed-access/tree/main/packages/ucp) library utilities. |
| 2 | + |
| 3 | +## Installing |
| 4 | + |
| 5 | +As of today (2 Februari 2024), this package is not on npm. |
| 6 | +Which means installing via `npm install @solidlab/ucp` does **not** work yet. |
| 7 | + |
| 8 | +However, it can still easily installed by adding `"@solidlab/ucp": "https://gitpkg.now.sh/SolidLabResearch/user-managed-access/packages/css?main"` to your dependencies in package.json, or executing the corresponding command of your favourite package manager, e.g. `yarn add @solidlab/ucp@"https://gitpkg.now.sh/SolidLabResearch/user-managed-access/packages/css?main"`. |
| 9 | + |
| 10 | +## Using the library |
| 11 | + |
| 12 | +First, a brief reminder of what the goal is of this library. |
| 13 | +What this library gives is a set of tools for creating **usage control decision** engines that are fully customizable. |
| 14 | +A **usage control decision** engine evaluates an *action request* against a set of *Usage Control Policies* to get a conclusion of *access grants*. |
| 15 | + |
| 16 | +### Example |
| 17 | + |
| 18 | +As an example, imagine that Ruben wants to know Wout his age. |
| 19 | +The age of Wout can be found in a *resource*, `urn:wout:age` (a unique identifier), and is safeguarded by Wout his *policy* that says Ruben has read access to the *resource*. |
| 20 | +oncretely, this policy could be modelled as a tuple (Requesting Party (RP), action, target resource, resource owner), which in this example would be (`urn:ruben`, `urn:modes:read`, `urn:wout:age`, `urn:wout`). |
| 21 | +The **usage control decision** engine, would then be able to interpret both the request and the policy to give as conclusion a grant: `urn:modes:read`. |
| 22 | +This means Ruben is able to know Wout his age and we know that the access is allowed conforming to the policies of Wout thanks to the engine. |
| 23 | + |
| 24 | +Note: that this example does not contain any usage control yet, but is rather access control. |
| 25 | +When a policy has additional to the current tuple expression and enforcement for e.g. Ruben has to delete the data after 30 days and/or that he can only use it for the purpose of for example buying a gift for Wout his Birthday, then we are talking about Usage Control. |
| 26 | +Though, you could see the current use case as preventive usage control without purposes. |
| 27 | + |
| 28 | +### High level Architecture |
| 29 | + |
| 30 | +There are two functions implemented to calculate the grants, both are part of the interface `UconEnforcementDecision`. |
| 31 | + |
| 32 | +1. `calculateAccessModes`: Calculate the *access grants* based on the set of *Usage Control Policies* , the *request* and how to *interpret the policies* (the algorithm). |
| 33 | +2. `calculateAndExplainAccessModes`: The same as `calculateAccessModes`, but also provides an **Explanation** of how the *access grants* are calculated. |
| 34 | + |
| 35 | +Both functions have as input a `UconRequest`. This is an interface that formalizes the action request e.g. (RP, requested action, resource) (`urn:ruben`, `urn:modes:read`, `urn:wout:age`). |
| 36 | + |
| 37 | +As output, `calculateAccessModes` has a list of strings (*access grants*) and `calculateAndExplainAccessModes` has an `Explanation` (which will be elaborated later). |
| 38 | + |
| 39 | +### The first usage control decision engine |
| 40 | + |
| 41 | +The implementation of the `UconEnforcementDecision` interface that this library provides is `UcpPatternEnforcement`. |
| 42 | + |
| 43 | +The first instantiation of this interface is what is referred here as the first **usage control decision** engine. |
| 44 | +Before this instantiation is given, an explanation of how it works is given in [the following section](#usage-control-decision-engine). |
| 45 | + |
| 46 | +#### Usage Control Decision engine |
| 47 | + |
| 48 | +The (`UcpPatternEnforcement`) engine has three components and can be consulted with the methods described in [the high level architecture](#high-level-architecture). |
| 49 | + |
| 50 | +The three components: |
| 51 | + |
| 52 | +- A **[storage](https://github.com/SolidLabResearch/user-managed-access/tree/main/packages/ucp/src/plugins)** to the set of *Usage Control Policies* |
| 53 | +- A **storage** to the set of [Notation3](https://w3c.github.io/N3/spec/) (N3) [interpretation rules](https://github.com/SolidLabResearch/user-managed-access/tree/main/packages/ucp/rules) |
| 54 | +- A configured instance of **[Koreografeye](https://github.com/eyereasoner/Koreografeye)** consisting of: |
| 55 | + - An **N3 reasoner** ([eye-js](https://github.com/eyereasoner/eye-js)) |
| 56 | + - A [Koreografeye policy/plugin executor](https://github.com/SolidLabResearch/user-managed-access/blob/main/packages/ucp/src/PolicyExecutor.ts) + [plugins](https://github.com/SolidLabResearch/user-managed-access/tree/main/packages/ucp/src/plugins) |
| 57 | + |
| 58 | +When a method (e.g. `calculateAccessModes`) is then called with an *action request* the following steps are then executed: |
| 59 | + |
| 60 | +1. The N3 Reasoner runs with as input: |
| 61 | + 1. The set of *Usage Control Policies* |
| 62 | + 2. The request (`UconRequest` serialized as RDF) |
| 63 | + 3. The N3 *interpretation rules* |
| 64 | +2. The conclusion from the Reasoner is then extracted by the Koreografeye policy/plugin executor (configured with plugins) |
| 65 | +3. The result is then returned |
| 66 | + |
| 67 | +This modular approach allows for fast prototyping of a formal Usage Control Policy language, which can then immediately be evaluated. |
| 68 | + |
| 69 | +#### Instantiation |
| 70 | + |
| 71 | +This first policy engine instantiation can perform an evaluation of policies modelled with [Open Digital Rights Language (ODRL)](https://www.w3.org/TR/odrl-model/). |
| 72 | +More specifically, with a subset that only can interpret `odrl:Permission`s with as **action** `odrl:modify`, `odrl:read` and `odrl:use` (which means both modify and read) against action requests and where there are **no Constraints**. |
| 73 | + |
| 74 | +To initialise `UcpPatternEnforcement` as this engine, the following code is required: |
| 75 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/simple-engine.ts#L1-L18 |
| 76 | + |
| 77 | + |
| 78 | +At this point, the engine is ready to be used. Which means that now you can use the `calculateAccessModes` function to request the **grants** for following *action request*: "Ruben wants to know the age of Wout". |
| 79 | + |
| 80 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/simple-engine.ts#L20-L27 |
| 81 | + |
| 82 | +Unfortunately, this results into an empty list `[]`. Which means no **grants** are given and thus Ruben cannot know the age of Wout. |
| 83 | + |
| 84 | +The reason for this is very simple, there is **no** *Usage Control Policy* in the storage. |
| 85 | + |
| 86 | +This can however be resolved by simply adding such a policy to the **Usage Control Rule Storage**: |
| 87 | + |
| 88 | +```ttl |
| 89 | +@prefix odrl: <http://www.w3.org/ns/odrl/2/> . |
| 90 | +@prefix : <http://example.org/usageControlRule> . |
| 91 | +
|
| 92 | +:permission |
| 93 | + a odrl:Permission ; |
| 94 | + odrl:action odrl:read ; |
| 95 | + odrl:target <urn:wout:age> ; |
| 96 | + odrl:assignee <https://pod.rubendedecker.be/profile/card#me> ; |
| 97 | + odrl:assigner <https://pod.woutslabbinck.com/profile/card#me> . |
| 98 | +``` |
| 99 | + |
| 100 | +To add this rule to the storage, the following code can be used: |
| 101 | + |
| 102 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/simple-engine.ts#L30-L41 |
| 103 | + |
| 104 | + |
| 105 | +From now on, when the access modes are calculated again, the following list of grants is received: |
| 106 | + |
| 107 | +```sh |
| 108 | +[ 'http://www.w3.org/ns/auth/acl#Read' ] |
| 109 | +``` |
| 110 | + |
| 111 | +With current initialisation of the **UC Decision engine**, grants are modelled with the [Access Control List (ACL)](https://www.w3.org/ns/auth/acl) Ontology. |
| 112 | +The reason for this is that this component is going to be used in an Authorisation Server (AS) for a [Solid](https://solidproject.org/) Resource Server (RS) using the [User-Managed Access (UMA)](https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html) specification. In the [Solid Protocol](https://solidproject.org/TR/protocol), ACL is the ontology used for **access modes** both its authorization specifications: the [Web Access Control (WAC)](https://solidproject.org/TR/wac) specification and the [Access Control Policy (ACP)](https://solidproject.org/TR/acp) specification. |
| 113 | + |
| 114 | +In the engine, this grant is calculated within the N3 interpretation rules, more specifically [here](https://github.com/SolidLabResearch/user-managed-access/blob/949917faa015195369e430f77200bf3273f79283/packages/ucp/rules/data-crud-rules.n3#L12-L38). |
| 115 | + |
| 116 | +The full code sample for this example can be found in [appendix I](#appendix-I-Full-code-snippet) |
| 117 | + |
| 118 | +### <!--Temporal Policy engine--> |
| 119 | + |
| 120 | +<!--TODO:--> |
| 121 | + |
| 122 | +### Engine with explanation |
| 123 | + |
| 124 | +First an elaboration is given for what is meant by explanation. |
| 125 | +<!--Note: after implementation, similarities have been found with the idea of **ODRL Evaluator** from the [ODRL Formal Semantics Community Group](https://w3c.github.io/odrl/formal-semantics/).--> |
| 126 | + |
| 127 | +#### Explanation |
| 128 | + |
| 129 | +So what is the explanation exactly? It is an interface which contains four components: |
| 130 | + |
| 131 | + |
| 132 | +An `Explanation` consists of four components: |
| 133 | + |
| 134 | +- `decision`: This is the same as the grants (array of access modes) from `calculateAccessModes`. It is the **result** of the evaluation |
| 135 | +- `request`: The input *action request* |
| 136 | +- `conclusions`: The conclusions of the reasoner. A conclusion itself consists of four parts: the **Rule Identifier**, the **Interpration N3 Rule Identifier**, the **grants** allowed (the actual conclusion) and the **timestamp** at which the conclusion was generated. A conclusion can be seen as the proof of following function: $interpretation(rule, context, timestamp) -> grants$ |
| 137 | +- `algorithm`: Which algorithm is used to interpret the set of conclusions |
| 138 | + - Note: only the **union** operator is currently implemented. That is: $\forall c \in C. grant \in c \Rightarrow grant \in D$ </br> |
| 139 | + For all conclusions in `conclusions`, if a grant is in conclusion, then it is part of the list of grants in `decision`. |
| 140 | + |
| 141 | +Having the **Explanation** after an evaluation thus allows for logging with provenance/proof of why a certain action was granted at a certain time. |
| 142 | + |
| 143 | +#### Instantiation |
| 144 | + |
| 145 | +To have a **usage control decision** engine that can give **Explanations**, it needs to be instantiated correctly. This can be done with following code: |
| 146 | + |
| 147 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/log-engine.ts#L1-L18 |
| 148 | + |
| 149 | +Not that compared to the previous engines, a different **plugin** and a different **N3 interpretation rules** are used. |
| 150 | +These allow for retrieving a proper explanation during the calculation of the requests. |
| 151 | + |
| 152 | +Another difference is the fact that know the method `calculateAndExplainAccessModes` has to be used. |
| 153 | +Luckily, this still uses a `UconRequest` as input: |
| 154 | + |
| 155 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/log-engine.ts#L34-L41 |
| 156 | +When a policy is added to the storage, the above code print out a Javascript Object, which is not very nice. |
| 157 | + |
| 158 | +Luckily, it is possible to have a nice RDF serialization as output: |
| 159 | + |
| 160 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/log-engine.ts#L46-L49 |
| 161 | + |
| 162 | +Or to be used as RDF in code with the N3 Store: |
| 163 | + |
| 164 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/log-engine.ts#L43-L44 |
| 165 | + |
| 166 | + |
| 167 | +## appendix I: Full code snippet |
| 168 | + |
| 169 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/simple-engine.ts#L1-L52 |
| 170 | + |
| 171 | + |
| 172 | +## appendix III: Full code snippet Explanation |
| 173 | + |
| 174 | +https://github.com/SolidLabResearch/user-managed-access/blob/1c0410b6f1c3f133843430f60d4f8c690273dff0/packages/ucp/docs/log-engine.ts#L1-L51 |
0 commit comments