From fc5ea9b0fe40b53cd98da3588d0823a7ea7302f3 Mon Sep 17 00:00:00 2001 From: Charith Ellawala Date: Mon, 5 Jun 2023 09:36:46 +0100 Subject: [PATCH] docs: Add page with output example (#1622) Update the API response to include outputs and introduce a new page with an example of how to use outputs. Signed-off-by: Charith Ellawala --- docs/modules/api/pages/index.adoc | 36 ++++++++---- docs/modules/policies/nav.adoc | 1 + docs/modules/policies/pages/outputs.adoc | 72 ++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 docs/modules/policies/pages/outputs.adoc diff --git a/docs/modules/api/pages/index.adoc b/docs/modules/api/pages/index.adoc index 4baae0252..22ae42f9a 100644 --- a/docs/modules/api/pages/index.adoc +++ b/docs/modules/api/pages/index.adoc @@ -135,7 +135,20 @@ This is the main API entrypoint for checking permissions for a set of resources. "view:public": "EFFECT_ALLOW", "approve": "EFFECT_DENY" }, - "validationErrors": [ <5> + "outputs": [ <5> + { + "src": "resource.leave_request.v20210210/acme#rule-001", <6> + "val": "create_allowed:john" <7> + }, + { + "src": "resource.leave_request.v20210210#public-view", + "val": { + "id": "john", + "keys": ["foo", "bar", "baz"] + } + } + ], + "validationErrors": [ <8> { "path": "/department", "message": "value must be one of \"marketing\", \"engineering\"", @@ -147,17 +160,17 @@ This is the main API entrypoint for checking permissions for a set of resources. "source": "SOURCE_RESOURCE" } ], - "meta": { <6> + "meta": { <9> "actions": { "view:public": { - "matchedPolicy": "resource.leave_request.v20210210/acme.corp", <7> - "matchedScope": "acme" <8> + "matchedPolicy": "resource.leave_request.v20210210/acme.corp", <10> + "matchedScope": "acme" <11> }, "approve": { "matchedPolicy": "resource.leave_request.v20210210/acme.corp" } }, - "effectiveDerivedRoles": [ <9> + "effectiveDerivedRoles": [ <12> "employee_that_owns_the_record", "any_employee" ] @@ -170,11 +183,14 @@ This is the main API entrypoint for checking permissions for a set of resources. <2> List of results. Items are in the same order as they were sent in the request. <3> Resource identifiers. <4> Access decisions for each of the actions. -<5> Validation errors, if xref:policies:schemas.adoc[schema enforcement] is enabled and the request didn't conform to the schema. -<6> Metadata (if `includeMeta` was true in the request) -<7> Name of the policy that produced the decision for this action. -<8> Name of the scope that was active when the decision was made for the action. -<9> List of derived roles that were activated. +<5> List of outputs from policy evaluation, if there are any. See xref:policies:outputs.adoc[]. +<6> Name of the rule that produced the output. +<7> Output value produced by the rule. +<8> Validation errors, if xref:policies:schemas.adoc[schema enforcement] is enabled and the request didn't conform to the schema. +<9> Metadata (if `includeMeta` was true in the request) +<10> Name of the policy that produced the decision for this action. +<11> Name of the scope that was active when the decision was made for the action. +<12> List of derived roles that were activated. === `CheckResourceSet` (`/api/check`) diff --git a/docs/modules/policies/nav.adoc b/docs/modules/policies/nav.adoc index dce4c34e1..25cdc97ce 100644 --- a/docs/modules/policies/nav.adoc +++ b/docs/modules/policies/nav.adoc @@ -5,6 +5,7 @@ * xref:principal_policies.adoc[Principal Policies] * xref:scoped_policies.adoc[Scoped Policies] * xref:conditions.adoc[Conditions] +* xref:outputs.adoc[Outputs] * xref:schemas.adoc[Schemas] * xref:compile.adoc[Validating and testing] * xref:best_practices.adoc[Best practices] diff --git a/docs/modules/policies/pages/outputs.adoc b/docs/modules/policies/pages/outputs.adoc new file mode 100644 index 000000000..c1846da48 --- /dev/null +++ b/docs/modules/policies/pages/outputs.adoc @@ -0,0 +1,72 @@ +include::ROOT:partial$attributes.adoc[] + += Outputs + +You can define an optional expression to be evaluated when a policy rule is activated. The collected outputs from all the activated rules are included in the Cerbos API response. + +Output expressions are useful if you want to take specific actions in your application based on the triggered rules. For example, if your policy contains a rule that denies access if the request is issued outside working hours, it could output a string that explains the restriction. Your application could then display that back to the user so that they know the specific reason why the request was denied. + + +Consider the following policy definition: + +[source,yaml,linenums] +---- +--- +apiVersion: api.cerbos.dev/v1 +resourcePolicy: + version: "default" + resource: "system_access" + rules: + - name: working-hours-only + actions: ['*'] + effect: EFFECT_DENY + roles: ['*'] + condition: + match: + expr: now().getHours() > 18 || now().getHours() < 8 + output: + expr: |- + {"principal": P.id, "resource": R.id, "timestamp": now(), "message": "System can only be accessed between 0800 and 1800"} +---- + +If a request is made outside working hours, the response from Cerbos would resemble the following: + +[source,json,linenums] +---- +{ + "requestId": "xx-010023-23459", + "results": [ + { + "resource": { + "id": "bastion_002", + "kind": "system_access" + }, + "actions": { + "login": "EFFECT_DENY" + }, + "meta": { + "actions": { + "login": { + "matchedPolicy": "resource.system_access.vdefault" + } + } + }, + "outputs": [ + { + "src": "resource.system_access.vdefault#working-hours-only", + "val": { + "message": "System can only be accessed between 0800 and 1800", + "principal": "john", + "resource": "bastion_002", + "timestamp": "2023-06-02T21:53:58.319506543+01:00" + } + } + ] + } + ] +} +---- + +Output expressions can be any valid CEL expression. You can return simple values such as strings, numbers and booleans or complex values such as maps and lists. + +CAUTION: Excessive use of output expressions could affect policy evaluation performance. If you use them for debugging purposes, remember to remove them before going to production.