DEV Community

Cover image for Authorization and Amazon Verified Permissions - A New Way to Manage Permissions Part IX: Hierarchies and ABAC
Daniel Aniszkiewicz for AWS Community Builders

Posted on • Updated on

Authorization and Amazon Verified Permissions - A New Way to Manage Permissions Part IX: Hierarchies and ABAC

Welcome back to our series on Amazon Verified Permissions (AVP)! In the previous article we've discussed how to integrate AVP with Cognito. Today, we're going to delve into a more advanced topic: hierarchies and entities in AVP.

Hierarchies vs Groups

In one of a previous article, we've seen how to use groups in AVP to manage permissions for a set of users. Groups are a powerful tool for simplifying permission management, especially when you have a large number of users with similar roles. For example, in our e-commerce platform, we might have a group for VIP customers who have access to preorder some products.

However, groups are not always sufficient to capture the full complexity of real-world authorization scenarios. For example, consider an e-commerce platform with a hierarchical customer structure, where permissions need to be inherited or overridden based on the customer's level in the hierarchy. In these cases, we need a more sophisticated way to model the relationships between users and resources. This is where hierarchies and entities come into play.

Entities and Attributes in AVP

In AVP, an entity is a representation of a principal, action, or resource in your application. Each entity has:

  • An identifier: This includes an entity type and an entity ID. For example, for a customer entity, the entity type might be "EcommercePlatform::Customer" and the entity ID might be "Daniel".
  • A set of attributes: These are properties or characteristics of the entity. For example, a customer entity might have attributes like 'purchase history' and 'loyalty level'.
  • A list of parent entities: This is used to define the parent entities. In our use case we will add departments.

Cedar vs AVP Format: A Comparative Look

To better understand the differences between the Cedar and AVP formats, let's take a look at how a Seller entity from our e-commerce example would be represented in each format:

Cedar Format:

{
    "uid": {
        "type": "Seller",
        "id": "1"
    },
    "attrs": {
        "rating": 5,
        "department": {
            "__entity": {
                "type": "Department",
                "id": "luxury"
            }
        }
    },
    "parents": []
}
Enter fullscreen mode Exit fullscreen mode

AVP Format:

{
    "identifier": {
        "entityType": "EcommercePlatform::Seller",
        "entityId": "1"
    },
    "attributes": {
        "rating": {
            "long": 5
        },
        "department": {
            "entityIdentifier": {
                "entityType": "EcommercePlatform::Department",
                "entityId": "luxury"
            }
        }
    },
    "parents": []
}

Enter fullscreen mode Exit fullscreen mode

Key Differences:

Entity Representation:

Cedar: Uses uid with type and id to represent the entity.
AVP: Uses identifier with entityType and entityId.

Attribute Types:

Cedar: Directly assigns values to attributes.
AVP: Attributes are typed, such as {"long": 5} for the rating.
Entity Relationships:

Cedar: Uses the __entity key inside attributes to denote relationships.
AVP: Uses the entityIdentifier key for relationships.
Entity Naming:

Cedar: Uses concise names like "Seller".
AVP: Uses namespaced names like "EcommercePlatform::Seller".

Ecommerce example

Let's take our ongoing example of an e-commerce system where we have Sellers, Customers, Products, and now, Departments. We've used these entities in our previous blog posts as well. This time, let's imagine we're dealing with a car dealership. Our sellers are car dealers, and they have actions like selling cars, giving discounts, and ordering new cars.

We can define our entities like this:

  • A Seller entity might have attributes like 'rating', and 'department'. The 'department' attribute links the Seller to a Department entity, indicating which department the seller belongs to.
  • A Department entity represents different departments within the dealership, each responsible for selling certain types of cars.
  • A Product (in this case, a Car) entity might have attributes like 'price', and 'department'. The 'department' attribute links the Car to a Department entity, indicating which department is responsible for selling this car.
  • A Customer entity might have attributes like and 'loyalty level'. In this setup, we're going to implement two rules:

Hierarchy Rule: A seller can sell a car if the seller's department matches the car's parent department. This rule represents a hierarchical relationship between sellers, departments, and cars.
ABAC Rule: Moreover a seller can sell if the rating (based on reputation) value is bigger than the specific value, as well whether the price is above some specific level. Those rules represent an attribute-based access control (ABAC) scenario where access decisions are made based on the attributes of the entities involved.

