Skip to content

Commit b39da16

Browse files
alkalescentjp-ayyappanjakedoublev
authored
feat: add obligations (#150)
Co-authored-by: Jp Ayyappan <108297634+jp-ayyappan@users.noreply.github.com> Co-authored-by: Jake Van Vorhis <83739412+jakedoublev@users.noreply.github.com>
1 parent 5b4924a commit b39da16

File tree

12 files changed

+1058
-116
lines changed

12 files changed

+1058
-116
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Obligations
2+
3+
Obligations are policy constructs that enable Policy Decision Point(PDP) - to - Policy Enforcement Point (PEP) directives that accompany a decision. They express additional controls the PEP should enforce—such as requiring MFA, applying watermarking, encrypting content, or limiting access by time. In effect, the PDP is saying “permit, provided these controls are enforced.” The PDP cannot compel or verify enforcement; it relies on the PEP to honor the obligations.
4+
If the PEP cannot or will not enforce an obligation, it should decline to grant access.
5+
## Composition
6+
7+
An obligation consists of:
8+
9+
1. A Namespace
10+
2. A Definition
11+
3. Values
12+
4. Triggers
13+
14+
Platform Policy Obligations can contain multiple Namespaces, each with multiple Definitions, and each Definition can have multiple Values. Each Value can have multiple Triggers. Each trigger can have an Action, Attribute Value, and PEP identifier (optional). Not specifying a PEP results in a global obligation that applies across *all* PEPs.
15+
16+
```mermaid
17+
graph LR;
18+
%% Every definition is namespaced.
19+
Namespace_A-->ObligationDefinition_A;
20+
21+
%% Define definition and value A.
22+
ObligationDefinition_A-->ObligationValue_A;
23+
24+
%% Define triggers.
25+
ObligationValue_A-->Trigger_A1
26+
Trigger_A1-->Action_A1
27+
Trigger_A1-->AttributeValue_A1
28+
Trigger_A1-->PEP_A
29+
30+
ObligationValue_A-->Trigger_A2
31+
Trigger_A2-->Action_A2
32+
Trigger_A2-->AttributeValue_A2
33+
34+
%% Define definition and value B.
35+
ObligationDefinition_A-->ObligationValue_B;
36+
37+
%% Define triggers.
38+
ObligationValue_B-->Trigger_B1
39+
Trigger_B1-->Action_B1
40+
Trigger_B1-->AttributeValue_B1
41+
42+
ObligationValue_B-->Trigger_B2
43+
Trigger_B2-->Action_B2
44+
Trigger_B2-->AttributeValue_B2
45+
Trigger_B2-->PEP_B
46+
```
47+
48+
## Standard Obligations
49+
50+
Standard Obligations are enforced by the Access PDP (Policy Decision Point) when validating whether an Entity of a specified Category can perform an Action on a given Resource. These obligations must be satisfied for access to be granted.
51+
52+
A Standard Obligation includes:
53+
- **Action**: The specific action being performed (READ, STORE, CREATE, UPDATE, DELETE)
54+
- **Resource Attribute Value**: The data attribute for which this obligation is scoped
55+
- **Obligation Value**: The required obligation value that must be satisfied
56+
57+
### Examples of Standard Obligations:
58+
59+
#### Watermarking
60+
Ensure document traceability:
61+
- **Obligation**: `https://example.com/obl/drm/value/watermarking`
62+
- **Applied to**: sensitive documents
63+
- **Condition**: PEP must apply watermark
64+
65+
#### Prevent Download
66+
Prevent download of plaintext content:
67+
- **Obligation**: `https://example.com/obl/drm/value/no-download`
68+
- **Applied to**: sensitive documents
69+
- **Condition**: PEP must not allow download
70+
71+
## FQN (Fully Qualified Name) Convention
72+
73+
Obligations use a specific naming convention to distinguish them from attributes:
74+
75+
- **Obligation Definition**: `<namespace>/obl/<obligation_name>`
76+
- **Obligation Value**: `<namespace>/obl/<obligation_name>/value/<obligation_value>`
77+
78+
For example:
79+
- `https://example.com/obl/drm` (definition)
80+
- `https://example.com/obl/drm/value/watermarking` (value)

specs/authorization/v2/authorization.openapi.yaml

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,25 @@ components:
296296
title: resources
297297
maxItems: 1000
298298
minItems: 1
299+
fulfillableObligationFqns:
300+
type: array
301+
items:
302+
type: string
303+
description: |+
304+
if provided, fulfillable_obligation_fqns must be between 1 and 50 in count with all valid FQNs:
305+
```
306+
this.size() == 0 || (this.size() <= 50 && this.all(item, item.isUri()))
307+
```
308+
309+
title: fulfillable_obligation_fqns
310+
description: |+
311+
obligations (fully qualified values) the requester is capable of fulfilling
312+
i.e. https://<namespace>/obl/<definition name>/value/<value>
313+
if provided, fulfillable_obligation_fqns must be between 1 and 50 in count with all valid FQNs:
314+
```
315+
this.size() == 0 || (this.size() <= 50 && this.all(item, item.isUri()))
316+
```
317+
299318
title: GetDecisionMultiResourceRequest
300319
required:
301320
- entityIdentifier
@@ -306,6 +325,9 @@ components:
306325
1. one entity reference (actor)
307326
2. one action
308327
3. multiple resources
328+
329+
If entitled, checks obligation policy: fulfillable obligations must satisfy all triggered.
330+
309331
Note: this is a more performant bulk request for multiple resource decisions, up to 1000 per request
310332
action.name must be provided:
311333
```
@@ -341,6 +363,25 @@ components:
341363
resource:
342364
title: resource
343365
$ref: '#/components/schemas/authorization.v2.Resource'
366+
fulfillableObligationFqns:
367+
type: array
368+
items:
369+
type: string
370+
description: |+
371+
if provided, fulfillable_obligation_fqns must be between 1 and 50 in count with all valid FQNs:
372+
```
373+
this.size() == 0 || (this.size() <= 50 && this.all(item, item.isUri()))
374+
```
375+
376+
title: fulfillable_obligation_fqns
377+
description: |+
378+
obligations (fully qualified values) the requester is capable of fulfilling
379+
i.e. https://<namespace>/obl/<definition name>/value/<value>
380+
if provided, fulfillable_obligation_fqns must be between 1 and 50 in count with all valid FQNs:
381+
```
382+
this.size() == 0 || (this.size() <= 50 && this.all(item, item.isUri()))
383+
```
384+
344385
title: GetDecisionRequest
345386
required:
346387
- entityIdentifier
@@ -352,6 +393,8 @@ components:
352393
1. one entity reference (actor)
353394
2. one action
354395
3. one resource
396+
397+
If entitled, checks obligation policy: fulfillable obligations must satisfy all triggered.
355398
action.name must be provided:
356399
```
357400
has(this.action.name)
@@ -362,9 +405,7 @@ components:
362405
properties:
363406
decision:
364407
title: decision
365-
description: |-
366-
decision on the resource optional list of obligations represented in URI format
367-
repeated string obligations = 2;
408+
description: decision on the resource
368409
$ref: '#/components/schemas/authorization.v2.ResourceDecision'
369410
title: GetDecisionResponse
370411
additionalProperties: false
@@ -457,6 +498,14 @@ components:
457498
title: decision
458499
description: decision result
459500
$ref: '#/components/schemas/authorization.v2.Decision'
501+
requiredObligations:
502+
type: array
503+
items:
504+
type: string
505+
title: required_obligations
506+
description: |-
507+
obligations (fully qualified values) the PEP is required to fulfill on the given resource
508+
i.e. https://<namespace>/obl/<definition name>/value/<value>
460509
title: ResourceDecision
461510
additionalProperties: false
462511
common.Metadata:

specs/policy/actions/actions.openapi.yaml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,81 @@ components:
665665
description: Keys for the namespace
666666
title: Namespace
667667
additionalProperties: false
668+
policy.Obligation:
669+
type: object
670+
properties:
671+
id:
672+
type: string
673+
title: id
674+
namespace:
675+
title: namespace
676+
$ref: '#/components/schemas/policy.Namespace'
677+
name:
678+
type: string
679+
title: name
680+
values:
681+
type: array
682+
items:
683+
$ref: '#/components/schemas/policy.ObligationValue'
684+
title: values
685+
fqn:
686+
type: string
687+
title: fqn
688+
metadata:
689+
title: metadata
690+
$ref: '#/components/schemas/common.Metadata'
691+
title: Obligation
692+
additionalProperties: false
693+
policy.ObligationTrigger:
694+
type: object
695+
properties:
696+
id:
697+
type: string
698+
title: id
699+
obligationValue:
700+
title: obligation_value
701+
$ref: '#/components/schemas/policy.ObligationValue'
702+
action:
703+
title: action
704+
$ref: '#/components/schemas/policy.Action'
705+
attributeValue:
706+
title: attribute_value
707+
$ref: '#/components/schemas/policy.Value'
708+
context:
709+
type: array
710+
items:
711+
$ref: '#/components/schemas/policy.RequestContext'
712+
title: context
713+
metadata:
714+
title: metadata
715+
$ref: '#/components/schemas/common.Metadata'
716+
title: ObligationTrigger
717+
additionalProperties: false
718+
policy.ObligationValue:
719+
type: object
720+
properties:
721+
id:
722+
type: string
723+
title: id
724+
obligation:
725+
title: obligation
726+
$ref: '#/components/schemas/policy.Obligation'
727+
value:
728+
type: string
729+
title: value
730+
triggers:
731+
type: array
732+
items:
733+
$ref: '#/components/schemas/policy.ObligationTrigger'
734+
title: triggers
735+
fqn:
736+
type: string
737+
title: fqn
738+
metadata:
739+
title: metadata
740+
$ref: '#/components/schemas/common.Metadata'
741+
title: ObligationValue
742+
additionalProperties: false
668743
policy.PageRequest:
669744
type: object
670745
properties:
@@ -707,6 +782,15 @@ components:
707782
description: Total count of entire list
708783
title: PageResponse
709784
additionalProperties: false
785+
policy.PolicyEnforcementPoint:
786+
type: object
787+
properties:
788+
clientId:
789+
type: string
790+
title: client_id
791+
minLength: 1
792+
title: PolicyEnforcementPoint
793+
additionalProperties: false
710794
policy.PublicKey:
711795
type: object
712796
oneOf:
@@ -735,6 +819,17 @@ components:
735819
title: PublicKey
736820
additionalProperties: false
737821
description: Deprecated
822+
policy.RequestContext:
823+
type: object
824+
properties:
825+
pep:
826+
title: pep
827+
$ref: '#/components/schemas/policy.PolicyEnforcementPoint'
828+
title: RequestContext
829+
required:
830+
- pep
831+
additionalProperties: false
832+
description: Holds the context needed for obligation fulfillment
738833
policy.ResourceMapping:
739834
type: object
740835
properties:
@@ -927,6 +1022,11 @@ components:
9271022
items:
9281023
$ref: '#/components/schemas/policy.ResourceMapping'
9291024
title: resource_mappings
1025+
obligations:
1026+
type: array
1027+
items:
1028+
$ref: '#/components/schemas/policy.Obligation'
1029+
title: obligations
9301030
metadata:
9311031
title: metadata
9321032
description: Common metadata

0 commit comments

Comments
 (0)