A playground environment to calculate Access Modes based on ODRL Rules, an UMA Client Request and Koreografeye (with accompanying N3 Rules and plugin(s)). This class will be used in the UMA Authorisation Server that is being developed to work with the Community Solid Server.
The UMA client request contains the following information
In main.ts
is an example of how it works given.
Running that script is done as follows:
npx ts-node main.ts
More information on how this library works can be found in the tutorial.
There are a couple of components:
any
instead of just boolean
)This means that in an Authorization Server, this component could be used as a decision component.
const ucpDecide: UconEnforcementDecision = ...
const accessModes = await ucpDecide.calculateAccessModes({
subject: "https://woslabbi.pod.knows.idlab.ugent.be/profile/card#me",
action: ["http://www.w3.org/ns/auth/acl#Read"],
resource: "http://localhost:3000/test.ttl",
owner: "http://localhost:3000/alice/profile/card#me"
});
console.log(accessModes);
> [ 'read' ]
In crud_engine.ts, a UconEnforcementDecision
component is initialised.
This means that CRUD action requests can be evaluated against a set of ucon rules and an ucon rules interpreter.
The ucon rule interpretation is a combination of N3 rules (data-crud-rules.n3), a N3 Reasoner (eye-js), a plugin executor (PolicyExecutor
) and a plugin (UcpPlugin
). These components all work together as described in Koreografeye.
The set of ucon rules can be dynamically generated and added through the ucon rules store through the functions createPolicy
and createTemporalPolicy
(see crudUtil.ts).
import { EyeJsReasoner, readText } from "koreografeye";
import { UcpPlugin } from "./src/plugins/UCPPlugin";
import { ContainerUCRulesStorage } from "./src/storage/ContainerUCRulesStorage";
import { PolicyExecutor } from "./src/PolicyExecutor";
// load plugin
const plugins = { "http://example.org/dataUsage": new UcpPlugin() }
// instantiate koreografeye policy executor
const policyExecutor = new PolicyExecutor(plugins)
// ucon storage
const uconRulesStorage = new ContainerUCRulesStorage(uconRulesContainer)
// load N3 Rules from a directory | TODO: utils are needed
const n3Rules: string[] = [readText('./rules/data-crud-rules.n3')!]
// instantiate the enforcer using the policy executor,
const ucpPatternEnforcement = new UcpPatternEnforcement(uconRulesStorage, n3Rules, new EyeJsReasoner([
"--quiet",
"--nope",
"--pass"]), policyExecutor)
The code in crud_engine.ts
evaluates 12 UconRequest
s using an instance of UconEnforcementDecision
against a variety of ucon rule sets to verify the engine is working as intended.
When an evaluation fails, e.g. through changing the code, an N3 file will be created in the debug
directory.
This file will include the request (transformed to RDF and serialized to n-triples), the ucon rule(s) and the N3 interpretation rules.
The contents of the file can then be used with the eye reasoner (either local or online).
An example of such file is crud_full, the conclusion of which can be locally tested with following command:
eye --quiet --nope --pass-only-new crud_full.n3
With as conclusion:
@prefix fno: <https://w3id.org/function/ontology#>.
@prefix : <http://example.org/>.
@prefix acl: <http://www.w3.org/ns/auth/acl#>.
<urn:uuid:b5e1c037-8f35-41f7-a0dc-58ed0efe229e> a fno:Execution.
<urn:uuid:b5e1c037-8f35-41f7-a0dc-58ed0efe229e> fno:executes :dataUsage.
<urn:uuid:b5e1c037-8f35-41f7-a0dc-58ed0efe229e> :accessModesAllowed acl:Write.
As an extra, the same evaluation is also tested for a crud engine that also supports temporal policies. The only difference in that engine is that a second set of N3 interpretation rules are added to interpret temporal ucon rules.
In log_engine.ts, a UconEnforcementDecision
component is initialised.
Here, calculateAndExplainAccessModes
is used to not only decide the access modes calculated, but also to add the explanation to why these access modes would be granted.
For this, another plugin (UCPLogPlugin) and rule interpretation (log-usage-rule.n3) is required.
The engine is initialised as follows:
import { EyeJsReasoner, readText } from "koreografeye";
import { UcpPlugin } from "./src/plugins/UCPPlugin";
import { ContainerUCRulesStorage } from "./src/storage/ContainerUCRulesStorage";
import { PolicyExecutor } from "./src/PolicyExecutor";
// load plugin
const plugins = { "http://example.org/dataUsageLog": new UCPLogPlugin() }
// instantiate koreografeye policy executor
const policyExecutor = new PolicyExecutor(plugins)
// ucon storage
const uconRulesStorage = new ContainerUCRulesStorage(uconRulesContainer)
// load N3 Rules from a directory | TODO: utils are needed
const n3Rules: string[] = [readText('./rules/log-usage-rule.n3')!]
// instantiate the enforcer using the policy executor,
const ucpPatternEnforcement = new UcpPatternEnforcement(uconRulesStorage, n3Rules, new EyeJsReasoner([
"--quiet",
"--nope",
"--pass"]), policyExecutor)
When evaluating a UCONRequest, an Explanation is retrieved.
const explanation = await ucpDecide.calculateAndExplainAccessModes({
subject: "https://woslabbi.pod.knows.idlab.ugent.be/profile/card#me",
action: ["http://www.w3.org/ns/auth/acl#Read"],
resource: "http://localhost:3000/test.ttl",
owner: "http://localhost:3000/alice/profile/card#me"
});
An Explanation consists of four components:
calculateAccessModes
. It is the result of the evaluationHaving the Explanation after an evaluation thus allows for logging with provenance/proof of why a certain action was granted at a certain time.
Some utility functions are added such that an explanation can be serialized to RDF:
explanationToRdf
: transforms the Javascript object Explanation to an N3 Store containing the explanation informationserializeFullExplanation
: Serializes the explanation (which contains the request), ucon policies and N3 interpretation to Notation3.import { Store } from "n3";
// use of explanationToRdf
const explanationStore: Store = explanationToRdf(explanation);
// use of serializeFullExplanation
const uconRules = await uconRulesStorage.getStore();
const serialized: string = serializeFullExplanation(explanation, uconRules, n3Rules.join('\n'));