And on the policy language. Polar is indeed a prolog variant. You can see pretty early we took the decision to diverge from a more familiar prolog syntax [1] because we wanted to make it a little more accessible.
oso was designed to be embedded directly in applications as a library. So there's no additional service to run to use it to make authorization decisions in an application.
The other part is that oso policies are written directly over your application data - e.g. the classes/types, and can access attributes and call methods. There's no integration work needed to get application data available to the policy to start making decisions, nothing to keep in sync, and no additional network overhead.
I suppose I could implement an OSO server to perform this function.
I’d also be interested to know if you’d compared the performance of oso policy vs Rego on comparable input.
We've done some internal proof of concepts of this, and have discussed it with various folks, and happy to share more of this with anyone interested.
> I’d also be interested to know if you’d compared the performance of oso policy vs Rego on comparable input.
Not yet, but this a great suggestion. I would be a little worried that it would be hard to do it in an unbiased way. The two have different design choices, etc.
EDIT: I see this question below is answered here: https://news.ycombinator.com/item?id=25443354
Another question would be around how one extends oso. For example, OPA supports custom built-ins: https://www.openpolicyagent.org/docs/latest/extensions/. The other option is to add functionality to the language itself, e.g. https://github.com/open-policy-agent/opa/pull/2538
Oso seems to support this by ‘registering’ objects in the host language, e.g. https://docs.osohq.com/using/libraries/ruby/index.html#worki... in Ruby. I like the look of this and I presume that this is how you’d rather have users build more advanced policy than extending what seems to be a pretty lightweight language (https://docs.osohq.com/using/polar-syntax.html). OPA seems to have gone the other way and has a lot of functionality in the language for common cases, e.g. x509, jwt, etc. Would I be right in assuming that the current design decision is not to add such functionality to oso?
What this means practically is either the data is processed through whatever data access layer you have (i.e. SQL, or an ORM). And there's more work we're doing here to make that experience seamless [1].
Or if you do have some large input data and you iterate over it in the policy, then the oso host library (the part in your app) will just iterate through it without sending the entire object back and forth.
> I presume that this is how you’d rather have users build more advanced policy than extending what seems to be a pretty lightweight language
Yep, that's the idea. I answered a similar question here [2]. You can call class + instance methods from Polar, so if there's anything you can't do you can add it that way. We have considered/are considering adding a standard library to provide common pieces out of the box, but it's not a limiting factor for using oso currently.
There are some side benefits though that a standard library would provide - like having a robust implementation of common operations in the Rust core.
[1]: https://docs.osohq.com/getting-started/list-filtering/index....
It’ll be interesting to see what this looks like in a polyglot stack, I think that’s where having functionality in in the policy language might be really valuable.
For the time being, it’d still be possible to build a oso based policy server which applications invoke to make consistent decisions - so there are options to achieve this in the meantime too.
Agreed! And I strongly recommend to anyone thinking about doing so to join our slack [1] and come chat with us :) We'll be happy to share our thoughts on this.
All these questions are also tempting me to go and put together a demo for this too...
Looks cool, but I feel it doesn't really help with the main goals that OPA, or any other policy engine is trying to achieve (IMHO): decoupling the authorization part from the application.
Do you have any particular use case on why this is an advantage? Maybe I'm laking the main purpose on having everything in the application if in the end the goal (or at least the one I perceived) is to keep the authorization decoupled.
In GitHub you might be able to merge a PR in a repository because you are the repo owner, or you were invited to it. Or because you're an organization admin, and the repo is in the same organization. (These are all common scenarios in b2b saas apps).
When a user attempts to merge a PR (or hits the API) you need to make that authorization decision based on what the application knows about the user.
So how do you allow the policy to access this information? Your options are basically: (a) you make it possible for the policy engine to independently lookup the data. You are now building a distributed monolith, since any change to the data requires updating both the policy engine and the application. (b) You send the relevant data into the policy decisions. Knowing what data you need to send to the policy is another form of coupling.
OPA is sort of a combination of (a) and (b). There is an API for sending authorization data to it, and you can also send data along with a request.
The problem is that the line between authorization and business logic is _so blurry_. Me being a member of a github org is fundamental application logic. But also crucial to making authorization decisions.
Because of this, traditionally people write this logic as a part of the application code. Normally a bunch of `if` statements. This is hard logic to abstract well in an app, because it's normally a bunch of conditionals and a decision flow. Which it turns out prologs/logic-based languages are great at solving (same conclusion OPA folks reached).
So given all this, the balance we wanted to strike was: decoupling the logic, but not the data. If your app already defines what a User is, what a Repository is, how a User becomes a Member of a Repository, then write your policy over those things, instead of re-implementing all of that logic elsewhere.
That being said, there are cases where the OPA-style decoupling works fine since there isn't the same kind of business logic/authz logic distinction. Or where the decision is being made over the entire input by default (things like checking terraform files, or other infra use cases).
[1] https://docs.osohq.com/more/design-principles.html#separatio...
[2] https://www.osohq.com/post/building-the-github-authorization...