> I prefer to have the entitlement itself just store the expiration date and the details about what entitlements the subscription grants during the time period it is active. The billing system can store the subscription and sync back to the entitlement as-needed. This makes both manual billing by human operators (not to mention debugging and patching around momentary issues) and something like a Stripe integration very easy.
Having worked with SaaS companies using our (Warrant) solution for customer entitlements [0] for the past couple years, this is the approach we arrived at as well (e.g customer stores entitlements in our system and checks against them when needed, adding rules/entitlements as subscriptions are updated/deleted with their payment provider). It makes it easier for companies to work with any (or multiple) payment providers, and there's a clear separation of concerns. Someone shared another blog post by OP about separating your billing and entitlement systems [1] below, but I'll share it here since it's more relevant within the context of this comment thread.
I think the ideal entitlement system is (1) dynamic (i.e. rules stored in a database), (2) can handle one off scenarios (for enterprise customers, etc.), and also has a policy layer built on top (so it supports almost any scenario a developer can throw at it -- e.g. pro plan supports <= 5 seats, growth plan supports X feature up to N times per day, etc). I think it's also a huge benefit to have a UI where non-technical folks can make changes for customers without needing to involve engineering (which was always a drag on engineering in my prior roles as an engineer).
I would describe this debate more as Policy-as-Data (Zanzibar) vs Policy-as-Code (OPA et al).
In Zanzibar, all of the information required to make an authorization decision (namespaces, relationship tuples, etc.) is stored in Zanzibar, and the decision engine resolves access checks based on this data. This data can be scaled horizontally (and consistently) as needed for an application’s needs. This makes Zanzibar a centralized, unified solution for all of an application’s authorization needs. I’ve found this approach more purpose built / well suited for application authorization.
With OPA and other policy engines, the data required for performing access checks lives somewhere else (maybe the application’s database) and must be separately queried and included as part of the authorization check because OPA et al. are stateless decision engines. This makes it such that you need to piece together data from different sources in order to get your final decision, which IMO is something most developers don’t want to deal with.
On the flip side, Zanzibar’s “namespaces” are a very simple policy layer not well suited to querying against data outside of Zanzibar’s scope (e.g. geolocation, time, etc). For scenarios like this, a full fledged policy-as-code solution is great. However, it should be noted that some open source Zanzibar implementations like Warrant[1] and SpiceDB[2] (mentioned in the article) also offer a policy-as-code layer on top of Zanzibar’s graph-based/ReBAC approach to tackle these scenarios.
I don't see the dichotomy. in all the work I've done lately in this area there is a defined schema for a rule - so its really not that hard to be code and data, maybe even more so in a declarative world.
> though we would have preferred a managed solution
We completely agree here, which is why we initially started out with our managed cloud offering, Warrant Cloud[1]. While Zanzibar is powerful, operating it with solid latency/availability can be quite challenging.
At Google, I believe some client applications build and maintain "permission-aware" search indexes based on the permissions in Zanzibar. In essence, Zanzibar can be queried to figure out the object ids a particular subject has access to. These object ids can then be hydrated via a database query or separate service call.
At Warrant, we're experimenting with allowing customers to maintain searchable metadata in Warrant and exposing a "query" API[1] that can automatically hydrate objects based on that metadata.
You've highlighted a very important part of the paper. A lot of the external consistency guarantees provided by Zanzibar are facilitated by Spanner and its TrueTime mechanism. Warrant doesn't currently support/use Spanner. However, for the databases we do support (MySQL and Postgres - which are both ACID compliant), we've implemented the zookie protocol using the incrementing transaction ids they provide. This approach works for single writer deployments of these databases, so know that write throughput and overall availability will be lower. We started with this approach because most teams still use MySQL/Postgres. Warrant is built to support running on different types of databases, so we will be working on support for Spanner and other multi-writer distributed databases like Cockroach and Yugabyte in the future. I hope that helps.
I think GraphQL might be a good example. Some might not consider it to be very niche, but its intention is to consolidate dependent API queries such that the client can fetch all the data it needs in a single request. In both Zanzibar and GraphQL, the idea behind the schema/modeling language is to provide a layer where logic specific to relationships between data (in the case of GraphQL) or logic specific to authorization (in the case of Zanzibar) can be specified such that neither the server nor the client need to worry about it and can instead query for data in a simpler way.
Thanks, I suppose GraphQL is a valid example, I was thinking niche in terms of application eg Zanzibar is auth only, and you would struggle to use it for much else
Google doesn't actually offer Zanzibar as a product/service (in GCP or otherwise) to customers. However, they do use it internally to manage permissions across their various products (Google Docs, Drive, YouTube, etc.) and have had a lot of success doing so. Because of that, there are many open source implementations of Zanzibar out there (as others have commented). Warrant also maintains our own open source implementation of Zanzibar[1] which powers our managed cloud offering, Warrant Cloud[2].
Another interesting feature of capability-based systems (that is outside Zanzibar's scope) is that capabilities can themselves be used to gain access to an object. This is because they are unforgeable tokens, meaning they essentially have authentication baked into them. Zanzibar leaves the authentication piece to an external service and focuses on providing the ability to define, store, and query access rights for subjects.
As I understand it, "capabilities" in capability-based schemes uniquely reference an object and specify a list of access rights on that object. This seems fairly similar to tuples in Zanzibar, which reference a unique object, an access right, and a unique subject whom the access right belongs to. You can think of Zanzibar as a layer used for defining, storing, and querying for capabilities.
Yeah, I believe capability/verb simply maps directly to relation in Zanzibar speak. “Can edit” vs “is an editor”. I’m more accustomed to the verb style, so whenever I read about authz systems that use relations or roles, I’m constantly mapping the concepts in my head to try to find examples where they aren't 1:1 and have yet to think of any.
Having worked with SaaS companies using our (Warrant) solution for customer entitlements [0] for the past couple years, this is the approach we arrived at as well (e.g customer stores entitlements in our system and checks against them when needed, adding rules/entitlements as subscriptions are updated/deleted with their payment provider). It makes it easier for companies to work with any (or multiple) payment providers, and there's a clear separation of concerns. Someone shared another blog post by OP about separating your billing and entitlement systems [1] below, but I'll share it here since it's more relevant within the context of this comment thread.
I think the ideal entitlement system is (1) dynamic (i.e. rules stored in a database), (2) can handle one off scenarios (for enterprise customers, etc.), and also has a policy layer built on top (so it supports almost any scenario a developer can throw at it -- e.g. pro plan supports <= 5 seats, growth plan supports X feature up to N times per day, etc). I think it's also a huge benefit to have a UI where non-technical folks can make changes for customers without needing to involve engineering (which was always a drag on engineering in my prior roles as an engineer).
[0] https://warrant.dev/use-cases/pricing-tiers-and-entitlements... [1] https://arnon.dk/why-you-should-separate-your-billing-from-e...