Themis是一个通用的策略引擎,受XACML架构的启发(但并不受其影响)。
Themis represents a set of tools for managing and enforcing security policies along with framework to create such tools:
Themis design is inspired by eXtensible Access Control Markup Language (XACML) [XACML-V3.0].
Policy Decision Point or PDP (according to [XACML-V3.0]) is an entity that evaluates applicable policy and renders an authorization decision. Themis provides PDP as a golang package.
To make a decision PDP evaluates policies it has on request context. A request context represents set of attributes together with local content (additional data which can be used by policies during the evaluation). Resulting decision consists of effect, status (reason) and set of obligations. Decision effect can be:
Some application may require more details for particular decision. For example if application can write log it may need a flag attached to decision which says when to do it. These details can be delivered as obligations. The obligations are set of attributes like in request context. Each attribute has name, type and value. Attribute name is arbitrary string (request context requires pair of attribute name and type to be unique). Following built-in types are defined:
Boolean value is accepted as “1”, “t”, “T”, “TRUE”, “true”, “True”, “0”, “f”, “F”, “FALSE”, “false”, “False” and serialized to “true” and “false”. Integer value is a decimal number in range [-9223372036854775808, 9223372036854775807]. Float value can be specified using decimal format (e.g. 3.1416) or scientific notation (e.g. 6.022E+23). Address accepted in dotted decimal (“192.0.2.1”) form or in IPv6 (“2001:68”) form and serialized respectively. Network is accepted as a CIDR notation IP address and prefix (for example “192.0.2.0/24” or “2001
:/32”). Domain name is accepted as string of labels separated by dots which satisfies to RFC1035, 2181 and 4343 requirements. Set of strings, set of domains, set of networks and list of strings aren’t accepted in request context but can appear in response’s obligations as comma separated list of values.
User can define her custom type based on flags metatype. A value of the type can be any combination of listed flags. PDP allows to define up to 64 flags for a type. Values can’t appear in request or returned as obligations.
PDP uses YAML based language (YAML Abstract Syntax Tree or YAST) or JSON based language (JSON Abstract Syntax Tree or JAST) to define policies and specifically constructed JSON to define local content (JSON Content or JCON). YAST can be converted to JAST (and vise versa) with any YAML to JSON converter.
Any policies definition consists of policies (required), attributes (optional) and types (optional) sections. Policies section contains root policy or policy set. Policy holds rules under its “rules” field while policy set is able to contain both inner policies or policy sets under its “policies” field. For example:
YAST
# All permit policy (without "attributes" section)
policies:
alg: FirstApplicableEffect
rules:
- effect: Permit
JAST
{
"policies": {
"alg": "FirstApplicableEffect",
"rules": [
{
"effect": "Permit"
}
]
}
}
Attributes section contains set of pairs attribute name and type:
YAST
# Permit if x is "test" otherwise Not Applicable
attributes:
x: string
policies:
alg: FirstApplicableEffect
target:
- equal:
- attr: x
- val:
type: string
content: "test"
rules:
- effect: Permit
JAST
{
"attributes": {
"x": "string"
},
"policies": {
"alg": "FirstApplicableEffect",
"target": [
{
"equal": [
{
"attr": "x"
},
{
"val": {
"type": "string",
"content": "test"
}
}
]
}
],
"rules": [
{
"effect": "Permit"
}
]
}
}
Types section is designed for custom type definitions which now are limited to only flags metatype:
YAST
types:
colors:
meta: flags
flags:
- red
- green
- blue
attributes:
c: list of strings
policies:
alg: FirstApplicableEffect
rules:
- effect: Permit
obligations:
- c:
list of strings:
- val:
type: colors
content:
- red
- blue
JAST
{
"types": {
"colors": {
"meta": "flags",
"flags": ["red", "green", "blue"]
}
},
"attributes": {
"c": "list of strings"
},
"policies": {
"alg": "FirstApplicableEffect",
"rules": [
{
"effect": "Permit",
"obligations": [
{
"c": {
"list of strings": [
{
"val": {
"type": "colors",
"content": ["red", "blue"]
}
}
]
}
}
]
}
]
}
}
Policy Set holds set of policies or inner policy sets and defines how to combine them. It has following fields:
Example of policy set with all its fields (it contains one hidden policy set and one hidden policy):
# Policy set with all its fields
...
id: "Test Policy Set"
target: # x == "test"
- equal:
- attr: x
- val:
type: string
content: "test"
alg: FirstApplicableEffect
policies:
- alg: FirstApplicableEffect
target:
- equal: # z == "example"
- attr: z
- val:
type: string
content: "example"
policies:
- alg: FirstApplicableEffect
rules:
- effect: Permit
- alg: FirstApplicableEffect
rules:
- effect: Deny
obligations:
- a:
val:
type: address
content: "192.0.2.1"
Policy stores set of rules and defines how to combine them. It has following fields:
Here is an example of policy with all fields defined (it contains one hidden rule):
# Policy with all its fields
...
id: "Test Policy"
target: # x == "test"
- equal:
- attr: x
- val:
type: string
content: "test"
alg: FirstApplicableEffect
rules:
- effect: Permit
obligations:
- a:
val:
type: address
content: "192.0.2.1"
Rule defines decision effect. Possible fields of a rule:
For example a rule with all fields:
# Rule with all its fields
...
id: "Test Rule"
target: # x == "test"
- equal:
- attr: x
- val:
type: string
content: "test"
condition: # not (c contains 192.0.2.1 or b)
not:
- or:
- contains:
- attr: c
- val:
type: address
content: "192.0.2.1"
- attr: b
effect: Permit
obligations:
- a:
val:
type: address
content: "192.0.2.1"
Any particular policy set or policy or rule is applicable only if request matches its target. Target is a list of any expressions. Any expression is a list of all expressions and all expression is a list of match expression. Match expression is a boolean expression of two arguments. One of arguments should be a request attribute and other should be a immediate value. Only two functions can represent match expression equal and contains. If list of match expressions for particular all expression contains single element all keyword can be dropped. Similarly if list of all expressions for particular any expression consists of one element any keyword can be dropped.
Request matches target when all any expressions match (if one or more of any expression doesn’t match, target also doesn’t match). Any expression matches request if one or more of its all expressions match the request (if all all expressions don’t match, any expression doesn’t match as well). And similarly to target all expression matches if all its inner expressions match as well. If during target evaluation error occurs the policy set, policy or rule effect becomes indeterminate (if rule effect is permit it is indeterminateP if deny - indeterminateD for policy and policy set kind of indeterminate depends on combining algorithm (see below).
Below an example of policy with different kinds of targets:
# Target examples
...
# ((x == test and c contains address(192.0.2.1)) or
# x == example) and
# (network(192.0.2.0/28) contains a or network(192.0.2.16/28) contains a)
target:
- any:
- all:
- equal:
- attr: x
- val:
type: string
content: "test"
- contains:
- attr: c
- val:
type: address
content: 192.0.2.1
- equal:
- attr: x
- val:
type: string
content: "example"
- any:
- contains:
- val:
type: network
content: 192.0.2.0/28
- attr: a
- contains:
- val:
type: network
content: 192.0.2.16/28
- attr: a
...
# (x == test or x == example) and (network(192.0.2.0/28) contains a or network(192.0.2.16/28) contains a)
target:
- any:
- equal:
- attr: x
- val:
type: string
content: "test"
- equal:
- attr: x
- val:
type: string
content: "example"
- any:
- contains:
- val:
type: network
content: 192.0.2.0/28
- attr: a
- contains:
- val:
type: network
content: 192.0.2.16/28
- attr: a
...
# x == test and network(192.0.2.0/24) contains a
target:
- equal:
- attr: x
- val:
type: string
content: "test"
- contains:
- val:
type: network
content: 192.0.2.0/24
- attr: a
...
# x == test
target:
- equal:
- attr: x
- val:
type: string
content: "test"
Condition is rule field which can be any boolean expression (for example see above “Rule with all its fields”). Following functions available to make such expression:
In any expression attribute can be referred with attr keyword and immediate value with val keyword (see below). There is special selector expression which is described below.
Immediate value can be referred with val keyword and has fields:
Example of policy with all possible values:
# All values example
...
# String
val:
type: string
content: test
...
obligations:
- s:
val:
type: string
content: example
...
# Address
val:
type: address
content: 192.0.2.1
...
obligations:
- a:
val:
type: address
content: 192.0.2.2
...
# Network
val:
type: network
content: 192.0.2.0/28
...
obligations:
- c:
val:
type: network
content: 192.0.2.16/28
...
# Domain
val:
type: domain
content: example.com
...
obligations:
- d:
val:
type: domain
content: example.com
...
# Set of Strings
val:
type: set of strings
content:
- first
- second
...
obligations:
- ss:
val:
type: set of strings
content:
- first
- second
...
# Set of Networks
val:
type: set of networks
content:
- 192.0.2.0/28
- 192.0.2.16/28
...
obligations:
- sn:
val:
type: set of networks
content:
- 192.0.2.0/28
- 192.0.2.16/28
...
# Set of Domains
val:
type: set of domains
content:
- example.com
- example.net
...
obligations:
- sd:
val:
type: set of domains
content:
- example.com
- example.net
...
# List of Strings
val:
type: list of strings
content:
- first
- second
...
obligations:
- ls:
val:
type: list of strings
content:
- first
- second
...
# Custom Flags
types:
colors:
meta: flags
flags: [red, green, blue]
...
val:
type: colors
content: [blue, green]
Selector expression is an expression to access additionally supplied data. Selector uses uri field to locate source of such data. Currently only “local” URI schema is supported which defines local selector.
Local selector uses local content data (see below) and has following fields:
type
field. If default
field is not set the expression from error
field is calculated. If both default
and error
are not set the error is returned to outer object.type
field. If error
field is not set the error is returned to outer object.disable
);Example of local selector:
# Selector example
...
selector:
uri: "local:content/domain-addresses"
path:
- val:
type: string
content: good
- attr: d
type: set of networks
default:
attr: x
error:
val:
type: set of networks
content: ["192.0.74.0/24", "192.0.94.0/24"]
Content for the example:
{
"id": "content",
"items": {
"domain-addresses": {
"keys": ["string", "domain"],
"type": "set of networks",
"data": {
"good": {
"example.com": ["192.0.2.16/28", "192.0.2.32/28"],
"test.com": ["192.0.2.48/28", "192.0.2.64/28"]
},
"bad": {
"example.com": ["2001:db8:1000::/40", "2001:db8:2000::/40"],
"test.com": ["2001:db8:3000::/40", "2001:db8:4000::/40"]
}
}
}
}
}
When result of mapping is a flags value selector matches flag names by order of definition. Flags defined in policies YAST or JSON must have the same number of names as content have. For example if policy defines names “one”, “two”, “three” for some flags type and content defines names “red”, “green” and “blue” for a map referred by selector URI, selector returns “one” for “red”, “two” for “green” and “three” for “blue”.
A numerical expression is constructed using the following numerical functions:
range - accepts three arguments - the first two of which specify a range, and the third a value to be compared against the range. The arguments are:
The result of the range function is a string, which can be one of the following:
Each of the above numerical functions performs the respective numerical operation using either integer or floating point arithmetic according to the following rule:
Both set of strings and list of strings have functions, in addition to equal and contains, related to analyzing the contents of the collection as a whole:
Note that like equal, intersect cannot mix string collection types (list and set); for comparing the two, convert the set of strings using list of strings (below).
There are several other functions available:
Local content is a set of content items (see example above). It’s identified by id field which can be any string with no slash character (/
). Each content item also has id (key of “items” JSON object) and following fields:
Local content supports string map (key type “string”), domain map (key type “domain”) and network map (key type “network” or “address”). Selector expects string expression as path item for string map, domain - for domain map and address or network - for network map (“address” expression is allowed even if content key is “network” and vice verse).
Any map supports also mapping to flags type. To create such map user needs to define flags in type field. Being defined a flags type can be used by name within the content and its updates. Type definition goes to type field of content item but it’s represented by JSON object instead of string. The object should have following fields:
For example:
{
"id": "content",
"items": {
"example-domains": {
"keys": ["domain"],
"type": {
"meta": "flags",
"name": "tags",
"flags": ["red", "green", "blue"]
},
"data": {
"example.com": ["red", "green"],
"example.net": ["red", "blue"],
"example.org": ["blue", "green"]
}
},
"test-domains": {
"keys": ["domain"],
"type": "tags",
"data": {
"test.com": ["red", "green"],
"test.net": ["red", "blue"],
"test.org": ["blue", "green"]
}
}
}
}
In case if content item expects string
key and selector provides a key of type list of strings
the content item can iterate over several paths using each string from the provided list of string
key as an individual string
key. The result will be an aggregated value obtained from several paths. The way how data is aggregated depends on the aggregation
field defined in selector expression.
The allowable values for aggregation
fields are
list of strings
key where string
key is expected by content item - it will result in error.list of strings
key will be skipped. This aggregation type can be defined with any content item type.list of strings
. The aggregated value will be the list of all strings from the content values found at the paths constructed from the list of strings
key. The order of strings in the aggregated value is preserved.See below an example where user roles are mapped to actions allowed
{
"id": "content",
"items": {
"example-aggregation": {
"type": "list of strings",
"keys": ["string"],
"data": {
"admin": ["create","reset"],
"reader": ["read"],
"writer": ["read", "write"]
}
}
}
}
In case if one person has several roles it’s possible to obtain all allowed actions with a selector like below, where attribute roles
has type list of strings
and includes all roles assigned to the person.
...
selector:
aggregation: append
path:
- attr: roles
type: list of strings
uri: "local:content/example-aggregation"
Thus, if attrubite roles
has value [“admin”,”supervisor”,”reader”] the selector above will return value [“create”,”reset”,”read”] (no actions for “supervisor” were defined).
Policy and rule combining algorithms define how to use child policies or rules of given policy set or policy and how to combine their effects, statuses and obligations. Themis supports following algorithms:
For any algorithm if effect of children evaluation is Deny or Permit policy or policy set adds its obligation to what it got from children.
The algorithm iterates child policies or rules and evaluates them one by one. User should not relay on any particular order (however for now it goes sequentionaly from first to the last). If any child evaluation effect is not NotApplicable the effect becomes overall policy or policy set result.
The algorithm as well evaluates child policies or rules one by one. User should not relay on any particular order (however for now it goes sequentionaly from first to the last). If any effect is Deny the effect becomes overall policy or policy set result and any other evaluation results are dropped. Other effects are combined as following:
Effects | Result |
---|---|
at least one IndeterminateDP or at least one IndeterminateD with at least one Permit or at least one IndeterminateP and any NotApplicable | IndeterminateDP |
at least one IndeterminateD and any NotApplicable | IndeterminateD |
at least one Permit and any IndeterminateP or NotApplicable | Permit |
at least one IndeterminateP and any NotApplicable | IndeterminateP |
only NotApplicable | NotApplicable |
In case of any Indeterminate result all statuses are combined together.
The algorithm is capable to select particular child policy or rule with no evaluation other children one by one. It has some parameters:
Any hidden child policy or rule is ignored by mapper algorithm.
For example policies:
# Mapper example
...
alg:
id: Mapper
map:
attr: p
default: DenyPolicy
error: ErrorPolicy
...
alg:
id: Mapper
map:
selector:
uri: "local:content/domain-policies"
path:
- attr: d
type: list of strings
default: DenyRule
alg: FirstApplicableEffect
order: Internal
and content for them:
{
"id": "content",
"items": {
"domain-policies": {
"keys": ["domain"],
"type": "list of strings",
"data": {
"example.com": ["PermitCom", "DenyCom"],
"example.net": ["PermitNet", "DenyNet"]
}
}
}
}
If result type of map is a flags type its flag names treated as id of policy to run. If flags value has several flags set they are ordered according of order in type definiton and passed to nested combining algorithm.
PDP server allows to run and control PDP. Additionally the server provides endpoint for healthcheck and supports OpenZipkin tracing. Started with no options pdpservers gets no initial policies and content. Policies and content in the case should be provided by control interface. Option -p
provides initial policy for the server from given YAML file. Option -j
provides content (it can be specified several times). For example (-v 3
sets maximal log level):
$ pdpserver -v 3 -p policy.yaml -j mapper.json -j content.json
INFO[0000] Starting PDP server
INFO[0000] Loading policy policy=policy.yaml
INFO[0000] Parsing policy policy=policy.yaml
INFO[0000] Opening content content=mapper.json
INFO[0000] Parsing content content=mapper.json
INFO[0000] Opening content content=content.json
INFO[0000] Parsing content content=content.json
INFO[0000] Opening service port address="0.0.0.0:5555"
INFO[0000] Opening control port address="0.0.0.0:5554"
INFO[0000] Creating service protocol handler
INFO[0000] Creating control protocol handler
INFO[0000] Serving decision requests
INFO[0000] Serving control requests
Other pdpserver options:
-c
- listen for policies on given address:port (default “0.0.0.0:5554”);-health
- health check endpoint;-l
- listen for decision requests on given address:port (default “0.0.0.0:5555”);-pprof
- performance profiler endpoint (see go tool pprof);-t
- OpenZipkin tracing endpoint;-v
- log verbosity (0 - error, 1 - warn (default), 2 - info, 3 - debug).To make decision requests, there are 3 options: create client from scratch which implements protocol defined by proto/service.proto
, use golang client package themis\pep
to implement client application, and for debug use simple PEPCLI client. To use PEPCLI, requests can be read in with -i
(strings ending in .yaml
or .json
will be treated as a filepath; anything else is parsed as raw JSON), for example:
attributes:
s: string
a: address
requests:
- s: Local Test
a: 127.0.0.1
- s: Example
a: 192.0.2.1
start PDP server with some policy (use for example “All permit policy” above):
$ pdpserver -v 3 -p all-permit-policy.yaml
INFO[0000] Starting PDP server
INFO[0000] Loading policy policy=all-permit-policy.yaml
INFO[0000] Parsing policy policy=all-permit-policy.yaml
INFO[0000] Opening service port address="0.0.0.0:5555"
INFO[0000] Opening control port address="0.0.0.0:5554"
INFO[0000] Creating service protocol handler
INFO[0000] Creating control protocol handler
INFO[0000] Serving decision requests
INFO[0000] Serving control requests
in the other terminal run PEPCLI:
$ pepcli -i requests.yaml test
Got 2 requests. Sending...
- effect: PERMIT
reason: "Ok"
- effect: PERMIT
reason: "Ok"
PEPCLI sends two requests which are listed in the file ang gets all permitted as instructed by the policy. In PDP’s terminal you can see respective logs:
...
INFO[0000] Serving decision requests
INFO[0000] Serving control requests
INFO[0089] Validating context
DEBU[0089] Request context context=attributes:
- a.(Address): 127.0.0.1
- s.(String): "Local Test"
INFO[0089] Returning response
DEBU[0089] Response effect=PERMIT obligation=no attributes reason=Ok
INFO[0089] Validating context
DEBU[0089] Request context context=attributes:
- s.(String): "Example"
- a.(Address): 192.0.2.1
INFO[0089] Returning response
DEBU[0089] Response effect=PERMIT obligation=no attributes reason=Ok
...
PDP Server accepts control requests to upload and update policies or content. Themis user can implement her own client from scratch using protocol definition from proto/control.proto
or using golang package themis/pdpctrl-client
. To make control requests for debug purpose Themis provides PAPCLI tool.
Update is a list of commands each contains three fields:
PDP supports add and delete commands. In case of add path should point to parent item and entity should contain appropriate child. For example if it is policy update and path points to policy set entity can be policy or other policy set. If path points to policy then only rule can be accepted as entity.
For example in one terminal start PDP server with no policies:
$ pdpserver -v 3
INFO[0000] Starting PDP server
INFO[0000] Opening service port address="0.0.0.0:5555"
INFO[0000] Opening control port address="0.0.0.0:5554"
INFO[0000] Creating service protocol handler
INFO[0000] Creating control protocol handler
INFO[0000] Serving decision requests
INFO[0000] Serving control requests
Then upload policy with PAPCLI (“All permit policy”):
$ papcli -s 127.0.0.1:5554 -p all-permit-policy.yaml
INFO[0000] Requesting data upload to PDP servers...
INFO[0000] Uploading data to PDP servers...
PDP got the data:
...
INFO[0000] Serving decision requests
INFO[0000] Serving control requests
INFO[0004] Got new control request
INFO[0004] Got new data stream
INFO[0004] Got apply command
INFO[0004] New policy has been applied id=1
...
PDP Server doesn’t accept updates to policy with no tag so upload other policy and set tag to it to make update later (here policy similar to “permit if x is test” is used but with ids (because commands add and delete doen’t see hidden policies or rules):
# Permit if x is "test" otherwise Not Applicable
attributes:
x: string
policies:
id: Root
alg: FirstApplicableEffect
target:
- equal:
- attr: x
- val:
type: string
content: "test"
rules:
- id: First Rule
effect: Permit
Run PAPCLI with the policy and initial tag (option -vt
the tag should be correct UUID):
$ papcli -s 127.0.0.1:5554 -p permit-test-x-policy.yaml -vt 823f79f2-0001-4eb2-9ba0-2a8c1b284443
INFO[0000] Requesting data upload to PDP servers...
INFO[0000] Uploading data to PDP servers...
PDP Server accepts the policy:
...
INFO[0016] Got new control request
INFO[0016] Got new data stream
INFO[0016] Got apply command
INFO[0016] New policy has been applied id=1 tag=823f79f2-0001-4eb2-9ba0-2a8c1b284443
...
Then policy can be updated (with following update which removes “First Rule” and adds other one):
- op: add
path:
- Root
entity:
id: Permit Rule With Obligation
effect: Permit
obligations:
- x: example
- op: delete
path:
- Root
- First Rule
Run PAPCLI with the update (you need to specify previous tag with option -vf
and new tag with option -vt
, when both options present PDP server considers data as update and checks if -vf
tag matches to tag current tag of updated to maintain update consistency):
$ papcli -s 127.0.0.1:5554 -p permit-test-x-policy-update.yaml -vf 823f79f2-0001-4eb2-9ba0-2a8c1b284443 -vt 93a17ce2-788d-476f-bd11-a5580a2f35f3
INFO[0000] Requesting data upload to PDP servers...
INFO[0000] Uploading data to PDP servers...
PDP accepts the update:
...
INFO[0373] Got new control request
INFO[0373] Got new data stream
DEBU[0373] Policy update update=policy update: 823f79f2-0001-4eb2-9ba0-2a8c1b284443 - 93a17ce2-788d-476f-bd11-a5580a2f35f3
commands:
- Add Path ("Root")
- Delete Path ("Root"/"First Rule")
INFO[0373] Got apply command
INFO[0373] Policy update has been applied curr-tag=93a17ce2-788d-476f-bd11-a5580a2f35f3 id=3 prev-tag=823f79f2-0001-4eb2-9ba0-2a8c1b284443
...
Consider content update. For example use “Selector example” policy. Start PDP with the policy:
$ pdpserver -v 3 -p selector-examle.yaml
INFO[0000] Starting PDP server
INFO[0000] Loading policy policy=selector-examle.yaml
INFO[0000] Parsing policy policy=selector-examle.yaml
INFO[0000] Opening service port address="0.0.0.0:5555"
INFO[0000] Opening control port address="0.0.0.0:5554"
INFO[0000] Creating service protocol handler
INFO[0000] Serving decision requests
INFO[0000] Creating control protocol handler
INFO[0000] Serving control requests
Then upload content with some tag (to be able to update it):
$ papcli -s 127.0.0.1:5554 -j selector-examle.json -vt 823f79f2-0001-4eb2-9ba0-2a8c1b284443
INFO[0000] Requesting data upload to PDP servers...
INFO[0000] Uploading data to PDP servers...
PDP server accepts upload:
...
INFO[0265] Got new control request
INFO[0265] Got new data stream
INFO[0265] Got apply command
INFO[0265] New content has been applied id=1 tag=823f79f2-0001-4eb2-9ba0-2a8c1b284443
...
Now lets move IPv4 addresses from “good” to “bad” map and IPv6 from
“bad” to “good” for “example.com”:
[
{
"op": "delete",
"path": ["domain-addresses", "good", "example.com"]
},
{
"op": "add",
"path": ["domain-addresses", "good", "example.com"],
"entity": {
"type": "set of networks",
"data": ["2001:db8:1000::/40", "2001:db8:2000::/40"]
}
},
{
"op": "delete",
"path": ["domain-addresses", "bad", "example.com"]
},
{
"op": "add",
"path": ["domain-addresses", "bad", "example.com"],
"entity": {
"type": "set of networks",
"data": ["192.0.2.16/28", "192.0.2.32/28"]
}
}
]
Note that update’s entities doesn’t contain keys field as data is immediate value (and has no any mappings). If update add some entity with mapping entity should have a keys filed. For example:
[
{
"op": "delete",
"path": ["domain-addresses", "good"]
},
{
"op": "add",
"path": ["domain-addresses", "good"],
"entity": {
"type": "set of networks",
"keys": ["domain"],
"data": {
"example.com": ["2001:db8:1000::/40", "2001:db8:2000::/40"],
"test.com": ["2001:db8:3000::/40", "2001:db8:4000::/40"]
}
}
}
]
Run PAPCLI with content update file:
$ papcli -s 127.0.0.1:5554 -id content -j selector-examle-update.json -vf 823f79f2-0001-4eb2-9ba0-2a8c1b284443 -vt 93a17ce2-788d-476f-bd11-a5580a2f35f3
INFO[0000] Requesting data upload to PDP servers...
INFO[0000] Uploading data to PDP servers...
Check PDP logs:
...
INFO[2190] Got new control request
INFO[2190] Got new data stream
DEBU[2190] Content update update=content update: 823f79f2-0001-4eb2-9ba0-2a8c1b284443 - 93a17ce2-788d-476f-bd11-a5580a2f35f3
content: "content"
commands:
- Delete Path ("domain-addresses"/"good"/"example.com")
- Add Path ("domain-addresses"/"good"/"example.com")
- Delete Path ("domain-addresses"/"bad"/"example.com")
- Add Path ("domain-addresses"/"bad"/"example.com")
INFO[2190] Got apply command
INFO[2190] Content update has been applied cid=content curr-tag=93a17ce2-788d-476f-bd11-a5580a2f35f3 id=5
...
Contents with different ids and policies can be updated independently and in parallel.
[XACML-V3.0] eXtensible Access Control Markup Language (XACML) Version 3.0. 22 January 2013. OASIS Standard. http://docs.oasis-open.org/xacml/3.0/xacml-3.0-core-spec-os-en.html.