Example 1: Basic ABAC with Verified Permissions and Cedar
In this example scenario, Amazon Verified Permissions is used to determine which users are allowed
to access information in a fictional Payroll microservice. This section includes
Cedar code snippets to demonstrate how you can use Cedar to render access control
decisions. These examples aren't intended to provide a full exploration of the
capabilities provided by Cedar and Verified Permissions. For a more thorough overview of Cedar, see
the Cedar documentation
In the following diagram, we would like to enforce two general business rules that
are associated with the viewSalary
GET
method: Employees can view their own salary
and Employees can view the salary of anyone who reports to
them. You can enforce these business rules by using Verified Permissions
policies.

Employees can view their own salary.
In Cedar, the basic construct is an entity, which represents a principal, action, or a resource. To make an authorization request and start an evaluation with a Verified Permissions policy, you need to provide a principal, an action, a resource, and a list of entities.
-
The principal (
principal
) is the logged in user or role. -
The action (
action
) is the operation that is evaluated by the request. -
The resource (
resource
) is the component that the action is accessing. -
The list of entities (
entityList
) contains all the required entities needed to evaluate the request.
To satisfy the business rule Employees can view their own salary, you can provide a Verified Permissions policy such as the following.
permit ( principal, action == Action::"viewSalary", resource ) when { principal == resource.owner };
This policy evaluates to ALLOW
if the Action
is
viewSalary
and the resource in the request has an attribute owner
that is equal to the principal. For example, if Bob is the logged in user who
requested the salary report and is also the owner of the salary report, the policy
evaluates to ALLOW
.
The following authorization request is submitted to Verified Permissions to be evaluated by the
sample policy. In this example, Bob is the logged in user who makes the
viewSalary
request. Therefore, Bob is the principal of the entity
type Employee
. The action Bob is trying to perform is
viewSalary,
and the resource that viewSalary
will
display is Salary-Bob
with the type Salary
. In order to
evaluate if Bob can view the Salary-Bob
resource, you need to provide
an entity structure that links the type Employee
with a value of
Bob
(the principal) to the owner attribute of the resource that has
the type Salary
. You provide this structure in an
entityList
, where the attributes associated with
Salary
include an owner, which specifies an
entityIdentifier
that contains the type Employee
and
value Bob
. Verified Permissions compares the principal
provided in the
authorization request to the owner
attribute that is associated with
the Salary
resource to make a decision.
{ "policyStoreId": "PAYROLLAPP_POLICYSTOREID", "principal": { "entityType": "PayrollApp::Employee", "entityId": "Bob" }, "action": { "actionType": "PayrollApp::Action", "actionId": "viewSalary" }, "resource": { "entityType": "PayrollApp::Salary", "entityId": "Salary-Bob" }, "entities": { "entityList": [ { "identifier": { "entityType": "PayrollApp::Salary", "entityId": "Salary-Bob" }, "attributes": { "owner": { "entityIdentifier": { "entityType": "PayrollApp::Employee", "entityId": "Bob" } } } }, { "identifier": { "entityType": "PayrollApp::Employee", "entityId": "Bob" }, "attributes": {} } ] } }
The authorization request to Verified Permissions returns the following as output, where the
attribute decision
is either ALLOW
or
DENY
.
{ "determiningPolicies": [ { "determiningPolicyId": "PAYROLLAPP_POLICYSTOREID" } ], "decision": "ALLOW", "errors": [] }
In this case, because Bob was trying to view his own salary, the authorization
request sent to Verified Permissions evaluates to ALLOW
. However, our objective was to
use Verified Permissions to enforce two business rules. The business rule that states the following
should also be true:
Employees can view the salary of anyone who reports to them.
To satisfy this business rule, you can provide another policy. The following
policy evaluates to ALLOW
if the action is viewSalary
and
the resource in the request has an attribute owner.manager
that is
equal to the principal. For example, if Alice is the logged in user who requested
the salary report and Alice is the manager of the report's owner, the policy
evaluates to ALLOW
.
permit ( principal, action == Action::"viewSalary", resource ) when { principal == resource.owner.manager };
The following authorization request is submitted to Verified Permissions to be evaluated by the
sample policy. In this example, Alice is the logged in user who makes the
viewSalary
request. Therefore Alice is the principal and the entity
is of the type Employee
. The action Alice is trying to perform is
viewSalary
, and the resource that viewSalary
will
display is of the type Salary
with a value of Salary-Bob
.
In order to evaluate if Alice can view the Salary-Bob
resource, you
need to provide an entity structure that links the type Employee
with a
value of Alice
to the manager
attribute, which must then
be associated with the owner
attribute of the type Salary
with a value of Salary-Bob
. You provide this structure in an
entityList
, where the attributes associated with
Salary
include an owner, which specifies an
entityIdentifier
that contains the type Employee
and
value Bob
. Verified Permissions first checks the owner
attribute, which
evaluates to the type Employee
and the value Bob
. Then,
Verified Permissions evaluates the manager
attribute that's associated with
Employee
and compares it to the provided principal to make an
authorization decision. In this case, the decision is ALLOW
because the
principal
and resource.owner.manager
attributes are
equivalent.
{ "policyStoreId": "PAYROLLAPP_POLICYSTOREID", "principal": { "entityType": "PayrollApp::Employee", "entityId": "Alice" }, "action": { "actionType": "PayrollApp::Action", "actionId": "viewSalary" }, "resource": { "entityType": "PayrollApp::Salary", "entityId": "Salary-Bob" }, "entities": { "entityList": [ { "identifier": { "entityType": "PayrollApp::Employee", "entityId": "Alice" }, "attributes": { "manager": { "entityIdentifier": { "entityType": "PayrollApp::Employee", "entityId": "None" } } }, "parents": [] }, { "identifier": { "entityType": "PayrollApp::Salary", "entityId": "Salary-Bob" }, "attributes": { "owner": { "entityIdentifier": { "entityType": "PayrollApp::Employee", "entityId": "Bob" } } }, "parents": [] }, { "identifier": { "entityType": "PayrollApp::Employee", "entityId": "Bob" }, "attributes": { "manager": { "entityIdentifier": { "entityType": "PayrollApp::Employee", "entityId": "Alice" } } }, "parents": [] } ] } }
So far in this example, we provided the two business rules associated with the
viewSalary
method, Employees can view their own
salary and Employees can view the salary of anyone who
reports to them, to Verified Permissions as policies to satisfy the conditions of
each business rule independently. You can also use a single Verified Permissions policy to satisfy
the conditions of both business rules:
Employees can view their own salary and the salary of anyone who reports to them.
When you use the previous authorization request, the following policy evaluates to
ALLOW
if the action is viewSalary
and the resource in
the request has an attribute owner.manager
that is equal to the
principal
, or an attribute owner
that is equal to the
principal
.
permit ( principal, action == PayrollApp::Action::"viewSalary", resource ) when { principal == resource.owner.manager || principal == resource.owner };
For example, if Alice is the logged in user who requests the salary report, and if
Alice is either the manager of the owner or the owner of the report, then the policy
evaluates to ALLOW
.
For more information about using logical operators with Cedar policies, see the
Cedar
documentation