Authorization Woes :
KETO way of solving
Wed Aug 09 2023
This is the third part of our Authorization series. In the previous blogs, we discussed typical challenges when implementing an authorization solution and how OPA helps to solve some of them. In this section we will examine authorization woes with respect to keto access control server. Keto is based on Google’s authorization solution Zanzibar, whose details have been published by google in 2019. Ory Keto is primarily designed to provide flexible and scalable access control for microservices and modern applications. It aims to be a complete access control solution for complex, distributed systems. Lets leverage the build blocks of keto and see some of the building blocks necessary and see how we can leverage it to implement the access control server using Keto.
Object: Typically represents the resource on which the access control has to be enforced. Keto recommends using UUIDs as they provide a high entropy and therefore are unique identifiers.
Subject: Represents something that tries to access the resource.
Subject Set: Set of all subjects that have a specific relation on an object. Subject sets within the context of Ory Keto can exhibit recursion by indirectly referencing other subject sets. Subject sets possess the ability to refer to an object by utilizing the empty relation, which essentially translates to "any relation, including the absence of one."
Namespace: Represents a category of resource. There would typically be a namespace for each type of resource that you would need to define access for. In the Ory Permission Language, namespaces are represented as TypeScript classes and should be named using the singular form of the type they describe. The naming convention for namespaces follows the upper camel case style.
Relation: Represents the relationship of any of the entities like Object with Subject_id , Subject Set.
Relationship: Relationships in the context of Ory Permissions serve to encode connections between objects (the resources intended for management) and subjects (the individuals or entities seeking access to these resources). Each relationship is associated with a designated namespace, where its specific relation must be defined and configured.
A sample representation of building blocks.
The Ory Permission Language is a syntactical subset of TypeScript. Along with type definitions for the syntax elements of the language (such as Namespace or Context), users can get context help from their IDE while writing the configuration.
ORY Keto is based on a permission language called ORY Access Control Policy Language
or simply 'OPL' language.
The Ory Permission Language(OPL
) is a declarative language used to define access control policies. It allows
developers to specify fine-grained access control rules and conditions for resources, actions, and subjects (users,
groups, etc.).
The OPL language is designed to be flexible and expressive, making it suitable for a wide range of access control use cases.
the following would be the OPL for example that we have represented in the above diagram.
class User implements Namespace { related: { manager: User[] } } class Group implements Namespace { related: { members: (User | Group)[] } } class Folder implements Namespace { related: { parents: File[] viewers: (User | SubjectSet<Group, "members">)[] } permits = { view: (ctx: Context): boolean => this.related.viewers.includes(ctx.subject), } } class File implements Namespace { related: { parents: (File | Folder)[] viewers: (User | SubjectSet<Group, "members">)[] owners: (User | SubjectSet<Group, "members">)[] siblings: File[] } permits = { view: (ctx: Context): boolean => this.related.parents.traverse((p) => p.related.viewers.includes(ctx.subject)) || this.related.parents.traverse((p) => p.permits.view(ctx)) || this.related.viewers.includes(ctx.subject) || this.related.owners.includes(ctx.subject), edit: (ctx: Context) => this.related.owners.includes(ctx.subject), rename: (ctx: Context) => this.related.siblings.traverse((s) => s.permits.edit(ctx)), } }
User
, Group
, Folder
, and File
are classes that implement the Namespace
interface. Each class has a related
property, which contains various relationships or associations with other entities.Folder
and File
classes have
additional properties like permits
, which define access control rules for different actions like view
, edit
, and
rename
. Access control regulations make use of a Context object (ctx
), which contains attributes for portraying the
current user or subject aiming to carry out actions on the namespaces. The permits
property in the File class defines
access control logic based onviewers
, owners
, parents
permissions, and sibling file permissions. The permits
property in the Folder
class defines access control logic based on viewers
and parent
folder permissions.
Having seen the OPL and building blocks of keto , we can now go ahead and figure out how to implement the keto access control server using their sdk and API endpoints.
The Write API's
offer multiple ways to insert and delete relationships.
Create or Delete Relationships: This API allows you to create or delete a relationship using Http and Grpc endpoints.
When a relationship need to be created/deleted between a main folder and a sub-folder or a sub-folder and a file , a tuple with relation parents is created using this write API.
The Read API's
offer ways to query relationships and permission checks.
List relationships: This API allows you to query relationships by providing a partial relationship using Http and Grpc endpoints. If we provide no relationship it returns all the relationship in db.
To retrieve a list of relationships involving a specific user. They can do this by providing a partial relationship in the API call. For instance, they might want to find all the relationships where
User A
is connected.
Check relationships:
The Check API
enables you to verify whether a subject possesses a relation to an object. It handles subject sets and
relationships by resolving them. When making a check request, you have the option to specify the maximum depth of the
search tree. If the provided value is less than 1 or exceeds the global max-depth limit, the global max-depth value will
be applied to maintain low latency and control resource usage per request. This API's primary purpose is to assess
permissions and enforce action restrictions. The endpoint supports
both HTTP
and gRPC protocols.
To check if
User A
has permission to readFile X
. They would make a request to theCheck API
endpoint, specifying the subject, object, and the desired action (read
).
So far we have seem way to implement the keto server. Lets check how keto solves Role based access control with some extra workarounds.
Role-based access control assign roles to subjects based on their responsibilities and functions and then associate those roles with the appropriate permissions or access rights. The objective of Hierarchical Role-Based Access Control (H-RBAC) is to simplify permission management by organizing subjects into roles and assigning permissions to those roles. This hierarchical approach allows for more structured and efficient access control in various systems and applications.
Let's look at a small example to understand how this H-RBAC works.
For example , If we have roles in hierarchy order from top to bottom are create
,edit
and view
roles respectively.
If a subject has role view
, then the subject can just view the file cannot edit
or create
one. Whereas if a
subject has role edit
, then that subject can have all permissions of role view
provided by this hierarchy.
Same way, if a subject has role create
, then that subject can have all permissions of edit
and view
role.
As mentioned in the previous blog of the series, having a centralized service with standard permission endpoints solves the problem of inconsistencies in the definitions.
Unlike rego’s test framework in OPA, we don’t have a dedicated toolkit that allows us to test the authorization policies. So any tests that you might have to write will be at your application layer.
Being a pre-packaged solution, ORY Keto certainly reduces the cost of development in the aspect that you don’t have to work on framework, definition and implementation of authorization.
There is also a chain of services such as ORY Hydra(OIDC), Kratos(for user management), which would work well together among themselves would help us to get a quick start.
There could be a minimal cost that you might have to pay for the learning curve, to get yourself comfortable with the Zanzibar concepts and fit in your requirement to the framework, which should be ok considering the gains.
Keto gets a bit of a boost by exposing its APIs as gRPC. Thus reducing the transit overhead to some extent.
c3-highcpu-8
(8 CPUs , 16 GB RAM). In which both the DB(MySQL) and
the Keto server were running in the same instances.We haven’t pushed the limits of Keto further. And neither do we have any benchmarks available outside. We are happy to know if there are any extensive studies done here.
Implementation of dynamic resource types would be challenging, as there is no straightforward way to get it done. The performance is not so great as discussed in the Operational Performance section. But there could be an option for improvement by throwing more hardware. The Permission language is still maturing and there is a lot of scope for improvement and optimization.
multi-tenancy
.time based access controls
to allow network access on the basis of time period.When considering ORY Keto as an access control solution, it is essential to recognize its benefits, including a centralized service with standard permission endpoints, reduced development cost, and performance improvements through gRPC. However, it is crucial to acknowledge its limitations, such as the lack of support for dynamic resource types, time-based access controls, and dynamicity in OPL.
In this context, it’s also important to note that the claims in Zanzibar paper like having a 99.9th percentile of 100ms cannot be expected from Zanzibar based implementations for 2 reasons, Google is running 1000s of servers for their authorization and none of the Zanzibar based implementations are 100% Zanzibar yet. For example, additional indexing servers like Leopard, Request hedging and many other optimizations are part of Zanzibar which are costly to get it done in the open source implementations.
We would love to hear from you! Reach us @
info@techconative.com