Implementation

We can either use AVP-CLI with scenario, or do it manually within the console.

AVP-CLI approach

I've prepared the scenario.

Simply run it locally:

➜  avp-cli git:(main) ✗ node index.js
Welcome to AVP CLI!
This tool is designed to help you interact with the AWS Verified Permissions (AVP) service. You can use it to create, manage, and delete policy stores, schemas, and policies.
Please ensure that you have set up your AWS credentials correctly to use this tool.
? What would you like to do? Use prepared scenarios
? Choose a scenario Ecommerce with Hierarchy and ABAC Scenario
Enter fullscreen mode Exit fullscreen mode

After a couple of seconds all resources will be deployed to AWS, grab the policy store ID from the output table and navigate to the AVP Test Bench to continue.

Manual approach

Navigate to the AVP console, and create a new policy store with empty store. Open the Schema and paste it:

{
    "EcommercePlatform": {
        "entityTypes": {
            "Department": {
                "shape": {
                    "attributes": {
                        "name": {
                            "type": "String"
                        }
                    },
                    "type": "Record"
                }
            },
            "Seller": {
                "shape": {
                    "type": "Record",
                    "attributes": {
                        "rating": {
                            "type": "Long"
                        },
                        "department": {
                            "name": "Department",
                            "type": "Entity"
                        }
                    }
                }
            },
            "Car": {
                "shape": {
                    "attributes": {
                        "price": {
                            "type": "Long"
                        },
                        "department": {
                            "name": "Department",
                            "type": "Entity"
                        }
                    },
                    "type": "Record"
                }
            }
        },
        "actions": {
            "Sell": {
                "appliesTo": {
                    "resourceTypes": [
                        "Car"
                    ],
                    "principalTypes": [
                        "Seller"
                    ]
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Schema

Policy

Now we can define policy as follows:

permit (
    principal,
    action in [EcommercePlatform::Action::"Sell"],
    resource
)
when
{
    principal.department == resource.department &&
    principal.department.name == "luxury" &&
    principal.rating >= 8 &&
    resource.price > 1000000
};
Enter fullscreen mode Exit fullscreen mode

Testing

We can either test it with AVP-CLI Test Scenario, or we can test it with Test Bench feature in AVP.

  • Switch to json mode and fill it as follows:

Principal: EcommercePlatform::Seller
ID: 1
Resource: EcommercePlatform::Car
ID: porsche
Action: EcommercePlatform::Action
ID: Sell

Test Bench

  • Leave Context untouched.

For Entities use:

[
    {
        "identifier": {
            "entityType": "EcommercePlatform::Seller",
            "entityId": "1"
        },
        "attributes": {
            "department": {
                "entityIdentifier": {
                    "entityType": "EcommercePlatform::Department",
                    "entityId": "1"
                }
            },
            "rating": {
                "long": 8
            }
        },
        "parents": []
    },
    {
        "identifier": {
            "entityType": "EcommercePlatform::Car",
            "entityId": "porsche"
        },
        "attributes": {
            "price": {
                "long": 10000000
            },
            "department": {
                "entityIdentifier": {
                    "entityType": "EcommercePlatform::Department",
                    "entityId": "1"
                }
            }
        },
        "parents": []
    },
    {
        "identifier": {
            "entityType": "EcommercePlatform::Department",
            "entityId": "1"
        },
        "attributes": {
            "name": {
                "string": "luxury"
            }
        },
        "parents": []
    }
]
Enter fullscreen mode Exit fullscreen mode

Above dataset defines entities for an e-commerce platform, specifically detailing sellers, cars, and departments. It outlines a seller with a rating and department affiliation, a luxury car with its price and associated department, and a department named "luxury" to which both the seller and the car are linked.

Feel free to now test it, the decision should be "allow".

Allow

Next steps

That's it for today. In the upcoming article, I'll dive deeper into the avp-cli, exploring its capabilities and demonstrating how it can improve your AVP workflows. If there are specific topics related to Cedar or AVP you'd like me to cover, please let me know.

Top comments (0)