Policy Simulation
This section describes how to use the Apcera Policy Simulator to test and troubleshoot policy.
- Introduction
- Use cases
- Command syntax
- Filter parameters
- Simulation permissions
- Command options
- Use of quotes
- Output fields
- Examples
The Apcera Policy Simulator is available starting with the initial Long Term Support (LTS) release of the Apcera Platform.
Introduction
Apcera provides you with a policy simulator to audit and test policy behavior in the system.
To invoke the policy simulator, you run the apc policy sim <realm(s)> [args]
command.
The simulator returns results based on the simulation parameters you provide:
╭───────────────────┬───────────┬───────────────────────────────────────────────────────────────────╮
│ Context │ Type │ Claim / Condition / FQN / Input Value │
├───────────────────┼───────────┼───────────────────────────────────────────────────────────────────┤
│ authPolicy.pol:41 │ Claim │ permit update │
│ authPolicy.pol:39 │ FQN │ policy::/sandbox/[name] │
│ authPolicy.pol:40 │ Condition │ (auth_server@apcera.me->name == [name] && ResType == "gateway") │
│ INPUT │ Input │ name fred │
│ ADD INPUT │ Input │ ResType "gateway" │
╰───────────────────┴───────────┴───────────────────────────────────────────────────────────────────╯
Use cases
There are two main use cases for the Apcera Policy Simulator:
Use Case | Description |
---|---|
Audit and troubleshoot existing policy. | Run policy simulations to determine why existing policy does not permit a user to act on a resource by providing the realm (FQN), user name, and permissions you want to check. |
Test new policy. | Upload a policy document containing policy you want to add and see if you get the results you expect. |
See Examples section below.
Command syntax
You run the Policy Simulator using APC commands.
apc policy sim <filter> [<filter>...] [-i <input_claims> [-i ...]] [-c <claimtype>[=value] [-c ...]] [-f <file> [-f ...]] [-y]
apc help policy sim
Or:
apc policy sim --help
Filter parameters
Use the filter parameter to specify one or more FQNs (realms) for the simulation. For example: apc policy sim "job::/" [args]
or apc policy sim "job::/" "service::/" [args]
.
You can process all FQNs using the "*"
wildcard character. For example: apc policy sim "*" [args]
. Note that processing all FQNs may return a lot of information.
Simulation permissions
The simulation requestor must have permit read
on all realms specified in the simulation command as well as on any additional realms to be returned. The simulation returns an "access denied" error if the requestor does not have such policy.
Command options
Command options include the following:
Command | Usage | Description |
---|---|---|
-i , --input |
Establish the user identity and other input claims for the simulation. | This option may be specified more than once if multiple input claims are required. Example inputs: name=bob , "Google->email=bob@gmail.com" , ResType=gateway . Use "name=*" to run the simulation against all user IDs. |
-c , --claimtype |
Claim types and optional values to return. | This option may be specified more than once if multiple claim types and/or specific values are to be returned. Example claim types: permit=read , role=<value> , max.package.size . If not specified then all claim types and their values are returned. |
-r , --replace |
Policy files to replace or add to the simulation. | The file(s) will replace existing policies in the system for this simulation only. They are not be saved in the system. If the filename does not match an existing policy document, then it is simply added to the list of policy documents for the simulation. This option may be specified more than once if multiple policy files are to be part of the simulation. The document name reported will be the filename specified with the .pol suffix stripped from the name. The file must be a standard policy text file such as one downloaded using the "apc policy export" command. |
-y , --hypothetical |
Request a hypothetical analysis. | During a hypothetical analysis, the simulation first determines any missing claims that are required to satisfy all the policy output claims for the realm. The simulation then uses the original input claims and the missing claims as the total set of input claims for the simulation. |
Use of quotes
If a command argument contains a reserved character, you must use quotes so that the shell does not perform special processing.
Unix recognizes single or double quotes. Windows requires double quotes.
Characters that have special meaning include: *
, @
, #
, $
, [
, and ]
.
If any of these characters are in the command argument, it must be properly quoted.
Output fields
Policy simulation returns the following output fields:
Command | Usage | Description |
---|---|---|
Context |
Indicates the source of the claim, condition, FQN, or input value. The majority of the lines contain the policy file and line number of the claim, condition or FQN in the format: (s) filename:nn where (s) indicates that the document is one stored in the system, filename is the name of the policy document, and nn is the line number. When a policy document is specified on the command line using the -r option, the indicator (a), added policy document, or (r), replaces an existing policy document, will precede the policy document name. Context contains "access_denied" if the requestor has access to the realm, but does not have access to the policy file. Context contains INPUT when the source of the field is one of the input parameters or implied from an input parameter. For example: Google->name=bob@gmail.com implies an input claim of AUTHTYPE Google. Context contains "ADD INPUT" when you have requested a hypothetical analysis (the -y option) and the required input claim was added to the simulation in order to determine why a user may not have access to a resource. | |
Type |
Indicates the value field type: Claim, FQN, Condition, or Input. | |
Claim / Cond... |
Contains the value of the Claim, Condition, FQN, or Input field. |
Note that when a policy document is listed in the Context
column, the row is prefaced by one of the following indicators:
- (s) indicating system stored document
- (r) indicating replaced system stored document
- (a) indicating added to the system documents by simulation
For example, the following simulation result is based on 3 existing system stored policy documents:
| (s) authPolicy.pol:41 │ Claim │ permit update
│ (s) authPolicy.pol:39 │ FQN │ policy::/sandbox/[name]
│ (s) authPolicy.pol:40 │ Condition │ (auth_server@apcera.me->name == [name] && ResType == "gateway")
│ INPUT │ Input │ name fred
│ ADD INPUT
Examples
This section provides some example simulations.
Basic example
The following simulation returns the policy tree on the stagpipe::/
realm where the claim is "role admin" and the name (userid) is "fred@apcera.com":
apc policy sim "stagpipe::/" -c role=admin -i "name=fred@apcera.com"
Compound example
The following simulation returns the policy tree for all resources where the claim type is either "permit" or "role dev" when the Google email and name are "fred@apcera.com":
apc policy sim "*" -i "Google->email=fred@apcera.com" -i "Google->name=fred@apcera.com" -c permit -c role=dev
Hypothetical example
This example demonstrates how to use the policy simulator hypothetical flag (-y
) to troubleshoot existing policy. In this case, we want the simulation to tell us why user Fred doesn't have permit update on the realm policy::/sandbox/fred
.
First, consider the following policy that grants permit update
if name=fred
and ResType
is equal to gateway
.
policy::/sandbox/[name] {
if (auth_server@apcera.me->name==[name] && ResType == "gateway") {
permit update
}
}
If you run the following simulation:
apc policy sim "policy::/sandbox/fred" -i name=fred -c permit=update
The simulation returns the message "No claims meet your criteria" because the only input claim provided is name=fred
. Since the policy grants permit update
only if both name=fred
and ResType
is equal to gateway
are true, the input claims do not meet the policy criteria.
Now, if you use the -y
parameter and run a hypothetical simulation, the results show why Fred doesn't have permit update on policy::/sandbox/fred
:
apc policy sim "policy::/sandbox/fred" -i name=fred -c permit=update -y
╭───────────────────┬───────────┬───────────────────────────────────────────────────────────────────╮
│ Context │ Type │ Claim / Condition / FQN / Input Value │
├───────────────────┼───────────┼───────────────────────────────────────────────────────────────────┤
│ authPolicy.pol:41 │ Claim │ permit update │
│ authPolicy.pol:39 │ FQN │ policy::/sandbox/[name] │
│ authPolicy.pol:40 │ Condition │ (auth_server@apcera.me->name == [name] && ResType == "gateway") │
│ INPUT │ Input │ name fred │
│ ADD INPUT │ Input │ ResType "gateway" │
╰───────────────────┴───────────┴───────────────────────────────────────────────────────────────────╯
In this case the simulation takes two passes. During the first pass the simulation records all the failures and the additional claims needed to turn those failures into successes. Then the simulation adds those additional claims and takes a second pass. The "ADD INPUT" value in the context column indicates that permit update
on that target realm (FQN) is only allowed when the input claims also provide restype=gateway
to the policy engine. Otherwise Fred isn't permitted update to that target FQN.
Now that we know what is wrong we can update policy for Fred or write a new rule.
Test new policy example
This example demonstrates how to use the policy simulator to test policy you want to add to the system. You do this by referencing the policy file you want to add. Note that the policy document is considered only for the simulation; it is not uploaded to the system.
For this example, consider the following policy that authorizes a user based on the Gmail address, generates a user ID, assigns this user to the "dev" role and defines the permissions for the "dev" role:
// Policy document dev-policy.pol
// Policy for dev auth
auth::/oauth2/http {
if (Google->email == "apcera.hcos@gmail.com") {
permit issue
name dev01
}
}
// Policy for dev role assignment
audit::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
cluster::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
gateway::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
job::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
network::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
package::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
policy::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
policydoc::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
principal::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
provider::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
route::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
sempiperule::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
service::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
stagpipe::/ {
if (auth_server@apcera.me->name == apcdev) { role dev }
}
// Policy for permission grants to dev role
audit::/ {
if (role == "dev") { permit read }
}
cluster::/ {
if (role == "dev") { permit read }
}
gateway::/ {
if (role == "dev") { permit use }
}
job::/ {
if (role == "dev") { permit all }
}
network::/ {
if (role == "dev") { permit all }
}
package::/ {
if (role == "dev") { permit all }
}
policy::/ {
if (role == "dev") { permit read }
}
policydoc::/ {
if (role == "dev") { permit read }
}
principal::/ {
if (role == "dev") { permit all }
}
provider::/ {
if (role == "dev") { permit all }
}
route::/ {
if (role == "dev") { permit map }
}
sempiperule::/ {
if (role == "dev") { permit all }
}
service::/ {
if (role == "dev") { permit all }
}
stagpipe::/ {
if (role == "dev") { permit all }
}
Running a simulation aginst the dev-policy.pol
policy document returns the following results that let you verify that the policy only grants the permissions you want:
apc policy sim "*" -c role=dev -i name=apcdev -r dev-policy.pol
╭───────────────────────┬───────────┬───────────────────────────────────────────╮
│ Context │ Type │ Claim / Condition / FQN / Input Value │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:21 │ Claim │ role dev │
│ (a) dev-policy.pol:20 │ FQN │ gateway::/ │
│ (a) dev-policy.pol:21 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:13 │ Claim │ role dev │
│ (a) dev-policy.pol:12 │ FQN │ audit::/ │
│ (a) dev-policy.pol:13 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:61 │ Claim │ role dev │
│ (a) dev-policy.pol:60 │ FQN │ service::/ │
│ (a) dev-policy.pol:61 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:41 │ Claim │ role dev │
│ (a) dev-policy.pol:40 │ FQN │ policydoc::/ │
│ (a) dev-policy.pol:41 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:65 │ Claim │ role dev │
│ (a) dev-policy.pol:64 │ FQN │ stagpipe::/ │
│ (a) dev-policy.pol:65 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:25 │ Claim │ role dev │
│ (a) dev-policy.pol:24 │ FQN │ job::/ │
│ (a) dev-policy.pol:25 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:45 │ Claim │ role dev │
│ (a) dev-policy.pol:44 │ FQN │ principal::/ │
│ (a) dev-policy.pol:45 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:49 │ Claim │ role dev │
│ (a) dev-policy.pol:48 │ FQN │ provider::/ │
│ (a) dev-policy.pol:49 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:17 │ Claim │ role dev │
│ (a) dev-policy.pol:16 │ FQN │ cluster::/ │
│ (a) dev-policy.pol:17 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:53 │ Claim │ role dev │
│ (a) dev-policy.pol:52 │ FQN │ route::/ │
│ (a) dev-policy.pol:53 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:57 │ Claim │ role dev │
│ (a) dev-policy.pol:56 │ FQN │ sempiperule::/ │
│ (a) dev-policy.pol:57 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:33 │ Claim │ role dev │
│ (a) dev-policy.pol:32 │ FQN │ package::/ │
│ (a) dev-policy.pol:33 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:37 │ Claim │ role dev │
│ (a) dev-policy.pol:36 │ FQN │ policy::/ │
│ (a) dev-policy.pol:37 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
│ │ │ │
├───────────────────────┼───────────┼───────────────────────────────────────────┤
│ (a) dev-policy.pol:29 │ Claim │ role dev │
│ (a) dev-policy.pol:28 │ FQN │ network::/ │
│ (a) dev-policy.pol:29 │ Condition │ (auth_server@apcera.me->name == apcdev) │
│ INPUT │ Input │ name apcdev │
╰───────────────────────┴───────────┴───────────────────────────────────────────╯