[HN Gopher] Aserto: Developer API for permissions and RBAC
___________________________________________________________________
Aserto: Developer API for permissions and RBAC
Author : vklmn
Score : 97 points
Date : 2022-02-16 15:33 UTC (7 hours ago)
(HTM) web link (www.aserto.com)
(TXT) w3m dump (www.aserto.com)
| fabian2k wrote:
| This is probably a pretty stupid question, or at least based on
| some misconception of mine about this space. But I don't really
| understand how permissions as a service or API can work
| efficiently.
|
| If I request a single resource, of course this can work if I ask
| a second API on whether the request is allowed or not. But if I
| query a database for a list of items, to add access control I
| need to modify the database query. I can't just filter after the
| fact, it's too easy to cause pathological performance issues
| there e.g. if the user has only access to a very small subset of
| a large list of results. How does this work with a separate
| access control API that can't directly modify the database query?
| samjs wrote:
| It's actually a pretty great question!
|
| As others have mentioned, authorization often requires both a
| single method to authorize "can the user perform this action on
| this resource" as well as more flexible versions like "what are
| all the resources this user can perform this action on". That's
| one part of why authorization is hard, I wrote an article on
| this a little while ago [1]. At Oso (disclaimer: I'm the CTO),
| we solve this by turning authorization logic into SQL [2].
|
| Supporting those APIs in a generic service definitely turns up
| the difficulty level -- you no longer have a single database to
| query.
|
| The thing is, if you have multiple services, you might
| _already_ be in that situation. If I need to query another
| service to ,e.g., find what projects a user belongs to, and
| then need to go combine that with data in my database, I 'm
| going to need to start worrying about how to do that
| efficiently. In those situations starting to centralize that
| data + logic starts making sense -- we talk about this in [3].
| So now there's a bunch of companies with different takes on how
| to best solve this, including Oso.
|
| ---
|
| I feel bad about self-promoting so many links here... but we're
| passionate about this subject so we've been writing a lot about
| it!
|
| [1]: https://www.osohq.com/post/why-authorization-is-hard
|
| [2]: https://www.osohq.com/post/authorization-logic-into-sql
|
| [3]: https://www.osohq.com/post/microservices-authorization-
| patte...
| ogazitt wrote:
| Welp, you know you're solving a hard problem when two other
| founders drop links in your HN thread :)
|
| More seriously, I agree that there are a number of
| challenges, and different use-cases tend to require different
| approaches. Over time, we think there will be a set of common
| patterns that emerge, which will help the industry move
| towards a more consistent set of authorization experiences.
| And that will be great for everyone.
| samjs wrote:
| Indeed ;) https://news.ycombinator.com/item?id=28559608
| lmeyerov wrote:
| We've passed on most of the google-pointing technologies in
| this thread precisely because of that architectural footgun
|
| Instead, we went with Casbin (microsoft research) because it
| can push to your DB (including multi-tenant-sharing if you
| scale) and a legit modern policy engine - A(R)BAC, ACL, etc.
| Definitely warts, but pretty close to what I'd hope
| architecturally, meaning a clear path to prettier UIs, plugging
| into automatic SMT solvers/verifiers, etc, and till then,
| pretty easy from whatever backend lang + SQL DB you use.
|
| Long-term, stuff like row-level security in your SQL / metadata
| store makes a lot of sense (people pointing that out in the
| thread below), but RLS is still awkward in practice for even
| basic enterprise RBAC/ACL policies. Until then, Casbin-style
| architectures are the equivalent of a flexible external policy
| decision point with the actual compute still being pushdown to
| wherever you want, including the DB: win/win.
|
| I wish the VC money went this way instead, but I see why $ goes
| to simpler "google for everyone else" pitches, so here we are
| :(
| ogazitt wrote:
| You bring up a good point with respect to the "Google for
| everyone else" technologies. The fact is that very few
| organizations are the size of Google (or have the SRE team /
| expertise that Google does). Zanzibar works at Google because
| they have a geo-scale private fiber investment, and an SRE
| team that can operate many global instances. The cache
| consistency elements of Zanzibar are the hard problem here.
|
| We chose a more pragmatic approach with Aserto. We believe
| that most authorization problems can be expressed as a
| combination of rules and data. A system that is 100% rules or
| 100% data isn't pragmatic.
| ogazitt wrote:
| Great question. There are two scenarios that are relevant for
| authorization:
|
| 1. Gating the operation (whether it's retrieving a single
| resource, or creating / updating / deleting a resource). In
| this scenario, the application does need to call the authorizer
| before performing the operation on the resource, but the
| relationship between the authorizer and the application is at
| "arms length".
|
| 2. Filtering a list of resources. In this scenario, the
| authorization system can help you by running what in OPA is
| known as a "partial evaluation", which returns an abstract
| syntax tree. Your code would then walk that tree and insert the
| proper where clauses (if you're talking to a SQL back-end). As
| you mentioned, by necessity, your application needs to work
| more closely with the authorizer.
| jzelinskie wrote:
| Disclaimer: I am a founder of Authzed (W21).
|
| Generally, this problem is called ACL-Filtering[0][1] and can
| be done in two ways: "pre-filter" and "post-filter". Sometimes
| you might even have to do both.
|
| If you decide to use a service/database for permissions,
| similar to SpiceDB[2], there are often specialized APIs for
| directly listing the entities a subject has access to in
| various ways. You can take these results and feed them into a
| database query to select only the authorized content. This
| doesn't have to just be a list of IDs, but can also be
| datastructures like bitmaps, effectively providing your
| database with a custom index for your query. Systems that
| implement some of the novel parts of the Zanzibar paper[3] can
| also enable you to cache these values in your database until
| your application performs an operation that invalidates the
| results.
|
| Filtering once you've queried all possible results from your
| database can also be more performant than you'd think, because
| you can amortize performance by lazy loading and performing
| permission checks in parallel. We have some pretty large
| systems that are purely using this strategy. The code for
| filtering can also be made extremely elegant because it can be
| hidden behind the iterator interface in whatever programming
| language you're using.
|
| [0]: https://docs.authzed.com/reference/glossary#acl-filtering
|
| [1]: https://authzed.com/blog/acl-filtering-in-authzed/
|
| [2]: https://github.com/authzed/spicedb
|
| [3]: https://authzed.com/blog/what-is-zanzibar/
| gertd wrote:
| So the idea is that you create a candidate set of resource
| keys from the permission system and join that with the
| external database and / or use it as a post filter?
| rad_gruchalski wrote:
| If you are using Postgres (or YugabyteDB) then you can use row
| level security for that.
| ogazitt wrote:
| Authorization is really about "defense in depth". In a ZTA
| model, your access proxy, authentication system, API gateway,
| application middleware, and data layer all provide additional
| levels of protection [0].
|
| Using your DB's row-level security for data filtering is
| definitely complementary to API authorization.
|
| [0] https://www.aserto.com/blog/modern-authorization-
| requires-de...
| rad_gruchalski wrote:
| Yup, and I'd use Keycloak with a PostgreSQL extension to
| drive both together. I'd drive RLS from Keycloak if I was
| going to go that way.
| claytongulick wrote:
| So much of authorization is context / application dependent, I'm
| struggling with this a bit.
|
| For example, I have a cluster of services. I allow access to some
| of them, for certain actions, based on whether the user is part
| of a patient's care team.
|
| That's very dynamic, I need to do a FHIR query to one of my
| services to determine that. Then there's a lot more logic, like
| what servicer / organization affiliation the user is part of,
| this is also a runtime lookup in a shared session state thing,
| etc...
|
| I just list all that as a basic example, there are so many things
| that are application specific that require runtime evaluation,
| it's hard for me to understand the benefit of writing all that in
| a different language, in a different place, where I can't use the
| libraries and utilities that are already part of the application.
| sizediterable wrote:
| But what if your services are written in different languages
| from each other and they need to perform similar authz checks?
| Sure, each service might need be responsible for its own data
| fetching, but the actual _logic_ over the data can be written
| in one common language (Rego) and have one single source of
| truth.
| claytongulick wrote:
| Well, I'm in exactly this situation right now.
|
| The approach I've taken is to implement my own application
| gateway using node-http-proxy.
|
| I use npm workspaces to share common functionality between
| all the node parts of the application, including the api
| gateway / reverse proxy.
|
| I configure the other services to trust a HTTP header that's
| injected in the api gateway (and explicitly deleted from
| incoming requests) that includes details about the user. For
| example, Apache Superset (and several other services) support
| the REMOTE_USER header.
|
| Honestly, doing this in a high-level language like NodeJS
| with node-http-proxy is even simpler to do and easier to read
| / audit than what I've seen in Rego, plus I get to use all
| the common utilities for dynamic service access, database
| access, etc...
|
| This borders on a "NIH" thing, but I think if you saw the
| actual implementation, it's even less complex than what I'm
| seeing from these examples. It took me a couple hours to
| throw together, it's easy to extend, and supports a multitude
| of authentication scenarios, including shared-session (which
| would be tough with Rego).
| ogazitt wrote:
| This is indeed one of the benefits of the policy-as-code
| approach.
|
| And Rego syntax is much easier to grok than other "-as-code"
| approaches (read: wall-of-yaml)
| itsronenh wrote:
| This goes straight to the core of what makes authorization in
| complex applications such a challenge. You hit the nail on the
| head when you say that authorization in inseparable from each
| application's unique circumstances.
|
| At the most abstract level, an authorization decision is an
| answer to the question "is an identity (user, service,
| computer, etc.) allowed to perform an action on a resource?".
|
| Each one of these constituents (identity, action, and resource)
| may include contextual information that is unique to the
| application at hand. Aserto gives you the ability to imbue each
| one with the necessary information.
|
| Identities are stored in a directory where they can be enriched
| with arbitrary data. Roles, teams, attributes, and anything
| else that is directly tied to an identity whose actions need to
| be authorized.
|
| Relevant information about the resource being accessed is
| collected by the application and sent as part of the
| authorization call.
|
| Then there are the authorization policies that receive identity
| and resource information and make decisions.
|
| There can be multiple ways to model an application's
| authorization scheme. In your example it sounds like the user
| (identity) is a care giver and the "resource" is patient data.
| If users belong to numerous care teams and their membership in
| them is highly dynamic, your application may perform the FHIR
| query to retrieve the identities of the the patient's care team
| prior to the authorization call and include that information in
| the resource context.
|
| The policy can then make decision based on whether or not the
| acting identity is a member of the team, as well as any other
| relevant information (e.g. are they the patient's primary care
| giver or a specialist?).
|
| There are many advantages to keeping authorization policies
| separate from application logic. Change management, provenance,
| and testability are a few.
|
| Having a single place where all authorization policies are
| defined allows us to reason more deeply about the behavior of
| our applications.
| claytongulick wrote:
| I totally get the benefits, the part I'm struggling with is
| the real-world details.
|
| Like, the amount of effort it would be to put in application
| logic in order to determine attributes that would then be put
| on to the profile would be more than that which would be
| required to just have auth native in the code.
|
| Then there's the problem of keeping those attributes in sync
| with the application as things change.
|
| Then there's the problem of debugging when things go wrong -
| instead of being able to inspect the application state and
| determine the issue, now I have two places and different
| processes for issue resolution.
|
| I'm not talking about this in a hypothetical sense - I've
| tried this before. All sort of declarative rule based
| systems, and integration with Auth0 with attributes stored as
| part of the Auth0 profile, etc...
|
| After doing it and balancing the benefits, I've found that
| having well-architected code base with auth as a separate
| concern, but embedded within the native code (as a separate
| class/service/module/etc... is more effective and less work
| with better performance characteristics.
|
| Obviously this doesn't apply to every situation, I can think
| of several scenarios where third-part auth would work very
| well, I just don't run into them a lot.
| ogazitt wrote:
| That's indeed why authorization is a harder problem than
| authentication - because much of it is domain-specific.
|
| Still, there are many things an authorization system can help
| with. For example, the service/organization affiliation of the
| user is easily expressed as a set of attributes / properties /
| roles on the user. If that's stored in a central directory, and
| the authorizer has a cached copy, you can use this context as
| part of your policy for making authorization decisions.
|
| Lifting the authorization policy into a central repo allows you
| to consolidate authorization logic, and also enables separation
| of concerns. SecOps can evolve the authorization policy of the
| application without having to ask developers to revisit the
| logic in all the places it exists. In fact, we have customers
| that have their secops team deploy new versions of the
| authorization policy without having to redeploy the
| application.
|
| Another example is having front-end code that can dynamically
| render component state (visible or enabled) based on the same
| authorization rules that the back-end / API uses. We have nice
| examples of this in our "peoplefinder" demo [0], which you can
| launch as a quickstart [1].
|
| [0] https://github.com/aserto-demo/peoplefinder
|
| [1] https://www.aserto.com/quickstarts
| dew2105 wrote:
| Auth is a major challenge and pain point... and Aserto is really
| impressive. Love the open source vs. completely walled garden
| approach.
| eatonphil wrote:
| There are a lot of new-ish products in the last 5 years in the
| auth/identity space. I have been meaning to dig into them:
| Kanadm, Keycloak, Ory, SuperTokens, Oso, FusionAuth, CAS, maybe
| Authzed. I hadn't heard of Aserto yet, adding them to the list.
| Although I'm most interested in OSS products and Aserto looks
| like it is hosted-only.
|
| If anyone has already done an independent study of the ecosystem
| I'd love a link.
| kache_ wrote:
| The biggest competitor in this space: build your own
|
| Hard to develop a SaaS service when the integration needs to
| have such close locality to your customers' systems.
| ogazitt wrote:
| Hi, this is Omri, co-founder of Aserto.
|
| Your comment is spot on - that's exactly what we've found.
| Authorization needs to be deployed right next to the
| application - no one is going to take a dependency on a SaaS
| developer API that is "the internet away", when authorization
| is in the critical path of every application request. That's
| why Aserto is packaged as a sidecar that you deploy right
| next to your application. The sidecar synchronizes state with
| the control plane, so authorization decisions are made with
| data that is locally cached.
|
| It's also the case that authorization has to be done in the
| context of users that come from an identity provider. Aserto
| automatically syncs users from identity providers /
| directories (Okta, Auth0, etc).
| itsronenh wrote:
| Aserto takes a hybrid approach. It runs a hosted control plane
| where you configure your user-directory, authorization
| policies, etc. But the authorization logic itself can run
| alongside the application that uses it, ensuring high
| availability and low latency.
| rad_gruchalski wrote:
| This can be done with Keycloak Authorization Services and
| custom logger. Keycloak loggers can be essentially anything,
| and they can listen and react to any kind of event happening
| inside. For example: policy create, update, delete. Those
| events can be forwarded to whatever needs to build your OPA
| policies.
|
| Keycloak is a very solid product. The main aspect speaking in
| favor of Keycloak is its extensibility. Nothing beats it.
|
| The problem with Keycloak is that people generally don't want
| to invest too much into learning it.
| ogazitt wrote:
| Aserto is based on a few open source projects: OPA [1], policy
| CLI [2], and Open Policy Registry [3].
|
| Architecturally, the Aserto authorizer is packaged up as a
| docker container and deployed as a sidecar or microservice in a
| customer environment. The control plane typically runs in
| Aserto's cloud (although you could run it on your own if you
| needed full control of the end-to-end solution).
|
| [1] https://www.openpolicyagent.org/
|
| [2] https://github.com/opcr-io/policy
|
| [3] https://www.openpolicyregistry.io/
| eatonphil wrote:
| Being based on open source projects doesn't mean _too_ much
| (Youtube is written in Python, so it 's based on open-
| source). Having a consistent language (OPA) does mean
| something.
|
| But fundamentally I meant that it doesn't seem like you can
| run your entire system self-hosted and the code for it is
| entirely OSS. Do I have that right?
| ogazitt wrote:
| You're right that the control plane currently is not OSS.
| Most people we talked to when we first embarked on the
| journey said that it was critical for the authorizer to run
| locally (and be OSS), but they preferred to not have to
| operate the control plane.
|
| With that said, our intent is to create the option to run
| the entire system self-hosted.
| eatonphil wrote:
| Thanks for clarifying!
| sparsely wrote:
| This looks so cool. I've always wanted something like this,
| especially being able to write the policies in Rego. I can't work
| out if it supports delegation though, i.e. service A temporarily
| allows service B to access a resource which normally only A has
| access to.
| viovanov wrote:
| If the caller can authenticate with the services, I think you
| can write some rego that does something like this. I'm
| interested in what the flow looks like. Does the caller talk to
| A first to initiate this delegation?
| gertd wrote:
| You can create rules which take in to account that there is a
| temporary grant, you do need to account for that somewhere in
| the form of accessible state. This could be achieved using the
| tenant level resource state, which is immediately updated and
| can be referenced from the rego rule.
| bradhe wrote:
| I've been following Aserto for a while actually, really excited
| to see this development. Makes a great compliment to Auth0. Also
| the stuff they're doing for the OPA ecosystem is awesome!
| ogazitt wrote:
| Thanks Brad! We're big fans of both Auth0 and OPA.
| rschwabco wrote:
| Can't I just use Auth0 for authorization?
| ogazitt wrote:
| Auth0 is a great developer API for authentication, and Aserto
| picks up where Auth0 leaves off. The "contract" between the
| authentication system (Auth0) and the authorization system
| (Aserto) is a signed JWT.
|
| You can get away with very simple access control using scopes
| embedded in a JWT token, but that approach runs out of room
| pretty quickly [0]
|
| With Aserto, you can write authorization rules that are
| evaluated for every application request, and reason about the
| user attributes, the operation, and any resource context that
| is involved in the authorization decision.
|
| [0] https://www.aserto.com/blog/oauth2-scopes-are-not-
| permission...
| kache_ wrote:
| Auth0 is building something pretty cool akin to Zanzibar
|
| https://play.fga.dev/
| wereHamster wrote:
| There are at least two startups which are re-implementing
| something like zanzibar. In my experience, RBAC is too
| simplistic for even not so advanced apps. For example, with
| RBAC alone you can't express <<User X can edit object Y>>, if
| object Y is one of many objects in a collection. Zanzibar -
| and any system building on top of tuples (subject, relation,
| object) - can express that quite intuitively.
| ogazitt wrote:
| RBAC is simple to get started with, but indeed pretty
| limited. We tend to use the term because it's more
| recognizable than ABAC or ReBAC.
|
| The {subject,relation,object} tuples do provide a
| convenient way to express an ACL-based system.
|
| Most real-world systems we've encountered tend to have a
| combination of user-centric and resource-centric aspects to
| them. With an ABAC-style policy, you can easily enforce
| relationships like "user X can edit objects in project Y,
| and can read objects in project Z". In fact, the Aserto
| policy for Aserto [1] uses this style of authorization,
| without going "full-tuple".
|
| In fact, for many use-cases, the prospect of creating an
| ACL for _every_ resource feels like a management nightmare
| for the folks we 've talked to, and they typically have a
| "resource group" construct or hierarchy that they want to
| treat the same from an authorization perspective.
|
| Finally, in addition to the user model, Aserto has a
| resource model, and we're exploring evolving it more
| towards the tuple approach.
|
| [1] https://github.com/aserto-dev/policy-aona
| wereHamster wrote:
| Zanzibar has a notion of <<User sets>> to allow
| expressing conditions such as <<File X can be viewed by
| (all users who can view Folder Y)>> to avoid too much
| duplication in the rule sets. One challenge they had was
| to make resolving these rules not too slow, since that
| forms basically a graph (= graph traversal)
| kache_ wrote:
| Reading the Zanzibar paper is actually how I learned
| about how powerful of an optimization technique
| denormalization could be
| janczukt wrote:
| As an ex-Auth0 I was watching Aserto for a while - it is indeed
| elegantly designed to naturally pick up where Auth0 leaves you.
| I wish this was available when we were adding authorization to
| Fusebit APIs. But well, next startup...
| ogazitt wrote:
| Thanks for the kind words! Maybe next time you look at
| evolving your authorization model, we can chat :)
| apoland wrote:
| I've built my own authz too many times. The prospect of having a
| standard framework to do this is encouraging.
___________________________________________________________________
(page generated 2022-02-16 23:02 UTC)