If so, does that become a chokepoint in a distributed microservice architecture? Or can that be avoided with an in-process or sidecar architecture in which a given microservice's objects are not separately referenced in auth persistence? If not, how do folks determine which objects to register with the auth service and which to handle independently?
>does that become a chokepoint in a distributed microservice architecture?
It actually does the opposite because now all of your microservices can query Zanzibar at any time to get answers to authorization questions that were previously isolated to only a single application.
Full disclosure: I work on https://authzed.com (YC W21) -- a permission system as a service inspired by Zanzibar. We're also planning on doing a PapersWeLove NYC on Zanzibar in the coming months, so stay tuned!
This sounds a bit like a chokepoint. Is the important point here that Zanzibar is distributed and therefore is a good thing to be querying from all over the system (as supposed to one centralised application).
Say your goal is to externalize just your authorization policies from your code. A simple implementation might look like an OPA sidecar to your services, with the policy itself being sourced from a separate control plane - this might be something as simple as a centrally-managed S3 bucket.
The service implementation provides the attributes to OPA to allow it to evaluate the authorization policy as part of the query. e.g. which groups is this user in, what document are they accessing, is this a read, write or delete operation.
If you want to externalize sourcing of the attributes as well, that becomes more complicated. Now you need your authorization framework to know that Bob is in "Accounting" or that quarter_end_results.xls is a document of type "Financial Results".
You can either go push or pull for attribute sourcing.
The push model is to have the relevant attribute universe delivered to each of the policy decision points, along with the policy itself. This improves static stability, as you reduce the number of real-time dependencies required for authorization queries but can be a serious data distribution and management problem - particularly if you need to be sure that data isn't going stale in some sidecar process somewhere for some reason.
The pull model is to have an attribute provider that can you can query as necessary; probably backed with an attribute cache for sanity's sake. The problems are basically the opposite set - liveness is guaranteed but static stability is more complicated.
The methods are not equivalent: in particular, the pull model is sufficient to answer simple authorization questions like 'can X do Y to Z?' - we pull the attributes of X, Y and Z and evaluate the authorization policy.
However, if you need to answer questions like 'to which Z can X do Y?', how does that work? For simple cases you may be able to iterate over the universe of Z's asking the prior question; but it generalizes poorly.
Evaluated scenario was: a company employs a director and IT staff, the director contracts a consultant, the IT staff subscribes to external services. Find out what the company pays for directly and indirectly.
The new Keto 0.6 works very nice.
Depending on your requirements, yes that's kind of what happens if you want to centralise. It can make sense for Google-scale problems where you really do need to handle the complex graph of relationships between all users and resources, and doing that in any one service is non-trivial.
In practice though, a lot of service-oriented architectures can get the same benefits by having a central user management service, and keeping most of the authorization in each service. That central service can provide information like what organizations/teams/roles etc. the user belongs to, and then the individual services can make decisions based on that data.
This is the approach I covered with the hybrid approach. With this you can still implement most complex authorization models.
https://www.pythonpodcast.com/oso-open-source-authorization-...
https://talkpython.fm/episodes/show/294/oso-authorizes-pytho...
I don't know the answer for Zanzibar, but take a look at how AWS IAM solves it. IAM has very few strong opinions in its model of the world (essentially it divides the world into AWS account ID namespaces and AWS service names/namespaces, and there's not much detail beyond that). Everything else is handled through symbolic references (via string/wildcard matching) to principals, resources, and actions in the JSON policies, as well as variables in policy evaluation contexts (and conditions, which are predicates on the values of those variables, or parameters to customizations (policy evaluation helper procedures) provided by each service).
IAM is loosely coupled with the namespaces of the services it serves, and that allows different services to update their authz models independently with pretty much no state or model information centralized in IAM itself. This is a key, underappreciated part of what makes AWS able to move so fast.
Each service has its own store of objects. Each store also has a directory of Metadata describing the objects contained in each service.
When you send an Auth request to a service; the service you are sending the request to looks up which service is the authority for the given object and then routes the request to that service for auth.
You can do away with the Metadata store if you offload responsibility for remembering which store to use to the user. You provide them with a cookie that tells any of your Auth servers which store contains this users data.
What the Zanzibar paper describes is two big things:
(1) The auth service gives those microservices an ability to set their own inheritance rules so that you do not need to store the fullest representation of those ACLs. If you are propertly targeting the DDD “bounded context” level with one bounded context per microservice, then in theory your microservice probably defines its own authorization scopes and inheritance rules between them. (A bounded context is a business-language namespace, and it is likely that your business-level users talking about “owners” in, say, the accounting context are different than the users talking about “owners” in a documentation context—or whatever you have.) Some upfront design is probably worthwhile to make the auth service handle that, rather than giving the clients each a library implementation of half of datalog and having each operation send a dozen RPCs to the auth service for each ACL check.
(2) The microservices agree on part of a protocol to allow some eventual consistency in the mix for caching: namely, the microservices agree that their domain entities will store these opaque version numbers called zookies (that the auth service generated) whenever they are modified, and hand them to the auth service when checking later ACLs. This, the paper says, gave them an ability to do things like building indexes behind the scenes to handle request load better, without sacrificing much security. Most of the ACL operations are going to not affect your one microservice over here because they happen in a different namespace or concern different objects in the same namespace: so, I need a mechanism in my auth service to tell me if I need an expensive query against the live data, or if I can use a cache as long as it's not too old.
And you have billions of users and their sharing permission models are complex and likely to keep evolving in the future with more devices, concepts of groups/family etc.
In such a scenario, doing access control in a safe and secure way that scales and evolves well to such a large base is itself a major undertaking. You want to decouple the access control metadata from the data blob storage itself so that they each can be optimally solved for their own unique challenges and they can evolve independently too.
https://medium.com/airbnb-engineering/himeji-a-scalable-cent...
Why do attackers have direct query access to your database? What useful information can they extract from knowing there is an unauthorized object in the database?
If the authorization check was fast enough (which it probably is for performance reasons anyway), this would be reduced to the attacker obtaining statistical information (roughly how many objects have cost over 1000). That might be acceptable, my problem is that a benign-looking performane problem could become a serious security problem.
My concern isn't access to single objects, but rather filtering of complex search results.
If the requirements were simple, the POSIX model would still work too :)
In the case of authz, the argument for separating it as a concern is that many applications can share the same scheme, and you can have specialized tools for provisioning, auditing, etc.
If you want the ability to remotely enable/disable a feature, then yes.
There are definitely good arguments for it, services like feature-flagging I mean, and such things are generally relatively low-cost; it's more the risk of adding a 'disappearable' dependency for anything and everything that'd put me off.
(^And if you don't know about this, OMG how can you not have heard about lucky 10k?! Just kidding. [1])
[0] - http://left-pad.io/
[1] - https://xkcd.com/1053/
Destroy can be done asynchronously with durable messaging but asynchronous creation of ACLs is annoying from an api consumer perspective.
[1]: https://metalgear.fandom.com/wiki/Zanzibar_Land_Disturbance
https://en.wikipedia.org/wiki/Stand_on_Zanzibar
It's not the kind of literary allusion I'd want to make, if I were a global multinational like Google/Alphabet, but there it is.
Zanzibar is an island off the coast of East Africa known for being a place where people traded cotton for enslaved humans.
Not sure the connection.
The availability guarantees necessary for basic authorization are far more strict than auditing. Auth fails closed, audit fails open.
Anything that can be stripped out of auth should be, even if we're talking about a best effort extra rpc from the auth service.
Auditing typically needs more information than auth as well, and making the auth pipe wide is a risk.
(maybe?)
https://www.researchgate.net/publication/325605315_The_1964_...
>On the fiftieth anniversary of the atrocious killing and raping of the Arabs of Zanzibar in the wake of the 1964 revolution in the Island, this paper sought to establish that this mayhem was genocide. In light of the almost complete failure to notice this tragedy, the paper pursued critical genocide studies and hidden genocide investigations to argue that this Arab tragedy in Zanzibar has been a denied genocide. Worse still, the paper showed that this genocide is commonly ignored even in studies devoted to bring to memory of hidden genocides life.
Signing in with Google yields (at a minimum) the e-mail address to the client which means that the list of third parties that have your e-mail (and can therefore spam you at will) is increasing exponentially. It would be great if Zanzibar extended the ACLs to include privacy controls with external services.
(Or I'm misunderstanding and this is only the component for internal Google authentication and not external federation for clients).