Example 1: Basic ABAC with Verified Permissions and Cedar - AWS Prescriptive Guidance

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.

Example of a basic ABAC implementation with Amazon Verified Permissions and Cedar to implement a PDP

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.