Hey James.
Thanks for the feedback, and good catch. Looks like that endpoint is pulling from a slightly out of date data source. The docs/dashboard currently are the best resources for the full catalog, but we'll update that API to match.
HN user
Website: https://www.samjs.io GitHub: samscott89 - github.com/samscott89/
Hey James.
Thanks for the feedback, and good catch. Looks like that endpoint is pulling from a slightly out of date data source. The docs/dashboard currently are the best resources for the full catalog, but we'll update that API to match.
Hey! I'm one of the engineers who built this :)
We'll be adding prices to the docs and the model catalog in the dashboard shortly.
In short: currently the pricing matches whatever the provider charges. You can buy unified billing credits [1] which charges a small processing fee.
Finally, would be great if this could return OpenAI AND Anthropic style completions.
Agreed! This will be coming shortly. Currently we'll match the provider themselves, but we plan to make it possible to specify an API format when using LLMs.
[1] https://developers.cloudflare.com/ai-gateway/features/unifie...
I've been building tooling for better debugger support for Rust types using debuginfo: https://github.com/samscott89/rudy
I'm planning on doing a proper writeup/release of this soon, but here's the short version: https://gist.github.com/samscott89/e819dcd35e387f99eb7ede156...
- Uses lldb's Python scripting extensions to register commands, and handle memory access. Talks to the Rust process over TCP.
- Supports pretty printing for custom structs + types from standard library (including Vec + HashMap).
- Some simple expression handling, like field access, array indexing, and map lookups.
- Can locate + call methods from binary.
Hey jdenquin, author/Oso cofounder here.
I'm obviously biased, but IMO the benefits of using a language over SQL is:
* Ability to write reusable logic (rules)
* Support for inline policy tests
* Abstracted from the data model, so easier for collaboration and distributing across multiple applications
Hey all!
I'm Sam, cofounder + CTO at Oso.
Thank you all for the great discussions going on here. If folks are interested in either learning more about the product or working on these kinds of problems, you can email me directly at sam [at] osohq.com.
Hey cratermoon, Oso CTO here.
I'm probably too close to it, so I'm not following: "a great many of the problems they are solving exist because of RBAC"
Oso supports authorization using any combination of RBAC/ReBAC/ABAC you want.
If anything, I would say that sticking with RBAC is the "easy way" to do it, but you push the complexity of managing it onto your end users (the ones who need to administer it). Whereas building authorization that uses attributes like you describe requires more implementation work, but can make the experience easier for users.
Am I understanding you correctly?
Ah got it, thanks for sharing! That's definitely context I'm missing from having never used it in an actual application.
I don't really have much desire to get into maintaining an auth library; there's just not enough time in the day!
Haha, well in some ways I'm glad to hear that. That's why we exist :)
It's pending publish, actually! I've got a devlog (more like a book at this point) for something I've been working on for years now, but no posts are going to be published until I hit a milestone. I'm almost there... not much further.
Send it over if you want another pair of eyes, and lmk when publishing so we can share with our community too. I'm sam [at] osohq.com
Biscuits are really cool, one day I plan to try and convince Geoffroy to integrate Polar for policies :)
Currently Biscuits + Polar are ideologically similar but with distinct use cases at the moment. Oso is a central service that your backend speaks to whereas biscuits are decentralized cryptographic tokens.
So Oso API calls are all done with service-specific API keys, and don't need a proof of identity beyond that.
My mental model for tokens like biscuits is that they work like a "decentralized cache". I.e. you can take an authentication/authorization decision, sign it, and provide it to a client. They can reuse that decision at services without the service needing to reach out to the authN/authZ provider again.
It would play _really_ nicely together with the Distributed Authorization concepts we're talking about here: a client could ask the authz service: "I want a token for managing issues". The authz service/Oso could respond with a partially evaluated policy, like: "this token grants the user access to issues that belong to repository 1, 2,3, or issues that they are the creator" (encoded as facts to check a la biscuits).
When receiving that token, the issues service would know what filtering to do locally, without having to reach out to Oso.
The information passed around between the services mostly stays the same, but rather than make an API call each time, the necessary authz information is encoded in the biscuit token.
And then next level: biscuits can cross federation boundaries and be attentuated, etc. So it really starts unlocking novel ways to integrate application-level authz with infrastructure-level authz.
That's a really clean implementation. And the shares are used to resolve authorization here [1], right?
Two things that we're solving for at Oso is: making it easier for multiple teams to collaborate on permissions (which we solve by having a declarative language), and solving the list filtering problem (as talked about in the post).
If you don't need either of those two things and are happy with a DIY approach, what you've shared would work great IMO. If you packaged that up as a standalone solution, I could see a lot of people getting value from it!
There are not enough people sharing authz implementations out there, a blog post on this shares approach would be super cool.
[1] https://github.com/bottledcode/durable-php/blob/3ad509fcdbb3...
This sounds really elegant, I love it. Have you seen this deployed in a service-oriented architecture or primarily integrated as part of a single app/db?
(Oso CTO here). Out of curiosity what do you not like about CASL? It always seemed to have a similar goal in mind which I loved, but I suspect it hit similar challenges we had when replying on ORM integrations.
Hey simon! Oso CTO here.
Definitely one of my favourite problems too! Some additional context for those who don't think about this all the time: in many cases, the solution is as simple as "write some SQL where clauses to do the filtering I care about". e.g. I suspect the vast majority of people have logic like `where tenant_id = ?` or similar and they pass in a tenant ID on every query.
Where things get challenging is when you want to decouple the logic (e.g. have an abstraction in your code, or centralize logic in a service). Because then you're in the world of what's the decoupled API that allows me to filter my database.
The easiest way to do that is just generate return a big list of IDs the user can see, and put `id in (... list of ids)` on the query. But that involves (a) syncing the data to the central service and (b) that list can get pretty long.
And so that's why you would even need to think about turning rules into WHERE clauses in the first place :)
Quick addition: in practice everyone that I know uses Git + CI/CD for managing + deploying policy changes.
However: you seem to target developers. Why do you force me to leave my IDE and use your "rules editor"? Can I not write all those things in my IDE, with all the support it brings, and integrate this into my CICD flow? (yes, there is the .polar file, but why force me to jump through hoops?)
Hey valenterry! Oso CTO here. You can absolutely write policies locally and integrate this with CI/CD. We have vscode extension for the former, and CI tools for running local dev environments and CI for running this locally or in CI or whatever.
The UI is mostly nice for getting started development experience, e.g. it integrates directly with Oso Cloud without needing to configure credentials.
Then, why did you create a new DSL and not a merely a (de-)serializable datastructure (which will indeed look like a dsl)? One, that is powerful enough to represent the capabilities you need. Then, I could in fact use any language (library) of my choice and create the rules from this language, which just has to create the datastructure.
We have a post on this coming soon! The short version is that Polar is a logic language based on Prolog/Datalog/miniKanren. And logic languages are a particularly good fit for representing the branching conditional logic you often see in authorization configurations.
And it made it easier for us to do custom work like add inline policy tests.
Apart from that, I really like the `yes, if` idea! Would be nice to hear a bit more about that (unfortunately, the article pretty much ends there). Such as: how to deal with actions that change things and can (or must) potentially be run before the authorization is completed and such.
We typically recommend authorizing in two places: at the start of a request, and then when fetching data.
e.g. in our demo app, authorizing "can a user create an issue" involves authorizing a "create_issue" action against the repository itself: https://github.com/osohq/gitcloud/blob/sam/list-filtering/se...
Whereas anything listing issues calls the `list_local` method and does the `yes, if` style approach.
Hey all!
Here's a feature I worked on recently at Oso -- it's a little UI for building example policies combining different authorization features.
I thought folks here might like it. It feels like there's been some growing excitement around logic languages, and our language Polar is inspired by a combination of prolog, datalog, and miniKanren! The builder shows a few examples of what's possible with that approach. Happy to answer any questions.
Please let me know if you do write something. I would love to read it!
Nice!
Is the request composer responsible for checking the authorization data? Like what roles/permissions the user has?
Honestly, if your authorization needs are coarse enough that you can (a) handle it as middleware at the controller level, and (b) mostly just rely on roles, then you're probably in a good place to keep going with that! It avoids a lot of the complexity of centralization.
Where we normally see people considering Oso is when the model gets more complex, or the data requirements get larger. E.g. when you introduce new features like user groups, projects, or sharing, then the amount of logic + data you need to share between the services grows beyond what's sustainable.
If you're current system is working for you, I'm not going to try and tell you otherwise! If that changes though, let me know ;)
I just don't see how "allowed to leave an emoji reaction to an issue inside a repository belonging to an organization" could be anything but application logic.
I think it's absolutely fair to say that authorization logic is a subset of application logic! The question is whether it's possible to separate any of the authorization logic from the application.
There are two reasons you might want to do that:
1. Separation of concerns (true whether monolith or microservices) 2. You have authorization logic shared across multiple services.
(1) is still a hard problem, but you can be a little less rigorous about it. (2) is where it gets really fun.
Continuing the example, that repository-specific blocked-users lists is _probably_ going to be needed across every other service.
I don't think any of that contradicts what you're saying, just clarifying that "in the application" might still mean you want to extract the shared logic into a service.
But to get to your last paragraph: yes it's definitely hard to build a service that's both sufficiently generic to handle all the kinds of authorization use cases people typically need to do.
You'd be surprised though at how many use cases fall into very similar patterns. We have some internal (soon to be external) documentation where we managed to get to about 20 distinct patterns -- from the common one like roles, and groups, to less common ones like impersonation and approval flows. And most of these share the same 2 or 3 distinct primitives (user is in a list of blocked users for a repository, emoji is in the disallowed-emoji list, etc.).
So you can build something less abstract than a general rules engine, but that still saves you the work of building from scratch for the nth time a roles system or a deny list.
Good catch, thanks!
Thanks epberry!
Love this article. My favourite part is:
"So the logical thing to do is to implement an authorization service and everybody would be able to use that and keep your precious service boundaries, right? WRONG. Your hell, has just begun!
Drawing the right boundary for authorization is near impossible. If I want to check whether the user is allowed to see who left an emoji reaction on a comment response to an issue inside a repository belonging to an organization -- do I store that entire hierarchy in my authorization service? Or do I leave some of that in the application? I've yet to see a good heuristic for the latter.
Also, thank you to the author for referencing us :) I'm Sam, Cofounder/CTO at Oso where we've been working on authorization through our open source library for the past couple of years. Authorization for microservices has been a recurrent theme over that time, and we've been furiously writing on the topic (e.g. [1], [2], [3]).
We'd be interested in talking to anyone who is currently facing the challenges of authorization for microservices (or really just multiple services). We're building authorization as a service, which you can learn more about here: https://www.osohq.com/oso-cloud. It's currently in private beta, but if you would rather _not_ speak with us first, there's also a free sandbox to try out the product linked from that page.
[1] https://www.osohq.com/post/why-authorization-is-hard
[2] https://www.osohq.com/post/microservices-authorization-patte...
[3] https://www.osohq.com/academy/microservices-authorization
Well, I potentially have some good news for you :)
There are a bunch of companies who popped up in the last few years to solve this problem. We're one of them -- Oso (I'm the CTO).
It's definitely a fun/challenging problem to work on. So if building a generalized authz SaaS is the dream, come join us!
This is definitely a consideration for authorization. To do it well you need to be able to distinguish when you want to reveal information.
For example, our APIs push people towards returning a 404 if the user doesn't have read access (you shouldn't even know it exists!), but a 403 if you can read but not edit.
You would probably want to do similar here -- only return a reason if the user is allowed to know it exists, but they don't have access. (e.g. it might be "read_exist" vs "read_details" -> "you cannot read the details of this document because you are not a member of this folder".)
Well this was fun to see! I'm the CTO of Oso, where we're building Polar (the second of the links mentioned https://docs.osohq.com/).
I have a few really minor nitpicks, so will try and make up for it by adding to the discussion :)
First of all, it doesn't really make sense to talk about Datalog as a good language for authorization, because much like with Prolog there doesn't really exist a single implementation of it. OPA's language Rego is a datalog variant, and Polar started out as a Prolog variant (although it's not really recognisable as one any more).
And that's an important point because otherwise it would be pretty reasonable to decide that: logic programming is good for authorization => you should go find the most battle-tested language out there and use that. For example, there's SWI Prolog [1] and Scryer Prolog [2] as two of my favourites.
To me, the thing that is mind-blowing about logic programming, is (a) how powerful the paradigm is, and (b) how concisely you can implement a logic programming language. Take miniKanren [3] which is a full-blown logic language in a few hundred lines of code.
In my mind, the original article makes a decent case that logic programming is a good fit for authorization. And just generally I love anyone bringing attention to that :)
But in my opinion the reason logic programming is such a solid foundation for authorization logic is the pieces you can build on top of it. For Polar, we've added:
- Types! So you can write authorization logic over your data types and help structure your logic. We've implemented this by simply adding an additional operator into the language that can check types
- Authorization primitives like roles and relationships (RBAC and ReBAC). These are all backed by the logical rules, so can be easily extended with custom logic
- And last but not least... the ability to convert authorization logic into SQL [4]. Which is done by having the language return constraints over any unbound (free) variables.
To me this is what makes logic programming exciting for authorization. It gives you this small kernel of declarative programming, and gives you a ton of freedom to build on top.
[1] https://www.swi-prolog.org/
Thank you! We're looking forward to sharing more about Oso cloud too :)
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...
If you're interested in resource-based rbac [1] with list endpoints [2], Oso supports both! You're right, it's a tough problem, we've invested a ton of time to make this work well without needing to rearchitect your app.
(I'm cofounder/CTO at Oso).