diff --git a/docs/docs/authz/policy.md b/docs/docs/authz/policy.md index 9afadc62c..e1a949a30 100644 --- a/docs/docs/authz/policy.md +++ b/docs/docs/authz/policy.md @@ -46,3 +46,47 @@ Similarly, instead of passing the unique UUID for the organization or project, o In case the object is not an organization or project, it can be a project resource and one can use format of **namespace:uuid** or **namespace:urn** in the resource field above. ::: + +## Internals of Policy and Permission + +Frontier uses the [SpiceDB](https://authzed.com/docs) permission system to manage and enforce access control policies. +SpiceDB is an open-source permission system inspired by Google Zanzibar that is capable of answering questions like: + +``` +does have on ? +``` + +Permissions are defined as relationships between users and resources. A user can be a user, a group, or any other entity +that needs to be granted permissions. A resource can be a file, a database, or any other object that needs to be protected. +There are well known pre-defined namespaces reserved for frontier resources like `app/user`, `app/organization`, +`app/project`, `app/role`, `app/rolebinding` etc prefixed with `app`. +Even though SpiceDB is used internally, the user does not need to interact with SpiceDB directly. Frontier provides a +Hierarchical Role Based Access Control built on top of relationships and permissions defined in SpiceDB. Authzed has a blog +that talks about how RBAC can be modeled on top of SpiceDB. You can read more about it [here](https://authzed.com/blog/google-cloud-iam-modeling). + +It works by defining Role and RoleBinding objects. A Role is a collection of relations that can be bound to a object namespace. +A RoleBinding binds a Role to a principal namespace(user/group/service account). The permissions are defined as relationships +between the principal and the object. + +We maintain spiceDB schema in [base_schema.zed](https://github.com/raystack/frontier/blob/4434204940f3a599b7e0ef399679f381db46c09a/internal/bootstrap/schema/base_schema.zed) +file in Frontier. The schema is then used to build the base set of permissions on predefined namespaces. Some permissions are +hardcoded in the schema, but Frontier allows custom permission set on Project resources. Custom permissions are dynamically +generated at frontier boot-up by merging them in the SpiceDB schema. To create custom permissions on a project resource +a [rule set](https://github.com/raystack/frontier/blob/ccf00da8a636f363546b1dbe6c7933323c369dca/internal/bootstrap/testdata/compute_service.yml) +can be configured in the [config.yaml](https://github.com/raystack/frontier/blob/7fca56ef567791bf4ea1280aa3f9b4ae997b1bf5/config/sample.config.yaml#L29) +file. Same is also exposed in the [Frontier API](../apis/admin-service-create-permission.api.mdx) to create +custom permissions on a project resource. + +Frontier models roles as collection of permissions which can be created/updated/deleted dynamically at run time. + +To give principal access to a resource, a RoleBinding object is created that binds the principal to a role. The role contains +the permissions that the principal is granted on the resource. When a permission check is performed, SpiceDB traverses the permissions +graph to determine whether the principal has relations that grant the required permission to access the resource. + +For example: To give a user access to a project, frontier create a policy that does following: +- A `app/role` object is created that creates a relation between a permission and `app/user` +- A `app/rolebinding` object is created that creates a relation between `role` and the created `app/role` object +- Another relation on same `app/rolebinding` object is created between `app/user` and `bearer` of role + +When the user tries to access the project, the SpiceDB engine checks if the user has the permission by traversing the +graph, checking if the role binding contains requested bearer and role->permission relation.